source: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntity.cpp @ 721

Revision 721, 16.4 KB checked in by igarcia, 18 years ago (diff)
Line 
1
2#include "BBCEntity.h"
3
4namespace BBC {
5
6Entity::Entity(): references(0) // initialize references to 0
7{
8        createSubEntity();
9}
10
11Entity::~Entity()       
12{
13
14}
15
16void Entity::createSubEntity()
17{
18        SubEntityPtr subEntityPtr((SubEntity*)new SubEntity());
19        mSubEntityList.push_back(subEntityPtr);
20}
21
22void Entity::addSubEntity(SubEntityPtr value)
23{
24        mSubEntityList.push_back(value);
25}
26
27SubEntityPtr Entity::getSubEntity(unsigned int index)
28{
29        return mSubEntityList[index];
30}
31
32void Entity::removeSubEntity(unsigned int index)
33{
34        mSubEntityList.erase(mSubEntityList.begin()+index);
35}
36
37void Entity::setSubEntitiesDistinctVertexColours()
38{
39        for (unsigned int iSubEntity = 0; iSubEntity < mSubEntityList.size(); iSubEntity++)
40        {
41                mSubEntityList[iSubEntity]->enableVertexColours(true);
42                float fRed = Ogre::Math::RangeRandom(0.0,1.0);
43                float fGreen = Ogre::Math::RangeRandom(0.0,1.0);
44                float fBlue = Ogre::Math::RangeRandom(0.0,1.0);
45                Ogre::ColourValue subEntityColour = Ogre::ColourValue(1.0,fRed,fGreen,fBlue);
46                for (unsigned int iVertex = 0; iVertex < mSubEntityList[iSubEntity]->getNumVertices(); iVertex++)
47                {
48                        mSubEntityList[iSubEntity]->setVertexColour(iVertex, subEntityColour.getAsRGBA());
49                }
50        }
51}
52
53MeshPtr Entity::getMesh()
54{
55        return mMesh;
56}
57
58void Entity::setMesh(MeshPtr value)
59{
60        mMesh = value;
61}
62
63unsigned int Entity::getEntityHandle() {
64        return mEntityHandle;
65}
66
67void Entity::setEntityHandle(unsigned int value)
68{
69        mEntityHandle = value;
70}
71
72void Entity::loadMesh(bool mergeSubMeshes = false)
73{
74   Ogre::Vector3 position = Ogre::Vector3::ZERO;
75   Ogre::Quaternion orient = Ogre::Quaternion(1.0,1.0,1.0,1.0);
76   Ogre::Vector3 scale = Ogre::Vector3::ZERO;
77   unsigned int coordset = 0;
78   unsigned short dimTexCoord = 2;
79
80   getMeshPositions(position,orient,scale,mergeSubMeshes);
81   getMeshNormals(orient,scale,mergeSubMeshes);
82   getMeshVertexColours(mergeSubMeshes);
83   getMeshTexCoords(mergeSubMeshes);
84   getMeshFacesVerticesID(mergeSubMeshes);
85}
86
87void Entity::sincronizeNumSubEntities()
88{
89        if (this->getNumSubEntities() < mMesh->get()->getNumSubMeshes())
90        {
91                while (this->getNumSubEntities() < mMesh->get()->getNumSubMeshes())
92                {
93                        this->createSubEntity();
94                }
95        }
96
97        if (this->getNumSubEntities() > mMesh->get()->getNumSubMeshes())
98        {
99                while (this->getNumSubEntities() > mMesh->get()->getNumSubMeshes())
100                {
101                        this->removeSubEntity(this->getNumSubEntities()-1);
102                }
103        }
104}
105
106void Entity::getMeshPositions(Ogre::Vector3 position, Ogre::Quaternion orient, Ogre::Vector3 scale, bool mergeSubMeshes)
107{       
108        bool added_shared = false;
109        size_t current_offset = 0;
110        size_t shared_offset = 0;
111        size_t next_offset = 0;
112
113        unsigned int numSubMeshes = mMesh->get()->getNumSubMeshes();
114        sincronizeNumSubEntities();
115       
116        added_shared = false;
117        for (unsigned short i = 0; i < mMesh->get()->getNumSubMeshes(); i++)
118        {
119                Ogre::SubMesh* subMesh = mMesh->get()->getSubMesh(i);
120                Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->get()->sharedVertexData : subMesh->vertexData;
121
122                if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
123                {
124                        if (subMesh->useSharedVertices)
125                        {
126                                added_shared = true;
127                                shared_offset = current_offset;
128                        }
129
130                        const Ogre::VertexElement* positionElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
131                        Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(positionElem->getSource());
132                        unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
133                        float* pReal;
134
135                        for(size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
136                        {
137                                positionElem->baseVertexPointerToElement(vertex, &pReal);
138                        Ogre::Vector3 position(pReal[0], pReal[1], pReal[2]);
139                               
140                                if (!mergeSubMeshes)
141                                {
142                                        UniqueVertex uniqueVertex;
143                                        uniqueVertex.position = position;
144                                        this->getSubEntity(i)->addUniqueVertex(uniqueVertex);                           
145                                }
146                                else
147                                {
148                                        UniqueVertex uniqueVertex;
149                                        uniqueVertex.position = position;                                       
150
151                                        this->getSubEntity(0)->addUniqueVertex(uniqueVertex);                           
152                                }
153                        }
154                        vbuf->unlock();
155                        next_offset += vertexData->vertexCount;
156                }     
157        }
158    current_offset = next_offset;
159}
160
161
162void Entity::getMeshNormals(Ogre::Quaternion orient, Ogre::Vector3 scale, bool mergeSubMeshes)
163{
164        bool added_shared = false;
165        size_t current_offset = 0;
166        size_t shared_offset = 0;
167        size_t next_offset = 0;
168
169        unsigned int numSubMeshes = mMesh->get()->getNumSubMeshes();
170        sincronizeNumSubEntities();
171       
172        added_shared = false;
173        for (unsigned short i = 0; i < mMesh->get()->getNumSubMeshes(); i++)
174        {
175                Ogre::SubMesh* subMesh = mMesh->get()->getSubMesh(i);
176                Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->get()->sharedVertexData : subMesh->vertexData;
177
178                if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
179                {
180                        if (subMesh->useSharedVertices)
181                        {
182                                added_shared = true;
183                                shared_offset = current_offset;
184                        }
185
186                        const Ogre::VertexElement* normalElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);
187                        Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(normalElem->getSource());
188                        unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
189                        float* pReal;
190
191                        for(size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
192                        {
193                                normalElem->baseVertexPointerToElement(vertex, &pReal);
194                        Ogre::Vector3 normal(pReal[0], pReal[1], pReal[2]);
195
196                                if (!mergeSubMeshes)
197                                {
198                                        this->getSubEntity(i)->setNormal(j,normal);     
199                                }
200                                else
201                                {
202                                        this->getSubEntity(0)->setNormal(j,normal);                                                             
203                                }
204                        }
205                        vbuf->unlock();
206                        next_offset += vertexData->vertexCount;
207                }     
208        }
209    current_offset = next_offset;
210}
211
212void Entity::getMeshVertexColours(bool mergeSubMeshes)
213{
214        bool added_shared = false;
215        size_t current_offset = 0;
216        size_t shared_offset = 0;
217        size_t next_offset = 0;
218
219        unsigned int numSubMeshes = mMesh->get()->getNumSubMeshes();
220        sincronizeNumSubEntities();
221       
222        added_shared = false;
223        for (unsigned short i = 0; i < mMesh->get()->getNumSubMeshes(); i++)
224        {
225                Ogre::SubMesh* subMesh = mMesh->get()->getSubMesh(i);
226                Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->get()->sharedVertexData : subMesh->vertexData;
227
228                if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
229                {
230                        if (subMesh->useSharedVertices)
231                        {
232                                added_shared = true;
233                                shared_offset = current_offset;
234                        }
235
236                        const Ogre::VertexElement* colourElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_DIFFUSE);
237            if (colourElem)
238            {
239                                //Ogre::LogManager::getSingleton().logMessage("Has vertex colours!");
240                                Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(colourElem->getSource());
241                                unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
242                                Ogre::RGBA *pSrcRGBA;
243
244                                for(size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
245                                {
246                                        if (colourElem)
247                                        {
248                                                colourElem->baseVertexPointerToElement(vertex, &pSrcRGBA);
249                                        }
250                                       
251                                        Ogre::ColourValue colour((Ogre::RGBA)(*pSrcRGBA));
252
253                                        if (!mergeSubMeshes)
254                                        {
255                                                this->getSubEntity(i)->setVertexColour(j,colour.getAsRGBA());   
256                                        }
257                                        else
258                                        {                               
259                                                this->getSubEntity(0)->setVertexColour(j,colour.getAsRGBA());
260                                        }
261                                }
262                                vbuf->unlock();
263                                next_offset += vertexData->vertexCount;
264
265                                if (!mergeSubMeshes)
266                                {
267                                        this->getSubEntity(i)->enableVertexColours(true);
268                                }
269                                else
270                                {
271                                        this->getSubEntity(0)->enableVertexColours(true);
272                                }
273                        }
274                }     
275        }
276    current_offset = next_offset;
277}
278
279void Entity::getMeshTexCoords(bool mergeSubMeshes)
280{       
281        bool added_shared = false;
282        size_t current_offset = 0;
283        size_t shared_offset = 0;
284        size_t next_offset = 0;
285
286        unsigned int numSubMeshes = mMesh->get()->getNumSubMeshes();
287        sincronizeNumSubEntities();
288       
289        added_shared = false;
290        for (unsigned short i = 0; i < mMesh->get()->getNumSubMeshes(); i++)
291        {
292                Ogre::SubMesh* subMesh = mMesh->get()->getSubMesh(i);
293                Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->get()->sharedVertexData : subMesh->vertexData;
294
295                if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
296                {
297                        if (subMesh->useSharedVertices)
298                        {
299                                added_shared = true;
300                                shared_offset = current_offset;
301                        }
302
303                        const Ogre::VertexElement* texcoordElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
304                        Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(texcoordElem->getSource());
305                        unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
306
307                        Ogre::VertexDeclaration* decl = vertexData->vertexDeclaration;
308                        Ogre::VertexBufferBinding* bind = vertexData->vertexBufferBinding;
309                        Ogre::VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend;
310                        bend = bind->getBindings().end();
311                        // Iterate over buffers
312                        for (b = bind->getBindings().begin(); b != bend; ++b)
313                        {
314                                const Ogre::HardwareVertexBufferSharedPtr vbuf = b->second;
315                                unsigned short bufferIdx = b->first;
316                                // Get all the elements that relate to this buffer
317                                Ogre::VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx);
318                                Ogre::VertexDeclaration::VertexElementList::iterator it, itend;
319                                itend = elems.end();
320
321                                // Skim over the elements to set up the general data
322                                unsigned short numTextureCoords = 0;
323                                std::vector<unsigned int> baseTexCoordSetIndex;
324                                for (it = elems.begin(); it != itend; ++it)
325                                {
326                                        Ogre::VertexElement& elem = *it;
327                                        if (elem.getSemantic() == Ogre::VES_TEXTURE_COORDINATES)
328                                        {
329                                                if (numTextureCoords == 0)
330                                                {
331                                                        baseTexCoordSetIndex.push_back(0);
332                                                        baseTexCoordSetIndex.push_back(Ogre::VertexElement::getTypeCount(elem.getType()));
333                                                }
334                                                ++numTextureCoords;
335                                        }
336                                }
337
338                                // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
339                                // as a second argument. So make it float, to avoid trouble when Ogre::Real will be
340                                // compiled/typedefed as double:
341                                // Ogre::Real* pReal;
342                                float* pReal;
343
344                                unsigned int baseTexCoord = 0;
345                                unsigned int texCoordSet = 0;
346                                unsigned int dimBaseTexCoord = 0;
347                                for (unsigned int texCoordSet = 0; texCoordSet < numTextureCoords; texCoordSet++)
348                                {
349                                        for (unsigned int iTexCoordSet = 0; iTexCoordSet <= texCoordSet; iTexCoordSet++)
350                                        {
351                                                baseTexCoord = baseTexCoord + baseTexCoordSetIndex[iTexCoordSet];
352                                        }
353                                        unsigned short dimTexCoord = (unsigned short)baseTexCoordSetIndex[texCoordSet+1];
354                                        for (size_t j = 0; j < vertexData->vertexCount; j++, vertex += vbuf->getVertexSize())
355                                        {
356                                                texcoordElem->baseVertexPointerToElement(vertex, &pReal);
357                                                Ogre::Vector3 texcoord;
358                                                if (baseTexCoordSetIndex[texCoordSet+1] == 2)
359                                                {
360                                                        texcoord = Ogre::Vector3(pReal[baseTexCoord + 0], pReal[baseTexCoord + 1], 0.0);
361                                                        dimBaseTexCoord = 2;
362                                                }
363                                                else if (baseTexCoordSetIndex[texCoordSet + 1] == 3)
364                                                {
365                                                        texcoord = Ogre::Vector3(pReal[baseTexCoord + 0], pReal[baseTexCoord + 1], pReal[baseTexCoord + 2]);
366                                                        dimBaseTexCoord = 3;
367                                                }
368                                       
369                                                if (!mergeSubMeshes)
370                                                {
371                                                        this->getSubEntity(i)->setTexCoord(j,texCoordSet,texcoord);
372                                                }
373                                                else
374                                                {
375                                                        this->getSubEntity(0)->setTexCoord(j,texCoordSet,texcoord);                             
376                                                }
377                                        }                       
378                       
379                                        if (!mergeSubMeshes)
380                                        {
381                                                this->getSubEntity(i)->addTextureCoordSet(dimBaseTexCoord);
382                                        }
383                                        else
384                                        {
385                                                if (i == 0)
386                                                {
387                                                        this->getSubEntity(0)->addTextureCoordSet(dimBaseTexCoord);
388                                                }
389                                        }
390                                }       
391                        }                       
392                        vbuf->unlock();
393                        next_offset += vertexData->vertexCount;
394                }     
395        }
396    current_offset = next_offset;
397}
398
399void Entity::getMeshFacesVerticesID(bool mergeSubMeshes)
400{
401        bool added_shared = false;
402        size_t current_offset = 0;
403        size_t shared_offset = 0;
404        size_t next_offset = 0;
405        size_t index_offset = 0;
406
407        unsigned int numSubMeshes = mMesh->get()->getNumSubMeshes();
408        sincronizeNumSubEntities();
409
410        added_shared = false;
411
412        // Run through the submeshes again, adding the data into the arrays
413        for ( unsigned short i = 0; i < mMesh->get()->getNumSubMeshes(); ++i)
414        {
415                Ogre::SubMesh* submesh = mMesh->get()->getSubMesh(i);
416
417                Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mMesh->get()->sharedVertexData : submesh->vertexData;
418
419                if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
420                {
421                        if(submesh->useSharedVertices)
422                        {
423                                added_shared = true;
424                                shared_offset = current_offset;
425                        }
426                        const Ogre::VertexElement* texcoordElem =
427                        vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
428
429                        Ogre::HardwareVertexBufferSharedPtr vbuf =
430                        vertex_data->vertexBufferBinding->getBuffer(texcoordElem->getSource());
431
432                        unsigned char* vertex =
433                        static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
434
435                        vbuf->unlock();
436                        next_offset += vertex_data->vertexCount;
437                }
438
439                Ogre::IndexData* index_data = submesh->indexData;
440                size_t numTris = index_data->indexCount / 3;
441                Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
442   
443                bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
444
445                unsigned long*  pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
446                unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
447
448                size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
449
450
451                if ( use32bitindexes )
452                {
453                        for ( size_t k = 0; k < numTris*3; k=k+3)
454                        {
455                                if (!mergeSubMeshes)
456                                {
457                                        Ogre::Vector3 indices(k,k+1,k+2);
458                                        this->getSubEntity(i)->addFaceVerticesIDs(indices);                             
459                                }
460                                else
461                                {
462                                        Ogre::Vector3 indices = Ogre::Vector3(pLong[k] + static_cast<unsigned long>(offset),pLong[k+1] + static_cast<unsigned long>(offset),pLong[k+2] + static_cast<unsigned long>(offset));
463                                        this->getSubEntity(0)->addFaceVerticesIDs(indices);                     
464                                }                       
465                                index_offset++;
466                        }
467                }
468                else
469                {
470                        for ( size_t k = 0; k < numTris*3; k=k+3)
471                        {                               
472                                if (!mergeSubMeshes)
473                                {
474                                        Ogre::Vector3 indices(k,k+1,k+2);
475                                        this->getSubEntity(i)->addFaceVerticesIDs(indices);                             
476                                }
477                                else
478                                {
479                                        Ogre::Vector3 indices = Ogre::Vector3(static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset),static_cast<unsigned long>(pShort[k+1]) + static_cast<unsigned long>(offset),static_cast<unsigned long>(pShort[k+2]) + static_cast<unsigned long>(offset));
480                                        this->getSubEntity(0)->addFaceVerticesIDs(indices);                     
481                                }
482                                index_offset++;
483                        }         
484                }               
485
486                ibuf->unlock();
487                current_offset = next_offset;
488        }
489}
490
491unsigned int Entity::getNumSubEntities()
492{
493        return mSubEntityList.size();
494}
495
496void Entity::mergeSubEntities()
497{
498        if (mSubEntityList.size() > 1)
499        {
500                unsigned int currentMaxNumVertices = mSubEntityList[0]->getNumVertices();
501                unsigned int iIDVertex = currentMaxNumVertices;
502                for (unsigned int iSubEntity = 1; iSubEntity < mSubEntityList.size(); iSubEntity++)
503                {
504                        if (mSubEntityList[iSubEntity]->getNumTexCoordSets() == mSubEntityList[0]->getNumTexCoordSets())
505                        {
506                                for (unsigned int iVertex = 0; iVertex < mSubEntityList[iSubEntity]->getNumVertices(); iVertex++)
507                                {
508                                        mSubEntityList[0]->addUniqueVertex(mSubEntityList[iSubEntity]->getUniqueVertex(iVertex));
509                                }
510                               
511                                // Vertices IDs go from [0,NUMVERT-1] -> First new vertex should be NUMVERT...
512                                for (unsigned int iFaceVerticesIDs = 0; iFaceVerticesIDs < mSubEntityList[iSubEntity]->getNumFaces(); iFaceVerticesIDs++)
513                                {
514                                        mSubEntityList[0]->addFaceVerticesIDs(Ogre::Vector3(iIDVertex,iIDVertex+1,iIDVertex+2));                               
515                                        iIDVertex = iIDVertex + 3;
516                                }
517                        }
518                        else
519                        {
520                                Ogre::LogManager::getSingleton().logMessage("Error: The number of texture coord. sets is not the same in all the subentities...");
521                        }                       
522                }
523
524                for (unsigned int iSubEntity = 1; iSubEntity < mSubEntityList.size(); iSubEntity)
525                {
526                        mSubEntityList.erase(mSubEntityList.begin()+iSubEntity);
527                }
528        }
529}
530
531}
Note: See TracBrowser for help on using the repository browser.