source: GTP/trunk/Lib/Illum/GPUObscurancesGT/src/OgreXMLMeshSerializer.cpp @ 930

Revision 930, 62.3 KB checked in by igarcia, 18 years ago (diff)
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#include "OgreAnimation.h"
35#include "OgreAnimationTrack.h"
36#include "OgreKeyFrame.h"
37
38namespace Ogre {
39
40    //---------------------------------------------------------------------
41    XMLMeshSerializer::XMLMeshSerializer()
42    {
43    }
44    //---------------------------------------------------------------------
45    XMLMeshSerializer::~XMLMeshSerializer()
46    {
47    }
48    //---------------------------------------------------------------------
49    void XMLMeshSerializer::importMesh(const String& filename,
50                VertexElementType colourElementType, Mesh* pMesh)
51    {
52        LogManager::getSingleton().logMessage("XMLMeshSerializer reading mesh data from " + filename + "...");
53        mpMesh = pMesh;
54                mColourElementType = colourElementType;
55        mXMLDoc = new TiXmlDocument(filename);
56        mXMLDoc->LoadFile();
57
58        TiXmlElement* elem;
59
60        TiXmlElement* rootElem = mXMLDoc->RootElement();
61
62        // shared geometry
63        elem = rootElem->FirstChildElement("sharedgeometry");
64        if (elem)
65        {
66            if(StringConverter::parseInt(elem->Attribute("vertexcount")) > 0)
67            {
68                mpMesh->sharedVertexData = new VertexData();
69                readGeometry(elem, mpMesh->sharedVertexData);
70            }
71        }
72
73        // submeshes
74        elem = rootElem->FirstChildElement("submeshes");
75        if (elem)
76            readSubMeshes(elem);
77
78        // skeleton link
79        elem = rootElem->FirstChildElement("skeletonlink");
80        if (elem)
81            readSkeletonLink(elem);
82
83        // bone assignments
84        elem = rootElem->FirstChildElement("boneassignments");
85        if (elem)
86            readBoneAssignments(elem);
87
88                //Lod
89                elem = rootElem->FirstChildElement("levelofdetail");
90                if (elem)
91                        readLodInfo(elem);
92
93                // submesh names
94                elem = rootElem->FirstChildElement("submeshnames");
95                if (elem)
96                        readSubMeshNames(elem, mpMesh);
97
98                // poses
99                elem = rootElem->FirstChildElement("poses");
100                if (elem)
101                        readPoses(elem, mpMesh);
102
103                // animations
104                elem = rootElem->FirstChildElement("animations");
105                if (elem)
106                        readAnimations(elem, mpMesh);
107
108                delete mXMLDoc;
109
110        LogManager::getSingleton().logMessage("XMLMeshSerializer import successful.");
111       
112    }
113    //---------------------------------------------------------------------
114    void XMLMeshSerializer::exportMesh(const Mesh* pMesh, const String& filename)
115    {
116        LogManager::getSingleton().logMessage("XMLMeshSerializer writing mesh data to " + filename + "...");
117       
118        mpMesh = const_cast<Mesh*>(pMesh);
119
120        mXMLDoc = new TiXmlDocument();
121        mXMLDoc->InsertEndChild(TiXmlElement("mesh"));
122        TiXmlElement* rootNode = mXMLDoc->RootElement();
123
124        LogManager::getSingleton().logMessage("Populating DOM...");
125
126           
127           
128        // Write to DOM
129        writeMesh(pMesh);
130        LogManager::getSingleton().logMessage("DOM populated, writing XML file..");
131
132        // Write out to a file
133        mXMLDoc->SaveFile(filename);
134
135   
136        delete mXMLDoc;
137
138        LogManager::getSingleton().logMessage("XMLMeshSerializer export successful.");
139
140    }
141    //---------------------------------------------------------------------
142    void XMLMeshSerializer::writeMesh(const Mesh* pMesh)
143    {
144        TiXmlElement* rootNode = mXMLDoc->RootElement();
145        // Write geometry
146                if (pMesh->sharedVertexData)
147                {
148                        TiXmlElement* geomNode =
149                                rootNode->InsertEndChild(TiXmlElement("sharedgeometry"))->ToElement();
150                        writeGeometry(geomNode, pMesh->sharedVertexData);
151                }
152
153        // Write Submeshes
154        TiXmlElement* subMeshesNode =
155            rootNode->InsertEndChild(TiXmlElement("submeshes"))->ToElement();
156        for (int i = 0; i < pMesh->getNumSubMeshes(); ++i)
157        {
158            LogManager::getSingleton().logMessage("Writing submesh...");
159            writeSubMesh(subMeshesNode, pMesh->getSubMesh(i));
160            LogManager::getSingleton().logMessage("Submesh exported.");
161        }
162
163        // Write skeleton info if required
164        if (pMesh->hasSkeleton())
165        {
166            LogManager::getSingleton().logMessage("Exporting skeleton link...");
167            // Write skeleton link
168            writeSkeletonLink(rootNode, pMesh->getSkeletonName());
169            LogManager::getSingleton().logMessage("Skeleton link exported.");
170
171            // Write bone assignments
172            Mesh::BoneAssignmentIterator bi = const_cast<Mesh*>(pMesh)->getBoneAssignmentIterator();
173            if (bi.hasMoreElements())
174            {
175                LogManager::getSingleton().logMessage("Exporting shared geometry bone assignments...");
176                TiXmlElement* boneAssignNode =
177                    rootNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement();
178
179                while (bi.hasMoreElements())
180                {
181                                        const VertexBoneAssignment& assign = bi.getNext();
182                    writeBoneAssignment(boneAssignNode, &assign);
183                }
184
185                LogManager::getSingleton().logMessage("Shared geometry bone assignments exported.");
186            }
187        }
188                if (pMesh->getNumLodLevels() > 1)
189                {
190            LogManager::getSingleton().logMessage("Exporting LOD information...");
191                        writeLodInfo(rootNode, pMesh);
192            LogManager::getSingleton().logMessage("LOD information exported.");
193                }
194        // Write submesh names
195        writeSubMeshNames(rootNode, pMesh);
196                // Write poses
197                writePoses(rootNode, pMesh);
198                // Write animations
199                writeAnimations(rootNode, pMesh);
200
201
202
203
204
205    }
206    //---------------------------------------------------------------------
207    void XMLMeshSerializer::writeSubMesh(TiXmlElement* mSubMeshesNode, const SubMesh* s)
208    {
209        TiXmlElement* subMeshNode =
210            mSubMeshesNode->InsertEndChild(TiXmlElement("submesh"))->ToElement();
211
212        size_t numFaces;
213
214        // Material name
215        subMeshNode->SetAttribute("material", s->getMaterialName());
216        // bool useSharedVertices
217        subMeshNode->SetAttribute("usesharedvertices",
218            StringConverter::toString(s->useSharedVertices) );
219        // bool use32BitIndexes
220                bool use32BitIndexes = (s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
221        subMeshNode->SetAttribute("use32bitindexes",
222            StringConverter::toString( use32BitIndexes ));
223
224        // Operation type
225        switch(s->operationType)
226        {
227        case RenderOperation::OT_LINE_LIST:
228        case RenderOperation::OT_LINE_STRIP:
229        case RenderOperation::OT_POINT_LIST:
230            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Unsupported operation type, only "
231                "triangle types are allowed.", "XMLMeshSerializer::writeSubMesh");
232            break;
233        case RenderOperation::OT_TRIANGLE_FAN:
234            subMeshNode->SetAttribute("operationtype", "triangle_fan");
235            break;
236        case RenderOperation::OT_TRIANGLE_LIST:
237            subMeshNode->SetAttribute("operationtype", "triangle_list");
238            break;
239        case RenderOperation::OT_TRIANGLE_STRIP:
240            subMeshNode->SetAttribute("operationtype", "triangle_strip");
241            break;
242        }
243
244        // Faces
245        TiXmlElement* facesNode =
246            subMeshNode->InsertEndChild(TiXmlElement("faces"))->ToElement();
247        if (s->operationType == RenderOperation::OT_TRIANGLE_LIST)
248        {
249            // tri list
250            numFaces = s->indexData->indexCount / 3;
251        }
252        else
253        {
254            // triangle fan or triangle strip
255            numFaces = s->indexData->indexCount - 2;
256        }
257        facesNode->SetAttribute("count",
258            StringConverter::toString(numFaces));
259        // Write each face in turn
260        ushort i;
261                unsigned int* pInt;
262                unsigned short* pShort;
263                HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer;
264                if (use32BitIndexes)
265                {
266                        pInt = static_cast<unsigned int*>(
267                                ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
268                }
269                else
270                {
271                        pShort = static_cast<unsigned short*>(
272                                ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
273                }
274        for (i = 0; i < numFaces; ++i)
275        {
276            TiXmlElement* faceNode =
277                facesNode->InsertEndChild(TiXmlElement("face"))->ToElement();
278                        if (use32BitIndexes)
279                        {
280                                faceNode->SetAttribute("v1", StringConverter::toString(*pInt++));
281                /// Only need all 3 vertex indices if trilist or first face
282                if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0)
283                {
284                                    faceNode->SetAttribute("v2", StringConverter::toString(*pInt++));
285                                    faceNode->SetAttribute("v3", StringConverter::toString(*pInt++));
286                }
287                        }
288                        else
289                        {
290                                faceNode->SetAttribute("v1", StringConverter::toString(*pShort++));
291                /// Only need all 3 vertex indices if trilist or first face
292                if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0)
293                {
294                                    faceNode->SetAttribute("v2", StringConverter::toString(*pShort++));
295                                    faceNode->SetAttribute("v3", StringConverter::toString(*pShort++));
296                }
297                        }
298        }
299
300        // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
301        if (!s->useSharedVertices)
302        {
303            TiXmlElement* geomNode =
304                subMeshNode->InsertEndChild(TiXmlElement("geometry"))->ToElement();
305            writeGeometry(geomNode, s->vertexData);
306        }
307
308        // texture aliases
309        writeTextureAliases(subMeshNode, s);
310
311        // Bone assignments
312        if (mpMesh->hasSkeleton())
313        {
314            SubMesh::BoneAssignmentIterator bi = const_cast<SubMesh*>(s)->getBoneAssignmentIterator();
315            LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");
316
317            TiXmlElement* boneAssignNode =
318                subMeshNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement();
319            while (bi.hasMoreElements())
320            {
321                                const VertexBoneAssignment& assign = bi.getNext();
322                writeBoneAssignment(boneAssignNode, &assign);
323            }
324        }
325        LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported.");
326
327    }
328    //---------------------------------------------------------------------
329    void XMLMeshSerializer::writeGeometry(TiXmlElement* mParentNode, const VertexData* vertexData)
330    {
331        // Write a vertex buffer per element
332
333        TiXmlElement *vbNode, *vertexNode, *dataNode;
334
335        // Set num verts on parent
336        mParentNode->SetAttribute("vertexcount", StringConverter::toString(vertexData->vertexCount));
337
338                VertexDeclaration* decl = vertexData->vertexDeclaration;
339                VertexBufferBinding* bind = vertexData->vertexBufferBinding;
340
341                VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend;
342                bend = bind->getBindings().end();
343                // Iterate over buffers
344                for(b = bind->getBindings().begin(); b != bend; ++b)
345                {
346                        vbNode = mParentNode->InsertEndChild(TiXmlElement("vertexbuffer"))->ToElement();
347                        const HardwareVertexBufferSharedPtr vbuf = b->second;
348                        unsigned short bufferIdx = b->first;
349                        // Get all the elements that relate to this buffer                     
350                        VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx);
351                        VertexDeclaration::VertexElementList::iterator i, iend;
352                        iend = elems.end();
353
354                        // Set up the data access for this buffer (lock read-only)
355                        unsigned char* pVert;
356                        float* pFloat;
357                        ARGB* pColour;
358
359                        pVert = static_cast<unsigned char*>(
360                                vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
361
362            // Skim over the elements to set up the general data
363            unsigned short numTextureCoords = 0;
364                        for (i = elems.begin(); i != iend; ++i)
365                        {
366                                VertexElement& elem = *i;
367                                switch(elem.getSemantic())
368                                {
369                                case VES_POSITION:
370                                        vbNode->SetAttribute("positions","true");
371                    break;
372                                case VES_NORMAL:
373                                        vbNode->SetAttribute("normals","true");
374                    break;
375                                case VES_DIFFUSE:
376                                        vbNode->SetAttribute("colours_diffuse","true");
377                    break;
378                                case VES_SPECULAR:
379                                        vbNode->SetAttribute("colours_specular","true");
380                    break;
381                case VES_TEXTURE_COORDINATES:
382                    vbNode->SetAttribute(
383                        "texture_coord_dimensions_" + StringConverter::toString(numTextureCoords),
384                        StringConverter::toString(VertexElement::getTypeCount(elem.getType())));
385                    ++numTextureCoords;
386                    break;
387                default:
388                    break;
389                }
390            }
391            if (numTextureCoords > 0)
392            {
393                vbNode->SetAttribute("texture_coords",
394                    StringConverter::toString(numTextureCoords));
395            }
396
397                        // For each vertex
398                        for (size_t v = 0; v < vertexData->vertexCount; ++v)
399                        {
400                vertexNode =
401                    vbNode->InsertEndChild(TiXmlElement("vertex"))->ToElement();
402                                // Iterate over the elements
403                                for (i = elems.begin(); i != iend; ++i)
404                                {
405                                        VertexElement& elem = *i;
406                                        switch(elem.getSemantic())
407                                        {
408                                        case VES_POSITION:
409                                                elem.baseVertexPointerToElement(pVert, &pFloat);
410                                                dataNode =
411                                                        vertexNode->InsertEndChild(TiXmlElement("position"))->ToElement();
412                                                dataNode->SetAttribute("x", StringConverter::toString(pFloat[0]));
413                                                dataNode->SetAttribute("y", StringConverter::toString(pFloat[1]));
414                                                dataNode->SetAttribute("z", StringConverter::toString(pFloat[2]));
415                                                break;
416                                        case VES_NORMAL:
417                                                elem.baseVertexPointerToElement(pVert, &pFloat);
418                                                dataNode =
419                                                        vertexNode->InsertEndChild(TiXmlElement("normal"))->ToElement();
420                                                dataNode->SetAttribute("x", StringConverter::toString(pFloat[0]));
421                                                dataNode->SetAttribute("y", StringConverter::toString(pFloat[1]));
422                                                dataNode->SetAttribute("z", StringConverter::toString(pFloat[2]));
423                                                break;
424                                        case VES_DIFFUSE:
425                                                elem.baseVertexPointerToElement(pVert, &pColour);
426                                                dataNode =
427                                                        vertexNode->InsertEndChild(TiXmlElement("colour_diffuse"))->ToElement();
428                                                {
429                                                        ARGB rc = *pColour++;
430                                                        ColourValue cv;
431                                                        cv.b = (rc & 0xFF) / 255.0f;            rc >>= 8;
432                                                        cv.g = (rc & 0xFF) / 255.0f;            rc >>= 8;
433                                                        cv.r = (rc & 0xFF) / 255.0f;            rc >>= 8;
434                                                        cv.a = (rc & 0xFF) / 255.0f;
435                            dataNode->SetAttribute("value", StringConverter::toString(cv));
436                                                }
437                                                break;
438                                        case VES_SPECULAR:
439                                                elem.baseVertexPointerToElement(pVert, &pColour);
440                                                dataNode =
441                                                        vertexNode->InsertEndChild(TiXmlElement("colour_specular"))->ToElement();
442                                                {
443                                                        ARGB rc = *pColour++;
444                                                        ColourValue cv;
445                                                        cv.b = (rc & 0xFF) / 255.0f;            rc >>= 8;
446                                                        cv.g = (rc & 0xFF) / 255.0f;            rc >>= 8;
447                                                        cv.r = (rc & 0xFF) / 255.0f;            rc >>= 8;
448                                                        cv.a = (rc & 0xFF) / 255.0f;
449                                                        dataNode->SetAttribute("value", StringConverter::toString(cv));
450                                                }
451                                                break;
452                                        case VES_TEXTURE_COORDINATES:
453                                                elem.baseVertexPointerToElement(pVert, &pFloat);
454                                                dataNode =
455                                                        vertexNode->InsertEndChild(TiXmlElement("texcoord"))->ToElement();
456
457                                                switch(elem.getType())
458                        {
459                        case VET_FLOAT1:
460                                                dataNode->SetAttribute("u", StringConverter::toString(*pFloat++));
461                            break;
462                        case VET_FLOAT2:
463                                                dataNode->SetAttribute("u", StringConverter::toString(*pFloat++));
464                                                dataNode->SetAttribute("v", StringConverter::toString(*pFloat++));
465                            break;
466                        case VET_FLOAT3:
467                                                dataNode->SetAttribute("u", StringConverter::toString(*pFloat++));
468                                                dataNode->SetAttribute("v", StringConverter::toString(*pFloat++));
469                                                dataNode->SetAttribute("w", StringConverter::toString(*pFloat++));
470                            break;
471                        default:
472                            break;
473                        }
474                                                break;
475                    default:
476                        break;
477
478                                        }
479                                }
480                                pVert += vbuf->getVertexSize();
481                        }
482                        vbuf->unlock();
483                }
484
485                getchar();
486
487    }
488    //---------------------------------------------------------------------
489    void XMLMeshSerializer::writeSkeletonLink(TiXmlElement* mMeshNode, const String& skelName)
490    {
491
492        TiXmlElement* skelNode =
493            mMeshNode->InsertEndChild(TiXmlElement("skeletonlink"))->ToElement();
494        skelNode->SetAttribute("name", skelName);
495    }
496    //---------------------------------------------------------------------
497    void XMLMeshSerializer::writeBoneAssignment(TiXmlElement* mBoneAssignNode, const VertexBoneAssignment* assign)
498    {
499        TiXmlElement* assignNode =
500            mBoneAssignNode->InsertEndChild(
501            TiXmlElement("vertexboneassignment"))->ToElement();
502
503        assignNode->SetAttribute("vertexindex",
504            StringConverter::toString(assign->vertexIndex));
505        assignNode->SetAttribute("boneindex",
506            StringConverter::toString(assign->boneIndex));
507        assignNode->SetAttribute("weight",
508            StringConverter::toString(assign->weight));
509
510
511    }
512    //---------------------------------------------------------------------
513    void XMLMeshSerializer::writeTextureAliases(TiXmlElement* mSubmeshesNode, const SubMesh* subMesh)
514    {
515        if (!subMesh->hasTextureAliases())
516            return; // do nothing
517
518        TiXmlElement* textureAliasesNode =
519            mSubmeshesNode->InsertEndChild(TiXmlElement("textures"))->ToElement();
520
521        // use ogre map iterator
522        SubMesh::AliasTextureIterator aliasIterator = subMesh->getAliasTextureIterator();
523
524        while (aliasIterator.hasMoreElements())
525        {
526            TiXmlElement* aliasTextureNode =
527                textureAliasesNode->InsertEndChild(TiXmlElement("texture"))->ToElement();
528            // iterator key is alias and value is texture name
529            aliasTextureNode->SetAttribute("alias", aliasIterator.peekNextKey());
530            aliasTextureNode->SetAttribute("name", aliasIterator.peekNextValue());
531            aliasIterator.moveNext();
532        }
533
534    }
535    //---------------------------------------------------------------------
536    void XMLMeshSerializer::readSubMeshes(TiXmlElement* mSubmeshesNode)
537    {
538        LogManager::getSingleton().logMessage("Reading submeshes...");
539
540        for (TiXmlElement* smElem = mSubmeshesNode->FirstChildElement();
541            smElem != 0; smElem = smElem->NextSiblingElement())
542        {
543            // All children should be submeshes
544            SubMesh* sm = mpMesh->createSubMesh();
545
546            const char* mat = smElem->Attribute("material");
547            if (mat)
548                sm->setMaterialName(mat);
549
550            // Read operation type
551            const char* optype = smElem->Attribute("operationtype");
552            if (optype)
553            {
554                if (!strcmp(optype, "triangle_list"))
555                {
556                    sm->operationType = RenderOperation::OT_TRIANGLE_LIST;
557                }
558                else if (!strcmp(optype, "triangle_fan"))
559                {
560                    sm->operationType = RenderOperation::OT_TRIANGLE_FAN;
561                }
562                else if (!strcmp(optype, "triangle_strip"))
563                {
564                    sm->operationType = RenderOperation::OT_TRIANGLE_STRIP;
565                }
566
567            }
568
569            const char* tmp = smElem->Attribute("usesharedvertices");
570            if (tmp)
571                sm->useSharedVertices = StringConverter::parseBool(tmp);
572            tmp = smElem->Attribute("use32bitindexes");
573            bool use32BitIndexes = false;
574            if (tmp)
575                use32BitIndexes = StringConverter::parseBool(tmp);
576           
577            // Faces
578            TiXmlElement* faces = smElem->FirstChildElement("faces");
579            if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST)
580            {
581                // tri list
582                sm->indexData->indexCount =
583                    StringConverter::parseInt(faces->Attribute("count")) * 3;
584            }
585            else
586            {
587                // tri strip or fan
588                sm->indexData->indexCount =
589                    StringConverter::parseInt(faces->Attribute("count")) + 2;
590            }
591
592            // Allocate space
593            HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
594                createIndexBuffer(
595                    use32BitIndexes? HardwareIndexBuffer::IT_32BIT : HardwareIndexBuffer::IT_16BIT,
596                    sm->indexData->indexCount,
597                    HardwareBuffer::HBU_DYNAMIC,
598                    false);
599            sm->indexData->indexBuffer = ibuf;
600            unsigned int *pInt;
601            unsigned short *pShort;
602            if (use32BitIndexes)
603            {
604                pInt = static_cast<unsigned int*>(
605                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
606            }
607            else
608            {
609                pShort = static_cast<unsigned short*>(
610                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
611            }
612            TiXmlElement* faceElem;
613            bool firstTri = true;
614            for (faceElem = faces->FirstChildElement();
615                faceElem != 0; faceElem = faceElem->NextSiblingElement())
616            {
617                if (use32BitIndexes)
618                {
619                    *pInt++ = StringConverter::parseInt(faceElem->Attribute("v1"));
620                    // only need all 3 vertices if it's a trilist or first tri
621                    if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri)
622                    {
623                        *pInt++ = StringConverter::parseInt(faceElem->Attribute("v2"));
624                        *pInt++ = StringConverter::parseInt(faceElem->Attribute("v3"));
625                    }
626                }
627                else
628                {
629                    *pShort++ = StringConverter::parseInt(faceElem->Attribute("v1"));
630                    // only need all 3 vertices if it's a trilist or first tri
631                    if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri)
632                    {
633                        *pShort++ = StringConverter::parseInt(faceElem->Attribute("v2"));
634                        *pShort++ = StringConverter::parseInt(faceElem->Attribute("v3"));
635                    }
636                }
637                firstTri = false;
638            }
639            ibuf->unlock();
640
641            // Geometry
642            if (!sm->useSharedVertices)
643            {
644                TiXmlElement* geomNode = smElem->FirstChildElement("geometry");
645                if (geomNode)
646                {
647                    sm->vertexData = new VertexData();
648                    readGeometry(geomNode, sm->vertexData);
649                }
650            }
651
652            // texture aliases
653            TiXmlElement* textureAliasesNode = smElem->FirstChildElement("textures");
654            if(textureAliasesNode)
655                readTextureAliases(textureAliasesNode, sm);
656
657            // Bone assignments
658            TiXmlElement* boneAssigns = smElem->FirstChildElement("boneassignments");
659            if(boneAssigns)
660                readBoneAssignments(boneAssigns, sm);
661
662        }
663        LogManager::getSingleton().logMessage("Submeshes done.");
664    }
665    //---------------------------------------------------------------------
666    void XMLMeshSerializer::readGeometry(TiXmlElement* mGeometryNode, VertexData* vertexData)
667    {
668        LogManager::getSingleton().logMessage("Reading geometry...");
669        unsigned char *pVert;
670        float *pFloat;
671        ARGB *pCol;
672
673        vertexData->vertexCount = StringConverter::parseInt(mGeometryNode->Attribute("vertexcount"));
674        // Skip empty
675        if (vertexData->vertexCount <= 0) return;
676       
677
678        VertexDeclaration* decl = vertexData->vertexDeclaration;
679        VertexBufferBinding* bind = vertexData->vertexBufferBinding;
680        unsigned short bufCount = 0;
681        unsigned short totalTexCoords = 0; // across all buffers
682
683        // Information for calculating bounds
684        Vector3 min, max, pos;
685        Real maxSquaredRadius = -1;
686        bool first = true;
687
688        // Iterate over all children (vertexbuffer entries)
689        for (TiXmlElement* vbElem = mGeometryNode->FirstChildElement();
690            vbElem != 0; vbElem = vbElem->NextSiblingElement())
691        {
692            size_t offset = 0;
693            // Skip non-vertexbuffer elems
694            if (stricmp(vbElem->Value(), "vertexbuffer")) continue;
695           
696            const char* attrib = vbElem->Attribute("positions");
697            if (attrib && StringConverter::parseBool(attrib))
698            {
699                // Add element
700                decl->addElement(bufCount, offset, VET_FLOAT3, VES_POSITION);
701                offset += VertexElement::getTypeSize(VET_FLOAT3);
702            }
703            attrib = vbElem->Attribute("normals");
704            if (attrib && StringConverter::parseBool(attrib))
705            {
706                // Add element
707                decl->addElement(bufCount, offset, VET_FLOAT3, VES_NORMAL);
708                offset += VertexElement::getTypeSize(VET_FLOAT3);
709            }
710            attrib = vbElem->Attribute("colours_diffuse");
711            if (attrib && StringConverter::parseBool(attrib))
712            {
713                // Add element
714                decl->addElement(bufCount, offset, mColourElementType, VES_DIFFUSE);
715                offset += VertexElement::getTypeSize(mColourElementType);
716            }
717            attrib = vbElem->Attribute("colours_specular");
718            if (attrib && StringConverter::parseBool(attrib))
719            {
720                // Add element
721                decl->addElement(bufCount, offset, mColourElementType, VES_SPECULAR);
722                offset += VertexElement::getTypeSize(mColourElementType);
723            }
724            attrib = vbElem->Attribute("texture_coords");
725            if (attrib && StringConverter::parseInt(attrib))
726            {
727                unsigned short numTexCoords = StringConverter::parseInt(vbElem->Attribute("texture_coords"));
728                for (unsigned short tx = 0; tx < numTexCoords; ++tx)
729                {
730                    // NB set is local to this buffer, but will be translated into a
731                    // global set number across all vertex buffers
732                    attrib = vbElem->Attribute("texture_coord_dimensions_" + StringConverter::toString(tx));
733                    unsigned short dims;
734                    if (attrib)
735                    {
736                        dims = StringConverter::parseInt(attrib);
737                    }
738                    else
739                    {
740                        // Default
741                        dims = 2;
742                    }
743                    // Add element
744                    VertexElementType vtype = VertexElement::multiplyTypeCount(VET_FLOAT1, dims);
745                    decl->addElement(bufCount, offset, vtype,
746                        VES_TEXTURE_COORDINATES, totalTexCoords++);
747                    offset += VertexElement::getTypeSize(vtype);
748                }
749            }
750            // Now create the vertex buffer
751            HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().
752                createVertexBuffer(offset, vertexData->vertexCount,
753                    HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
754            // Bind it
755            bind->setBinding(bufCount, vbuf);
756            // Lock it
757            pVert = static_cast<unsigned char*>(
758                vbuf->lock(HardwareBuffer::HBL_DISCARD));
759
760            // Get the element list for this buffer alone
761            VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufCount);
762            // Now the buffer is set up, parse all the vertices
763            for (TiXmlElement* vertexElem = vbElem->FirstChildElement();
764            vertexElem != 0; vertexElem = vertexElem->NextSiblingElement())
765            {
766                // Now parse the elements, ensure they are all matched
767                VertexDeclaration::VertexElementList::const_iterator ielem, ielemend;
768                TiXmlElement* xmlElem;
769                TiXmlElement* texCoordElem = 0;
770                ielemend = elems.end();
771                for (ielem = elems.begin(); ielem != ielemend; ++ielem)
772                {
773                    const VertexElement& elem = *ielem;
774                    // Find child for this element
775                    switch(elem.getSemantic())
776                    {
777                    case VES_POSITION:
778                        xmlElem = vertexElem->FirstChildElement("position");
779                        if (!xmlElem)
780                        {
781                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <position> element.",
782                                "XMLSerializer::readGeometry");
783                        }
784                        elem.baseVertexPointerToElement(pVert, &pFloat);
785
786                        *pFloat++ = StringConverter::parseReal(
787                            xmlElem->Attribute("x"));
788                        *pFloat++ = StringConverter::parseReal(
789                            xmlElem->Attribute("y"));
790                        *pFloat++ = StringConverter::parseReal(
791                            xmlElem->Attribute("z"));
792
793                        pos.x = StringConverter::parseReal(
794                            xmlElem->Attribute("x"));
795                        pos.y = StringConverter::parseReal(
796                            xmlElem->Attribute("y"));
797                        pos.z = StringConverter::parseReal(
798                            xmlElem->Attribute("z"));
799                       
800                        if (first)
801                        {
802                            min = max = pos;
803                            maxSquaredRadius = pos.squaredLength();
804                            first = false;
805                        }
806                        else
807                        {
808                            min.makeFloor(pos);
809                            max.makeCeil(pos);
810                            maxSquaredRadius = std::max(pos.squaredLength(), maxSquaredRadius);
811                        }
812                        break;
813                    case VES_NORMAL:
814                        xmlElem = vertexElem->FirstChildElement("normal");
815                        if (!xmlElem)
816                        {
817                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <normal> element.",
818                                "XMLSerializer::readGeometry");
819                        }
820                        elem.baseVertexPointerToElement(pVert, &pFloat);
821
822                        *pFloat++ = StringConverter::parseReal(
823                            xmlElem->Attribute("x"));
824                        *pFloat++ = StringConverter::parseReal(
825                            xmlElem->Attribute("y"));
826                        *pFloat++ = StringConverter::parseReal(
827                            xmlElem->Attribute("z"));
828                        break;
829                    case VES_DIFFUSE:
830                        xmlElem = vertexElem->FirstChildElement("colour_diffuse");
831                        if (!xmlElem)
832                        {
833                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_diffuse> element.",
834                                "XMLSerializer::readGeometry");
835                        }
836                        elem.baseVertexPointerToElement(pVert, &pCol);
837                                                {
838                                                        ColourValue cv;
839                                                        cv = StringConverter::parseColourValue(
840                                                                xmlElem->Attribute("value"));
841                                                        *pCol++ = VertexElement::convertColourValue(cv, mColourElementType);
842                                                }
843                        break;
844                    case VES_SPECULAR:
845                        xmlElem = vertexElem->FirstChildElement("colour_specular");
846                        if (!xmlElem)
847                        {
848                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_specular> element.",
849                                "XMLSerializer::readGeometry");
850                        }
851                        elem.baseVertexPointerToElement(pVert, &pCol);
852                                                {
853                                                        ColourValue cv;
854                                                        cv = StringConverter::parseColourValue(
855                                                                xmlElem->Attribute("value"));
856                                                        *pCol++ = VertexElement::convertColourValue(cv, mColourElementType);
857                                                }
858                        break;
859                    case VES_TEXTURE_COORDINATES:
860                        if (!texCoordElem)
861                        {
862                            // Get first texcoord
863                            xmlElem = vertexElem->FirstChildElement("texcoord");
864                        }
865                        else
866                        {
867                            // Get next texcoord
868                            xmlElem = texCoordElem->NextSiblingElement("texcoord");
869                        }
870                        if (!xmlElem)
871                        {
872                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <texcoord> element.",
873                                "XMLSerializer::readGeometry");
874                        }
875                                                // Record the latest texture coord entry
876                                                texCoordElem = xmlElem;
877                        elem.baseVertexPointerToElement(pVert, &pFloat);
878
879                        *pFloat++ = StringConverter::parseReal(
880                            xmlElem->Attribute("u"));
881                        if (VertexElement::getTypeCount(elem.getType()) > 1)
882                        {
883                            *pFloat++ = StringConverter::parseReal(
884                                xmlElem->Attribute("v"));
885                        }
886                        if (VertexElement::getTypeCount(elem.getType()) > 2)
887                        {
888                            *pFloat++ = StringConverter::parseReal(
889                                xmlElem->Attribute("w"));
890                        }
891
892                        break;
893                    default:
894                        break;
895                    }
896                } // semantic
897                pVert += vbuf->getVertexSize();
898            } // vertex
899            bufCount++;
900            vbuf->unlock();
901        } // vertexbuffer
902
903        // Set bounds
904        const AxisAlignedBox& currBox = mpMesh->getBounds();
905        Real currRadius = mpMesh->getBoundingSphereRadius();
906        if (currBox.isNull())
907        {
908            //do not pad the bounding box
909            mpMesh->_setBounds(AxisAlignedBox(min, max), false);
910            mpMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
911        }
912        else
913        {
914            AxisAlignedBox newBox(min, max);
915            newBox.merge(currBox);
916            //do not pad the bounding box
917            mpMesh->_setBounds(newBox, false);
918            mpMesh->_setBoundingSphereRadius(std::max(Math::Sqrt(maxSquaredRadius), currRadius));
919        }
920       
921
922        LogManager::getSingleton().logMessage("Geometry done...");
923    }
924    //---------------------------------------------------------------------
925    void XMLMeshSerializer::readSkeletonLink(TiXmlElement* mSkelNode)
926    {
927        mpMesh->setSkeletonName(mSkelNode->Attribute("name"));
928    }
929    //---------------------------------------------------------------------
930    void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode)
931    {
932        LogManager::getSingleton().logMessage("Reading bone assignments...");
933
934        // Iterate over all children (vertexboneassignment entries)
935        for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement();
936        elem != 0; elem = elem->NextSiblingElement())
937        {
938            VertexBoneAssignment vba;
939            vba.vertexIndex = StringConverter::parseInt(
940                elem->Attribute("vertexindex"));
941            vba.boneIndex = StringConverter::parseInt(
942                elem->Attribute("boneindex"));
943            vba.weight= StringConverter::parseReal(
944                elem->Attribute("weight"));
945
946            mpMesh->addBoneAssignment(vba);
947        }
948
949        LogManager::getSingleton().logMessage("Bone assignments done.");
950    }
951    //---------------------------------------------------------------------
952    void XMLMeshSerializer::readTextureAliases(TiXmlElement* mTextureAliasesNode, SubMesh* subMesh)
953    {
954        LogManager::getSingleton().logMessage("Reading sub mesh texture aliases...");
955
956        // Iterate over all children (texture entries)
957        for (TiXmlElement* elem = mTextureAliasesNode->FirstChildElement();
958             elem != 0; elem = elem->NextSiblingElement())
959        {
960            // pass alias and texture name to submesh
961            // read attribute "alias"
962            String alias = elem->Attribute("alias");
963            // read attribute "name"
964            String name = elem->Attribute("name");
965
966            subMesh->addTextureAlias(alias, name);
967        }
968
969        LogManager::getSingleton().logMessage("Texture aliases done.");
970    }
971    //---------------------------------------------------------------------
972        void XMLMeshSerializer::readSubMeshNames(TiXmlElement* mMeshNamesNode, Mesh *sm)
973        {
974                LogManager::getSingleton().logMessage("Reading mesh names...");
975
976                // Iterate over all children (vertexboneassignment entries)
977                for (TiXmlElement* elem = mMeshNamesNode->FirstChildElement();
978                        elem != 0; elem = elem->NextSiblingElement())
979                {
980                        String meshName = elem->Attribute("name");
981                        int index = StringConverter::parseInt(elem->Attribute("index"));
982
983                        sm->nameSubMesh(meshName, index);
984                }
985
986                LogManager::getSingleton().logMessage("Mesh names done.");
987        }
988    //---------------------------------------------------------------------
989    void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode, SubMesh* sm)
990    {
991        LogManager::getSingleton().logMessage("Reading bone assignments...");
992        // Iterate over all children (vertexboneassignment entries)
993        for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement();
994        elem != 0; elem = elem->NextSiblingElement())
995        {
996            VertexBoneAssignment vba;
997            vba.vertexIndex = StringConverter::parseInt(
998                elem->Attribute("vertexindex"));
999            vba.boneIndex = StringConverter::parseInt(
1000                elem->Attribute("boneindex"));
1001            vba.weight= StringConverter::parseReal(
1002                elem->Attribute("weight"));
1003
1004            sm->addBoneAssignment(vba);
1005        }
1006        LogManager::getSingleton().logMessage("Bone assignments done.");
1007    }
1008    //---------------------------------------------------------------------
1009        void XMLMeshSerializer::writeLodInfo(TiXmlElement* mMeshNode, const Mesh* pMesh)
1010        {
1011        TiXmlElement* lodNode =
1012            mMeshNode->InsertEndChild(TiXmlElement("levelofdetail"))->ToElement();
1013
1014                unsigned short numLvls = pMesh->getNumLodLevels();
1015                bool manual = pMesh->isLodManual();
1016                lodNode->SetAttribute("numlevels", StringConverter::toString(numLvls));
1017                lodNode->SetAttribute("manual", StringConverter::toString(manual));
1018
1019                // Iterate from level 1, not 0 (full detail)
1020                for (unsigned short i = 1; i < numLvls; ++i)
1021                {
1022                        const MeshLodUsage& usage = pMesh->getLodLevel(i);
1023                        if (manual)
1024                        {
1025                                writeLodUsageManual(lodNode, i, usage);
1026                        }
1027                        else
1028                        {
1029                                writeLodUsageGenerated(lodNode, i, usage, pMesh);
1030                        }
1031                }
1032
1033        }
1034    //---------------------------------------------------------------------
1035    void XMLMeshSerializer::writeSubMeshNames(TiXmlElement* mMeshNode, const Mesh* m)
1036    {
1037        const Mesh::SubMeshNameMap& nameMap = m->getSubMeshNameMap();
1038        if (nameMap.empty())
1039            return; // do nothing
1040
1041        TiXmlElement* namesNode =
1042            mMeshNode->InsertEndChild(TiXmlElement("submeshnames"))->ToElement();
1043        Mesh::SubMeshNameMap::const_iterator i, iend;
1044        iend = nameMap.end();
1045        for (i = nameMap.begin(); i != iend; ++i)
1046        {
1047            TiXmlElement* subNameNode =
1048                namesNode->InsertEndChild(TiXmlElement("submeshname"))->ToElement();
1049
1050            subNameNode->SetAttribute("name", i->first);
1051            subNameNode->SetAttribute("index",
1052                StringConverter::toString(i->second));
1053        }
1054
1055    }
1056    //---------------------------------------------------------------------
1057        void XMLMeshSerializer::writeLodUsageManual(TiXmlElement* usageNode,
1058                unsigned short levelNum, const MeshLodUsage& usage)
1059        {
1060                TiXmlElement* manualNode =
1061                        usageNode->InsertEndChild(TiXmlElement("lodmanual"))->ToElement();
1062
1063                manualNode->SetAttribute("fromdepthsquared",
1064                        StringConverter::toString(usage.fromDepthSquared));
1065                manualNode->SetAttribute("meshname", usage.manualName);
1066
1067        }
1068    //---------------------------------------------------------------------
1069        void XMLMeshSerializer::writeLodUsageGenerated(TiXmlElement* usageNode,
1070                unsigned short levelNum,  const MeshLodUsage& usage,
1071                const Mesh* pMesh)
1072        {
1073                TiXmlElement* generatedNode =
1074                        usageNode->InsertEndChild(TiXmlElement("lodgenerated"))->ToElement();
1075                generatedNode->SetAttribute("fromdepthsquared",
1076                        StringConverter::toString(usage.fromDepthSquared));
1077
1078                // Iterate over submeshes at this level
1079                unsigned short numsubs = pMesh->getNumSubMeshes();
1080
1081                for (unsigned short subi = 0; subi < numsubs; ++subi)
1082                {
1083                        TiXmlElement* subNode =
1084                                generatedNode->InsertEndChild(TiXmlElement("lodfacelist"))->ToElement();
1085                        SubMesh* sub = pMesh->getSubMesh(subi);
1086                        subNode->SetAttribute("submeshindex", StringConverter::toString(subi));
1087                        // NB level - 1 because SubMeshes don't store the first index in geometry
1088                    IndexData* facedata = sub->mLodFaceList[levelNum - 1];
1089                        subNode->SetAttribute("numfaces", StringConverter::toString(facedata->indexCount / 3));
1090
1091                        // Write each face in turn
1092                    bool use32BitIndexes = (facedata->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
1093
1094            // Write each face in turn
1095                    unsigned int* pInt;
1096                    unsigned short* pShort;
1097                    HardwareIndexBufferSharedPtr ibuf = facedata->indexBuffer;
1098                    if (use32BitIndexes)
1099                    {
1100                            pInt = static_cast<unsigned int*>(
1101                                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1102                    }
1103                    else
1104                    {
1105                            pShort = static_cast<unsigned short*>(
1106                                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1107                    }
1108                       
1109                        for (size_t f = 0; f < facedata->indexCount; f += 3)
1110                        {
1111                                TiXmlElement* faceNode =
1112                                        subNode->InsertEndChild(TiXmlElement("face"))->ToElement();
1113                if (use32BitIndexes)
1114                {
1115                                    faceNode->SetAttribute("v1", StringConverter::toString(*pInt++));
1116                                    faceNode->SetAttribute("v2", StringConverter::toString(*pInt++));
1117                                    faceNode->SetAttribute("v3", StringConverter::toString(*pInt++));
1118                }
1119                else
1120                {
1121                                    faceNode->SetAttribute("v1", StringConverter::toString(*pShort++));
1122                                    faceNode->SetAttribute("v2", StringConverter::toString(*pShort++));
1123                                    faceNode->SetAttribute("v3", StringConverter::toString(*pShort++));
1124                }
1125
1126                        }
1127
1128
1129
1130                }
1131
1132        }
1133    //---------------------------------------------------------------------
1134        void XMLMeshSerializer::readLodInfo(TiXmlElement*  lodNode)
1135        {
1136               
1137        LogManager::getSingleton().logMessage("Parsing LOD information...");
1138
1139                const char* val = lodNode->Attribute("numlevels");
1140                unsigned short numLevels = static_cast<unsigned short>(
1141                        StringConverter::parseUnsignedInt(val));
1142
1143                val = lodNode->Attribute("manual");
1144                bool manual = StringConverter::parseBool(val);
1145
1146                // Set up the basic structures
1147                mpMesh->_setLodInfo(numLevels, manual);
1148
1149                // Parse the detail, start from 1 (the first sub-level of detail)
1150                unsigned short i = 1;
1151                TiXmlElement* usageElem;
1152                if (manual)
1153                {
1154                        usageElem = lodNode->FirstChildElement("lodmanual");
1155                }
1156                else
1157                {
1158                        usageElem = lodNode->FirstChildElement("lodgenerated");
1159                }
1160                while (usageElem)
1161                {
1162                        if (manual)
1163                        {
1164                                readLodUsageManual(usageElem, i);
1165                                usageElem = usageElem->NextSiblingElement();
1166                        }
1167                        else
1168                        {
1169                                readLodUsageGenerated(usageElem, i);
1170                                usageElem = usageElem->NextSiblingElement();
1171                        }
1172                        ++i;
1173                }
1174               
1175        LogManager::getSingleton().logMessage("LOD information done.");
1176               
1177        }
1178    //---------------------------------------------------------------------
1179        void XMLMeshSerializer::readLodUsageManual(TiXmlElement* manualNode, unsigned short index)
1180        {
1181                MeshLodUsage usage;
1182                const char* val = manualNode->Attribute("fromdepthsquared");
1183                usage.fromDepthSquared = StringConverter::parseReal(val);
1184                usage.manualName = manualNode->Attribute("meshname");
1185        usage.edgeData = NULL;
1186
1187                mpMesh->_setLodUsage(index, usage);
1188        }
1189    //---------------------------------------------------------------------
1190        void XMLMeshSerializer::readLodUsageGenerated(TiXmlElement* genNode, unsigned short index)
1191        {
1192                MeshLodUsage usage;
1193                const char* val = genNode->Attribute("fromdepthsquared");
1194                usage.fromDepthSquared = StringConverter::parseReal(val);
1195                usage.manualMesh.setNull();
1196                usage.manualName = "";
1197        usage.edgeData = NULL;
1198
1199                mpMesh->_setLodUsage(index, usage);
1200
1201                // Read submesh face lists
1202                TiXmlElement* faceListElem = genNode->FirstChildElement("lodfacelist");
1203                while (faceListElem)
1204                {
1205                        val = faceListElem->Attribute("submeshindex");
1206                        unsigned short subidx = StringConverter::parseUnsignedInt(val);
1207                        val = faceListElem->Attribute("numfaces");
1208                        unsigned short numFaces = StringConverter::parseUnsignedInt(val);
1209            // use of 32bit indexes depends on submesh
1210            HardwareIndexBuffer::IndexType itype =
1211                mpMesh->getSubMesh(subidx)->indexData->indexBuffer->getType();
1212            bool use32bitindexes = (itype == HardwareIndexBuffer::IT_32BIT);
1213
1214            // Assign memory: this will be deleted by the submesh
1215            HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
1216                createIndexBuffer(
1217                    itype, numFaces * 3, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
1218
1219            unsigned short *pShort;
1220            unsigned int *pInt;
1221            if (use32bitindexes)
1222            {
1223                pInt = static_cast<unsigned int*>(
1224                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
1225            }
1226            else
1227            {
1228                pShort = static_cast<unsigned short*>(
1229                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
1230            }
1231            TiXmlElement* faceElem = faceListElem->FirstChildElement("face");
1232                        for (unsigned int face = 0; face < numFaces; ++face, faceElem = faceElem->NextSiblingElement())
1233                        {
1234                if (use32bitindexes)
1235                {
1236                    val = faceElem->Attribute("v1");
1237                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1238                                    val = faceElem->Attribute("v2");
1239                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1240                                    val = faceElem->Attribute("v3");
1241                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1242                }
1243                else
1244                {
1245                    val = faceElem->Attribute("v1");
1246                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1247                                    val = faceElem->Attribute("v2");
1248                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1249                                    val = faceElem->Attribute("v3");
1250                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1251                }
1252
1253                        }
1254
1255            ibuf->unlock();
1256                        IndexData* facedata = new IndexData(); // will be deleted by SubMesh
1257                        facedata->indexCount = numFaces * 3;
1258            facedata->indexStart = 0;
1259            facedata->indexBuffer = ibuf;
1260                        mpMesh->_setSubMeshLodFaceList(subidx, index, facedata);
1261
1262                        faceListElem = faceListElem->NextSiblingElement();
1263                }
1264       
1265        }
1266        //-----------------------------------------------------------------------------
1267        void XMLMeshSerializer::readPoses(TiXmlElement* posesNode, Mesh *m)
1268        {
1269                TiXmlElement* poseNode = posesNode->FirstChildElement("pose");
1270
1271                while (poseNode)
1272                {
1273                        const char* target = poseNode->Attribute("target");
1274                        if (!target)
1275                        {
1276                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1277                                        "Required attribute 'target' missing on pose",
1278                                        "XMLMeshSerializer::readPoses");
1279                        }
1280                        unsigned short targetID;
1281                        if(target == "mesh")
1282                        {
1283                                targetID = 0;
1284                        }
1285                        else
1286                        {
1287                                // submesh, get index
1288                                const char* val = poseNode->Attribute("index");
1289                                if (!val)
1290                                {
1291                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1292                                                "Required attribute 'index' missing on pose",
1293                                                "XMLMeshSerializer::readPoses");
1294                                }
1295                                unsigned short submeshIndex = static_cast<unsigned short>(
1296                                        StringConverter::parseUnsignedInt(val));
1297
1298                                targetID = submeshIndex + 1;
1299                        }
1300
1301                        String name;
1302                        const char* val = poseNode->Attribute("name");
1303                        if (val)
1304                                name = val;
1305                        Pose* pose = m->createPose(targetID, name);
1306
1307                        TiXmlElement* poseOffsetNode = poseNode->FirstChildElement("poseoffset");
1308                        while (poseOffsetNode)
1309                        {
1310                                uint index = StringConverter::parseUnsignedInt(
1311                                        poseOffsetNode->Attribute("index"));
1312                                Vector3 offset;
1313                                offset.x = StringConverter::parseReal(poseOffsetNode->Attribute("x"));
1314                                offset.y = StringConverter::parseReal(poseOffsetNode->Attribute("y"));
1315                                offset.z = StringConverter::parseReal(poseOffsetNode->Attribute("z"));
1316
1317                                pose->addVertex(index, offset);
1318
1319                                poseOffsetNode = poseOffsetNode->NextSiblingElement();
1320                        }
1321
1322                        poseNode = poseNode->NextSiblingElement();
1323
1324                }
1325
1326
1327        }
1328        //-----------------------------------------------------------------------------
1329        void XMLMeshSerializer::readAnimations(TiXmlElement* mAnimationsNode, Mesh *pMesh)
1330        {
1331                TiXmlElement* animElem = mAnimationsNode->FirstChildElement("animation");
1332                while (animElem)
1333                {
1334                        String name = animElem->Attribute("name");
1335                        const char* charLen = animElem->Attribute("length");
1336                        Real len = StringConverter::parseReal(charLen);
1337
1338                        Animation* anim = pMesh->createAnimation(name, len);
1339
1340                        TiXmlElement* tracksNode = animElem->FirstChildElement("tracks");
1341                        if (tracksNode)
1342                        {
1343                                readTracks(tracksNode, pMesh, anim);
1344                        }
1345
1346                        animElem = animElem->NextSiblingElement();
1347
1348                }
1349
1350
1351        }
1352        //-----------------------------------------------------------------------------
1353        void XMLMeshSerializer::readTracks(TiXmlElement* tracksNode, Mesh *m, Animation* anim)
1354        {
1355                TiXmlElement* trackNode = tracksNode->FirstChildElement("track");
1356                while (trackNode)
1357                {
1358                        String target = trackNode->Attribute("target");
1359                        unsigned short targetID;
1360                        VertexData* vertexData = 0;
1361                        if(target == "mesh")
1362                        {
1363                                targetID = 0;
1364                                vertexData = m->sharedVertexData;
1365                        }
1366                        else
1367                        {
1368                                // submesh, get index
1369                                const char* val = trackNode->Attribute("index");
1370                                if (!val)
1371                                {
1372                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1373                                                "Required attribute 'index' missing on submesh track",
1374                                                "XMLMeshSerializer::readTracks");
1375                                }
1376                                unsigned short submeshIndex = static_cast<unsigned short>(
1377                                        StringConverter::parseUnsignedInt(val));
1378
1379                                targetID = submeshIndex + 1;
1380                                vertexData = m->getSubMesh(submeshIndex)->vertexData;
1381
1382                        }
1383
1384                        if (!vertexData)
1385                        {
1386                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1387                                        "Track cannot be created for " + target + " since VertexData "
1388                                        "does not exist at the specified index",
1389                                        "XMLMeshSerializer::readTracks");
1390                        }
1391
1392                        // Get type
1393                        VertexAnimationType animType = VAT_NONE;
1394                        String strAnimType = trackNode->Attribute("type");
1395                        if (strAnimType == "morph")
1396                        {
1397                                animType = VAT_MORPH;
1398                        }
1399                        else if (strAnimType == "pose")
1400                        {
1401                                animType = VAT_POSE;
1402                        }
1403                        else
1404                        {
1405                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1406                                        "Unrecognised animation track type '" + strAnimType + "'",
1407                                        "XMLMeshSerializer::readTracks");
1408                        }
1409
1410                        // Create track
1411                        VertexAnimationTrack* track =
1412                                anim->createVertexTrack(targetID, vertexData, animType);
1413
1414                        TiXmlElement* keyframesNode = trackNode->FirstChildElement("keyframes");
1415                        if (keyframesNode)
1416                        {
1417                                if (track->getAnimationType() == VAT_MORPH)
1418                                {
1419                                        readMorphKeyFrames(keyframesNode, track, vertexData->vertexCount);
1420                                }
1421                                else // VAT_POSE
1422                                {
1423                                        readPoseKeyFrames(keyframesNode, track);
1424                                }
1425                        }
1426
1427                        trackNode = trackNode->NextSiblingElement();
1428                }
1429        }
1430        //-----------------------------------------------------------------------------
1431        void XMLMeshSerializer::readMorphKeyFrames(TiXmlElement* keyframesNode,
1432                VertexAnimationTrack* track, size_t vertexCount)
1433        {
1434                TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe");
1435                while (keyNode)
1436                {
1437                        const char* val = keyNode->Attribute("time");
1438                        if (!val)
1439                        {
1440                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1441                                        "Required attribute 'time' missing on keyframe",
1442                                        "XMLMeshSerializer::readKeyFrames");
1443                        }
1444                        Real time = StringConverter::parseReal(val);
1445
1446                        VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(time);
1447
1448                        // create a vertex buffer
1449                        HardwareVertexBufferSharedPtr vbuf =
1450                                HardwareBufferManager::getSingleton().createVertexBuffer(
1451                                VertexElement::getTypeSize(VET_FLOAT3), vertexCount,
1452                                HardwareBuffer::HBU_STATIC, true);
1453
1454                        float* pFloat = static_cast<float*>(
1455                                vbuf->lock(HardwareBuffer::HBL_DISCARD));
1456
1457
1458                        TiXmlElement* posNode = keyNode->FirstChildElement("position");
1459                        for (size_t v = 0; v < vertexCount; ++v)
1460                        {
1461                                if (!posNode)
1462                                {
1463                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1464                                                "Not enough 'position' elements under keyframe",
1465                                                "XMLMeshSerializer::readKeyFrames");
1466
1467                                }
1468
1469                                *pFloat++ = StringConverter::parseReal(
1470                                        posNode->Attribute("x"));
1471                                *pFloat++ = StringConverter::parseReal(
1472                                        posNode->Attribute("y"));
1473                                *pFloat++ = StringConverter::parseReal(
1474                                        posNode->Attribute("z"));
1475
1476
1477                                posNode = posNode->NextSiblingElement("position");
1478                        }
1479
1480                        vbuf->unlock();
1481
1482                        kf->setVertexBuffer(vbuf);
1483                               
1484
1485                        keyNode = keyNode->NextSiblingElement();
1486                }
1487
1488
1489        }
1490        //-----------------------------------------------------------------------------
1491        void XMLMeshSerializer::readPoseKeyFrames(TiXmlElement* keyframesNode, VertexAnimationTrack* track)
1492        {
1493                TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe");
1494                while (keyNode)
1495                {
1496                        const char* val = keyNode->Attribute("time");
1497                        if (!val)
1498                        {
1499                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1500                                        "Required attribute 'time' missing on keyframe",
1501                                        "XMLMeshSerializer::readKeyFrames");
1502                        }
1503                        Real time = StringConverter::parseReal(val);
1504
1505                        VertexPoseKeyFrame* kf = track->createVertexPoseKeyFrame(time);
1506
1507                        // Read all pose references
1508                        TiXmlElement* poseRefNode = keyNode->FirstChildElement("poseref");
1509                        while (poseRefNode)
1510                        {
1511                                const char* val = poseRefNode->Attribute("poseindex");
1512                                if (!val)
1513                                {
1514                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1515                                                "Required attribute 'poseindex' missing on poseref",
1516                                                "XMLMeshSerializer::readPoseKeyFrames");
1517                                }
1518                                unsigned short poseIndex = StringConverter::parseUnsignedInt(val);
1519                                Real influence = 1.0f;
1520                                val = poseRefNode->Attribute("influence");
1521                                if (val)
1522                                {
1523                                        influence = StringConverter::parseReal(val);
1524                                }
1525
1526                                kf->addPoseReference(poseIndex, influence);
1527
1528                                poseRefNode = poseRefNode->NextSiblingElement();
1529                        }
1530
1531                        keyNode = keyNode->NextSiblingElement();
1532                }
1533
1534        }
1535        //-----------------------------------------------------------------------------
1536        void XMLMeshSerializer::writePoses(TiXmlElement* meshNode, const Mesh* m)
1537        {
1538                if (m->getPoseCount() == 0)
1539                        return;
1540
1541                TiXmlElement* posesNode =
1542                        meshNode->InsertEndChild(TiXmlElement("poses"))->ToElement();
1543
1544                Mesh::ConstPoseIterator poseIt = m->getPoseIterator();
1545                while (poseIt.hasMoreElements())
1546                {
1547                        const Pose* pose = poseIt.getNext();
1548                        TiXmlElement* poseNode =
1549                                posesNode->InsertEndChild(TiXmlElement("pose"))->ToElement();
1550                        unsigned short target = pose->getTarget();
1551                        if (target == 0)
1552                        {
1553                                // Main mesh
1554                                poseNode->SetAttribute("target", "mesh");
1555                        }
1556                        else
1557                        {
1558                                // Submesh - rebase index
1559                                poseNode->SetAttribute("target", "submesh");
1560                                poseNode->SetAttribute("index",
1561                                        StringConverter::toString(target - 1));
1562                        }
1563                        poseNode->SetAttribute("name", pose->getName());
1564
1565                        Pose::ConstVertexOffsetIterator vit = pose->getVertexOffsetIterator();
1566                        while (vit.hasMoreElements())
1567                        {
1568                                TiXmlElement* poseOffsetElement = poseNode->InsertEndChild(
1569                                        TiXmlElement("poseoffset"))->ToElement();
1570
1571                                poseOffsetElement->SetAttribute("index",
1572                                        StringConverter::toString(vit.peekNextKey()));
1573
1574                                Vector3 offset = vit.getNext();
1575                                poseOffsetElement->SetAttribute("x", StringConverter::toString(offset.x));
1576                                poseOffsetElement->SetAttribute("y", StringConverter::toString(offset.y));
1577                                poseOffsetElement->SetAttribute("z", StringConverter::toString(offset.z));
1578
1579
1580                        }
1581
1582                }
1583
1584        }
1585        //-----------------------------------------------------------------------------
1586        void XMLMeshSerializer::writeAnimations(TiXmlElement* meshNode, const Mesh* m)
1587        {
1588                // Skip if no animation
1589                if (!m->hasVertexAnimation())
1590                        return;
1591
1592                TiXmlElement* animationsNode =
1593                        meshNode->InsertEndChild(TiXmlElement("animations"))->ToElement();
1594
1595                for (unsigned short a = 0; a < m->getNumAnimations(); ++a)
1596                {
1597                        Animation* anim = m->getAnimation(a);
1598
1599                        TiXmlElement* animNode =
1600                                animationsNode->InsertEndChild(TiXmlElement("animation"))->ToElement();
1601                        animNode->SetAttribute("name", anim->getName());
1602                        animNode->SetAttribute("length",
1603                                StringConverter::toString(anim->getLength()));
1604
1605                        TiXmlElement* tracksNode =
1606                                animNode->InsertEndChild(TiXmlElement("tracks"))->ToElement();
1607                        Animation::VertexTrackIterator iter = anim->getVertexTrackIterator();
1608                        while(iter.hasMoreElements())
1609                        {
1610                                const VertexAnimationTrack* track = iter.getNext();
1611                                TiXmlElement* trackNode =
1612                                        tracksNode->InsertEndChild(TiXmlElement("track"))->ToElement();
1613
1614                                unsigned short targetID = track->getHandle();
1615                                if (targetID == 0)
1616                                {
1617                                        trackNode->SetAttribute("target", "mesh");
1618                                }
1619                                else
1620                                {
1621                                        trackNode->SetAttribute("target", "submesh");
1622                                        trackNode->SetAttribute("index",
1623                                                StringConverter::toString(targetID-1));
1624                                }
1625
1626                                if (track->getAnimationType() == VAT_MORPH)
1627                                {
1628                                        trackNode->SetAttribute("type", "morph");
1629                                        writeMorphKeyFrames(trackNode, track);
1630                                }
1631                                else
1632                                {
1633                                        trackNode->SetAttribute("type", "pose");
1634                                        writePoseKeyFrames(trackNode, track);
1635                                }
1636
1637
1638                        }
1639                }
1640
1641               
1642        }
1643        //-----------------------------------------------------------------------------
1644        void XMLMeshSerializer::writeMorphKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track)
1645        {
1646                TiXmlElement* keyframesNode =
1647                        trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement();
1648
1649                size_t vertexCount = track->getAssociatedVertexData()->vertexCount;
1650
1651                for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k)
1652                {
1653                        VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(k);
1654                        TiXmlElement* keyNode =
1655                                keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement();
1656                        keyNode->SetAttribute("time",
1657                                StringConverter::toString(kf->getTime()));
1658
1659                        HardwareVertexBufferSharedPtr vbuf = kf->getVertexBuffer();
1660                        float* pFloat = static_cast<float*>(
1661                                vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
1662
1663                        for (size_t v = 0; v < vertexCount; ++v)
1664                        {
1665                                TiXmlElement* posNode =
1666                                        keyNode->InsertEndChild(TiXmlElement("position"))->ToElement();
1667                                posNode->SetAttribute("x", StringConverter::toString(*pFloat++));
1668                                posNode->SetAttribute("y", StringConverter::toString(*pFloat++));
1669                                posNode->SetAttribute("z", StringConverter::toString(*pFloat++));
1670                        }
1671
1672                }
1673        }
1674        //-----------------------------------------------------------------------------
1675        void XMLMeshSerializer::writePoseKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track)
1676        {
1677                TiXmlElement* keyframesNode =
1678                        trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement();
1679
1680                for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k)
1681                {
1682                        VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(k);
1683                        TiXmlElement* keyNode =
1684                                keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement();
1685                        keyNode->SetAttribute("time",
1686                                StringConverter::toString(kf->getTime()));
1687
1688                        VertexPoseKeyFrame::PoseRefIterator poseIt = kf->getPoseReferenceIterator();
1689                        while (poseIt.hasMoreElements())
1690                        {
1691                                const VertexPoseKeyFrame::PoseRef& poseRef = poseIt.getNext();
1692                                TiXmlElement* poseRefNode =
1693                                        keyNode->InsertEndChild(TiXmlElement("poseref"))->ToElement();
1694
1695                                poseRefNode->SetAttribute("poseindex",
1696                                        StringConverter::toString(poseRef.poseIndex));
1697                                poseRefNode->SetAttribute("influence",
1698                                        StringConverter::toString(poseRef.influence));
1699
1700                        }
1701
1702                }
1703
1704
1705        }
1706
1707
1708
1709
1710}
1711
Note: See TracBrowser for help on using the repository browser.