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

Revision 692, 62.3 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

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    }
486    //---------------------------------------------------------------------
487    void XMLMeshSerializer::writeSkeletonLink(TiXmlElement* mMeshNode, const String& skelName)
488    {
489
490        TiXmlElement* skelNode =
491            mMeshNode->InsertEndChild(TiXmlElement("skeletonlink"))->ToElement();
492        skelNode->SetAttribute("name", skelName);
493    }
494    //---------------------------------------------------------------------
495    void XMLMeshSerializer::writeBoneAssignment(TiXmlElement* mBoneAssignNode, const VertexBoneAssignment* assign)
496    {
497        TiXmlElement* assignNode =
498            mBoneAssignNode->InsertEndChild(
499            TiXmlElement("vertexboneassignment"))->ToElement();
500
501        assignNode->SetAttribute("vertexindex",
502            StringConverter::toString(assign->vertexIndex));
503        assignNode->SetAttribute("boneindex",
504            StringConverter::toString(assign->boneIndex));
505        assignNode->SetAttribute("weight",
506            StringConverter::toString(assign->weight));
507
508
509    }
510    //---------------------------------------------------------------------
511    void XMLMeshSerializer::writeTextureAliases(TiXmlElement* mSubmeshesNode, const SubMesh* subMesh)
512    {
513        if (!subMesh->hasTextureAliases())
514            return; // do nothing
515
516        TiXmlElement* textureAliasesNode =
517            mSubmeshesNode->InsertEndChild(TiXmlElement("textures"))->ToElement();
518
519        // use ogre map iterator
520        SubMesh::AliasTextureIterator aliasIterator = subMesh->getAliasTextureIterator();
521
522        while (aliasIterator.hasMoreElements())
523        {
524            TiXmlElement* aliasTextureNode =
525                textureAliasesNode->InsertEndChild(TiXmlElement("texture"))->ToElement();
526            // iterator key is alias and value is texture name
527            aliasTextureNode->SetAttribute("alias", aliasIterator.peekNextKey());
528            aliasTextureNode->SetAttribute("name", aliasIterator.peekNextValue());
529            aliasIterator.moveNext();
530        }
531
532    }
533    //---------------------------------------------------------------------
534    void XMLMeshSerializer::readSubMeshes(TiXmlElement* mSubmeshesNode)
535    {
536        LogManager::getSingleton().logMessage("Reading submeshes...");
537
538        for (TiXmlElement* smElem = mSubmeshesNode->FirstChildElement();
539            smElem != 0; smElem = smElem->NextSiblingElement())
540        {
541            // All children should be submeshes
542            SubMesh* sm = mpMesh->createSubMesh();
543
544            const char* mat = smElem->Attribute("material");
545            if (mat)
546                sm->setMaterialName(mat);
547
548            // Read operation type
549            const char* optype = smElem->Attribute("operationtype");
550            if (optype)
551            {
552                if (!strcmp(optype, "triangle_list"))
553                {
554                    sm->operationType = RenderOperation::OT_TRIANGLE_LIST;
555                }
556                else if (!strcmp(optype, "triangle_fan"))
557                {
558                    sm->operationType = RenderOperation::OT_TRIANGLE_FAN;
559                }
560                else if (!strcmp(optype, "triangle_strip"))
561                {
562                    sm->operationType = RenderOperation::OT_TRIANGLE_STRIP;
563                }
564
565            }
566
567            const char* tmp = smElem->Attribute("usesharedvertices");
568            if (tmp)
569                sm->useSharedVertices = StringConverter::parseBool(tmp);
570            tmp = smElem->Attribute("use32bitindexes");
571            bool use32BitIndexes = false;
572            if (tmp)
573                use32BitIndexes = StringConverter::parseBool(tmp);
574           
575            // Faces
576            TiXmlElement* faces = smElem->FirstChildElement("faces");
577            if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST)
578            {
579                // tri list
580                sm->indexData->indexCount =
581                    StringConverter::parseInt(faces->Attribute("count")) * 3;
582            }
583            else
584            {
585                // tri strip or fan
586                sm->indexData->indexCount =
587                    StringConverter::parseInt(faces->Attribute("count")) + 2;
588            }
589
590            // Allocate space
591            HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
592                createIndexBuffer(
593                    use32BitIndexes? HardwareIndexBuffer::IT_32BIT : HardwareIndexBuffer::IT_16BIT,
594                    sm->indexData->indexCount,
595                    HardwareBuffer::HBU_DYNAMIC,
596                    false);
597            sm->indexData->indexBuffer = ibuf;
598            unsigned int *pInt;
599            unsigned short *pShort;
600            if (use32BitIndexes)
601            {
602                pInt = static_cast<unsigned int*>(
603                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
604            }
605            else
606            {
607                pShort = static_cast<unsigned short*>(
608                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
609            }
610            TiXmlElement* faceElem;
611            bool firstTri = true;
612            for (faceElem = faces->FirstChildElement();
613                faceElem != 0; faceElem = faceElem->NextSiblingElement())
614            {
615                if (use32BitIndexes)
616                {
617                    *pInt++ = StringConverter::parseInt(faceElem->Attribute("v1"));
618                    // only need all 3 vertices if it's a trilist or first tri
619                    if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri)
620                    {
621                        *pInt++ = StringConverter::parseInt(faceElem->Attribute("v2"));
622                        *pInt++ = StringConverter::parseInt(faceElem->Attribute("v3"));
623                    }
624                }
625                else
626                {
627                    *pShort++ = StringConverter::parseInt(faceElem->Attribute("v1"));
628                    // only need all 3 vertices if it's a trilist or first tri
629                    if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri)
630                    {
631                        *pShort++ = StringConverter::parseInt(faceElem->Attribute("v2"));
632                        *pShort++ = StringConverter::parseInt(faceElem->Attribute("v3"));
633                    }
634                }
635                firstTri = false;
636            }
637            ibuf->unlock();
638
639            // Geometry
640            if (!sm->useSharedVertices)
641            {
642                TiXmlElement* geomNode = smElem->FirstChildElement("geometry");
643                if (geomNode)
644                {
645                    sm->vertexData = new VertexData();
646                    readGeometry(geomNode, sm->vertexData);
647                }
648            }
649
650            // texture aliases
651            TiXmlElement* textureAliasesNode = smElem->FirstChildElement("textures");
652            if(textureAliasesNode)
653                readTextureAliases(textureAliasesNode, sm);
654
655            // Bone assignments
656            TiXmlElement* boneAssigns = smElem->FirstChildElement("boneassignments");
657            if(boneAssigns)
658                readBoneAssignments(boneAssigns, sm);
659
660        }
661        LogManager::getSingleton().logMessage("Submeshes done.");
662    }
663    //---------------------------------------------------------------------
664    void XMLMeshSerializer::readGeometry(TiXmlElement* mGeometryNode, VertexData* vertexData)
665    {
666        LogManager::getSingleton().logMessage("Reading geometry...");
667        unsigned char *pVert;
668        float *pFloat;
669        ARGB *pCol;
670
671        vertexData->vertexCount = StringConverter::parseInt(mGeometryNode->Attribute("vertexcount"));
672        // Skip empty
673        if (vertexData->vertexCount <= 0) return;
674       
675
676        VertexDeclaration* decl = vertexData->vertexDeclaration;
677        VertexBufferBinding* bind = vertexData->vertexBufferBinding;
678        unsigned short bufCount = 0;
679        unsigned short totalTexCoords = 0; // across all buffers
680
681        // Information for calculating bounds
682        Vector3 min, max, pos;
683        Real maxSquaredRadius = -1;
684        bool first = true;
685
686        // Iterate over all children (vertexbuffer entries)
687        for (TiXmlElement* vbElem = mGeometryNode->FirstChildElement();
688            vbElem != 0; vbElem = vbElem->NextSiblingElement())
689        {
690            size_t offset = 0;
691            // Skip non-vertexbuffer elems
692            if (stricmp(vbElem->Value(), "vertexbuffer")) continue;
693           
694            const char* attrib = vbElem->Attribute("positions");
695            if (attrib && StringConverter::parseBool(attrib))
696            {
697                // Add element
698                decl->addElement(bufCount, offset, VET_FLOAT3, VES_POSITION);
699                offset += VertexElement::getTypeSize(VET_FLOAT3);
700            }
701            attrib = vbElem->Attribute("normals");
702            if (attrib && StringConverter::parseBool(attrib))
703            {
704                // Add element
705                decl->addElement(bufCount, offset, VET_FLOAT3, VES_NORMAL);
706                offset += VertexElement::getTypeSize(VET_FLOAT3);
707            }
708            attrib = vbElem->Attribute("colours_diffuse");
709            if (attrib && StringConverter::parseBool(attrib))
710            {
711                // Add element
712                decl->addElement(bufCount, offset, mColourElementType, VES_DIFFUSE);
713                offset += VertexElement::getTypeSize(mColourElementType);
714            }
715            attrib = vbElem->Attribute("colours_specular");
716            if (attrib && StringConverter::parseBool(attrib))
717            {
718                // Add element
719                decl->addElement(bufCount, offset, mColourElementType, VES_SPECULAR);
720                offset += VertexElement::getTypeSize(mColourElementType);
721            }
722            attrib = vbElem->Attribute("texture_coords");
723            if (attrib && StringConverter::parseInt(attrib))
724            {
725                unsigned short numTexCoords = StringConverter::parseInt(vbElem->Attribute("texture_coords"));
726                for (unsigned short tx = 0; tx < numTexCoords; ++tx)
727                {
728                    // NB set is local to this buffer, but will be translated into a
729                    // global set number across all vertex buffers
730                    attrib = vbElem->Attribute("texture_coord_dimensions_" + StringConverter::toString(tx));
731                    unsigned short dims;
732                    if (attrib)
733                    {
734                        dims = StringConverter::parseInt(attrib);
735                    }
736                    else
737                    {
738                        // Default
739                        dims = 2;
740                    }
741                    // Add element
742                    VertexElementType vtype = VertexElement::multiplyTypeCount(VET_FLOAT1, dims);
743                    decl->addElement(bufCount, offset, vtype,
744                        VES_TEXTURE_COORDINATES, totalTexCoords++);
745                    offset += VertexElement::getTypeSize(vtype);
746                }
747            }
748            // Now create the vertex buffer
749            HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().
750                createVertexBuffer(offset, vertexData->vertexCount,
751                    HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
752            // Bind it
753            bind->setBinding(bufCount, vbuf);
754            // Lock it
755            pVert = static_cast<unsigned char*>(
756                vbuf->lock(HardwareBuffer::HBL_DISCARD));
757
758            // Get the element list for this buffer alone
759            VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufCount);
760            // Now the buffer is set up, parse all the vertices
761            for (TiXmlElement* vertexElem = vbElem->FirstChildElement();
762            vertexElem != 0; vertexElem = vertexElem->NextSiblingElement())
763            {
764                // Now parse the elements, ensure they are all matched
765                VertexDeclaration::VertexElementList::const_iterator ielem, ielemend;
766                TiXmlElement* xmlElem;
767                TiXmlElement* texCoordElem = 0;
768                ielemend = elems.end();
769                for (ielem = elems.begin(); ielem != ielemend; ++ielem)
770                {
771                    const VertexElement& elem = *ielem;
772                    // Find child for this element
773                    switch(elem.getSemantic())
774                    {
775                    case VES_POSITION:
776                        xmlElem = vertexElem->FirstChildElement("position");
777                        if (!xmlElem)
778                        {
779                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <position> element.",
780                                "XMLSerializer::readGeometry");
781                        }
782                        elem.baseVertexPointerToElement(pVert, &pFloat);
783
784                        *pFloat++ = StringConverter::parseReal(
785                            xmlElem->Attribute("x"));
786                        *pFloat++ = StringConverter::parseReal(
787                            xmlElem->Attribute("y"));
788                        *pFloat++ = StringConverter::parseReal(
789                            xmlElem->Attribute("z"));
790
791                        pos.x = StringConverter::parseReal(
792                            xmlElem->Attribute("x"));
793                        pos.y = StringConverter::parseReal(
794                            xmlElem->Attribute("y"));
795                        pos.z = StringConverter::parseReal(
796                            xmlElem->Attribute("z"));
797                       
798                        if (first)
799                        {
800                            min = max = pos;
801                            maxSquaredRadius = pos.squaredLength();
802                            first = false;
803                        }
804                        else
805                        {
806                            min.makeFloor(pos);
807                            max.makeCeil(pos);
808                            maxSquaredRadius = std::max(pos.squaredLength(), maxSquaredRadius);
809                        }
810                        break;
811                    case VES_NORMAL:
812                        xmlElem = vertexElem->FirstChildElement("normal");
813                        if (!xmlElem)
814                        {
815                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <normal> element.",
816                                "XMLSerializer::readGeometry");
817                        }
818                        elem.baseVertexPointerToElement(pVert, &pFloat);
819
820                        *pFloat++ = StringConverter::parseReal(
821                            xmlElem->Attribute("x"));
822                        *pFloat++ = StringConverter::parseReal(
823                            xmlElem->Attribute("y"));
824                        *pFloat++ = StringConverter::parseReal(
825                            xmlElem->Attribute("z"));
826                        break;
827                    case VES_DIFFUSE:
828                        xmlElem = vertexElem->FirstChildElement("colour_diffuse");
829                        if (!xmlElem)
830                        {
831                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_diffuse> element.",
832                                "XMLSerializer::readGeometry");
833                        }
834                        elem.baseVertexPointerToElement(pVert, &pCol);
835                                                {
836                                                        ColourValue cv;
837                                                        cv = StringConverter::parseColourValue(
838                                                                xmlElem->Attribute("value"));
839                                                        *pCol++ = VertexElement::convertColourValue(cv, mColourElementType);
840                                                }
841                        break;
842                    case VES_SPECULAR:
843                        xmlElem = vertexElem->FirstChildElement("colour_specular");
844                        if (!xmlElem)
845                        {
846                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_specular> element.",
847                                "XMLSerializer::readGeometry");
848                        }
849                        elem.baseVertexPointerToElement(pVert, &pCol);
850                                                {
851                                                        ColourValue cv;
852                                                        cv = StringConverter::parseColourValue(
853                                                                xmlElem->Attribute("value"));
854                                                        *pCol++ = VertexElement::convertColourValue(cv, mColourElementType);
855                                                }
856                        break;
857                    case VES_TEXTURE_COORDINATES:
858                        if (!texCoordElem)
859                        {
860                            // Get first texcoord
861                            xmlElem = vertexElem->FirstChildElement("texcoord");
862                        }
863                        else
864                        {
865                            // Get next texcoord
866                            xmlElem = texCoordElem->NextSiblingElement("texcoord");
867                        }
868                        if (!xmlElem)
869                        {
870                            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <texcoord> element.",
871                                "XMLSerializer::readGeometry");
872                        }
873                                                // Record the latest texture coord entry
874                                                texCoordElem = xmlElem;
875                        elem.baseVertexPointerToElement(pVert, &pFloat);
876
877                        *pFloat++ = StringConverter::parseReal(
878                            xmlElem->Attribute("u"));
879                        if (VertexElement::getTypeCount(elem.getType()) > 1)
880                        {
881                            *pFloat++ = StringConverter::parseReal(
882                                xmlElem->Attribute("v"));
883                        }
884                        if (VertexElement::getTypeCount(elem.getType()) > 2)
885                        {
886                            *pFloat++ = StringConverter::parseReal(
887                                xmlElem->Attribute("w"));
888                        }
889
890                        break;
891                    default:
892                        break;
893                    }
894                } // semantic
895                pVert += vbuf->getVertexSize();
896            } // vertex
897            bufCount++;
898            vbuf->unlock();
899        } // vertexbuffer
900
901        // Set bounds
902        const AxisAlignedBox& currBox = mpMesh->getBounds();
903        Real currRadius = mpMesh->getBoundingSphereRadius();
904        if (currBox.isNull())
905        {
906            //do not pad the bounding box
907            mpMesh->_setBounds(AxisAlignedBox(min, max), false);
908            mpMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
909        }
910        else
911        {
912            AxisAlignedBox newBox(min, max);
913            newBox.merge(currBox);
914            //do not pad the bounding box
915            mpMesh->_setBounds(newBox, false);
916            mpMesh->_setBoundingSphereRadius(std::max(Math::Sqrt(maxSquaredRadius), currRadius));
917        }
918       
919
920        LogManager::getSingleton().logMessage("Geometry done...");
921    }
922    //---------------------------------------------------------------------
923    void XMLMeshSerializer::readSkeletonLink(TiXmlElement* mSkelNode)
924    {
925        mpMesh->setSkeletonName(mSkelNode->Attribute("name"));
926    }
927    //---------------------------------------------------------------------
928    void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode)
929    {
930        LogManager::getSingleton().logMessage("Reading bone assignments...");
931
932        // Iterate over all children (vertexboneassignment entries)
933        for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement();
934        elem != 0; elem = elem->NextSiblingElement())
935        {
936            VertexBoneAssignment vba;
937            vba.vertexIndex = StringConverter::parseInt(
938                elem->Attribute("vertexindex"));
939            vba.boneIndex = StringConverter::parseInt(
940                elem->Attribute("boneindex"));
941            vba.weight= StringConverter::parseReal(
942                elem->Attribute("weight"));
943
944            mpMesh->addBoneAssignment(vba);
945        }
946
947        LogManager::getSingleton().logMessage("Bone assignments done.");
948    }
949    //---------------------------------------------------------------------
950    void XMLMeshSerializer::readTextureAliases(TiXmlElement* mTextureAliasesNode, SubMesh* subMesh)
951    {
952        LogManager::getSingleton().logMessage("Reading sub mesh texture aliases...");
953
954        // Iterate over all children (texture entries)
955        for (TiXmlElement* elem = mTextureAliasesNode->FirstChildElement();
956             elem != 0; elem = elem->NextSiblingElement())
957        {
958            // pass alias and texture name to submesh
959            // read attribute "alias"
960            String alias = elem->Attribute("alias");
961            // read attribute "name"
962            String name = elem->Attribute("name");
963
964            subMesh->addTextureAlias(alias, name);
965        }
966
967        LogManager::getSingleton().logMessage("Texture aliases done.");
968    }
969    //---------------------------------------------------------------------
970        void XMLMeshSerializer::readSubMeshNames(TiXmlElement* mMeshNamesNode, Mesh *sm)
971        {
972                LogManager::getSingleton().logMessage("Reading mesh names...");
973
974                // Iterate over all children (vertexboneassignment entries)
975                for (TiXmlElement* elem = mMeshNamesNode->FirstChildElement();
976                        elem != 0; elem = elem->NextSiblingElement())
977                {
978                        String meshName = elem->Attribute("name");
979                        int index = StringConverter::parseInt(elem->Attribute("index"));
980
981                        sm->nameSubMesh(meshName, index);
982                }
983
984                LogManager::getSingleton().logMessage("Mesh names done.");
985        }
986    //---------------------------------------------------------------------
987    void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode, SubMesh* sm)
988    {
989        LogManager::getSingleton().logMessage("Reading bone assignments...");
990        // Iterate over all children (vertexboneassignment entries)
991        for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement();
992        elem != 0; elem = elem->NextSiblingElement())
993        {
994            VertexBoneAssignment vba;
995            vba.vertexIndex = StringConverter::parseInt(
996                elem->Attribute("vertexindex"));
997            vba.boneIndex = StringConverter::parseInt(
998                elem->Attribute("boneindex"));
999            vba.weight= StringConverter::parseReal(
1000                elem->Attribute("weight"));
1001
1002            sm->addBoneAssignment(vba);
1003        }
1004        LogManager::getSingleton().logMessage("Bone assignments done.");
1005    }
1006    //---------------------------------------------------------------------
1007        void XMLMeshSerializer::writeLodInfo(TiXmlElement* mMeshNode, const Mesh* pMesh)
1008        {
1009        TiXmlElement* lodNode =
1010            mMeshNode->InsertEndChild(TiXmlElement("levelofdetail"))->ToElement();
1011
1012                unsigned short numLvls = pMesh->getNumLodLevels();
1013                bool manual = pMesh->isLodManual();
1014                lodNode->SetAttribute("numlevels", StringConverter::toString(numLvls));
1015                lodNode->SetAttribute("manual", StringConverter::toString(manual));
1016
1017                // Iterate from level 1, not 0 (full detail)
1018                for (unsigned short i = 1; i < numLvls; ++i)
1019                {
1020                        const MeshLodUsage& usage = pMesh->getLodLevel(i);
1021                        if (manual)
1022                        {
1023                                writeLodUsageManual(lodNode, i, usage);
1024                        }
1025                        else
1026                        {
1027                                writeLodUsageGenerated(lodNode, i, usage, pMesh);
1028                        }
1029                }
1030
1031        }
1032    //---------------------------------------------------------------------
1033    void XMLMeshSerializer::writeSubMeshNames(TiXmlElement* mMeshNode, const Mesh* m)
1034    {
1035        const Mesh::SubMeshNameMap& nameMap = m->getSubMeshNameMap();
1036        if (nameMap.empty())
1037            return; // do nothing
1038
1039        TiXmlElement* namesNode =
1040            mMeshNode->InsertEndChild(TiXmlElement("submeshnames"))->ToElement();
1041        Mesh::SubMeshNameMap::const_iterator i, iend;
1042        iend = nameMap.end();
1043        for (i = nameMap.begin(); i != iend; ++i)
1044        {
1045            TiXmlElement* subNameNode =
1046                namesNode->InsertEndChild(TiXmlElement("submeshname"))->ToElement();
1047
1048            subNameNode->SetAttribute("name", i->first);
1049            subNameNode->SetAttribute("index",
1050                StringConverter::toString(i->second));
1051        }
1052
1053    }
1054    //---------------------------------------------------------------------
1055        void XMLMeshSerializer::writeLodUsageManual(TiXmlElement* usageNode,
1056                unsigned short levelNum, const MeshLodUsage& usage)
1057        {
1058                TiXmlElement* manualNode =
1059                        usageNode->InsertEndChild(TiXmlElement("lodmanual"))->ToElement();
1060
1061                manualNode->SetAttribute("fromdepthsquared",
1062                        StringConverter::toString(usage.fromDepthSquared));
1063                manualNode->SetAttribute("meshname", usage.manualName);
1064
1065        }
1066    //---------------------------------------------------------------------
1067        void XMLMeshSerializer::writeLodUsageGenerated(TiXmlElement* usageNode,
1068                unsigned short levelNum,  const MeshLodUsage& usage,
1069                const Mesh* pMesh)
1070        {
1071                TiXmlElement* generatedNode =
1072                        usageNode->InsertEndChild(TiXmlElement("lodgenerated"))->ToElement();
1073                generatedNode->SetAttribute("fromdepthsquared",
1074                        StringConverter::toString(usage.fromDepthSquared));
1075
1076                // Iterate over submeshes at this level
1077                unsigned short numsubs = pMesh->getNumSubMeshes();
1078
1079                for (unsigned short subi = 0; subi < numsubs; ++subi)
1080                {
1081                        TiXmlElement* subNode =
1082                                generatedNode->InsertEndChild(TiXmlElement("lodfacelist"))->ToElement();
1083                        SubMesh* sub = pMesh->getSubMesh(subi);
1084                        subNode->SetAttribute("submeshindex", StringConverter::toString(subi));
1085                        // NB level - 1 because SubMeshes don't store the first index in geometry
1086                    IndexData* facedata = sub->mLodFaceList[levelNum - 1];
1087                        subNode->SetAttribute("numfaces", StringConverter::toString(facedata->indexCount / 3));
1088
1089                        // Write each face in turn
1090                    bool use32BitIndexes = (facedata->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
1091
1092            // Write each face in turn
1093                    unsigned int* pInt;
1094                    unsigned short* pShort;
1095                    HardwareIndexBufferSharedPtr ibuf = facedata->indexBuffer;
1096                    if (use32BitIndexes)
1097                    {
1098                            pInt = static_cast<unsigned int*>(
1099                                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1100                    }
1101                    else
1102                    {
1103                            pShort = static_cast<unsigned short*>(
1104                                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1105                    }
1106                       
1107                        for (size_t f = 0; f < facedata->indexCount; f += 3)
1108                        {
1109                                TiXmlElement* faceNode =
1110                                        subNode->InsertEndChild(TiXmlElement("face"))->ToElement();
1111                if (use32BitIndexes)
1112                {
1113                                    faceNode->SetAttribute("v1", StringConverter::toString(*pInt++));
1114                                    faceNode->SetAttribute("v2", StringConverter::toString(*pInt++));
1115                                    faceNode->SetAttribute("v3", StringConverter::toString(*pInt++));
1116                }
1117                else
1118                {
1119                                    faceNode->SetAttribute("v1", StringConverter::toString(*pShort++));
1120                                    faceNode->SetAttribute("v2", StringConverter::toString(*pShort++));
1121                                    faceNode->SetAttribute("v3", StringConverter::toString(*pShort++));
1122                }
1123
1124                        }
1125
1126
1127
1128                }
1129
1130        }
1131    //---------------------------------------------------------------------
1132        void XMLMeshSerializer::readLodInfo(TiXmlElement*  lodNode)
1133        {
1134               
1135        LogManager::getSingleton().logMessage("Parsing LOD information...");
1136
1137                const char* val = lodNode->Attribute("numlevels");
1138                unsigned short numLevels = static_cast<unsigned short>(
1139                        StringConverter::parseUnsignedInt(val));
1140
1141                val = lodNode->Attribute("manual");
1142                bool manual = StringConverter::parseBool(val);
1143
1144                // Set up the basic structures
1145                mpMesh->_setLodInfo(numLevels, manual);
1146
1147                // Parse the detail, start from 1 (the first sub-level of detail)
1148                unsigned short i = 1;
1149                TiXmlElement* usageElem;
1150                if (manual)
1151                {
1152                        usageElem = lodNode->FirstChildElement("lodmanual");
1153                }
1154                else
1155                {
1156                        usageElem = lodNode->FirstChildElement("lodgenerated");
1157                }
1158                while (usageElem)
1159                {
1160                        if (manual)
1161                        {
1162                                readLodUsageManual(usageElem, i);
1163                                usageElem = usageElem->NextSiblingElement();
1164                        }
1165                        else
1166                        {
1167                                readLodUsageGenerated(usageElem, i);
1168                                usageElem = usageElem->NextSiblingElement();
1169                        }
1170                        ++i;
1171                }
1172               
1173        LogManager::getSingleton().logMessage("LOD information done.");
1174               
1175        }
1176    //---------------------------------------------------------------------
1177        void XMLMeshSerializer::readLodUsageManual(TiXmlElement* manualNode, unsigned short index)
1178        {
1179                MeshLodUsage usage;
1180                const char* val = manualNode->Attribute("fromdepthsquared");
1181                usage.fromDepthSquared = StringConverter::parseReal(val);
1182                usage.manualName = manualNode->Attribute("meshname");
1183        usage.edgeData = NULL;
1184
1185                mpMesh->_setLodUsage(index, usage);
1186        }
1187    //---------------------------------------------------------------------
1188        void XMLMeshSerializer::readLodUsageGenerated(TiXmlElement* genNode, unsigned short index)
1189        {
1190                MeshLodUsage usage;
1191                const char* val = genNode->Attribute("fromdepthsquared");
1192                usage.fromDepthSquared = StringConverter::parseReal(val);
1193                usage.manualMesh.setNull();
1194                usage.manualName = "";
1195        usage.edgeData = NULL;
1196
1197                mpMesh->_setLodUsage(index, usage);
1198
1199                // Read submesh face lists
1200                TiXmlElement* faceListElem = genNode->FirstChildElement("lodfacelist");
1201                while (faceListElem)
1202                {
1203                        val = faceListElem->Attribute("submeshindex");
1204                        unsigned short subidx = StringConverter::parseUnsignedInt(val);
1205                        val = faceListElem->Attribute("numfaces");
1206                        unsigned short numFaces = StringConverter::parseUnsignedInt(val);
1207            // use of 32bit indexes depends on submesh
1208            HardwareIndexBuffer::IndexType itype =
1209                mpMesh->getSubMesh(subidx)->indexData->indexBuffer->getType();
1210            bool use32bitindexes = (itype == HardwareIndexBuffer::IT_32BIT);
1211
1212            // Assign memory: this will be deleted by the submesh
1213            HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
1214                createIndexBuffer(
1215                    itype, numFaces * 3, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
1216
1217            unsigned short *pShort;
1218            unsigned int *pInt;
1219            if (use32bitindexes)
1220            {
1221                pInt = static_cast<unsigned int*>(
1222                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
1223            }
1224            else
1225            {
1226                pShort = static_cast<unsigned short*>(
1227                    ibuf->lock(HardwareBuffer::HBL_DISCARD));
1228            }
1229            TiXmlElement* faceElem = faceListElem->FirstChildElement("face");
1230                        for (unsigned int face = 0; face < numFaces; ++face, faceElem = faceElem->NextSiblingElement())
1231                        {
1232                if (use32bitindexes)
1233                {
1234                    val = faceElem->Attribute("v1");
1235                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1236                                    val = faceElem->Attribute("v2");
1237                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1238                                    val = faceElem->Attribute("v3");
1239                                    *pInt++ = StringConverter::parseUnsignedInt(val);
1240                }
1241                else
1242                {
1243                    val = faceElem->Attribute("v1");
1244                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1245                                    val = faceElem->Attribute("v2");
1246                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1247                                    val = faceElem->Attribute("v3");
1248                                    *pShort++ = StringConverter::parseUnsignedInt(val);
1249                }
1250
1251                        }
1252
1253            ibuf->unlock();
1254                        IndexData* facedata = new IndexData(); // will be deleted by SubMesh
1255                        facedata->indexCount = numFaces * 3;
1256            facedata->indexStart = 0;
1257            facedata->indexBuffer = ibuf;
1258                        mpMesh->_setSubMeshLodFaceList(subidx, index, facedata);
1259
1260                        faceListElem = faceListElem->NextSiblingElement();
1261                }
1262       
1263        }
1264        //-----------------------------------------------------------------------------
1265        void XMLMeshSerializer::readPoses(TiXmlElement* posesNode, Mesh *m)
1266        {
1267                TiXmlElement* poseNode = posesNode->FirstChildElement("pose");
1268
1269                while (poseNode)
1270                {
1271                        const char* target = poseNode->Attribute("target");
1272                        if (!target)
1273                        {
1274                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1275                                        "Required attribute 'target' missing on pose",
1276                                        "XMLMeshSerializer::readPoses");
1277                        }
1278                        unsigned short targetID;
1279                        if(target == "mesh")
1280                        {
1281                                targetID = 0;
1282                        }
1283                        else
1284                        {
1285                                // submesh, get index
1286                                const char* val = poseNode->Attribute("index");
1287                                if (!val)
1288                                {
1289                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1290                                                "Required attribute 'index' missing on pose",
1291                                                "XMLMeshSerializer::readPoses");
1292                                }
1293                                unsigned short submeshIndex = static_cast<unsigned short>(
1294                                        StringConverter::parseUnsignedInt(val));
1295
1296                                targetID = submeshIndex + 1;
1297                        }
1298
1299                        String name;
1300                        const char* val = poseNode->Attribute("name");
1301                        if (val)
1302                                name = val;
1303                        Pose* pose = m->createPose(targetID, name);
1304
1305                        TiXmlElement* poseOffsetNode = poseNode->FirstChildElement("poseoffset");
1306                        while (poseOffsetNode)
1307                        {
1308                                uint index = StringConverter::parseUnsignedInt(
1309                                        poseOffsetNode->Attribute("index"));
1310                                Vector3 offset;
1311                                offset.x = StringConverter::parseReal(poseOffsetNode->Attribute("x"));
1312                                offset.y = StringConverter::parseReal(poseOffsetNode->Attribute("y"));
1313                                offset.z = StringConverter::parseReal(poseOffsetNode->Attribute("z"));
1314
1315                                pose->addVertex(index, offset);
1316
1317                                poseOffsetNode = poseOffsetNode->NextSiblingElement();
1318                        }
1319
1320                        poseNode = poseNode->NextSiblingElement();
1321
1322                }
1323
1324
1325        }
1326        //-----------------------------------------------------------------------------
1327        void XMLMeshSerializer::readAnimations(TiXmlElement* mAnimationsNode, Mesh *pMesh)
1328        {
1329                TiXmlElement* animElem = mAnimationsNode->FirstChildElement("animation");
1330                while (animElem)
1331                {
1332                        String name = animElem->Attribute("name");
1333                        const char* charLen = animElem->Attribute("length");
1334                        Real len = StringConverter::parseReal(charLen);
1335
1336                        Animation* anim = pMesh->createAnimation(name, len);
1337
1338                        TiXmlElement* tracksNode = animElem->FirstChildElement("tracks");
1339                        if (tracksNode)
1340                        {
1341                                readTracks(tracksNode, pMesh, anim);
1342                        }
1343
1344                        animElem = animElem->NextSiblingElement();
1345
1346                }
1347
1348
1349        }
1350        //-----------------------------------------------------------------------------
1351        void XMLMeshSerializer::readTracks(TiXmlElement* tracksNode, Mesh *m, Animation* anim)
1352        {
1353                TiXmlElement* trackNode = tracksNode->FirstChildElement("track");
1354                while (trackNode)
1355                {
1356                        String target = trackNode->Attribute("target");
1357                        unsigned short targetID;
1358                        VertexData* vertexData = 0;
1359                        if(target == "mesh")
1360                        {
1361                                targetID = 0;
1362                                vertexData = m->sharedVertexData;
1363                        }
1364                        else
1365                        {
1366                                // submesh, get index
1367                                const char* val = trackNode->Attribute("index");
1368                                if (!val)
1369                                {
1370                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1371                                                "Required attribute 'index' missing on submesh track",
1372                                                "XMLMeshSerializer::readTracks");
1373                                }
1374                                unsigned short submeshIndex = static_cast<unsigned short>(
1375                                        StringConverter::parseUnsignedInt(val));
1376
1377                                targetID = submeshIndex + 1;
1378                                vertexData = m->getSubMesh(submeshIndex)->vertexData;
1379
1380                        }
1381
1382                        if (!vertexData)
1383                        {
1384                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1385                                        "Track cannot be created for " + target + " since VertexData "
1386                                        "does not exist at the specified index",
1387                                        "XMLMeshSerializer::readTracks");
1388                        }
1389
1390                        // Get type
1391                        VertexAnimationType animType = VAT_NONE;
1392                        String strAnimType = trackNode->Attribute("type");
1393                        if (strAnimType == "morph")
1394                        {
1395                                animType = VAT_MORPH;
1396                        }
1397                        else if (strAnimType == "pose")
1398                        {
1399                                animType = VAT_POSE;
1400                        }
1401                        else
1402                        {
1403                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1404                                        "Unrecognised animation track type '" + strAnimType + "'",
1405                                        "XMLMeshSerializer::readTracks");
1406                        }
1407
1408                        // Create track
1409                        VertexAnimationTrack* track =
1410                                anim->createVertexTrack(targetID, vertexData, animType);
1411
1412                        TiXmlElement* keyframesNode = trackNode->FirstChildElement("keyframes");
1413                        if (keyframesNode)
1414                        {
1415                                if (track->getAnimationType() == VAT_MORPH)
1416                                {
1417                                        readMorphKeyFrames(keyframesNode, track, vertexData->vertexCount);
1418                                }
1419                                else // VAT_POSE
1420                                {
1421                                        readPoseKeyFrames(keyframesNode, track);
1422                                }
1423                        }
1424
1425                        trackNode = trackNode->NextSiblingElement();
1426                }
1427        }
1428        //-----------------------------------------------------------------------------
1429        void XMLMeshSerializer::readMorphKeyFrames(TiXmlElement* keyframesNode,
1430                VertexAnimationTrack* track, size_t vertexCount)
1431        {
1432                TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe");
1433                while (keyNode)
1434                {
1435                        const char* val = keyNode->Attribute("time");
1436                        if (!val)
1437                        {
1438                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1439                                        "Required attribute 'time' missing on keyframe",
1440                                        "XMLMeshSerializer::readKeyFrames");
1441                        }
1442                        Real time = StringConverter::parseReal(val);
1443
1444                        VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(time);
1445
1446                        // create a vertex buffer
1447                        HardwareVertexBufferSharedPtr vbuf =
1448                                HardwareBufferManager::getSingleton().createVertexBuffer(
1449                                VertexElement::getTypeSize(VET_FLOAT3), vertexCount,
1450                                HardwareBuffer::HBU_STATIC, true);
1451
1452                        float* pFloat = static_cast<float*>(
1453                                vbuf->lock(HardwareBuffer::HBL_DISCARD));
1454
1455
1456                        TiXmlElement* posNode = keyNode->FirstChildElement("position");
1457                        for (size_t v = 0; v < vertexCount; ++v)
1458                        {
1459                                if (!posNode)
1460                                {
1461                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1462                                                "Not enough 'position' elements under keyframe",
1463                                                "XMLMeshSerializer::readKeyFrames");
1464
1465                                }
1466
1467                                *pFloat++ = StringConverter::parseReal(
1468                                        posNode->Attribute("x"));
1469                                *pFloat++ = StringConverter::parseReal(
1470                                        posNode->Attribute("y"));
1471                                *pFloat++ = StringConverter::parseReal(
1472                                        posNode->Attribute("z"));
1473
1474
1475                                posNode = posNode->NextSiblingElement("position");
1476                        }
1477
1478                        vbuf->unlock();
1479
1480                        kf->setVertexBuffer(vbuf);
1481                               
1482
1483                        keyNode = keyNode->NextSiblingElement();
1484                }
1485
1486
1487        }
1488        //-----------------------------------------------------------------------------
1489        void XMLMeshSerializer::readPoseKeyFrames(TiXmlElement* keyframesNode, VertexAnimationTrack* track)
1490        {
1491                TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe");
1492                while (keyNode)
1493                {
1494                        const char* val = keyNode->Attribute("time");
1495                        if (!val)
1496                        {
1497                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1498                                        "Required attribute 'time' missing on keyframe",
1499                                        "XMLMeshSerializer::readKeyFrames");
1500                        }
1501                        Real time = StringConverter::parseReal(val);
1502
1503                        VertexPoseKeyFrame* kf = track->createVertexPoseKeyFrame(time);
1504
1505                        // Read all pose references
1506                        TiXmlElement* poseRefNode = keyNode->FirstChildElement("poseref");
1507                        while (poseRefNode)
1508                        {
1509                                const char* val = poseRefNode->Attribute("poseindex");
1510                                if (!val)
1511                                {
1512                                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1513                                                "Required attribute 'poseindex' missing on poseref",
1514                                                "XMLMeshSerializer::readPoseKeyFrames");
1515                                }
1516                                unsigned short poseIndex = StringConverter::parseUnsignedInt(val);
1517                                Real influence = 1.0f;
1518                                val = poseRefNode->Attribute("influence");
1519                                if (val)
1520                                {
1521                                        influence = StringConverter::parseReal(val);
1522                                }
1523
1524                                kf->addPoseReference(poseIndex, influence);
1525
1526                                poseRefNode = poseRefNode->NextSiblingElement();
1527                        }
1528
1529                        keyNode = keyNode->NextSiblingElement();
1530                }
1531
1532        }
1533        //-----------------------------------------------------------------------------
1534        void XMLMeshSerializer::writePoses(TiXmlElement* meshNode, const Mesh* m)
1535        {
1536                if (m->getPoseCount() == 0)
1537                        return;
1538
1539                TiXmlElement* posesNode =
1540                        meshNode->InsertEndChild(TiXmlElement("poses"))->ToElement();
1541
1542                Mesh::ConstPoseIterator poseIt = m->getPoseIterator();
1543                while (poseIt.hasMoreElements())
1544                {
1545                        const Pose* pose = poseIt.getNext();
1546                        TiXmlElement* poseNode =
1547                                posesNode->InsertEndChild(TiXmlElement("pose"))->ToElement();
1548                        unsigned short target = pose->getTarget();
1549                        if (target == 0)
1550                        {
1551                                // Main mesh
1552                                poseNode->SetAttribute("target", "mesh");
1553                        }
1554                        else
1555                        {
1556                                // Submesh - rebase index
1557                                poseNode->SetAttribute("target", "submesh");
1558                                poseNode->SetAttribute("index",
1559                                        StringConverter::toString(target - 1));
1560                        }
1561                        poseNode->SetAttribute("name", pose->getName());
1562
1563                        Pose::ConstVertexOffsetIterator vit = pose->getVertexOffsetIterator();
1564                        while (vit.hasMoreElements())
1565                        {
1566                                TiXmlElement* poseOffsetElement = poseNode->InsertEndChild(
1567                                        TiXmlElement("poseoffset"))->ToElement();
1568
1569                                poseOffsetElement->SetAttribute("index",
1570                                        StringConverter::toString(vit.peekNextKey()));
1571
1572                                Vector3 offset = vit.getNext();
1573                                poseOffsetElement->SetAttribute("x", StringConverter::toString(offset.x));
1574                                poseOffsetElement->SetAttribute("y", StringConverter::toString(offset.y));
1575                                poseOffsetElement->SetAttribute("z", StringConverter::toString(offset.z));
1576
1577
1578                        }
1579
1580                }
1581
1582        }
1583        //-----------------------------------------------------------------------------
1584        void XMLMeshSerializer::writeAnimations(TiXmlElement* meshNode, const Mesh* m)
1585        {
1586                // Skip if no animation
1587                if (!m->hasVertexAnimation())
1588                        return;
1589
1590                TiXmlElement* animationsNode =
1591                        meshNode->InsertEndChild(TiXmlElement("animations"))->ToElement();
1592
1593                for (unsigned short a = 0; a < m->getNumAnimations(); ++a)
1594                {
1595                        Animation* anim = m->getAnimation(a);
1596
1597                        TiXmlElement* animNode =
1598                                animationsNode->InsertEndChild(TiXmlElement("animation"))->ToElement();
1599                        animNode->SetAttribute("name", anim->getName());
1600                        animNode->SetAttribute("length",
1601                                StringConverter::toString(anim->getLength()));
1602
1603                        TiXmlElement* tracksNode =
1604                                animNode->InsertEndChild(TiXmlElement("tracks"))->ToElement();
1605                        Animation::VertexTrackIterator iter = anim->getVertexTrackIterator();
1606                        while(iter.hasMoreElements())
1607                        {
1608                                const VertexAnimationTrack* track = iter.getNext();
1609                                TiXmlElement* trackNode =
1610                                        tracksNode->InsertEndChild(TiXmlElement("track"))->ToElement();
1611
1612                                unsigned short targetID = track->getHandle();
1613                                if (targetID == 0)
1614                                {
1615                                        trackNode->SetAttribute("target", "mesh");
1616                                }
1617                                else
1618                                {
1619                                        trackNode->SetAttribute("target", "submesh");
1620                                        trackNode->SetAttribute("index",
1621                                                StringConverter::toString(targetID-1));
1622                                }
1623
1624                                if (track->getAnimationType() == VAT_MORPH)
1625                                {
1626                                        trackNode->SetAttribute("type", "morph");
1627                                        writeMorphKeyFrames(trackNode, track);
1628                                }
1629                                else
1630                                {
1631                                        trackNode->SetAttribute("type", "pose");
1632                                        writePoseKeyFrames(trackNode, track);
1633                                }
1634
1635
1636                        }
1637                }
1638
1639               
1640        }
1641        //-----------------------------------------------------------------------------
1642        void XMLMeshSerializer::writeMorphKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track)
1643        {
1644                TiXmlElement* keyframesNode =
1645                        trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement();
1646
1647                size_t vertexCount = track->getAssociatedVertexData()->vertexCount;
1648
1649                for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k)
1650                {
1651                        VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(k);
1652                        TiXmlElement* keyNode =
1653                                keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement();
1654                        keyNode->SetAttribute("time",
1655                                StringConverter::toString(kf->getTime()));
1656
1657                        HardwareVertexBufferSharedPtr vbuf = kf->getVertexBuffer();
1658                        float* pFloat = static_cast<float*>(
1659                                vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
1660
1661                        for (size_t v = 0; v < vertexCount; ++v)
1662                        {
1663                                TiXmlElement* posNode =
1664                                        keyNode->InsertEndChild(TiXmlElement("position"))->ToElement();
1665                                posNode->SetAttribute("x", StringConverter::toString(*pFloat++));
1666                                posNode->SetAttribute("y", StringConverter::toString(*pFloat++));
1667                                posNode->SetAttribute("z", StringConverter::toString(*pFloat++));
1668                        }
1669
1670                }
1671        }
1672        //-----------------------------------------------------------------------------
1673        void XMLMeshSerializer::writePoseKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track)
1674        {
1675                TiXmlElement* keyframesNode =
1676                        trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement();
1677
1678                for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k)
1679                {
1680                        VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(k);
1681                        TiXmlElement* keyNode =
1682                                keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement();
1683                        keyNode->SetAttribute("time",
1684                                StringConverter::toString(kf->getTime()));
1685
1686                        VertexPoseKeyFrame::PoseRefIterator poseIt = kf->getPoseReferenceIterator();
1687                        while (poseIt.hasMoreElements())
1688                        {
1689                                const VertexPoseKeyFrame::PoseRef& poseRef = poseIt.getNext();
1690                                TiXmlElement* poseRefNode =
1691                                        keyNode->InsertEndChild(TiXmlElement("poseref"))->ToElement();
1692
1693                                poseRefNode->SetAttribute("poseindex",
1694                                        StringConverter::toString(poseRef.poseIndex));
1695                                poseRefNode->SetAttribute("influence",
1696                                        StringConverter::toString(poseRef.influence));
1697
1698                        }
1699
1700                }
1701
1702
1703        }
1704
1705
1706
1707
1708}
1709
Note: See TracBrowser for help on using the repository browser.