source: OGRE/trunk/ogrenew/Tools/XMLConverter/src/OgreXMLMeshSerializer.cpp @ 657

Revision 657, 46.5 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25
26
27#include "OgreXMLMeshSerializer.h"
28#include "OgreSubMesh.h"
29#include "OgreLogManager.h"
30#include "OgreSkeleton.h"
31#include "OgreStringConverter.h"
32#include "OgreHardwareBufferManager.h"
33#include "OgreException.h"
34
35namespace Ogre {
36
37    //---------------------------------------------------------------------
38    XMLMeshSerializer::XMLMeshSerializer()
39    {
40    }
41    //---------------------------------------------------------------------
42    XMLMeshSerializer::~XMLMeshSerializer()
43    {
44    }
45    //---------------------------------------------------------------------
46    void XMLMeshSerializer::importMesh(const String& filename, Mesh* pMesh)
47    {
48        LogManager::getSingleton().logMessage("XMLMeshSerializer reading mesh data from " + filename + "...");
49        mpMesh = pMesh;
50        mXMLDoc = new TiXmlDocument(filename);
51        mXMLDoc->LoadFile();
52
53        TiXmlElement* elem;
54
55        TiXmlElement* rootElem = mXMLDoc->RootElement();
56
57        // shared geometry
58        elem = rootElem->FirstChildElement("sharedgeometry");
59        if (elem)
60        {
61            if(StringConverter::parseInt(elem->Attribute("vertexcount")) > 0)
62            {
63                mpMesh->sharedVertexData = new VertexData();
64                readGeometry(elem, mpMesh->sharedVertexData);
65            }
66        }
67
68        // submeshes
69        elem = rootElem->FirstChildElement("submeshes");
70        if (elem)
71            readSubMeshes(elem);
72
73        // skeleton link
74        elem = rootElem->FirstChildElement("skeletonlink");
75        if (elem)
76            readSkeletonLink(elem);
77
78        // bone assignments
79        elem = rootElem->FirstChildElement("boneassignments");
80        if (elem)
81            readBoneAssignments(elem);
82
83                //Lod
84                elem = rootElem->FirstChildElement("levelofdetail");
85                if (elem)
86                        readLodInfo(elem);
87
88                // submesh names
89                elem = rootElem->FirstChildElement("submeshnames");
90                if (elem)
91                        readSubMeshNames(elem, mpMesh);
92
93        delete mXMLDoc;
94
95        LogManager::getSingleton().logMessage("XMLMeshSerializer import successful.");
96       
97    }
98    //---------------------------------------------------------------------
99    void XMLMeshSerializer::exportMesh(const Mesh* pMesh, const String& filename)
100    {
101        LogManager::getSingleton().logMessage("XMLMeshSerializer writing mesh data to " + filename + "...");
102       
103        mpMesh = const_cast<Mesh*>(pMesh);
104
105        mXMLDoc = new TiXmlDocument();
106        mXMLDoc->InsertEndChild(TiXmlElement("mesh"));
107        TiXmlElement* rootNode = mXMLDoc->RootElement();
108
109        LogManager::getSingleton().logMessage("Populating DOM...");
110
111           
112           
113        // Write to DOM
114        writeMesh(pMesh);
115        LogManager::getSingleton().logMessage("DOM populated, writing XML file..");
116
117        // Write out to a file
118        mXMLDoc->SaveFile(filename);
119
120   
121        delete mXMLDoc;
122
123        LogManager::getSingleton().logMessage("XMLMeshSerializer export successful.");
124
125    }
126    //---------------------------------------------------------------------
127    void XMLMeshSerializer::writeMesh(const Mesh* pMesh)
128    {
129        TiXmlElement* rootNode = mXMLDoc->RootElement();
130        // Write geometry
131                if (pMesh->sharedVertexData)
132                {
133                        TiXmlElement* geomNode =
134                                rootNode->InsertEndChild(TiXmlElement("sharedgeometry"))->ToElement();
135                        writeGeometry(geomNode, pMesh->sharedVertexData);
136                }
137
138        // Write Submeshes
139        TiXmlElement* subMeshesNode =
140            rootNode->InsertEndChild(TiXmlElement("submeshes"))->ToElement();
141        for (int i = 0; i < pMesh->getNumSubMeshes(); ++i)
142        {
143            LogManager::getSingleton().logMessage("Writing submesh...");
144            writeSubMesh(subMeshesNode, pMesh->getSubMesh(i));
145            LogManager::getSingleton().logMessage("Submesh exported.");
146        }
147
148        // Write skeleton info if required
149        if (pMesh->hasSkeleton())
150        {
151            LogManager::getSingleton().logMessage("Exporting skeleton link...");
152            // Write skeleton link
153            writeSkeletonLink(rootNode, pMesh->getSkeletonName());
154            LogManager::getSingleton().logMessage("Skeleton link exported.");
155
156            // Write bone assignments
157            Mesh::BoneAssignmentIterator bi = const_cast<Mesh*>(pMesh)->getBoneAssignmentIterator();
158            if (bi.hasMoreElements())
159            {
160                LogManager::getSingleton().logMessage("Exporting shared geometry bone assignments...");
161                TiXmlElement* boneAssignNode =
162                    rootNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement();
163
164                while (bi.hasMoreElements())
165                {
166                    writeBoneAssignment(boneAssignNode, &(bi.getNext()));
167                }
168
169                LogManager::getSingleton().logMessage("Shared geometry bone assignments exported.");
170            }
171        }
172                if (pMesh->getNumLodLevels() > 1)
173                {
174            LogManager::getSingleton().logMessage("Exporting LOD information...");
175                        writeLodInfo(rootNode, pMesh);
176            LogManager::getSingleton().logMessage("LOD information exported.");
177                }
178        // Write submesh names
179        writeSubMeshNames(rootNode, pMesh);
180
181
182
183
184
185    }
186    //---------------------------------------------------------------------
187    void XMLMeshSerializer::writeSubMesh(TiXmlElement* mSubMeshesNode, const SubMesh* s)
188    {
189        TiXmlElement* subMeshNode =
190            mSubMeshesNode->InsertEndChild(TiXmlElement("submesh"))->ToElement();
191
192        size_t numFaces;
193
194        // Material name
195        subMeshNode->SetAttribute("material", s->getMaterialName());
196        // bool useSharedVertices
197        subMeshNode->SetAttribute("usesharedvertices",
198            StringConverter::toString(s->useSharedVertices) );
199        // bool use32BitIndexes
200                bool use32BitIndexes = (s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
201        subMeshNode->SetAttribute("use32bitindexes",
202            StringConverter::toString( use32BitIndexes ));
203
204        // Operation type
205        switch(s->operationType)
206        {
207        case RenderOperation::OT_LINE_LIST:
208        case RenderOperation::OT_LINE_STRIP:
209        case RenderOperation::OT_POINT_LIST:
210            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Unsupported operation type, only "
211                "triangle types are allowed.", "XMLMeshSerializer::writeSubMesh");
212            break;
213        case RenderOperation::OT_TRIANGLE_FAN:
214            subMeshNode->SetAttribute("operationtype", "triangle_fan");
215            break;
216        case RenderOperation::OT_TRIANGLE_LIST:
217            subMeshNode->SetAttribute("operationtype", "triangle_list");
218            break;
219        case RenderOperation::OT_TRIANGLE_STRIP:
220            subMeshNode->SetAttribute("operationtype", "triangle_strip");
221            break;
222        }
223
224        // Faces
225        TiXmlElement* facesNode =
226            subMeshNode->InsertEndChild(TiXmlElement("faces"))->ToElement();
227        if (s->operationType == RenderOperation::OT_TRIANGLE_LIST)
228        {
229            // tri list
230            numFaces = s->indexData->indexCount / 3;
231        }
232        else
233        {
234            // triangle fan or triangle strip
235            numFaces = s->indexData->indexCount - 2;
236        }
237        facesNode->SetAttribute("count",
238            StringConverter::toString(numFaces));
239        // Write each face in turn
240        ushort i;
241                unsigned int* pInt;
242                unsigned short* pShort;
243                HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer;
244                if (use32BitIndexes)
245                {
246                        pInt = static_cast<unsigned int*>(
247                                ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
248                }
249                else
250                {
251                        pShort = static_cast<unsigned short*>(
252                                ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
253                }
254        for (i = 0; i < numFaces; ++i)
255        {
256            TiXmlElement* faceNode =
257                facesNode->InsertEndChild(TiXmlElement("face"))->ToElement();
258                        if (use32BitIndexes)
259                        {
260                                faceNode->SetAttribute("v1", StringConverter::toString(*pInt++));
261                /// Only need all 3 vertex indices if trilist or first face
262                if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0)
263                {
264                                    faceNode->SetAttribute("v2", StringConverter::toString(*pInt++));
265                                    faceNode->SetAttribute("v3", StringConverter::toString(*pInt++));
266                }
267                        }
268                        else
269                        {
270                                faceNode->SetAttribute("v1", StringConverter::toString(*pShort++));
271                /// Only need all 3 vertex indices if trilist or first face
272                if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0)
273                {
274                                    faceNode->SetAttribute("v2", StringConverter::toString(*pShort++));
275                                    faceNode->SetAttribute("v3", StringConverter::toString(*pShort++));
276                }
277                        }
278        }
279
280        // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
281        if (!s->useSharedVertices)
282        {
283            TiXmlElement* geomNode =
284                subMeshNode->InsertEndChild(TiXmlElement("geometry"))->ToElement();
285            writeGeometry(geomNode, s->vertexData);
286        }
287
288        // Bone assignments
289        if (mpMesh->hasSkeleton())
290        {
291            SubMesh::BoneAssignmentIterator bi = const_cast<SubMesh*>(s)->getBoneAssignmentIterator();
292            LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");
293
294            TiXmlElement* boneAssignNode =
295                subMeshNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement();
296            while (bi.hasMoreElements())
297            {
298                writeBoneAssignment(boneAssignNode, &bi.getNext());
299            }
300        }
301        LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported.");
302
303    }
304    //---------------------------------------------------------------------
305    void XMLMeshSerializer::writeGeometry(TiXmlElement* mParentNode, const VertexData* vertexData)
306    {
307        // Write a vertex buffer per element
308
309        TiXmlElement *vbNode, *vertexNode, *dataNode;
310
311        // Set num verts on parent
312        mParentNode->SetAttribute("vertexcount", StringConverter::toString(vertexData->vertexCount));
313
314                VertexDeclaration* decl = vertexData->vertexDeclaration;
315                VertexBufferBinding* bind = vertexData->vertexBufferBinding;
316
317                VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend;
318                bend = bind->getBindings().end();
319                // Iterate over buffers
320                for(b = bind->getBindings().begin(); b != bend; ++b)
321                {
322                        vbNode = mParentNode->InsertEndChild(TiXmlElement("vertexbuffer"))->ToElement();
323                        const HardwareVertexBufferSharedPtr vbuf = b->second;
324                        unsigned short bufferIdx = b->first;
325                        // Get all the elements that relate to this buffer                     
326                        VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx);
327                        VertexDeclaration::VertexElementList::iterator i, iend;
328                        iend = elems.end();
329
330                        // Set up the data access for this buffer (lock read-only)
331                        unsigned char* pVert;
332                        float* pFloat;
333                        ARGB* pColour;
334
335                        pVert = static_cast<unsigned char*>(
336                                vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
337
338            // Skim over the elements to set up the general data
339            unsigned short numTextureCoords = 0;
340                        for (i = elems.begin(); i != iend; ++i)
341                        {
342                                VertexElement& elem = *i;
343                                switch(elem.getSemantic())
344                                {
345                                case VES_POSITION:
346                                        vbNode->SetAttribute("positions","true");
347                    break;
348                                case VES_NORMAL:
349                                        vbNode->SetAttribute("normals","true");
350                    break;
351                                case VES_DIFFUSE:
352                                        vbNode->SetAttribute("colours_diffuse","true");
353                    break;
354                                case VES_SPECULAR:
355                                        vbNode->SetAttribute("colours_specular","true");
356                    break;
357                case VES_TEXTURE_COORDINATES:
358                    vbNode->SetAttribute(
359                        "texture_coord_dimensions_" + StringConverter::toString(numTextureCoords),
360                        StringConverter::toString(VertexElement::getTypeCount(elem.getType())));
361                    ++numTextureCoords;
362                    break;
363                default:
364                    break;
365                }
366            }
367            if (numTextureCoords > 0)
368            {
369                vbNode->SetAttribute("texture_coords",
370                    StringConverter::toString(numTextureCoords));
371            }
372
373                        // For each vertex
374                        for (size_t v = 0; v < vertexData->vertexCount; ++v)
375                        {
376                vertexNode =
377                    vbNode->InsertEndChild(TiXmlElement("vertex"))->ToElement();
378                                // Iterate over the elements
379                                for (i = elems.begin(); i != iend; ++i)
380                                {
381                                        VertexElement& elem = *i;
382                                        switch(elem.getSemantic())
383                                        {
384                                        case VES_POSITION:
385                                                elem.baseVertexPointerToElement(pVert, &pFloat);
386                                                dataNode =
387                                                        vertexNode->InsertEndChild(TiXmlElement("position"))->ToElement();
388                                                dataNode->SetAttribute("x", StringConverter::toString(pFloat[0]));
389                                                dataNode->SetAttribute("y", StringConverter::toString(pFloat[1]));
390                                                dataNode->SetAttribute("z", StringConverter::toString(pFloat[2]));
391                                                break;
392                                        case VES_NORMAL:
393                                                elem.baseVertexPointerToElement(pVert, &pFloat);
394                                                dataNode =
395                                                        vertexNode->InsertEndChild(TiXmlElement("normal"))->ToElement();
396                                                dataNode->SetAttribute("x", StringConverter::toString(pFloat[0]));
397                                                dataNode->SetAttribute("y", StringConverter::toString(pFloat[1]));
398                                                dataNode->SetAttribute("z", StringConverter::toString(pFloat[2]));
399                                                break;
400                                        case VES_DIFFUSE:
401                                                elem.baseVertexPointerToElement(pVert, &pColour);
402                                                dataNode =
403                                                        vertexNode->InsertEndChild(TiXmlElement("colour_diffuse"))->ToElement();
404                                                {
405                                                        ARGB rc = *pColour++;
406                                                        ColourValue cv;
407                                                        cv.b = (rc & 0xFF) / 255.0f;            rc >>= 8;
408                                                        cv.g = (rc & 0xFF) / 255.0f;            rc >>= 8;
409                                                        cv.r = (rc & 0xFF) / 255.0f;            rc >>= 8;
410                                                        cv.a = (rc & 0xFF) / 255.0f;
411                            dataNode->SetAttribute("value", StringConverter::toString(cv));
412                                                }
413                                                break;
414                                        case VES_SPECULAR:
415                                                elem.baseVertexPointerToElement(pVert, &pColour);
416                                                dataNode =
417                                                        vertexNode->InsertEndChild(TiXmlElement("colour_specular"))->ToElement();
418                                                {
419                                                        ARGB rc = *pColour++;
420                                                        ColourValue cv;
421                                                        cv.b = (rc & 0xFF) / 255.0f;            rc >>= 8;
422                                                        cv.g = (rc & 0xFF) / 255.0f;            rc >>= 8;
423                                                        cv.r = (rc & 0xFF) / 255.0f;            rc >>= 8;
424                                                        cv.a = (rc & 0xFF) / 255.0f;
425                                                        dataNode->SetAttribute("value", StringConverter::toString(cv));
426                                                }
427                                                break;
428                                        case VES_TEXTURE_COORDINATES:
429                                                elem.baseVertexPointerToElement(pVert, &pFloat);
430                                                dataNode =
431                                                        vertexNode->InsertEndChild(TiXmlElement("texcoord"))->ToElement();
432
433                                                switch(elem.getType())
434                        {
435                        case VET_FLOAT1:
436                                                dataNode->SetAttribute("u", StringConverter::toString(*pFloat++));
437                            break;
438                        case VET_FLOAT2:
439                                                dataNode->SetAttribute("u", StringConverter::toString(*pFloat++));
440                                                dataNode->SetAttribute("v", StringConverter::toString(*pFloat++));
441                            break;
442                        case VET_FLOAT3:
443                                                dataNode->SetAttribute("u", StringConverter::toString(*pFloat++));
444                                                dataNode->SetAttribute("v", StringConverter::toString(*pFloat++));
445                                                dataNode->SetAttribute("w", StringConverter::toString(*pFloat++));
446                            break;
447                        default:
448                            break;
449                        }
450                                                break;
451                    default:
452                        break;
453
454                                        }
455                                }
456                                pVert += vbuf->getVertexSize();
457                        }
458                        vbuf->unlock();
459                }
460
461    }
462    //---------------------------------------------------------------------
463    void XMLMeshSerializer::writeSkeletonLink(TiXmlElement* mMeshNode, const String& skelName)
464    {
465
466        TiXmlElement* skelNode =
467            mMeshNode->InsertEndChild(TiXmlElement("skeletonlink"))->ToElement();
468        skelNode->SetAttribute("name", skelName);
469    }
470    //---------------------------------------------------------------------
471    void XMLMeshSerializer::writeBoneAssignment(TiXmlElement* mBoneAssignNode, const VertexBoneAssignment* assign)
472    {
473        TiXmlElement* assignNode =
474            mBoneAssignNode->InsertEndChild(
475            TiXmlElement("vertexboneassignment"))->ToElement();
476
477        assignNode->SetAttribute("vertexindex",
478            StringConverter::toString(assign->vertexIndex));
479        assignNode->SetAttribute("boneindex",
480            StringConverter::toString(assign->boneIndex));
481        assignNode->SetAttribute("weight",
482            StringConverter::toString(assign->weight));
483
484
485    }
486    //---------------------------------------------------------------------
487    void XMLMeshSerializer::readSubMeshes(TiXmlElement* mSubmeshesNode)
488    {
489        LogManager::getSingleton().logMessage("Reading submeshes...");
490
491        for (TiXmlElement* smElem = mSubmeshesNode->FirstChildElement();
492            smElem != 0; smElem = smElem->NextSiblingElement())
493        {
494            // All children should be submeshes
495            SubMesh* sm = mpMesh->createSubMesh();
496
497            const char* mat = smElem->Attribute("material");
498            if (mat)
499                sm->setMaterialName(mat);
500
501            // Read operation type
502            const char* optype = smElem->Attribute("operationtype");
503            if (optype)
504            {
505                if (!strcmp(optype, "triangle_list"))
506                {
507                    sm->operationType = RenderOperation::OT_TRIANGLE_LIST;
508                }
509                else if (!strcmp(optype, "triangle_fan"))
510                {
511                    sm->operationType = RenderOperation::OT_TRIANGLE_FAN;
512                }
513                else if (!strcmp(optype, "triangle_strip"))
514                {
515                    sm->operationType = RenderOperation::OT_TRIANGLE_STRIP;
516                }
517
518            }
519
520            const char* tmp = smElem->Attribute("usesharedvertices");
521            if (tmp)
522                sm->useSharedVertices = StringConverter::parseBool(tmp);
523            tmp = smElem->Attribute("use32bitindexes");
524            bool use32BitIndexes = false;
525            if (tmp)
526                use32BitIndexes = StringConverter::parseBool(tmp);
527           
528            // Faces
529            TiXmlElement* faces = smElem->FirstChildElement("faces");
530            if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST)
531            {
532                // tri list
533                sm->indexData->indexCount =
534                    StringConverter::parseInt(faces->Attribute("count")) * 3;
535            }
536            else
537            {
538                // tri strip or fan
539                sm->indexData->indexCount =
540                    StringConverter::parseInt(faces->Attribute("count")) + 2;
541            }
542
543            // Allocate space
544            HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
545                createIndexBuffer(
546                    use32BitIndexes? HardwareIndexBuffer::IT_32BIT : HardwareIndexBuffer::IT_16BIT,
547                    sm->indexData->indexCount,
548                    HardwareBuffer::HBU_DYNAMIC,
549                    false);
550            sm->indexData->indexBuffer = ibuf;
551            unsigned int *pInt;
552            unsigned short *pShort;
553            if (use32BitIndexes)
554            {
555                pInt = static_cast<unsigned int*>(
556                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
557            }
558            else
559            {
560                pShort = static_cast<unsigned short*>(
561                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
562            }
563            TiXmlElement* faceElem;
564            bool firstTri = true;
565            for (faceElem = faces->FirstChildElement();
566                faceElem != 0; faceElem = faceElem->NextSiblingElement())
567            {
568                if (use32BitIndexes)
569                {
570                    *pInt++ = StringConverter::parseInt(faceElem->Attribute("v1"));
571                    // only need all 3 vertices if it's a trilist or first tri
572                    if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri)
573                    {
574                        *pInt++ = StringConverter::parseInt(faceElem->Attribute("v2"));
575                        *pInt++ = StringConverter::parseInt(faceElem->Attribute("v3"));
576                    }
577                }
578                else
579                {
580                    *pShort++ = StringConverter::parseInt(faceElem->Attribute("v1"));
581                    // only need all 3 vertices if it's a trilist or first tri
582                    if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri)
583                    {
584                        *pShort++ = StringConverter::parseInt(faceElem->Attribute("v2"));
585                        *pShort++ = StringConverter::parseInt(faceElem->Attribute("v3"));
586                    }
587                }
588                firstTri = false;
589            }
590            ibuf->unlock();
591
592            // Geometry
593            if (!sm->useSharedVertices)
594            {
595                TiXmlElement* geomNode = smElem->FirstChildElement("geometry");
596                if (geomNode)
597                {
598                    sm->vertexData = new VertexData();
599                    readGeometry(geomNode, sm->vertexData);
600                }
601            }
602
603            // Bone assignments
604            TiXmlElement* boneAssigns = smElem->FirstChildElement("boneassignments");
605            if(boneAssigns)
606                readBoneAssignments(boneAssigns, sm);
607
608        }
609        LogManager::getSingleton().logMessage("Submeshes done.");
610    }
611    //---------------------------------------------------------------------
612    void XMLMeshSerializer::readGeometry(TiXmlElement* mGeometryNode, VertexData* vertexData)
613    {
614        LogManager::getSingleton().logMessage("Reading geometry...");
615        unsigned char *pVert;
616        float *pFloat;
617        ARGB *pCol;
618
619        vertexData->vertexCount = StringConverter::parseInt(mGeometryNode->Attribute("vertexcount"));
620        // Skip empty
621        if (vertexData->vertexCount <= 0) return;
622       
623
624        VertexDeclaration* decl = vertexData->vertexDeclaration;
625        VertexBufferBinding* bind = vertexData->vertexBufferBinding;
626        unsigned short bufCount = 0;
627        unsigned short totalTexCoords = 0; // across all buffers
628
629        // Information for calculating bounds
630        Vector3 min, max, pos;
631        Real maxSquaredRadius = -1;
632        bool first = true;
633
634        // Iterate over all children (vertexbuffer entries)
635        for (TiXmlElement* vbElem = mGeometryNode->FirstChildElement();
636            vbElem != 0; vbElem = vbElem->NextSiblingElement())
637        {
638            size_t offset = 0;
639            // Skip non-vertexbuffer elems
640            if (stricmp(vbElem->Value(), "vertexbuffer")) continue;
641           
642            const char* attrib = vbElem->Attribute("positions");
643            if (attrib && StringConverter::parseBool(attrib))
644            {
645                // Add element
646                decl->addElement(bufCount, offset, VET_FLOAT3, VES_POSITION);
647                offset += VertexElement::getTypeSize(VET_FLOAT3);
648            }
649            attrib = vbElem->Attribute("normals");
650            if (attrib && StringConverter::parseBool(attrib))
651            {
652                // Add element
653                decl->addElement(bufCount, offset, VET_FLOAT3, VES_NORMAL);
654                offset += VertexElement::getTypeSize(VET_FLOAT3);
655            }
656            attrib = vbElem->Attribute("colours_diffuse");
657            if (attrib && StringConverter::parseBool(attrib))
658            {
659                // Add element
660                decl->addElement(bufCount, offset, VET_COLOUR, VES_DIFFUSE);
661                offset += VertexElement::getTypeSize(VET_COLOUR);
662            }
663            attrib = vbElem->Attribute("colours_specular");
664            if (attrib && StringConverter::parseBool(attrib))
665            {
666                // Add element
667                decl->addElement(bufCount, offset, VET_COLOUR, VES_SPECULAR);
668                offset += VertexElement::getTypeSize(VET_COLOUR);
669            }
670            attrib = vbElem->Attribute("texture_coords");
671            if (attrib && StringConverter::parseInt(attrib))
672            {
673                unsigned short numTexCoords = StringConverter::parseInt(vbElem->Attribute("texture_coords"));
674                for (unsigned short tx = 0; tx < numTexCoords; ++tx)
675                {
676                    // NB set is local to this buffer, but will be translated into a
677                    // global set number across all vertex buffers
678                    attrib = vbElem->Attribute("texture_coord_dimensions_" + StringConverter::toString(tx));
679                    unsigned short dims;
680                    if (attrib)
681                    {
682                        dims = StringConverter::parseInt(attrib);
683                    }
684                    else
685                    {
686                        // Default
687                        dims = 2;
688                    }
689                    // Add element
690                    VertexElementType vtype = VertexElement::multiplyTypeCount(VET_FLOAT1, dims);
691                    decl->addElement(bufCount, offset, vtype,
692                        VES_TEXTURE_COORDINATES, totalTexCoords++);
693                    offset += VertexElement::getTypeSize(vtype);
694                }
695            }
696            // Now create the vertex buffer
697            HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().
698                createVertexBuffer(offset, vertexData->vertexCount,
699                    HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
700            // Bind it
701            bind->setBinding(bufCount, vbuf);
702            // Lock it
703            pVert = static_cast<unsigned char*>(
704                vbuf->lock(HardwareBuffer::HBL_DISCARD));
705
706            // Get the element list for this buffer alone
707            VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufCount);
708            // Now the buffer is set up, parse all the vertices
709            for (TiXmlElement* vertexElem = vbElem->FirstChildElement();
710            vertexElem != 0; vertexElem = vertexElem->NextSiblingElement())
711            {
712                // Now parse the elements, ensure they are all matched
713                VertexDeclaration::VertexElementList::const_iterator ielem, ielemend;
714                TiXmlElement* xmlElem;
715                TiXmlElement* texCoordElem = 0;
716                ielemend = elems.end();
717                for (ielem = elems.begin(); ielem != ielemend; ++ielem)
718                {
719                    const VertexElement& elem = *ielem;
720                    // Find child for this element
721                    switch(elem.getSemantic())
722                    {
723                    case VES_POSITION:
724                        xmlElem = vertexElem->FirstChildElement("position");
725                        if (!xmlElem)
726                        {
727                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <position> element.",
728                                "XMLSerializer::readGeometry");
729                        }
730                        elem.baseVertexPointerToElement(pVert, &pFloat);
731
732                        *pFloat++ = StringConverter::parseReal(
733                            xmlElem->Attribute("x"));
734                        *pFloat++ = StringConverter::parseReal(
735                            xmlElem->Attribute("y"));
736                        *pFloat++ = StringConverter::parseReal(
737                            xmlElem->Attribute("z"));
738
739                        pos.x = StringConverter::parseReal(
740                            xmlElem->Attribute("x"));
741                        pos.y = StringConverter::parseReal(
742                            xmlElem->Attribute("y"));
743                        pos.z = StringConverter::parseReal(
744                            xmlElem->Attribute("z"));
745                       
746                        if (first)
747                        {
748                            min = max = pos;
749                            maxSquaredRadius = pos.squaredLength();
750                            first = false;
751                        }
752                        else
753                        {
754                            min.makeFloor(pos);
755                            max.makeCeil(pos);
756                            maxSquaredRadius = std::max(pos.squaredLength(), maxSquaredRadius);
757                        }
758                        break;
759                    case VES_NORMAL:
760                        xmlElem = vertexElem->FirstChildElement("normal");
761                        if (!xmlElem)
762                        {
763                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <normal> element.",
764                                "XMLSerializer::readGeometry");
765                        }
766                        elem.baseVertexPointerToElement(pVert, &pFloat);
767
768                        *pFloat++ = StringConverter::parseReal(
769                            xmlElem->Attribute("x"));
770                        *pFloat++ = StringConverter::parseReal(
771                            xmlElem->Attribute("y"));
772                        *pFloat++ = StringConverter::parseReal(
773                            xmlElem->Attribute("z"));
774                        break;
775                    case VES_DIFFUSE:
776                        xmlElem = vertexElem->FirstChildElement("colour_diffuse");
777                        if (!xmlElem)
778                        {
779                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_diffuse> element.",
780                                "XMLSerializer::readGeometry");
781                        }
782                        elem.baseVertexPointerToElement(pVert, &pCol);
783                                                {
784                                                        ColourValue cv;
785                                                        cv = StringConverter::parseColourValue(
786                                                                xmlElem->Attribute("value"));
787                                                        *pCol++ = cv.getAsARGB();
788                                                }
789                        break;
790                    case VES_SPECULAR:
791                        xmlElem = vertexElem->FirstChildElement("colour_specular");
792                        if (!xmlElem)
793                        {
794                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_specular> element.",
795                                "XMLSerializer::readGeometry");
796                        }
797                        elem.baseVertexPointerToElement(pVert, &pCol);
798                                                {
799                                                        ColourValue cv;
800                                                        cv = StringConverter::parseColourValue(
801                                                                xmlElem->Attribute("value"));
802                                                        *pCol++ = cv.getAsARGB();
803                                                }
804                        break;
805                    case VES_TEXTURE_COORDINATES:
806                        if (!texCoordElem)
807                        {
808                            // Get first texcoord
809                            xmlElem = vertexElem->FirstChildElement("texcoord");
810                        }
811                        else
812                        {
813                            // Get next texcoord
814                            xmlElem = texCoordElem->NextSiblingElement("texcoord");
815                        }
816                        if (!xmlElem)
817                        {
818                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <texcoord> element.",
819                                "XMLSerializer::readGeometry");
820                        }
821                                                // Record the latest texture coord entry
822                                                texCoordElem = xmlElem;
823                        elem.baseVertexPointerToElement(pVert, &pFloat);
824
825                        *pFloat++ = StringConverter::parseReal(
826                            xmlElem->Attribute("u"));
827                        if (VertexElement::getTypeCount(elem.getType()) > 1)
828                        {
829                            *pFloat++ = StringConverter::parseReal(
830                                xmlElem->Attribute("v"));
831                        }
832                        if (VertexElement::getTypeCount(elem.getType()) > 2)
833                        {
834                            *pFloat++ = StringConverter::parseReal(
835                                xmlElem->Attribute("w"));
836                        }
837
838                        break;
839                    default:
840                        break;
841                    }
842                } // semantic
843                pVert += vbuf->getVertexSize();
844            } // vertex
845            bufCount++;
846            vbuf->unlock();
847        } // vertexbuffer
848
849        // Set bounds
850        const AxisAlignedBox& currBox = mpMesh->getBounds();
851        Real currRadius = mpMesh->getBoundingSphereRadius();
852        if (currBox.isNull())
853        {
854            //do not pad the bounding box
855            mpMesh->_setBounds(AxisAlignedBox(min, max), false);
856            mpMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
857        }
858        else
859        {
860            AxisAlignedBox newBox(min, max);
861            newBox.merge(currBox);
862            //do not pad the bounding box
863            mpMesh->_setBounds(newBox, false);
864            mpMesh->_setBoundingSphereRadius(std::max(Math::Sqrt(maxSquaredRadius), currRadius));
865        }
866       
867
868        LogManager::getSingleton().logMessage("Geometry done...");
869    }
870    //---------------------------------------------------------------------
871    void XMLMeshSerializer::readSkeletonLink(TiXmlElement* mSkelNode)
872    {
873        mpMesh->setSkeletonName(mSkelNode->Attribute("name"));
874    }
875    //---------------------------------------------------------------------
876    void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode)
877    {
878        LogManager::getSingleton().logMessage("Reading bone assignments...");
879
880        // Iterate over all children (vertexboneassignment entries)
881        for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement();
882        elem != 0; elem = elem->NextSiblingElement())
883        {
884            VertexBoneAssignment vba;
885            vba.vertexIndex = StringConverter::parseInt(
886                elem->Attribute("vertexindex"));
887            vba.boneIndex = StringConverter::parseInt(
888                elem->Attribute("boneindex"));
889            vba.weight= StringConverter::parseReal(
890                elem->Attribute("weight"));
891
892            mpMesh->addBoneAssignment(vba);
893        }
894
895        LogManager::getSingleton().logMessage("Bone assignments done.");
896    }
897    //---------------------------------------------------------------------
898        void XMLMeshSerializer::readSubMeshNames(TiXmlElement* mMeshNamesNode, Mesh *sm)
899        {
900                LogManager::getSingleton().logMessage("Reading mesh names...");
901
902                // Iterate over all children (vertexboneassignment entries)
903                for (TiXmlElement* elem = mMeshNamesNode->FirstChildElement();
904                        elem != 0; elem = elem->NextSiblingElement())
905                {
906                        String meshName = elem->Attribute("name");
907                        int index = StringConverter::parseInt(elem->Attribute("index"));
908
909                        sm->nameSubMesh(meshName, index);
910                }
911
912                LogManager::getSingleton().logMessage("Mesh names done.");
913        }
914    //---------------------------------------------------------------------
915    void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode, SubMesh* sm)
916    {
917        LogManager::getSingleton().logMessage("Reading bone assignments...");
918        // Iterate over all children (vertexboneassignment entries)
919        for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement();
920        elem != 0; elem = elem->NextSiblingElement())
921        {
922            VertexBoneAssignment vba;
923            vba.vertexIndex = StringConverter::parseInt(
924                elem->Attribute("vertexindex"));
925            vba.boneIndex = StringConverter::parseInt(
926                elem->Attribute("boneindex"));
927            vba.weight= StringConverter::parseReal(
928                elem->Attribute("weight"));
929
930            sm->addBoneAssignment(vba);
931        }
932        LogManager::getSingleton().logMessage("Bone assignments done.");
933    }
934    //---------------------------------------------------------------------
935        void XMLMeshSerializer::writeLodInfo(TiXmlElement* mMeshNode, const Mesh* pMesh)
936        {
937        TiXmlElement* lodNode =
938            mMeshNode->InsertEndChild(TiXmlElement("levelofdetail"))->ToElement();
939
940                unsigned short numLvls = pMesh->getNumLodLevels();
941                bool manual = pMesh->isLodManual();
942                lodNode->SetAttribute("numlevels", StringConverter::toString(numLvls));
943                lodNode->SetAttribute("manual", StringConverter::toString(manual));
944
945                // Iterate from level 1, not 0 (full detail)
946                for (unsigned short i = 1; i < numLvls; ++i)
947                {
948                        const MeshLodUsage& usage = pMesh->getLodLevel(i);
949                        if (manual)
950                        {
951                                writeLodUsageManual(lodNode, i, usage);
952                        }
953                        else
954                        {
955                                writeLodUsageGenerated(lodNode, i, usage, pMesh);
956                        }
957                }
958
959        }
960    //---------------------------------------------------------------------
961    void XMLMeshSerializer::writeSubMeshNames(TiXmlElement* mMeshNode, const Mesh* m)
962    {
963        const Mesh::SubMeshNameMap& nameMap = m->getSubMeshNameMap();
964        if (nameMap.empty())
965            return; // do nothing
966
967        TiXmlElement* namesNode =
968            mMeshNode->InsertEndChild(TiXmlElement("submeshnames"))->ToElement();
969        Mesh::SubMeshNameMap::const_iterator i, iend;
970        iend = nameMap.end();
971        for (i = nameMap.begin(); i != iend; ++i)
972        {
973            TiXmlElement* subNameNode =
974                namesNode->InsertEndChild(TiXmlElement("submeshname"))->ToElement();
975
976            subNameNode->SetAttribute("name", i->first);
977            subNameNode->SetAttribute("index",
978                StringConverter::toString(i->second));
979        }
980
981    }
982    //---------------------------------------------------------------------
983        void XMLMeshSerializer::writeLodUsageManual(TiXmlElement* usageNode,
984                unsigned short levelNum, const MeshLodUsage& usage)
985        {
986                TiXmlElement* manualNode =
987                        usageNode->InsertEndChild(TiXmlElement("lodmanual"))->ToElement();
988
989                manualNode->SetAttribute("fromdepthsquared",
990                        StringConverter::toString(usage.fromDepthSquared));
991                manualNode->SetAttribute("meshname", usage.manualName);
992
993        }
994    //---------------------------------------------------------------------
995        void XMLMeshSerializer::writeLodUsageGenerated(TiXmlElement* usageNode,
996                unsigned short levelNum,  const MeshLodUsage& usage,
997                const Mesh* pMesh)
998        {
999                TiXmlElement* generatedNode =
1000                        usageNode->InsertEndChild(TiXmlElement("lodgenerated"))->ToElement();
1001                generatedNode->SetAttribute("fromdepthsquared",
1002                        StringConverter::toString(usage.fromDepthSquared));
1003
1004                // Iterate over submeshes at this level
1005                unsigned short numsubs = pMesh->getNumSubMeshes();
1006
1007                for (unsigned short subi = 0; subi < numsubs; ++subi)
1008                {
1009                        TiXmlElement* subNode =
1010                                generatedNode->InsertEndChild(TiXmlElement("lodfacelist"))->ToElement();
1011                        SubMesh* sub = pMesh->getSubMesh(subi);
1012                        subNode->SetAttribute("submeshindex", StringConverter::toString(subi));
1013                        // NB level - 1 because SubMeshes don't store the first index in geometry
1014                    IndexData* facedata = sub->mLodFaceList[levelNum - 1];
1015                        subNode->SetAttribute("numfaces", StringConverter::toString(facedata->indexCount / 3));
1016
1017                        // Write each face in turn
1018                    bool use32BitIndexes = (facedata->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
1019
1020            // Write each face in turn
1021                    unsigned int* pInt;
1022                    unsigned short* pShort;
1023                    HardwareIndexBufferSharedPtr ibuf = facedata->indexBuffer;
1024                    if (use32BitIndexes)
1025                    {
1026                            pInt = static_cast<unsigned int*>(
1027                                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1028                    }
1029                    else
1030                    {
1031                            pShort = static_cast<unsigned short*>(
1032                                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1033                    }
1034                       
1035                        for (size_t f = 0; f < facedata->indexCount; f += 3)
1036                        {
1037                                TiXmlElement* faceNode =
1038                                        subNode->InsertEndChild(TiXmlElement("face"))->ToElement();
1039                if (use32BitIndexes)
1040                {
1041                                    faceNode->SetAttribute("v1", StringConverter::toString(*pInt++));
1042                                    faceNode->SetAttribute("v2", StringConverter::toString(*pInt++));
1043                                    faceNode->SetAttribute("v3", StringConverter::toString(*pInt++));
1044                }
1045                else
1046                {
1047                                    faceNode->SetAttribute("v1", StringConverter::toString(*pShort++));
1048                                    faceNode->SetAttribute("v2", StringConverter::toString(*pShort++));
1049                                    faceNode->SetAttribute("v3", StringConverter::toString(*pShort++));
1050                }
1051
1052                        }
1053
1054
1055
1056                }
1057
1058        }
1059    //---------------------------------------------------------------------
1060        void XMLMeshSerializer::readLodInfo(TiXmlElement*  lodNode)
1061        {
1062               
1063        LogManager::getSingleton().logMessage("Parsing LOD information...");
1064
1065                const char* val = lodNode->Attribute("numlevels");
1066                unsigned short numLevels = static_cast<unsigned short>(
1067                        StringConverter::parseUnsignedInt(val));
1068
1069                val = lodNode->Attribute("manual");
1070                bool manual = StringConverter::parseBool(val);
1071
1072                // Set up the basic structures
1073                mpMesh->_setLodInfo(numLevels, manual);
1074
1075                // Parse the detail, start from 1 (the first sub-level of detail)
1076                unsigned short i = 1;
1077                TiXmlElement* usageElem;
1078                if (manual)
1079                {
1080                        usageElem = lodNode->FirstChildElement("lodmanual");
1081                }
1082                else
1083                {
1084                        usageElem = lodNode->FirstChildElement("lodgenerated");
1085                }
1086                while (usageElem)
1087                {
1088                        if (manual)
1089                        {
1090                                readLodUsageManual(usageElem, i);
1091                                usageElem = usageElem->NextSiblingElement();
1092                        }
1093                        else
1094                        {
1095                                readLodUsageGenerated(usageElem, i);
1096                                usageElem = usageElem->NextSiblingElement();
1097                        }
1098                        ++i;
1099                }
1100               
1101        LogManager::getSingleton().logMessage("LOD information done.");
1102               
1103        }
1104    //---------------------------------------------------------------------
1105        void XMLMeshSerializer::readLodUsageManual(TiXmlElement* manualNode, unsigned short index)
1106        {
1107                MeshLodUsage usage;
1108                const char* val = manualNode->Attribute("fromdepthsquared");
1109                usage.fromDepthSquared = StringConverter::parseReal(val);
1110                usage.manualName = manualNode->Attribute("meshname");
1111        usage.edgeData = NULL;
1112
1113                mpMesh->_setLodUsage(index, usage);
1114        }
1115    //---------------------------------------------------------------------
1116        void XMLMeshSerializer::readLodUsageGenerated(TiXmlElement* genNode, unsigned short index)
1117        {
1118                MeshLodUsage usage;
1119                const char* val = genNode->Attribute("fromdepthsquared");
1120                usage.fromDepthSquared = StringConverter::parseReal(val);
1121                usage.manualMesh.setNull();
1122                usage.manualName = "";
1123        usage.edgeData = NULL;
1124
1125                mpMesh->_setLodUsage(index, usage);
1126
1127                // Read submesh face lists
1128                TiXmlElement* faceListElem = genNode->FirstChildElement("lodfacelist");
1129                while (faceListElem)
1130                {
1131                        val = faceListElem->Attribute("submeshindex");
1132                        unsigned short subidx = StringConverter::parseUnsignedInt(val);
1133                        val = faceListElem->Attribute("numfaces");
1134                        unsigned short numFaces = StringConverter::parseUnsignedInt(val);
1135            // use of 32bit indexes depends on submesh
1136            HardwareIndexBuffer::IndexType itype =
1137                mpMesh->getSubMesh(subidx)->indexData->indexBuffer->getType();
1138            bool use32bitindexes = (itype == HardwareIndexBuffer::IT_32BIT);
1139
1140            // Assign memory: this will be deleted by the submesh
1141            HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
1142                createIndexBuffer(
1143                    itype, numFaces * 3, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
1144
1145            unsigned short *pShort;
1146            unsigned int *pInt;
1147            if (use32bitindexes)
1148            {
1149                pInt = static_cast<unsigned int*>(
1150                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
1151            }
1152            else
1153            {
1154                pShort = static_cast<unsigned short*>(
1155                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
1156            }
1157            TiXmlElement* faceElem = faceListElem->FirstChildElement("face");
1158                        for (unsigned int face = 0; face < numFaces; ++face, faceElem = faceElem->NextSiblingElement())
1159                        {
1160                if (use32bitindexes)
1161                {
1162                    val = faceElem->Attribute("v1");
1163                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1164                                    val = faceElem->Attribute("v2");
1165                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1166                                    val = faceElem->Attribute("v3");
1167                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1168                }
1169                else
1170                {
1171                    val = faceElem->Attribute("v1");
1172                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1173                                    val = faceElem->Attribute("v2");
1174                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1175                                    val = faceElem->Attribute("v3");
1176                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1177                }
1178
1179                        }
1180
1181            ibuf->unlock();
1182                        IndexData* facedata = new IndexData(); // will be deleted by SubMesh
1183                        facedata->indexCount = numFaces * 3;
1184            facedata->indexStart = 0;
1185            facedata->indexBuffer = ibuf;
1186                        mpMesh->_setSubMeshLodFaceList(subidx, index, facedata);
1187
1188                        faceListElem = faceListElem->NextSiblingElement();
1189                }
1190       
1191        }
1192
1193}
1194
Note: See TracBrowser for help on using the repository browser.