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

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