source: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCOgreMeshSerializer.cpp @ 969

Revision 969, 11.0 KB checked in by igarcia, 19 years ago (diff)
Line 
1#include "BBCOgreMeshSerializer.h"
2
3namespace BBC {
4
5    UniqueVertex::UniqueVertex()
6        : position(Ogre::Vector3::ZERO), normal(Ogre::Vector3::ZERO), colour(0), nextIndex(0)
7    {
8        for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; ++i)
9            uv[i] = Ogre::Vector3::ZERO;
10    }
11
12    bool UniqueVertex::operator==(const UniqueVertex& rhs) const
13    {
14        bool ret = position == rhs.position &&
15            normal == rhs.normal &&
16            colour == rhs.colour;
17        if (!ret) return ret;
18
19        for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS && ret; ++i)
20        {
21            ret = ret && (uv[i] == rhs.uv[i]);
22        }
23
24        return ret;
25    }
26
27        void OgreMeshSerializer::setEntity(EntityPtr entity)
28        {
29                mEntity = entity;
30        }
31
32        EntityPtr OgreMeshSerializer::getEntity()
33        {
34                return mEntity;
35        }
36
37    OgreMeshSerializer::OgreMeshSerializer()
38    {
39    }
40
41    OgreMeshSerializer::~OgreMeshSerializer()
42    {
43    }
44
45
46        void OgreMeshSerializer::exportMesh(const Ogre::String& fileName, bool mergeSubMeshes = false, bool tangents = false)
47    {
48
49                Ogre::LogManager::getSingleton().logMessage("** Begin OGRE Mesh Export **");
50        // Derive the scene root
51
52        // Construct mesh               
53                BBC::MeshPtr pMesh(new BBC::Mesh(Ogre::MeshManager::getSingleton().createManual(fileName, fileName).getPointer()));
54               
55                Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(fileName, fileName);
56
57                Ogre::LogManager::getSingleton().logMessage("Num.SubEntities:" + Ogre::StringConverter::toString(mEntity->getNumSubEntities()));
58
59                mEntity->setMesh(pMesh);
60
61                // write the data into a mesh
62                buildMesh(pMesh, mergeSubMeshes);
63
64        if(tangents)
65        {
66            Ogre::LogManager::getSingleton().logMessage("Calculating tangents");
67            unsigned short src, dest;
68            if (pMesh->get()->suggestTangentVectorBuildParams(src, dest))
69            {
70                pMesh->get()->buildTangentVectors(src, dest);
71            }
72            else
73            {
74                Ogre::LogManager::getSingleton().logMessage("Could not derive tangents parameters");
75            }
76        }
77
78                Ogre::LogManager::getSingleton().logMessage("** OGRE Mesh Export Complete **");
79    }
80 
81        void OgreMeshSerializer::buildMesh(MeshPtr pMesh, bool mergeSubmeshes)
82        {
83                if (!mergeSubmeshes)
84                {
85                        // build contents of this polymesh into ProtoSubMesh(es)
86                        generateEntityAABB(pMesh);
87                       
88                        // export out at the end of every PolygonMesh
89                        exportSubMeshes(pMesh);
90                }
91                // TODO
92                if (mergeSubmeshes)
93                {
94                        // build contents of this polymesh into ProtoSubMesh(es)
95                        mEntity->mergeSubEntities();
96
97                        generateEntityAABB(pMesh);
98
99                        // export out the combined result
100                        exportSubMeshes(pMesh);
101                }               
102        }
103 
104        void OgreMeshSerializer::generateEntityAABB(MeshPtr pMesh)
105        {
106                // Bounds calculation
107                Ogre::Real squaredRadius = 0.0f;
108        Ogre::Vector3 min, max;
109        bool first = true;
110               
111                for (unsigned int iSubEntity = 0; iSubEntity < mEntity->getNumSubEntities(); iSubEntity++)
112                {
113                        for (size_t jVertex = 0; jVertex < mEntity->getSubEntity(iSubEntity)->getNumVertices(); jVertex++)
114                        {
115                                if (first)
116                                {
117                                        squaredRadius = mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position.squaredLength();
118                                        min = max = mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position;
119                                        first = false;
120                                }
121                                else
122                                {
123                                        size_t numVertices = (unsigned int)mEntity->getSubEntity(iSubEntity)->getNumVertices();
124                                        //Ogre::LogManager::getSingleton().logMessage("NumVertices:" + Ogre::StringConverter::toString(numVertices));
125                                        //Ogre::LogManager::getSingleton().logMessage("IDVertex:" + Ogre::StringConverter::toString(jVertex) + "--" + Ogre::StringConverter::toString(iSubEntity) + "--" + Ogre::StringConverter::toString(mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position));
126                                        squaredRadius =
127                                                std::max(squaredRadius,mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position.squaredLength());
128                                        min.makeFloor(mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position);
129                                        max.makeCeil(mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position);
130                                }
131                        }
132        }
133
134                // Merge bounds
135                Ogre::AxisAlignedBox box;
136        box.setExtents(min, max);
137        box.merge(pMesh->get()->getBounds());
138        pMesh->get()->_setBounds(box);
139        pMesh->get()->_setBoundingSphereRadius(
140                        std::max(
141                                pMesh->get()->getBoundingSphereRadius(),
142                                Ogre::Math::Sqrt(squaredRadius)));     
143
144                Ogre::LogManager::getSingleton().logMessage("Bounds:" + Ogre::StringConverter::toString(pMesh->get()->getBoundingSphereRadius()) + " -- Generated:" + Ogre::StringConverter::toString(pMesh->get()->getBounds().isNull()));
145        }
146 
147        void OgreMeshSerializer::exportSubMeshes(MeshPtr pMesh)
148        {
149                for (unsigned int iSubEntity = 0; iSubEntity < mEntity->getNumSubEntities(); iSubEntity++)
150                {
151                        exportSubMesh(pMesh,mEntity->getSubEntity(iSubEntity));
152                }               
153        }
154 
155        void OgreMeshSerializer::exportSubMesh(MeshPtr pMesh, SubEntityPtr subEntity)
156        {               
157        Ogre::SubMesh* sm = 0;
158        if (subEntity->getName() == "")
159        {
160            sm = pMesh->get()->createSubMesh();
161        }
162        else
163        {
164            sm = pMesh->get()->createSubMesh(subEntity->getName());
165        }
166        // Set material
167        sm->setMaterialName(subEntity->getMaterialName());
168        // never use shared geometry
169        sm->useSharedVertices = false;
170                sm->vertexData = new Ogre::VertexData();
171        // always do triangle list
172        sm->indexData->indexCount = subEntity->getNumFaces()*3;
173               
174                sm->vertexData->vertexCount = subEntity->getNumVertices();
175        // Determine index size
176        bool use32BitIndexes = false;
177        if (subEntity->getNumVertices() > 65536)
178        {
179            use32BitIndexes = true;
180        }
181
182        sm->indexData->indexBuffer =
183            Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
184            use32BitIndexes ? Ogre::HardwareIndexBuffer::IT_32BIT : Ogre::HardwareIndexBuffer::IT_16BIT,
185            sm->indexData->indexCount,
186            Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
187
188        if (use32BitIndexes)
189        {
190            unsigned int* pIdx = static_cast<unsigned int*>(
191                sm->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
192                writeIndexes(pIdx,subEntity);
193                sm->indexData->indexBuffer->unlock();
194        }
195        else
196        {
197            unsigned short int* pIdx = static_cast<unsigned short int*>(
198                sm->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
199                                writeIndexes(pIdx,subEntity);
200                                sm->indexData->indexBuffer->unlock();
201        }
202               
203               
204        // define vertex declaration
205        unsigned buf = 0;
206        size_t offset = 0;
207                // always add position and normal
208        sm->vertexData->vertexDeclaration->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
209                offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
210        sm->vertexData->vertexDeclaration->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
211                offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
212
213                // Optional vertex colour
214        if(subEntity->hasVertexColors())
215        {
216            sm->vertexData->vertexDeclaration->addElement(buf, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
217                        offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
218        }
219
220        // Define UVs
221        for (unsigned short uvi = 0; uvi < subEntity->getNumTexCoordSets(); uvi++)
222        {
223                        Ogre::VertexElementType uvType = Ogre::VertexElement::multiplyTypeCount(Ogre::VET_FLOAT1, subEntity->getTexCoordDimensions(uvi));
224            sm->vertexData->vertexDeclaration->addElement(buf, offset, uvType, Ogre::VES_TEXTURE_COORDINATES, uvi);
225                        offset += Ogre::VertexElement::getTypeSize(uvType);
226        }
227
228        // create & fill buffer(s)
229        for (unsigned short b = 0; b <= sm->vertexData->vertexDeclaration->getMaxSource(); ++b)
230        {
231            createVertexBuffer(sm->vertexData, b, subEntity->getUniqueVertices());
232        }
233        }
234 
235    template <typename T>
236    void OgreMeshSerializer::writeIndexes(T* buf, SubEntityPtr subEntity)
237    {
238        for (unsigned int i = 0;  i < subEntity->getNumFaces(); i++)
239        {                       
240                        Ogre::Vector3 indexes = subEntity->getFaceVerticesIDs(i);
241                        unsigned int i0, i1, i2;
242                        i0 = (unsigned int)indexes[0];
243                        i1 = (unsigned int)indexes[1];
244                        i2 = (unsigned int)indexes[2];
245            *buf++ = static_cast<T>(i0);
246                        *buf++ = static_cast<T>(i1);
247                        *buf++ = static_cast<T>(i2);
248        }
249    }
250
251        void OgreMeshSerializer::createVertexBuffer(Ogre::VertexData* vd,
252                unsigned short bufIdx, UniqueVertexList *uniqueVertexList)
253    {
254                Ogre::HardwareVertexBufferSharedPtr vbuf =
255                        Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
256                vd->vertexDeclaration->getVertexSize(bufIdx),
257                vd->vertexCount,
258                Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
259        vd->vertexBufferBinding->setBinding(bufIdx, vbuf);
260        size_t vertexSize = vd->vertexDeclaration->getVertexSize(bufIdx);
261
262        char* pBase = static_cast<char*>(
263                                vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
264
265                Ogre::VertexDeclaration::VertexElementList elems =
266                        vd->vertexDeclaration->findElementsBySource(bufIdx);
267                Ogre::VertexDeclaration::VertexElementList::iterator ei, eiend;
268        eiend = elems.end();
269        float* pFloat;
270        Ogre::RGBA* pRGBA;
271
272        UniqueVertexList::iterator srci = uniqueVertexList->begin();
273
274        for (size_t v = 0; v < vd->vertexCount; ++v, ++srci)
275        {
276            for (ei = elems.begin(); ei != eiend; ++ei)
277            {
278                                Ogre::VertexElement& elem = *ei;
279                switch(elem.getSemantic())
280                {
281                case Ogre::VES_POSITION:
282                    elem.baseVertexPointerToElement(pBase, &pFloat);
283                    *pFloat++ = srci->position.x;
284                    *pFloat++ = srci->position.y;
285                    *pFloat++ = srci->position.z;
286                    break;
287                case Ogre::VES_NORMAL:
288                    elem.baseVertexPointerToElement(pBase, &pFloat);
289                    *pFloat++ = srci->normal.x;
290                    *pFloat++ = srci->normal.y;
291                    *pFloat++ = srci->normal.z;
292                    break;
293                case Ogre::VES_DIFFUSE:
294                    elem.baseVertexPointerToElement(pBase, &pRGBA);
295                    *pRGBA = srci->colour;
296                    break;
297                case Ogre::VES_TEXTURE_COORDINATES:
298                    elem.baseVertexPointerToElement(pBase, &pFloat);
299                                        for (int t = 0; t < Ogre::VertexElement::getTypeCount(elem.getType()); ++t)
300                                        {
301                                                Ogre::Real val = srci->uv[elem.getIndex()][t];
302                                                *pFloat++ = val;
303                                        }
304                    break;
305                }
306            }
307            pBase += vertexSize;
308        }
309        vbuf->unlock();
310
311    }
312
313}
Note: See TracBrowser for help on using the repository browser.