Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreMeshSerializerImpl.cpp @ 5

Last change on this file since 5 was 5, checked in by anonymous, 17 years ago

=hoffentlich gehts jetzt

File size: 97.2 KB
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30
31#include "OgreMeshSerializerImpl.h"
32#include "OgreMeshFileFormat.h"
33#include "OgreMesh.h"
34#include "OgreSubMesh.h"
35#include "OgreException.h"
36#include "OgreLogManager.h"
37#include "OgreSkeleton.h"
38#include "OgreHardwareBufferManager.h"
39#include "OgreMaterial.h"
40#include "OgreTechnique.h"
41#include "OgrePass.h"
42#include "OgreAnimation.h"
43#include "OgreAnimationTrack.h"
44#include "OgreKeyFrame.h"
45#include "OgreRoot.h"
46
47#if OGRE_COMPILER == OGRE_COMPILER_MSVC
48// Disable conversion warnings, we do a lot of them, intentionally
49#   pragma warning (disable : 4267)
50#endif
51
52
53namespace Ogre {
54
55    /// stream overhead = ID + size
56    const long STREAM_OVERHEAD_SIZE = sizeof(uint16) + sizeof(uint32);
57    //---------------------------------------------------------------------
58    MeshSerializerImpl::MeshSerializerImpl()
59    {
60
61        // Version number
62        mVersion = "[MeshSerializer_v1.40]";
63    }
64    //---------------------------------------------------------------------
65    MeshSerializerImpl::~MeshSerializerImpl()
66    {
67    }
68    //---------------------------------------------------------------------
69    void MeshSerializerImpl::exportMesh(const Mesh* pMesh, 
70                const String& filename, Endian endianMode)
71    {
72        LogManager::getSingleton().logMessage("MeshSerializer writing mesh data to " + filename + "...");
73
74                // Decide on endian mode
75                determineEndianness(endianMode);
76
77        // Check that the mesh has it's bounds set
78        if (pMesh->getBounds().isNull() || pMesh->getBoundingSphereRadius() == 0.0f)
79        {
80            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The Mesh you have supplied does not have its"
81                " bounds completely defined. Define them first before exporting.",
82                "MeshSerializerImpl::exportMesh");
83        }
84        mpfFile = fopen(filename.c_str(), "wb");
85                if (!mpfFile)
86                {
87                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
88                                "Unable to open file " + filename + " for writing",
89                                "MeshSerializerImpl::exportMesh");
90                }
91
92        writeFileHeader();
93        LogManager::getSingleton().logMessage("File header written.");
94
95
96        LogManager::getSingleton().logMessage("Writing mesh data...");
97        writeMesh(pMesh);
98        LogManager::getSingleton().logMessage("Mesh data exported.");
99
100        fclose(mpfFile);
101        LogManager::getSingleton().logMessage("MeshSerializer export successful.");
102    }
103    //---------------------------------------------------------------------
104    void MeshSerializerImpl::importMesh(DataStreamPtr& stream, Mesh* pMesh)
105    {
106                // Determine endianness (must be the first thing we do!)
107                determineEndianness(stream);
108
109        // Check header
110        readFileHeader(stream);
111
112        unsigned short streamID;
113        while(!stream->eof())
114        {
115            streamID = readChunk(stream);
116            switch (streamID)
117            {
118            case M_MESH:
119                readMesh(stream, pMesh);
120                break;
121                        }
122
123        }
124    }
125    //---------------------------------------------------------------------
126    void MeshSerializerImpl::writeMesh(const Mesh* pMesh)
127    {
128        // Header
129        writeChunkHeader(M_MESH, calcMeshSize(pMesh));
130
131                // bool skeletallyAnimated
132                bool skelAnim = pMesh->hasSkeleton();
133                writeBools(&skelAnim, 1);
134
135        // Write shared geometry
136        if (pMesh->sharedVertexData)
137            writeGeometry(pMesh->sharedVertexData);
138
139        // Write Submeshes
140        for (int i = 0; i < pMesh->getNumSubMeshes(); ++i)
141        {
142            LogManager::getSingleton().logMessage("Writing submesh...");
143            writeSubMesh(pMesh->getSubMesh(i));
144            LogManager::getSingleton().logMessage("Submesh exported.");
145        }
146
147        // Write skeleton info if required
148        if (pMesh->hasSkeleton())
149        {
150            LogManager::getSingleton().logMessage("Exporting skeleton link...");
151            // Write skeleton link
152            writeSkeletonLink(pMesh->getSkeletonName());
153            LogManager::getSingleton().logMessage("Skeleton link exported.");
154
155            // Write bone assignments
156            if (!pMesh->mBoneAssignments.empty())
157            {
158                LogManager::getSingleton().logMessage("Exporting shared geometry bone assignments...");
159
160                Mesh::VertexBoneAssignmentList::const_iterator vi;
161                for (vi = pMesh->mBoneAssignments.begin();
162                vi != pMesh->mBoneAssignments.end(); ++vi)
163                {
164                    writeMeshBoneAssignment(vi->second);
165                }
166
167                LogManager::getSingleton().logMessage("Shared geometry bone assignments exported.");
168            }
169        }
170
171        // Write LOD data if any
172        if (pMesh->getNumLodLevels() > 1)
173        {
174            LogManager::getSingleton().logMessage("Exporting LOD information....");
175            writeLodInfo(pMesh);
176            LogManager::getSingleton().logMessage("LOD information exported.");
177
178        }
179        // Write bounds information
180        LogManager::getSingleton().logMessage("Exporting bounds information....");
181        writeBoundsInfo(pMesh);
182        LogManager::getSingleton().logMessage("Bounds information exported.");
183
184                // Write submesh name table
185                LogManager::getSingleton().logMessage("Exporting submesh name table...");
186                writeSubMeshNameTable(pMesh);
187                LogManager::getSingleton().logMessage("Submesh name table exported.");
188
189                // Write edge lists
190                if (pMesh->isEdgeListBuilt())
191                {
192                        LogManager::getSingleton().logMessage("Exporting edge lists...");
193                        writeEdgeList(pMesh);
194                        LogManager::getSingleton().logMessage("Edge lists exported");
195                }
196
197                // Write morph animation
198                writePoses(pMesh);
199                if (pMesh->hasVertexAnimation())
200                {
201                        writeAnimations(pMesh);
202        }
203
204        // Write submesh extremes
205        writeExtremes(pMesh);
206    }
207    //---------------------------------------------------------------------
208        // Added by DrEvil
209        void MeshSerializerImpl::writeSubMeshNameTable(const Mesh* pMesh)
210        {
211                // Header
212                writeChunkHeader(M_SUBMESH_NAME_TABLE, calcSubMeshNameTableSize(pMesh));
213
214                // Loop through and save out the index and names.
215                Mesh::SubMeshNameMap::const_iterator it = pMesh->mSubMeshNameMap.begin();
216
217                while(it != pMesh->mSubMeshNameMap.end())
218                {
219                        // Header
220                        writeChunkHeader(M_SUBMESH_NAME_TABLE_ELEMENT, STREAM_OVERHEAD_SIZE +
221                                sizeof(unsigned short) + (unsigned long)it->first.length() + 1);
222
223                        // write the index
224                        writeShorts(&it->second, 1);
225                        // name
226                writeString(it->first);
227
228                        ++it;
229                }
230        }
231    //---------------------------------------------------------------------
232    void MeshSerializerImpl::writeSubMesh(const SubMesh* s)
233    {
234        // Header
235        writeChunkHeader(M_SUBMESH, calcSubMeshSize(s));
236
237        // char* materialName
238        writeString(s->getMaterialName());
239
240        // bool useSharedVertices
241        writeBools(&s->useSharedVertices, 1);
242
243                unsigned int indexCount = s->indexData->indexCount;
244        writeInts(&indexCount, 1);
245
246        // bool indexes32Bit
247        bool idx32bit = (s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
248        writeBools(&idx32bit, 1);
249
250        // unsigned short* faceVertexIndices ((indexCount)
251        HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer;
252        void* pIdx = ibuf->lock(HardwareBuffer::HBL_READ_ONLY);
253        if (idx32bit)
254        {
255            unsigned int* pIdx32 = static_cast<unsigned int*>(pIdx);
256            writeInts(pIdx32, s->indexData->indexCount);
257        }
258        else
259        {
260            unsigned short* pIdx16 = static_cast<unsigned short*>(pIdx);
261            writeShorts(pIdx16, s->indexData->indexCount);
262        }
263        ibuf->unlock();
264
265        // M_GEOMETRY stream (Optional: present only if useSharedVertices = false)
266        if (!s->useSharedVertices)
267        {
268            writeGeometry(s->vertexData);
269        }
270
271        // end of sub mesh chunk
272
273        // write out texture alias chunks
274        writeSubMeshTextureAliases(s);
275
276        // Operation type
277        writeSubMeshOperation(s);
278
279        // Bone assignments
280        if (!s->mBoneAssignments.empty())
281        {
282            LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");
283
284            SubMesh::VertexBoneAssignmentList::const_iterator vi;
285            for (vi = s->mBoneAssignments.begin();
286            vi != s->mBoneAssignments.end(); ++vi)
287            {
288                writeSubMeshBoneAssignment(vi->second);
289            }
290
291            LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported.");
292        }
293
294
295    }
296    //---------------------------------------------------------------------
297    void MeshSerializerImpl::writeExtremes(const Mesh *pMesh)
298    {
299        bool has_extremes = false;
300        for (int i = 0; i < pMesh->getNumSubMeshes(); ++i)
301        {
302            SubMesh *sm = pMesh->getSubMesh(i);
303            if (sm->extremityPoints.empty())
304                continue;
305            if (!has_extremes)
306            {
307                has_extremes = true;
308                LogManager::getSingleton().logMessage("Writing submesh extremes...");
309            }
310            writeSubMeshExtremes(i, sm);
311        }
312        if (has_extremes)
313            LogManager::getSingleton().logMessage("Extremes exported.");
314    }
315    //---------------------------------------------------------------------
316    void MeshSerializerImpl::writeSubMeshExtremes(unsigned short idx, const SubMesh* s)
317    {
318        size_t chunkSize = STREAM_OVERHEAD_SIZE + sizeof (unsigned short) +
319            s->extremityPoints.size () * sizeof (float) * 3;
320        writeChunkHeader(M_TABLE_EXTREMES, chunkSize);
321
322        writeShorts(&idx, 1);
323
324        float *vertices = new float [s->extremityPoints.size() * 3];
325                float *pVert = vertices;
326
327        for (std::vector<Vector3>::const_iterator i = s->extremityPoints.begin();
328             i != s->extremityPoints.end(); ++i)
329        {
330                        *pVert++ = i->x;
331                        *pVert++ = i->y;
332                        *pVert++ = i->z;
333        }
334
335        writeFloats(vertices, s->extremityPoints.size () * 3);
336        delete [] vertices;
337    }
338    //---------------------------------------------------------------------
339    void MeshSerializerImpl::writeSubMeshTextureAliases(const SubMesh* s)
340    {
341        size_t chunkSize;
342        AliasTextureNamePairList::const_iterator i;
343
344                LogManager::getSingleton().logMessage("Exporting submesh texture aliases...");
345
346        // iterate through texture aliases and write them out as a chunk
347        for (i = s->mTextureAliases.begin(); i != s->mTextureAliases.end(); ++i)
348        {
349            // calculate chunk size based on string length + 1.  Add 1 for the line feed.
350            chunkSize = STREAM_OVERHEAD_SIZE + i->first.length() + i->second.length() + 2;
351                        writeChunkHeader(M_SUBMESH_TEXTURE_ALIAS, chunkSize);
352            // write out alias name
353            writeString(i->first);
354            // write out texture name
355            writeString(i->second);
356        }
357
358                LogManager::getSingleton().logMessage("Submesh texture aliases exported.");
359    }
360
361    //---------------------------------------------------------------------
362    void MeshSerializerImpl::writeSubMeshOperation(const SubMesh* sm)
363    {
364        // Header
365        writeChunkHeader(M_SUBMESH_OPERATION, calcSubMeshOperationSize(sm));
366
367        // unsigned short operationType
368        unsigned short opType = static_cast<unsigned short>(sm->operationType);
369        writeShorts(&opType, 1);
370    }
371    //---------------------------------------------------------------------
372    void MeshSerializerImpl::writeGeometry(const VertexData* vertexData)
373    {
374                // calc size
375        const VertexDeclaration::VertexElementList& elemList =
376            vertexData->vertexDeclaration->getElements();
377        const VertexBufferBinding::VertexBufferBindingMap& bindings =
378            vertexData->vertexBufferBinding->getBindings();
379        VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbiend;
380
381                size_t size = STREAM_OVERHEAD_SIZE + sizeof(unsigned int) + // base
382                        (STREAM_OVERHEAD_SIZE + elemList.size() * (STREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5)); // elements
383        vbiend = bindings.end();
384                for (vbi = bindings.begin(); vbi != vbiend; ++vbi)
385                {
386                        const HardwareVertexBufferSharedPtr& vbuf = vbi->second;
387                        size += (STREAM_OVERHEAD_SIZE * 2) + (sizeof(unsigned short) * 2) + vbuf->getSizeInBytes();
388                }
389
390                // Header
391        writeChunkHeader(M_GEOMETRY, size);
392
393        unsigned int vertexCount = vertexData->vertexCount;
394        writeInts(&vertexCount, 1);
395
396                // Vertex declaration
397                size = STREAM_OVERHEAD_SIZE + elemList.size() * (STREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5);
398                writeChunkHeader(M_GEOMETRY_VERTEX_DECLARATION, size);
399
400        VertexDeclaration::VertexElementList::const_iterator vei, veiend;
401                veiend = elemList.end();
402                unsigned short tmp;
403                size = STREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5;
404                for (vei = elemList.begin(); vei != veiend; ++vei)
405                {
406                        const VertexElement& elem = *vei;
407                        writeChunkHeader(M_GEOMETRY_VERTEX_ELEMENT, size);
408                        // unsigned short source;       // buffer bind source
409                        tmp = elem.getSource();
410                        writeShorts(&tmp, 1);
411                        // unsigned short type;         // VertexElementType
412                        tmp = static_cast<unsigned short>(elem.getType());
413                        writeShorts(&tmp, 1);
414                        // unsigned short semantic; // VertexElementSemantic
415                        tmp = static_cast<unsigned short>(elem.getSemantic());
416                        writeShorts(&tmp, 1);
417                        // unsigned short offset;       // start offset in buffer in bytes
418                        tmp = static_cast<unsigned short>(elem.getOffset());
419                        writeShorts(&tmp, 1);
420                        // unsigned short index;        // index of the semantic (for colours and texture coords)
421                        tmp = elem.getIndex();
422                        writeShorts(&tmp, 1);
423
424                }
425
426                // Buffers and bindings
427                vbiend = bindings.end();
428                for (vbi = bindings.begin(); vbi != vbiend; ++vbi)
429                {
430                        const HardwareVertexBufferSharedPtr& vbuf = vbi->second;
431                        size = (STREAM_OVERHEAD_SIZE * 2) + (sizeof(unsigned short) * 2) + vbuf->getSizeInBytes();
432                        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER,  size);
433                        // unsigned short bindIndex;    // Index to bind this buffer to
434                        tmp = vbi->first;
435                        writeShorts(&tmp, 1);
436                        // unsigned short vertexSize;   // Per-vertex size, must agree with declaration at this index
437                        tmp = (unsigned short)vbuf->getVertexSize();
438                        writeShorts(&tmp, 1);
439
440                        // Data
441                        size = STREAM_OVERHEAD_SIZE + vbuf->getSizeInBytes();
442                        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
443                        void* pBuf = vbuf->lock(HardwareBuffer::HBL_READ_ONLY);
444
445                        if (mFlipEndian)
446                        {
447                                // endian conversion
448                                // Copy data
449                                unsigned char* tempData = new unsigned char[vbuf->getSizeInBytes()];
450                                memcpy(tempData, pBuf, vbuf->getSizeInBytes());
451                                flipToLittleEndian(
452                                        tempData,
453                                        vertexData->vertexCount,
454                                        vbuf->getVertexSize(),
455                                        vertexData->vertexDeclaration->findElementsBySource(vbi->first));
456                                writeData(tempData, vbuf->getVertexSize(), vertexData->vertexCount);
457                                delete [] tempData;
458                        }
459                        else
460                        {
461                                writeData(pBuf, vbuf->getVertexSize(), vertexData->vertexCount);
462                        }
463            vbuf->unlock();
464                }
465
466
467    }
468    //---------------------------------------------------------------------
469        size_t MeshSerializerImpl::calcSubMeshNameTableSize(const Mesh* pMesh)
470        {
471                size_t size = STREAM_OVERHEAD_SIZE;
472                // Figure out the size of the Name table.
473                // Iterate through the subMeshList & add up the size of the indexes and names.
474                Mesh::SubMeshNameMap::const_iterator it = pMesh->mSubMeshNameMap.begin();
475                while(it != pMesh->mSubMeshNameMap.end())
476                {
477                        // size of the index + header size for each element chunk
478                        size += STREAM_OVERHEAD_SIZE + sizeof(uint16);
479                        // name
480                        size += it->first.length() + 1;
481
482                        ++it;
483                }
484
485                // size of the sub-mesh name table.
486                return size;
487        }
488    //---------------------------------------------------------------------
489    size_t MeshSerializerImpl::calcMeshSize(const Mesh* pMesh)
490    {
491        size_t size = STREAM_OVERHEAD_SIZE;
492
493        // Num shared vertices
494        size += sizeof(uint32);
495
496        // Geometry
497        if (pMesh->sharedVertexData && pMesh->sharedVertexData->vertexCount > 0)
498        {
499            size += calcGeometrySize(pMesh->sharedVertexData);
500        }
501
502        // Submeshes
503        for (unsigned short i = 0; i < pMesh->getNumSubMeshes(); ++i)
504        {
505            size += calcSubMeshSize(pMesh->getSubMesh(i));
506        }
507
508        // Skeleton link
509        if (pMesh->hasSkeleton())
510        {
511            size += calcSkeletonLinkSize(pMesh->getSkeletonName());
512        }
513
514                // Submesh name table
515                size += calcSubMeshNameTableSize(pMesh);
516
517                // Edge list
518                if (pMesh->isEdgeListBuilt())
519                {
520                        size += calcEdgeListSize(pMesh);
521                }
522
523                // Animations
524                for (unsigned short a = 0; a < pMesh->getNumAnimations(); ++a)
525                {
526                        Animation* anim = pMesh->getAnimation(a);
527                        size += calcAnimationSize(anim);
528                }
529
530                return size;
531    }
532    //---------------------------------------------------------------------
533    size_t MeshSerializerImpl::calcSubMeshSize(const SubMesh* pSub)
534    {
535        size_t size = STREAM_OVERHEAD_SIZE;
536
537        // Material name
538        size += pSub->getMaterialName().length() + 1;
539
540        // bool useSharedVertices
541        size += sizeof(bool);
542        // unsigned int indexCount
543        size += sizeof(unsigned int);
544        // bool indexes32bit
545        size += sizeof(bool);
546        // unsigned int* faceVertexIndices
547        size += sizeof(unsigned int) * pSub->indexData->indexCount;
548
549        // Geometry
550        if (!pSub->useSharedVertices)
551        {
552            size += calcGeometrySize(pSub->vertexData);
553        }
554
555        size += calcSubMeshTextureAliasesSize(pSub);
556        size += calcSubMeshOperationSize(pSub);
557
558        // Bone assignments
559        if (!pSub->mBoneAssignments.empty())
560        {
561            SubMesh::VertexBoneAssignmentList::const_iterator vi;
562            for (vi = pSub->mBoneAssignments.begin();
563                 vi != pSub->mBoneAssignments.end(); ++vi)
564            {
565                size += calcBoneAssignmentSize();
566            }
567        }
568
569        return size;
570    }
571    //---------------------------------------------------------------------
572    size_t MeshSerializerImpl::calcSubMeshOperationSize(const SubMesh* pSub)
573    {
574        return STREAM_OVERHEAD_SIZE + sizeof(uint16);
575    }
576    //---------------------------------------------------------------------
577    size_t MeshSerializerImpl::calcSubMeshTextureAliasesSize(const SubMesh* pSub)
578    {
579        size_t chunkSize = 0;
580        AliasTextureNamePairList::const_iterator i;
581
582        // iterate through texture alias map and calc size of strings
583        for (i = pSub->mTextureAliases.begin(); i != pSub->mTextureAliases.end(); ++i)
584        {
585            // calculate chunk size based on string length + 1.  Add 1 for the line feed.
586            chunkSize += STREAM_OVERHEAD_SIZE + i->first.length() + i->second.length() + 2;
587        }
588
589        return chunkSize;
590    }
591    //---------------------------------------------------------------------
592    size_t MeshSerializerImpl::calcGeometrySize(const VertexData* vertexData)
593    {
594        size_t size = STREAM_OVERHEAD_SIZE;
595
596        // Num vertices
597        size += sizeof(unsigned int);
598
599        const VertexDeclaration::VertexElementList& elems =
600            vertexData->vertexDeclaration->getElements();
601
602        VertexDeclaration::VertexElementList::const_iterator i, iend;
603        iend = elems.end();
604        for (i = elems.begin(); i != iend; ++i)
605        {
606            const VertexElement& elem = *i;
607            // Vertex element
608            size += VertexElement::getTypeSize(elem.getType()) * vertexData->vertexCount;
609        }
610        return size;
611    }
612    //---------------------------------------------------------------------
613    void MeshSerializerImpl::readGeometry(DataStreamPtr& stream, Mesh* pMesh,
614        VertexData* dest)
615    {
616
617        dest->vertexStart = 0;
618
619        unsigned int vertexCount = 0;
620        readInts(stream, &vertexCount, 1);
621        dest->vertexCount = vertexCount;
622
623        // Find optional geometry streams
624        if (!stream->eof())
625        {
626            unsigned short streamID = readChunk(stream);
627            while(!stream->eof() &&
628                (streamID == M_GEOMETRY_VERTEX_DECLARATION ||
629                 streamID == M_GEOMETRY_VERTEX_BUFFER ))
630            {
631                switch (streamID)
632                {
633                case M_GEOMETRY_VERTEX_DECLARATION:
634                    readGeometryVertexDeclaration(stream, pMesh, dest);
635                    break;
636                case M_GEOMETRY_VERTEX_BUFFER:
637                    readGeometryVertexBuffer(stream, pMesh, dest);
638                    break;
639                }
640                // Get next stream
641                if (!stream->eof())
642                {
643                    streamID = readChunk(stream);
644                }
645            }
646            if (!stream->eof())
647            {
648                // Backpedal back to start of non-submesh stream
649                stream->skip(-STREAM_OVERHEAD_SIZE);
650            }
651        }
652
653                // Perform any necessary colour conversion for an active rendersystem
654                if (Root::getSingletonPtr() && Root::getSingleton().getRenderSystem())
655                {
656                        // We don't know the source type if it's VET_COLOUR, but assume ARGB
657                        // since that's the most common. Won't get used unless the mesh is
658                        // ambiguous anyway, which will have been warned about in the log
659                        dest->convertPackedColour(VET_COLOUR_ARGB, 
660                                VertexElement::getBestColourVertexElementType());
661                }
662    }
663    //---------------------------------------------------------------------
664    void MeshSerializerImpl::readGeometryVertexDeclaration(DataStreamPtr& stream,
665        Mesh* pMesh, VertexData* dest)
666    {
667        // Find optional geometry streams
668        if (!stream->eof())
669        {
670            unsigned short streamID = readChunk(stream);
671            while(!stream->eof() &&
672                (streamID == M_GEOMETRY_VERTEX_ELEMENT ))
673            {
674                switch (streamID)
675                {
676                case M_GEOMETRY_VERTEX_ELEMENT:
677                    readGeometryVertexElement(stream, pMesh, dest);
678                    break;
679                }
680                // Get next stream
681                if (!stream->eof())
682                {
683                    streamID = readChunk(stream);
684                }
685            }
686            if (!stream->eof())
687            {
688                // Backpedal back to start of non-submesh stream
689                stream->skip(-STREAM_OVERHEAD_SIZE);
690            }
691        }
692
693        }
694    //---------------------------------------------------------------------
695    void MeshSerializerImpl::readGeometryVertexElement(DataStreamPtr& stream,
696        Mesh* pMesh, VertexData* dest)
697    {
698                unsigned short source, offset, index, tmp;
699                VertexElementType vType;
700                VertexElementSemantic vSemantic;
701                // unsigned short source;       // buffer bind source
702                readShorts(stream, &source, 1);
703                // unsigned short type;         // VertexElementType
704                readShorts(stream, &tmp, 1);
705                vType = static_cast<VertexElementType>(tmp);
706                // unsigned short semantic; // VertexElementSemantic
707                readShorts(stream, &tmp, 1);
708                vSemantic = static_cast<VertexElementSemantic>(tmp);
709                // unsigned short offset;       // start offset in buffer in bytes
710                readShorts(stream, &offset, 1);
711                // unsigned short index;        // index of the semantic
712                readShorts(stream, &index, 1);
713
714                dest->vertexDeclaration->addElement(source, offset, vType, vSemantic, index);
715
716                if (vType == VET_COLOUR)
717                {
718                        StringUtil::StrStreamType s;
719                        s << "Warning: VET_COLOUR element type is deprecated, you should use "
720                                << "one of the more specific types to indicate the byte order. "
721                                << "Use OgreMeshUpgrade on " << pMesh->getName() << " as soon as possible. ";
722                        LogManager::getSingleton().logMessage(s.str());
723                }
724
725        }
726    //---------------------------------------------------------------------
727    void MeshSerializerImpl::readGeometryVertexBuffer(DataStreamPtr& stream,
728        Mesh* pMesh, VertexData* dest)
729    {
730                unsigned short bindIndex, vertexSize;
731                // unsigned short bindIndex;    // Index to bind this buffer to
732                readShorts(stream, &bindIndex, 1);
733                // unsigned short vertexSize;   // Per-vertex size, must agree with declaration at this index
734                readShorts(stream, &vertexSize, 1);
735
736                // Check for vertex data header
737                unsigned short headerID;
738                headerID = readChunk(stream);
739                if (headerID != M_GEOMETRY_VERTEX_BUFFER_DATA)
740                {
741                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Can't find vertex buffer data area",
742                "MeshSerializerImpl::readGeometryVertexBuffer");
743                }
744                // Check that vertex size agrees
745                if (dest->vertexDeclaration->getVertexSize(bindIndex) != vertexSize)
746                {
747                        OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Buffer vertex size does not agree with vertex declaration",
748                "MeshSerializerImpl::readGeometryVertexBuffer");
749                }
750
751                // Create / populate vertex buffer
752                HardwareVertexBufferSharedPtr vbuf;
753        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
754            vertexSize,
755            dest->vertexCount,
756            pMesh->mVertexBufferUsage,
757                        pMesh->mVertexBufferShadowBuffer);
758        void* pBuf = vbuf->lock(HardwareBuffer::HBL_DISCARD);
759        stream->read(pBuf, dest->vertexCount * vertexSize);
760
761                // endian conversion for OSX
762                flipFromLittleEndian(
763                        pBuf,
764                        dest->vertexCount,
765                        vertexSize,
766                        dest->vertexDeclaration->findElementsBySource(bindIndex));
767        vbuf->unlock();
768
769                // Set binding
770        dest->vertexBufferBinding->setBinding(bindIndex, vbuf);
771
772        }
773    //---------------------------------------------------------------------
774        void MeshSerializerImpl::readSubMeshNameTable(DataStreamPtr& stream, Mesh* pMesh)
775        {
776                // The map for
777                std::map<unsigned short, String> subMeshNames;
778                unsigned short streamID, subMeshIndex;
779
780                // Need something to store the index, and the objects name
781                // This table is a method that imported meshes can retain their naming
782                // so that the names established in the modelling software can be used
783                // to get the sub-meshes by name. The exporter must support exporting
784                // the optional stream M_SUBMESH_NAME_TABLE.
785
786        // Read in all the sub-streams. Each sub-stream should contain an index and Ogre::String for the name.
787                if (!stream->eof())
788                {
789                        streamID = readChunk(stream);
790                        while(!stream->eof() && (streamID == M_SUBMESH_NAME_TABLE_ELEMENT ))
791                        {
792                                // Read in the index of the submesh.
793                                readShorts(stream, &subMeshIndex, 1);
794                                // Read in the String and map it to its index.
795                                subMeshNames[subMeshIndex] = readString(stream);
796
797                                // If we're not end of file get the next stream ID
798                                if (!stream->eof())
799                                        streamID = readChunk(stream);
800                        }
801                        if (!stream->eof())
802                        {
803                                // Backpedal back to start of stream
804                                stream->skip(-STREAM_OVERHEAD_SIZE);
805                        }
806                }
807
808                // Set all the submeshes names
809                // ?
810
811                // Loop through and save out the index and names.
812                std::map<unsigned short, String>::const_iterator it = subMeshNames.begin();
813
814                while(it != subMeshNames.end())
815                {
816                        // Name this submesh to the stored name.
817                        pMesh->nameSubMesh(it->second, it->first);
818                        ++it;
819                }
820
821
822
823        }
824    //---------------------------------------------------------------------
825    void MeshSerializerImpl::readMesh(DataStreamPtr& stream, Mesh* pMesh)
826    {
827        unsigned short streamID;
828
829        // Never automatically build edge lists for this version
830        // expect them in the file or not at all
831        pMesh->mAutoBuildEdgeLists = false;
832
833                // bool skeletallyAnimated
834                bool skeletallyAnimated;
835                readBools(stream, &skeletallyAnimated, 1);
836
837        // Find all substreams
838        if (!stream->eof())
839        {
840            streamID = readChunk(stream);
841            while(!stream->eof() &&
842                (streamID == M_GEOMETRY ||
843                                 streamID == M_SUBMESH ||
844                 streamID == M_MESH_SKELETON_LINK ||
845                 streamID == M_MESH_BONE_ASSIGNMENT ||
846                                 streamID == M_MESH_LOD ||
847                 streamID == M_MESH_BOUNDS ||
848                                 streamID == M_SUBMESH_NAME_TABLE ||
849                                 streamID == M_EDGE_LISTS ||
850                                 streamID == M_POSES ||
851                                 streamID == M_ANIMATIONS ||
852                                 streamID == M_TABLE_EXTREMES))
853            {
854                switch(streamID)
855                {
856                                case M_GEOMETRY:
857                                        pMesh->sharedVertexData = new VertexData();
858                                        try {
859                                                readGeometry(stream, pMesh, pMesh->sharedVertexData);
860                                        }
861                                        catch (Exception& e)
862                                        {
863                                                if (e.getNumber() == Exception::ERR_ITEM_NOT_FOUND)
864                                                {
865                                                        // duff geometry data entry with 0 vertices
866                                                        delete pMesh->sharedVertexData;
867                                                        pMesh->sharedVertexData = 0;
868                                                        // Skip this stream (pointer will have been returned to just after header)
869                                                        stream->skip(mCurrentstreamLen - STREAM_OVERHEAD_SIZE);
870                                                }
871                                                else
872                                                {
873                                                        throw;
874                                                }
875                                        }
876                                        break;
877                case M_SUBMESH:
878                    readSubMesh(stream, pMesh);
879                    break;
880                case M_MESH_SKELETON_LINK:
881                    readSkeletonLink(stream, pMesh);
882                    break;
883                case M_MESH_BONE_ASSIGNMENT:
884                    readMeshBoneAssignment(stream, pMesh);
885                    break;
886                case M_MESH_LOD:
887                                        readMeshLodInfo(stream, pMesh);
888                                        break;
889                case M_MESH_BOUNDS:
890                    readBoundsInfo(stream, pMesh);
891                    break;
892                                case M_SUBMESH_NAME_TABLE:
893                    readSubMeshNameTable(stream, pMesh);
894                                        break;
895                case M_EDGE_LISTS:
896                    readEdgeList(stream, pMesh);
897                    break;
898                                case M_POSES:
899                                        readPoses(stream, pMesh);
900                                        break;
901                                case M_ANIMATIONS:
902                                        readAnimations(stream, pMesh);
903                    break;
904                case M_TABLE_EXTREMES:
905                    readExtremes(stream, pMesh);
906                    break;
907                }
908
909                if (!stream->eof())
910                {
911                    streamID = readChunk(stream);
912                }
913
914            }
915            if (!stream->eof())
916            {
917                // Backpedal back to start of stream
918                stream->skip(-STREAM_OVERHEAD_SIZE);
919            }
920        }
921
922    }
923    //---------------------------------------------------------------------
924    void MeshSerializerImpl::readSubMesh(DataStreamPtr& stream, Mesh* pMesh)
925    {
926        unsigned short streamID;
927
928        SubMesh* sm = pMesh->createSubMesh();
929        // char* materialName
930        String materialName = readString(stream);
931        sm->setMaterialName(materialName);
932        // bool useSharedVertices
933        readBools(stream,&sm->useSharedVertices, 1);
934
935        sm->indexData->indexStart = 0;
936        unsigned int indexCount = 0;
937        readInts(stream, &indexCount, 1);
938        sm->indexData->indexCount = indexCount;
939
940        HardwareIndexBufferSharedPtr ibuf;
941        // bool indexes32Bit
942        bool idx32bit;
943        readBools(stream, &idx32bit, 1);
944        if (idx32bit)
945        {
946            ibuf = HardwareBufferManager::getSingleton().
947                createIndexBuffer(
948                    HardwareIndexBuffer::IT_32BIT,
949                    sm->indexData->indexCount,
950                    pMesh->mIndexBufferUsage,
951                                        pMesh->mIndexBufferShadowBuffer);
952            // unsigned int* faceVertexIndices
953            unsigned int* pIdx = static_cast<unsigned int*>(
954                ibuf->lock(HardwareBuffer::HBL_DISCARD)
955                );
956            readInts(stream, pIdx, sm->indexData->indexCount);
957            ibuf->unlock();
958
959        }
960        else // 16-bit
961        {
962            ibuf = HardwareBufferManager::getSingleton().
963                createIndexBuffer(
964                    HardwareIndexBuffer::IT_16BIT,
965                    sm->indexData->indexCount,
966                    pMesh->mIndexBufferUsage,
967                                        pMesh->mIndexBufferShadowBuffer);
968            // unsigned short* faceVertexIndices
969            unsigned short* pIdx = static_cast<unsigned short*>(
970                ibuf->lock(HardwareBuffer::HBL_DISCARD)
971                );
972            readShorts(stream, pIdx, sm->indexData->indexCount);
973            ibuf->unlock();
974        }
975        sm->indexData->indexBuffer = ibuf;
976
977        // M_GEOMETRY stream (Optional: present only if useSharedVertices = false)
978        if (!sm->useSharedVertices)
979        {
980            streamID = readChunk(stream);
981            if (streamID != M_GEOMETRY)
982            {
983                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Missing geometry data in mesh file",
984                    "MeshSerializerImpl::readSubMesh");
985            }
986            sm->vertexData = new VertexData();
987            readGeometry(stream, pMesh, sm->vertexData);
988        }
989
990
991        // Find all bone assignments, submesh operation, and texture aliases (if present)
992        if (!stream->eof())
993        {
994            streamID = readChunk(stream);
995            while(!stream->eof() &&
996                (streamID == M_SUBMESH_BONE_ASSIGNMENT ||
997                 streamID == M_SUBMESH_OPERATION ||
998                 streamID == M_SUBMESH_TEXTURE_ALIAS))
999            {
1000                switch(streamID)
1001                {
1002                case M_SUBMESH_OPERATION:
1003                    readSubMeshOperation(stream, pMesh, sm);
1004                    break;
1005                case M_SUBMESH_BONE_ASSIGNMENT:
1006                    readSubMeshBoneAssignment(stream, pMesh, sm);
1007                    break;
1008                case M_SUBMESH_TEXTURE_ALIAS:
1009                    readSubMeshTextureAlias(stream, pMesh, sm);
1010                    break;
1011                }
1012
1013                if (!stream->eof())
1014                {
1015                    streamID = readChunk(stream);
1016                }
1017
1018            }
1019            if (!stream->eof())
1020            {
1021                // Backpedal back to start of stream
1022                stream->skip(-STREAM_OVERHEAD_SIZE);
1023            }
1024        }
1025
1026
1027    }
1028    //---------------------------------------------------------------------
1029    void MeshSerializerImpl::readSubMeshOperation(DataStreamPtr& stream,
1030        Mesh* pMesh, SubMesh* sm)
1031    {
1032        // unsigned short operationType
1033        unsigned short opType;
1034        readShorts(stream, &opType, 1);
1035        sm->operationType = static_cast<RenderOperation::OperationType>(opType);
1036    }
1037    //---------------------------------------------------------------------
1038    void MeshSerializerImpl::readSubMeshTextureAlias(DataStreamPtr& stream, Mesh* pMesh, SubMesh* sub)
1039    {
1040        String aliasName = readString(stream);
1041        String textureName = readString(stream);
1042        sub->addTextureAlias(aliasName, textureName);
1043    }
1044    //---------------------------------------------------------------------
1045    void MeshSerializerImpl::writeSkeletonLink(const String& skelName)
1046    {
1047        writeChunkHeader(M_MESH_SKELETON_LINK, calcSkeletonLinkSize(skelName));
1048
1049        writeString(skelName);
1050
1051    }
1052    //---------------------------------------------------------------------
1053    void MeshSerializerImpl::readSkeletonLink(DataStreamPtr& stream, Mesh* pMesh)
1054    {
1055        String skelName = readString(stream);
1056        pMesh->setSkeletonName(skelName);
1057    }
1058    //---------------------------------------------------------------------
1059    void MeshSerializerImpl::readTextureLayer(DataStreamPtr& stream, Mesh* pMesh,
1060        MaterialPtr& pMat)
1061    {
1062        // Material definition section phased out of 1.1
1063    }
1064    //---------------------------------------------------------------------
1065    size_t MeshSerializerImpl::calcSkeletonLinkSize(const String& skelName)
1066    {
1067        size_t size = STREAM_OVERHEAD_SIZE;
1068
1069        size += skelName.length() + 1;
1070
1071        return size;
1072
1073    }
1074    //---------------------------------------------------------------------
1075    void MeshSerializerImpl::writeMeshBoneAssignment(const VertexBoneAssignment& assign)
1076    {
1077        writeChunkHeader(M_MESH_BONE_ASSIGNMENT, calcBoneAssignmentSize());
1078
1079        // unsigned int vertexIndex;
1080        writeInts(&(assign.vertexIndex), 1);
1081        // unsigned short boneIndex;
1082        writeShorts(&(assign.boneIndex), 1);
1083        // float weight;
1084        writeFloats(&(assign.weight), 1);
1085    }
1086    //---------------------------------------------------------------------
1087    void MeshSerializerImpl::writeSubMeshBoneAssignment(const VertexBoneAssignment& assign)
1088    {
1089        writeChunkHeader(M_SUBMESH_BONE_ASSIGNMENT, calcBoneAssignmentSize());
1090
1091        // unsigned int vertexIndex;
1092        writeInts(&(assign.vertexIndex), 1);
1093        // unsigned short boneIndex;
1094        writeShorts(&(assign.boneIndex), 1);
1095        // float weight;
1096        writeFloats(&(assign.weight), 1);
1097    }
1098    //---------------------------------------------------------------------
1099    void MeshSerializerImpl::readMeshBoneAssignment(DataStreamPtr& stream, Mesh* pMesh)
1100    {
1101        VertexBoneAssignment assign;
1102
1103        // unsigned int vertexIndex;
1104        readInts(stream, &(assign.vertexIndex),1);
1105        // unsigned short boneIndex;
1106        readShorts(stream, &(assign.boneIndex),1);
1107        // float weight;
1108        readFloats(stream, &(assign.weight), 1);
1109
1110        pMesh->addBoneAssignment(assign);
1111
1112    }
1113    //---------------------------------------------------------------------
1114    void MeshSerializerImpl::readSubMeshBoneAssignment(DataStreamPtr& stream,
1115        Mesh* pMesh, SubMesh* sub)
1116    {
1117        VertexBoneAssignment assign;
1118
1119        // unsigned int vertexIndex;
1120        readInts(stream, &(assign.vertexIndex),1);
1121        // unsigned short boneIndex;
1122        readShorts(stream, &(assign.boneIndex),1);
1123        // float weight;
1124        readFloats(stream, &(assign.weight), 1);
1125
1126        sub->addBoneAssignment(assign);
1127
1128    }
1129    //---------------------------------------------------------------------
1130    size_t MeshSerializerImpl::calcBoneAssignmentSize(void)
1131    {
1132        size_t size = STREAM_OVERHEAD_SIZE;
1133
1134        // Vert index
1135        size += sizeof(unsigned int);
1136        // Bone index
1137        size += sizeof(unsigned short);
1138        // weight
1139        size += sizeof(float);
1140
1141        return size;
1142    }
1143    //---------------------------------------------------------------------
1144    void MeshSerializerImpl::writeLodInfo(const Mesh* pMesh)
1145    {
1146        unsigned short numLods = pMesh->getNumLodLevels();
1147        bool manual = pMesh->isLodManual();
1148        writeLodSummary(numLods, manual);
1149
1150                // Loop from LOD 1 (not 0, this is full detail)
1151        for (unsigned short i = 1; i < numLods; ++i)
1152        {
1153                        const MeshLodUsage& usage = pMesh->getLodLevel(i);
1154                        if (manual)
1155                        {
1156                                writeLodUsageManual(usage);
1157                        }
1158                        else
1159                        {
1160                                writeLodUsageGenerated(pMesh, usage, i);
1161                        }
1162
1163        }
1164
1165
1166    }
1167    //---------------------------------------------------------------------
1168    void MeshSerializerImpl::writeLodSummary(unsigned short numLevels, bool manual)
1169    {
1170        // Header
1171        size_t size = STREAM_OVERHEAD_SIZE;
1172        // unsigned short numLevels;
1173        size += sizeof(unsigned short);
1174        // bool manual;  (true for manual alternate meshes, false for generated)
1175        size += sizeof(bool);
1176        writeChunkHeader(M_MESH_LOD, size);
1177
1178        // Details
1179        // unsigned short numLevels;
1180        writeShorts(&numLevels, 1);
1181        // bool manual;  (true for manual alternate meshes, false for generated)
1182        writeBools(&manual, 1);
1183
1184
1185    }
1186    //---------------------------------------------------------------------
1187    void MeshSerializerImpl::writeLodUsageManual(const MeshLodUsage& usage)
1188    {
1189        // Header
1190        size_t size = STREAM_OVERHEAD_SIZE;
1191        size_t manualSize = STREAM_OVERHEAD_SIZE;
1192        // float fromDepthSquared;
1193        size += sizeof(float);
1194        // Manual part size
1195
1196        // String manualMeshName;
1197        manualSize += usage.manualName.length() + 1;
1198
1199        size += manualSize;
1200
1201        writeChunkHeader(M_MESH_LOD_USAGE, size);
1202        writeFloats(&(usage.fromDepthSquared), 1);
1203
1204        writeChunkHeader(M_MESH_LOD_MANUAL, manualSize);
1205        writeString(usage.manualName);
1206
1207
1208    }
1209    //---------------------------------------------------------------------
1210    void MeshSerializerImpl::writeLodUsageGenerated(const Mesh* pMesh, const MeshLodUsage& usage,
1211                unsigned short lodNum)
1212    {
1213                // Usage Header
1214        size_t size = STREAM_OVERHEAD_SIZE;
1215                unsigned short subidx;
1216
1217        // float fromDepthSquared;
1218        size += sizeof(float);
1219
1220        // Calc generated SubMesh sections size
1221                for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
1222                {
1223                        // header
1224                        size += STREAM_OVERHEAD_SIZE;
1225                        // unsigned int numFaces;
1226                        size += sizeof(unsigned int);
1227                        SubMesh* sm = pMesh->getSubMesh(subidx);
1228            const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
1229
1230            // bool indexes32Bit
1231                        size += sizeof(bool);
1232                        // unsigned short*/int* faceIndexes;
1233            if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
1234            {
1235                            size += static_cast<unsigned long>(
1236                    sizeof(unsigned int) * indexData->indexCount);
1237            }
1238            else
1239            {
1240                            size += static_cast<unsigned long>(
1241                    sizeof(unsigned short) * indexData->indexCount);
1242            }
1243
1244                }
1245
1246        writeChunkHeader(M_MESH_LOD_USAGE, size);
1247        writeFloats(&(usage.fromDepthSquared), 1);
1248
1249                // Now write sections
1250        // Calc generated SubMesh sections size
1251                for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
1252                {
1253                        size = STREAM_OVERHEAD_SIZE;
1254                        // unsigned int numFaces;
1255                        size += sizeof(unsigned int);
1256                        SubMesh* sm = pMesh->getSubMesh(subidx);
1257            const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
1258            // bool indexes32Bit
1259                        size += sizeof(bool);
1260                        // unsigned short*/int* faceIndexes;
1261            if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
1262            {
1263                            size += static_cast<unsigned long>(
1264                    sizeof(unsigned int) * indexData->indexCount);
1265            }
1266            else
1267            {
1268                            size += static_cast<unsigned long>(
1269                    sizeof(unsigned short) * indexData->indexCount);
1270            }
1271
1272                        writeChunkHeader(M_MESH_LOD_GENERATED, size);
1273                        unsigned int idxCount = static_cast<unsigned int>(indexData->indexCount);
1274                        writeInts(&idxCount, 1);
1275            // Lock index buffer to write
1276            HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
1277                        // bool indexes32bit
1278                        bool idx32 = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
1279                        writeBools(&idx32, 1);
1280            if (idx32)
1281            {
1282                unsigned int* pIdx = static_cast<unsigned int*>(
1283                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1284                            writeInts(pIdx, indexData->indexCount);
1285                ibuf->unlock();
1286            }
1287            else
1288            {
1289                unsigned short* pIdx = static_cast<unsigned short*>(
1290                    ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1291                            writeShorts(pIdx, indexData->indexCount);
1292                ibuf->unlock();
1293            }
1294                }
1295
1296
1297    }
1298    //---------------------------------------------------------------------
1299    void MeshSerializerImpl::writeBoundsInfo(const Mesh* pMesh)
1300    {
1301                // Usage Header
1302        unsigned long size = STREAM_OVERHEAD_SIZE;
1303
1304        size += sizeof(float) * 7;
1305        writeChunkHeader(M_MESH_BOUNDS, size);
1306
1307        // float minx, miny, minz
1308        const Vector3& min = pMesh->mAABB.getMinimum();
1309        const Vector3& max = pMesh->mAABB.getMaximum();
1310        writeFloats(&min.x, 1);
1311        writeFloats(&min.y, 1);
1312        writeFloats(&min.z, 1);
1313        // float maxx, maxy, maxz
1314        writeFloats(&max.x, 1);
1315        writeFloats(&max.y, 1);
1316        writeFloats(&max.z, 1);
1317        // float radius
1318        writeFloats(&pMesh->mBoundRadius, 1);
1319
1320    }
1321    //---------------------------------------------------------------------
1322    void MeshSerializerImpl::readBoundsInfo(DataStreamPtr& stream, Mesh* pMesh)
1323    {
1324        Vector3 min, max;
1325        // float minx, miny, minz
1326        readFloats(stream, &min.x, 1);
1327        readFloats(stream, &min.y, 1);
1328        readFloats(stream, &min.z, 1);
1329        // float maxx, maxy, maxz
1330        readFloats(stream, &max.x, 1);
1331        readFloats(stream, &max.y, 1);
1332        readFloats(stream, &max.z, 1);
1333        AxisAlignedBox box(min, max);
1334        pMesh->_setBounds(box, true);
1335        // float radius
1336        float radius;
1337        readFloats(stream, &radius, 1);
1338        pMesh->_setBoundingSphereRadius(radius);
1339
1340
1341
1342    }
1343    //---------------------------------------------------------------------
1344        void MeshSerializerImpl::readMeshLodInfo(DataStreamPtr& stream, Mesh* pMesh)
1345        {
1346                unsigned short streamID, i;
1347
1348        // unsigned short numLevels;
1349                readShorts(stream, &(pMesh->mNumLods), 1);
1350        // bool manual;  (true for manual alternate meshes, false for generated)
1351                readBools(stream, &(pMesh->mIsLodManual), 1);
1352
1353                // Preallocate submesh lod face data if not manual
1354                if (!pMesh->mIsLodManual)
1355                {
1356                        unsigned short numsubs = pMesh->getNumSubMeshes();
1357                        for (i = 0; i < numsubs; ++i)
1358                        {
1359                                SubMesh* sm = pMesh->getSubMesh(i);
1360                                sm->mLodFaceList.resize(pMesh->mNumLods-1);
1361                        }
1362                }
1363
1364                // Loop from 1 rather than 0 (full detail index is not in file)
1365                for (i = 1; i < pMesh->mNumLods; ++i)
1366                {
1367                        streamID = readChunk(stream);
1368                        if (streamID != M_MESH_LOD_USAGE)
1369                        {
1370                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1371                                        "Missing M_MESH_LOD_USAGE stream in " + pMesh->getName(),
1372                                        "MeshSerializerImpl::readMeshLodInfo");
1373                        }
1374                        // Read depth
1375                        MeshLodUsage usage;
1376                        readFloats(stream, &(usage.fromDepthSquared), 1);
1377
1378                        if (pMesh->isLodManual())
1379                        {
1380                                readMeshLodUsageManual(stream, pMesh, i, usage);
1381                        }
1382                        else //(!pMesh->isLodManual)
1383                        {
1384                                readMeshLodUsageGenerated(stream, pMesh, i, usage);
1385                        }
1386            usage.edgeData = NULL;
1387
1388                        // Save usage
1389                        pMesh->mMeshLodUsageList.push_back(usage);
1390                }
1391
1392
1393        }
1394    //---------------------------------------------------------------------
1395        void MeshSerializerImpl::readMeshLodUsageManual(DataStreamPtr& stream,
1396        Mesh* pMesh, unsigned short lodNum, MeshLodUsage& usage)
1397        {
1398                unsigned long streamID;
1399                // Read detail stream
1400                streamID = readChunk(stream);
1401                if (streamID != M_MESH_LOD_MANUAL)
1402                {
1403                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1404                                "Missing M_MESH_LOD_MANUAL stream in " + pMesh->getName(),
1405                                "MeshSerializerImpl::readMeshLodUsageManual");
1406                }
1407
1408                usage.manualName = readString(stream);
1409                usage.manualMesh.setNull(); // will trigger load later
1410        }
1411    //---------------------------------------------------------------------
1412        void MeshSerializerImpl::readMeshLodUsageGenerated(DataStreamPtr& stream,
1413        Mesh* pMesh, unsigned short lodNum, MeshLodUsage& usage)
1414        {
1415                usage.manualName = "";
1416                usage.manualMesh.setNull();
1417
1418                // Get one set of detail per SubMesh
1419                unsigned short numSubs, i;
1420                unsigned long streamID;
1421                numSubs = pMesh->getNumSubMeshes();
1422                for (i = 0; i < numSubs; ++i)
1423                {
1424                        streamID = readChunk(stream);
1425                        if (streamID != M_MESH_LOD_GENERATED)
1426                        {
1427                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1428                                        "Missing M_MESH_LOD_GENERATED stream in " + pMesh->getName(),
1429                                        "MeshSerializerImpl::readMeshLodUsageGenerated");
1430                        }
1431
1432                        SubMesh* sm = pMesh->getSubMesh(i);
1433                        // lodNum - 1 because SubMesh doesn't store full detail LOD
1434            sm->mLodFaceList[lodNum - 1] = new IndexData();
1435                        IndexData* indexData = sm->mLodFaceList[lodNum - 1];
1436            // unsigned int numIndexes
1437            unsigned int numIndexes;
1438                        readInts(stream, &numIndexes, 1);
1439            indexData->indexCount = static_cast<size_t>(numIndexes);
1440            // bool indexes32Bit
1441            bool idx32Bit;
1442            readBools(stream, &idx32Bit, 1);
1443            // unsigned short*/int* faceIndexes;  ((v1, v2, v3) * numFaces)
1444            if (idx32Bit)
1445            {
1446                indexData->indexBuffer = HardwareBufferManager::getSingleton().
1447                    createIndexBuffer(HardwareIndexBuffer::IT_32BIT, indexData->indexCount,
1448                    pMesh->mIndexBufferUsage, pMesh->mIndexBufferShadowBuffer);
1449                unsigned int* pIdx = static_cast<unsigned int*>(
1450                    indexData->indexBuffer->lock(
1451                        0,
1452                        indexData->indexBuffer->getSizeInBytes(),
1453                        HardwareBuffer::HBL_DISCARD) );
1454
1455                            readInts(stream, pIdx, indexData->indexCount);
1456                indexData->indexBuffer->unlock();
1457
1458            }
1459            else
1460            {
1461                indexData->indexBuffer = HardwareBufferManager::getSingleton().
1462                    createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount,
1463                    pMesh->mIndexBufferUsage, pMesh->mIndexBufferShadowBuffer);
1464                unsigned short* pIdx = static_cast<unsigned short*>(
1465                    indexData->indexBuffer->lock(
1466                        0,
1467                        indexData->indexBuffer->getSizeInBytes(),
1468                        HardwareBuffer::HBL_DISCARD) );
1469                            readShorts(stream, pIdx, indexData->indexCount);
1470                indexData->indexBuffer->unlock();
1471
1472            }
1473
1474                }
1475        }
1476    //---------------------------------------------------------------------
1477    void MeshSerializerImpl::flipFromLittleEndian(void* pData, size_t vertexCount,
1478        size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
1479        {
1480                if (mFlipEndian)
1481                {
1482                flipEndian(pData, vertexCount, vertexSize, elems);
1483                }
1484    }
1485    //---------------------------------------------------------------------
1486    void MeshSerializerImpl::flipToLittleEndian(void* pData, size_t vertexCount,
1487                        size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
1488        {
1489                if (mFlipEndian)
1490                {
1491                flipEndian(pData, vertexCount, vertexSize, elems);
1492                }
1493        }
1494    //---------------------------------------------------------------------
1495    void MeshSerializerImpl::flipEndian(void* pData, size_t vertexCount,
1496        size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
1497        {
1498                void *pBase = pData;
1499                for (size_t v = 0; v < vertexCount; ++v)
1500                {
1501                        VertexDeclaration::VertexElementList::const_iterator ei, eiend;
1502                        eiend = elems.end();
1503                        for (ei = elems.begin(); ei != eiend; ++ei)
1504                        {
1505                                void *pElem;
1506                                // re-base pointer to the element
1507                                (*ei).baseVertexPointerToElement(pBase, &pElem);
1508                                // Flip the endian based on the type
1509                                size_t typeSize = 0;
1510                                switch (VertexElement::getBaseType((*ei).getType()))
1511                                {
1512                                        case VET_FLOAT1:
1513                                                typeSize = sizeof(float);
1514                                                break;
1515                                        case VET_SHORT1:
1516                                                typeSize = sizeof(short);
1517                                                break;
1518                                        case VET_COLOUR:
1519                                        case VET_COLOUR_ABGR:
1520                                        case VET_COLOUR_ARGB:
1521                                                typeSize = sizeof(RGBA);
1522                                                break;
1523                                        case VET_UBYTE4:
1524                                                typeSize = 0; // NO FLIPPING
1525                                                break;
1526                                        default:
1527                                                assert(false); // Should never happen
1528                                };
1529                Serializer::flipEndian(pElem, typeSize,
1530                                        VertexElement::getTypeCount((*ei).getType()));
1531
1532                        }
1533
1534                        pBase = static_cast<void*>(
1535                                static_cast<unsigned char*>(pBase) + vertexSize);
1536
1537                }
1538        }
1539    //---------------------------------------------------------------------
1540        size_t MeshSerializerImpl::calcEdgeListSize(const Mesh* pMesh)
1541        {
1542        size_t size = STREAM_OVERHEAD_SIZE;
1543
1544        for (ushort i = 0; i < pMesh->getNumLodLevels(); ++i)
1545        {
1546
1547            const EdgeData* edgeData = pMesh->getEdgeList(i);
1548            bool isManual = pMesh->isLodManual() && (i > 0);
1549
1550            size += calcEdgeListLodSize(edgeData, isManual);
1551
1552        }
1553
1554        return size;
1555        }
1556    //---------------------------------------------------------------------
1557    size_t MeshSerializerImpl::calcEdgeListLodSize(const EdgeData* edgeData, bool isManual)
1558    {
1559        size_t size = STREAM_OVERHEAD_SIZE;
1560
1561        // unsigned short lodIndex
1562        size += sizeof(uint16);
1563
1564        // bool isManual                        // If manual, no edge data here, loaded from manual mesh
1565        size += sizeof(bool);
1566        if (!isManual)
1567        {
1568            // bool isClosed
1569            size += sizeof(bool);
1570            // unsigned long numTriangles
1571            size += sizeof(uint32);
1572            // unsigned long numEdgeGroups
1573            size += sizeof(uint32);
1574            // Triangle* triangleList
1575            size_t triSize = 0;
1576            // unsigned long indexSet
1577            // unsigned long vertexSet
1578            // unsigned long vertIndex[3]
1579            // unsigned long sharedVertIndex[3]
1580            // float normal[4]
1581            triSize += sizeof(uint32) * 8
1582                    + sizeof(float) * 4;
1583
1584            size += triSize * edgeData->triangles.size();
1585            // Write the groups
1586            for (EdgeData::EdgeGroupList::const_iterator gi = edgeData->edgeGroups.begin();
1587                gi != edgeData->edgeGroups.end(); ++gi)
1588            {
1589                const EdgeData::EdgeGroup& edgeGroup = *gi;
1590                size += calcEdgeGroupSize(edgeGroup);
1591            }
1592
1593        }
1594
1595        return size;
1596    }
1597    //---------------------------------------------------------------------
1598    size_t MeshSerializerImpl::calcEdgeGroupSize(const EdgeData::EdgeGroup& group)
1599    {
1600        size_t size = STREAM_OVERHEAD_SIZE;
1601
1602        // unsigned long vertexSet
1603        size += sizeof(uint32);
1604        // unsigned long triStart
1605        size += sizeof(uint32);
1606        // unsigned long triCount
1607        size += sizeof(uint32);
1608        // unsigned long numEdges
1609        size += sizeof(uint32);
1610        // Edge* edgeList
1611        size_t edgeSize = 0;
1612        // unsigned long  triIndex[2]
1613        // unsigned long  vertIndex[2]
1614        // unsigned long  sharedVertIndex[2]
1615        // bool degenerate
1616        edgeSize += sizeof(uint32) * 6 + sizeof(bool);
1617        size += edgeSize * group.edges.size();
1618
1619        return size;
1620    }
1621    //---------------------------------------------------------------------
1622        void MeshSerializerImpl::writeEdgeList(const Mesh* pMesh)
1623        {
1624        writeChunkHeader(M_EDGE_LISTS, calcEdgeListSize(pMesh));
1625
1626        for (ushort i = 0; i < pMesh->getNumLodLevels(); ++i)
1627        {
1628            const EdgeData* edgeData = pMesh->getEdgeList(i);
1629            bool isManual = pMesh->isLodManual() && (i > 0);
1630            writeChunkHeader(M_EDGE_LIST_LOD, calcEdgeListLodSize(edgeData, isManual));
1631
1632            // unsigned short lodIndex
1633            writeShorts(&i, 1);
1634
1635            // bool isManual                    // If manual, no edge data here, loaded from manual mesh
1636            writeBools(&isManual, 1);
1637            if (!isManual)
1638            {
1639                // bool isClosed
1640                writeBools(&edgeData->isClosed, 1);
1641                // unsigned long  numTriangles
1642                uint32 count = static_cast<uint32>(edgeData->triangles.size());
1643                writeInts(&count, 1);
1644                // unsigned long numEdgeGroups
1645                count = static_cast<uint32>(edgeData->edgeGroups.size());
1646                writeInts(&count, 1);
1647                // Triangle* triangleList
1648                // Iterate rather than writing en-masse to allow endian conversion
1649                EdgeData::TriangleList::const_iterator t = edgeData->triangles.begin();
1650                EdgeData::TriangleFaceNormalList::const_iterator fni = edgeData->triangleFaceNormals.begin();
1651                for ( ; t != edgeData->triangles.end(); ++t, ++fni)
1652                {
1653                    const EdgeData::Triangle& tri = *t;
1654                    // unsigned long indexSet;
1655                    uint32 tmp[3];
1656                    tmp[0] = tri.indexSet;
1657                    writeInts(tmp, 1);
1658                    // unsigned long vertexSet;
1659                    tmp[0] = tri.vertexSet;
1660                    writeInts(tmp, 1);
1661                    // unsigned long vertIndex[3];
1662                    tmp[0] = tri.vertIndex[0];
1663                    tmp[1] = tri.vertIndex[1];
1664                    tmp[2] = tri.vertIndex[2];
1665                    writeInts(tmp, 3);
1666                    // unsigned long sharedVertIndex[3];
1667                    tmp[0] = tri.sharedVertIndex[0];
1668                    tmp[1] = tri.sharedVertIndex[1];
1669                    tmp[2] = tri.sharedVertIndex[2];
1670                    writeInts(tmp, 3);
1671                    // float normal[4];
1672                    writeFloats(&(fni->x), 4);
1673
1674                }
1675                // Write the groups
1676                for (EdgeData::EdgeGroupList::const_iterator gi = edgeData->edgeGroups.begin();
1677                    gi != edgeData->edgeGroups.end(); ++gi)
1678                {
1679                    const EdgeData::EdgeGroup& edgeGroup = *gi;
1680                    writeChunkHeader(M_EDGE_GROUP, calcEdgeGroupSize(edgeGroup));
1681                    // unsigned long vertexSet
1682                    uint32 vertexSet = static_cast<uint32>(edgeGroup.vertexSet);
1683                    writeInts(&vertexSet, 1);
1684                    // unsigned long triStart
1685                    uint32 triStart = static_cast<uint32>(edgeGroup.triStart);
1686                    writeInts(&triStart, 1);
1687                    // unsigned long triCount
1688                    uint32 triCount = static_cast<uint32>(edgeGroup.triCount);
1689                    writeInts(&triCount, 1);
1690                    // unsigned long numEdges
1691                    count = static_cast<uint32>(edgeGroup.edges.size());
1692                    writeInts(&count, 1);
1693                    // Edge* edgeList
1694                    // Iterate rather than writing en-masse to allow endian conversion
1695                    for (EdgeData::EdgeList::const_iterator ei = edgeGroup.edges.begin();
1696                        ei != edgeGroup.edges.end(); ++ei)
1697                    {
1698                        const EdgeData::Edge& edge = *ei;
1699                        uint32 tmp[2];
1700                        // unsigned long  triIndex[2]
1701                        tmp[0] = edge.triIndex[0];
1702                        tmp[1] = edge.triIndex[1];
1703                        writeInts(tmp, 2);
1704                        // unsigned long  vertIndex[2]
1705                        tmp[0] = edge.vertIndex[0];
1706                        tmp[1] = edge.vertIndex[1];
1707                        writeInts(tmp, 2);
1708                        // unsigned long  sharedVertIndex[2]
1709                        tmp[0] = edge.sharedVertIndex[0];
1710                        tmp[1] = edge.sharedVertIndex[1];
1711                        writeInts(tmp, 2);
1712                        // bool degenerate
1713                        writeBools(&(edge.degenerate), 1);
1714                    }
1715
1716                }
1717
1718            }
1719
1720        }
1721        }
1722    //---------------------------------------------------------------------
1723        void MeshSerializerImpl::readEdgeList(DataStreamPtr& stream, Mesh* pMesh)
1724        {
1725        unsigned short streamID;
1726
1727        if (!stream->eof())
1728        {
1729            streamID = readChunk(stream);
1730            while(!stream->eof() &&
1731                streamID == M_EDGE_LIST_LOD)
1732            {
1733                // Process single LOD
1734
1735                // unsigned short lodIndex
1736                unsigned short lodIndex;
1737                readShorts(stream, &lodIndex, 1);
1738
1739                // bool isManual                        // If manual, no edge data here, loaded from manual mesh
1740                bool isManual;
1741                readBools(stream, &isManual, 1);
1742                // Only load in non-manual levels; others will be connected up by Mesh on demand
1743                if (!isManual)
1744                {
1745                    MeshLodUsage& usage = const_cast<MeshLodUsage&>(pMesh->getLodLevel(lodIndex));
1746
1747                    usage.edgeData = new EdgeData();
1748
1749                    // Read detail information of the edge list
1750                    readEdgeListLodInfo(stream, usage.edgeData);
1751
1752                    // Postprocessing edge groups
1753                    EdgeData::EdgeGroupList::iterator egi, egend;
1754                    egend = usage.edgeData->edgeGroups.end();
1755                    for (egi = usage.edgeData->edgeGroups.begin(); egi != egend; ++egi)
1756                    {
1757                        EdgeData::EdgeGroup& edgeGroup = *egi;
1758                        // Populate edgeGroup.vertexData pointers
1759                        // If there is shared vertex data, vertexSet 0 is that,
1760                        // otherwise 0 is first dedicated
1761                        if (pMesh->sharedVertexData)
1762                        {
1763                            if (edgeGroup.vertexSet == 0)
1764                            {
1765                                edgeGroup.vertexData = pMesh->sharedVertexData;
1766                            }
1767                            else
1768                            {
1769                                edgeGroup.vertexData = pMesh->getSubMesh(
1770                                    edgeGroup.vertexSet-1)->vertexData;
1771                            }
1772                        }
1773                        else
1774                        {
1775                            edgeGroup.vertexData = pMesh->getSubMesh(
1776                                edgeGroup.vertexSet)->vertexData;
1777                        }
1778                    }
1779                }
1780
1781                if (!stream->eof())
1782                {
1783                    streamID = readChunk(stream);
1784                }
1785
1786            }
1787            if (!stream->eof())
1788            {
1789                // Backpedal back to start of stream
1790                stream->skip(-STREAM_OVERHEAD_SIZE);
1791            }
1792        }
1793
1794        pMesh->mEdgeListsBuilt = true;
1795        }
1796        //---------------------------------------------------------------------
1797    void MeshSerializerImpl::readEdgeListLodInfo(DataStreamPtr& stream,
1798        EdgeData* edgeData)
1799    {
1800        // bool isClosed
1801        readBools(stream, &edgeData->isClosed, 1);
1802        // unsigned long numTriangles
1803        uint32 numTriangles;
1804        readInts(stream, &numTriangles, 1);
1805        // Allocate correct amount of memory
1806        edgeData->triangles.resize(numTriangles);
1807        edgeData->triangleFaceNormals.resize(numTriangles);
1808        edgeData->triangleLightFacings.resize(numTriangles);
1809        // unsigned long numEdgeGroups
1810        uint32 numEdgeGroups;
1811        readInts(stream, &numEdgeGroups, 1);
1812        // Allocate correct amount of memory
1813        edgeData->edgeGroups.resize(numEdgeGroups);
1814        // Triangle* triangleList
1815        uint32 tmp[3];
1816        for (size_t t = 0; t < numTriangles; ++t)
1817        {
1818            EdgeData::Triangle& tri = edgeData->triangles[t];
1819            // unsigned long indexSet
1820            readInts(stream, tmp, 1);
1821            tri.indexSet = tmp[0];
1822            // unsigned long vertexSet
1823            readInts(stream, tmp, 1);
1824            tri.vertexSet = tmp[0];
1825            // unsigned long vertIndex[3]
1826            readInts(stream, tmp, 3);
1827            tri.vertIndex[0] = tmp[0];
1828            tri.vertIndex[1] = tmp[1];
1829            tri.vertIndex[2] = tmp[2];
1830            // unsigned long sharedVertIndex[3]
1831            readInts(stream, tmp, 3);
1832            tri.sharedVertIndex[0] = tmp[0];
1833            tri.sharedVertIndex[1] = tmp[1];
1834            tri.sharedVertIndex[2] = tmp[2];
1835            // float normal[4]
1836            readFloats(stream, &(edgeData->triangleFaceNormals[t].x), 4);
1837
1838        }
1839
1840        for (uint32 eg = 0; eg < numEdgeGroups; ++eg)
1841        {
1842            unsigned short streamID = readChunk(stream);
1843            if (streamID != M_EDGE_GROUP)
1844            {
1845                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
1846                    "Missing M_EDGE_GROUP stream",
1847                    "MeshSerializerImpl::readEdgeListLodInfo");
1848            }
1849            EdgeData::EdgeGroup& edgeGroup = edgeData->edgeGroups[eg];
1850
1851            // unsigned long vertexSet
1852            readInts(stream, tmp, 1);
1853            edgeGroup.vertexSet = tmp[0];
1854            // unsigned long triStart
1855            readInts(stream, tmp, 1);
1856            edgeGroup.triStart = tmp[0];
1857            // unsigned long triCount
1858            readInts(stream, tmp, 1);
1859            edgeGroup.triCount = tmp[0];
1860            // unsigned long numEdges
1861            uint32 numEdges;
1862            readInts(stream, &numEdges, 1);
1863            edgeGroup.edges.resize(numEdges);
1864            // Edge* edgeList
1865            for (uint32 e = 0; e < numEdges; ++e)
1866            {
1867                EdgeData::Edge& edge = edgeGroup.edges[e];
1868                // unsigned long  triIndex[2]
1869                readInts(stream, tmp, 2);
1870                edge.triIndex[0] = tmp[0];
1871                edge.triIndex[1] = tmp[1];
1872                // unsigned long  vertIndex[2]
1873                readInts(stream, tmp, 2);
1874                edge.vertIndex[0] = tmp[0];
1875                edge.vertIndex[1] = tmp[1];
1876                // unsigned long  sharedVertIndex[2]
1877                readInts(stream, tmp, 2);
1878                edge.sharedVertIndex[0] = tmp[0];
1879                edge.sharedVertIndex[1] = tmp[1];
1880                // bool degenerate
1881                readBools(stream, &(edge.degenerate), 1);
1882            }
1883        }
1884    }
1885        //---------------------------------------------------------------------
1886        size_t MeshSerializerImpl::calcAnimationsSize(const Mesh* pMesh)
1887        {
1888                size_t size = STREAM_OVERHEAD_SIZE;
1889
1890                for (unsigned short a = 0; a < pMesh->getNumAnimations(); ++a)
1891                {
1892                        Animation* anim = pMesh->getAnimation(a);
1893                        size += calcAnimationSize(anim);
1894                }
1895                return size;
1896
1897        }
1898        //---------------------------------------------------------------------
1899        size_t MeshSerializerImpl::calcAnimationSize(const Animation* anim)
1900        {
1901                size_t size = STREAM_OVERHEAD_SIZE;
1902                // char* name
1903                size += anim->getName().length() + 1;
1904
1905                // float length
1906                size += sizeof(float);
1907
1908                Animation::VertexTrackIterator trackIt = anim->getVertexTrackIterator();
1909                while (trackIt.hasMoreElements())
1910                {
1911                        VertexAnimationTrack* vt = trackIt.getNext();
1912                        size += calcAnimationTrackSize(vt);
1913                }
1914
1915                return size;
1916        }
1917        //---------------------------------------------------------------------
1918        size_t MeshSerializerImpl::calcAnimationTrackSize(const VertexAnimationTrack* track)
1919        {
1920                size_t size = STREAM_OVERHEAD_SIZE;
1921                // uint16 type
1922                size += sizeof(uint16);
1923                // unsigned short target                // 0 for shared geometry,
1924                size += sizeof(unsigned short);
1925
1926                if (track->getAnimationType() == VAT_MORPH)
1927                {
1928                        for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
1929                        {
1930                                VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(i);
1931                                size += calcMorphKeyframeSize(kf, track->getAssociatedVertexData()->vertexCount);
1932                        }
1933                }
1934                else
1935                {
1936                        for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
1937                        {
1938                                VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(i);
1939                                size += calcPoseKeyframeSize(kf);
1940                        }
1941                }
1942                return size;
1943        }
1944        //---------------------------------------------------------------------
1945        size_t MeshSerializerImpl::calcMorphKeyframeSize(const VertexMorphKeyFrame* kf,
1946                size_t vertexCount)
1947        {
1948                size_t size = STREAM_OVERHEAD_SIZE;
1949                // float time
1950                size += sizeof(float);
1951                // bool isOriginalGeometry  // point at original geometry?
1952                size += sizeof(bool);
1953                // float x,y,z
1954                size += sizeof(float) * 3 * vertexCount;
1955
1956                return size;
1957        }
1958        //---------------------------------------------------------------------
1959        size_t MeshSerializerImpl::calcPoseKeyframeSize(const VertexPoseKeyFrame* kf)
1960        {
1961                size_t size = STREAM_OVERHEAD_SIZE;
1962
1963                // float time
1964                size += sizeof(float);
1965
1966                size += calcPoseKeyframePoseRefSize() * kf->getPoseReferences().size();
1967
1968                return size;
1969
1970        }
1971        //---------------------------------------------------------------------
1972        size_t MeshSerializerImpl::calcPoseKeyframePoseRefSize(void)
1973        {
1974                size_t size = STREAM_OVERHEAD_SIZE;
1975                // unsigned short poseIndex
1976                size += sizeof(uint16);
1977                // float influence
1978                size += sizeof(float);
1979
1980                return size;
1981
1982        }
1983        //---------------------------------------------------------------------
1984        size_t MeshSerializerImpl::calcPosesSize(const Mesh* pMesh)
1985        {
1986                size_t size = STREAM_OVERHEAD_SIZE;
1987
1988                Mesh::ConstPoseIterator poseIt = pMesh->getPoseIterator();
1989                while (poseIt.hasMoreElements())
1990                {
1991                        size += calcPoseSize(poseIt.getNext());
1992                }
1993                return size;
1994        }
1995        //---------------------------------------------------------------------
1996        size_t MeshSerializerImpl::calcPoseSize(const Pose* pose)
1997        {
1998                size_t size = STREAM_OVERHEAD_SIZE;
1999
2000                // char* name (may be blank)
2001                size += pose->getName().length() + 1;
2002                // unsigned short target
2003                size += sizeof(uint16);
2004
2005                // vertex offsets
2006                size += pose->getVertexOffsets().size() * calcPoseVertexSize();
2007
2008                return size;
2009
2010        }
2011        //---------------------------------------------------------------------
2012        size_t MeshSerializerImpl::calcPoseVertexSize(void)
2013        {
2014                size_t size = STREAM_OVERHEAD_SIZE;
2015                // unsigned long vertexIndex
2016                size += sizeof(uint32);
2017                // float xoffset, yoffset, zoffset
2018                size += sizeof(float) * 3;
2019
2020                return size;
2021        }
2022        //---------------------------------------------------------------------
2023        void MeshSerializerImpl::writePoses(const Mesh* pMesh)
2024        {
2025                Mesh::ConstPoseIterator poseIterator = pMesh->getPoseIterator();
2026                if (poseIterator.hasMoreElements())
2027                {
2028                        writeChunkHeader(M_POSES, calcPosesSize(pMesh));
2029                        while (poseIterator.hasMoreElements())
2030                        {
2031                                writePose(poseIterator.getNext());
2032                        }
2033                }
2034
2035        }
2036        //---------------------------------------------------------------------
2037        void MeshSerializerImpl::writePose(const Pose* pose)
2038        {
2039                writeChunkHeader(M_POSE, calcPoseSize(pose));
2040
2041                // char* name (may be blank)
2042                writeString(pose->getName());
2043
2044                // unsigned short target
2045                ushort val = pose->getTarget();
2046                writeShorts(&val, 1);
2047
2048                size_t vertexSize = calcPoseVertexSize();
2049                Pose::ConstVertexOffsetIterator vit = pose->getVertexOffsetIterator();
2050                while (vit.hasMoreElements())
2051                {
2052                        uint32 vertexIndex = (uint32)vit.peekNextKey();
2053                        Vector3 offset = vit.getNext();
2054                        writeChunkHeader(M_POSE_VERTEX, vertexSize);
2055                        // unsigned long vertexIndex
2056                        writeInts(&vertexIndex, 1);
2057                        // float xoffset, yoffset, zoffset
2058                        writeFloats(offset.ptr(), 3);
2059                }
2060
2061
2062        }
2063        //---------------------------------------------------------------------
2064        void MeshSerializerImpl::writeAnimations(const Mesh* pMesh)
2065        {
2066                writeChunkHeader(M_ANIMATIONS, calcAnimationsSize(pMesh));
2067
2068                for (unsigned short a = 0; a < pMesh->getNumAnimations(); ++a)
2069                {
2070                        Animation* anim = pMesh->getAnimation(a);
2071                        LogManager::getSingleton().logMessage("Exporting animation " + anim->getName());
2072                        writeAnimation(anim);
2073                        LogManager::getSingleton().logMessage("Animation exported.");
2074                }
2075        }
2076        //---------------------------------------------------------------------
2077        void MeshSerializerImpl::writeAnimation(const Animation* anim)
2078        {
2079                writeChunkHeader(M_ANIMATION, calcAnimationSize(anim));
2080                // char* name
2081                writeString(anim->getName());
2082                // float length
2083                float len = anim->getLength();
2084                writeFloats(&len, 1);
2085                Animation::VertexTrackIterator trackIt = anim->getVertexTrackIterator();
2086                while (trackIt.hasMoreElements())
2087                {
2088                        VertexAnimationTrack* vt = trackIt.getNext();
2089                        writeAnimationTrack(vt);
2090                }
2091
2092
2093        }
2094    //---------------------------------------------------------------------
2095        void MeshSerializerImpl::writeAnimationTrack(const VertexAnimationTrack* track)
2096        {
2097                writeChunkHeader(M_ANIMATION_TRACK, calcAnimationTrackSize(track));
2098                // unsigned short type                  // 1 == morph, 2 == pose
2099                uint16 animType = (uint16)track->getAnimationType();
2100                writeShorts(&animType, 1);
2101                // unsigned short target
2102                uint16 target = track->getHandle();
2103                writeShorts(&target, 1);
2104
2105                if (track->getAnimationType() == VAT_MORPH)
2106                {
2107                        for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
2108                        {
2109                                VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(i);
2110                                writeMorphKeyframe(kf, track->getAssociatedVertexData()->vertexCount);
2111                        }
2112                }
2113                else // VAT_POSE
2114                {
2115                        for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
2116                        {
2117                                VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(i);
2118                                writePoseKeyframe(kf);
2119                        }
2120                }
2121
2122        }
2123        //---------------------------------------------------------------------
2124        void MeshSerializerImpl::writeMorphKeyframe(const VertexMorphKeyFrame* kf, size_t vertexCount)
2125        {
2126                writeChunkHeader(M_ANIMATION_MORPH_KEYFRAME, calcMorphKeyframeSize(kf, vertexCount));
2127                // float time
2128                float timePos = kf->getTime();
2129                writeFloats(&timePos, 1);
2130                // float x,y,z                  // repeat by number of vertices in original geometry
2131                float* pSrc = static_cast<float*>(
2132                        kf->getVertexBuffer()->lock(HardwareBuffer::HBL_READ_ONLY));
2133                writeFloats(pSrc, vertexCount * 3);
2134                kf->getVertexBuffer()->unlock();
2135        }
2136        //---------------------------------------------------------------------
2137        void MeshSerializerImpl::writePoseKeyframe(const VertexPoseKeyFrame* kf)
2138        {
2139                writeChunkHeader(M_ANIMATION_POSE_KEYFRAME, calcPoseKeyframeSize(kf));
2140                // float time
2141                float timePos = kf->getTime();
2142                writeFloats(&timePos, 1);
2143
2144                // pose references
2145                VertexPoseKeyFrame::ConstPoseRefIterator poseRefIt =
2146                        kf->getPoseReferenceIterator();
2147                while (poseRefIt.hasMoreElements())
2148                {
2149                        writePoseKeyframePoseRef(poseRefIt.getNext());
2150                }
2151
2152
2153
2154        }
2155        //---------------------------------------------------------------------
2156        void MeshSerializerImpl::writePoseKeyframePoseRef(
2157                const VertexPoseKeyFrame::PoseRef& poseRef)
2158        {
2159                writeChunkHeader(M_ANIMATION_POSE_REF, calcPoseKeyframePoseRefSize());
2160                // unsigned short poseIndex
2161                writeShorts(&(poseRef.poseIndex), 1);
2162                // float influence
2163                writeFloats(&(poseRef.influence), 1);
2164        }
2165        //---------------------------------------------------------------------
2166        void MeshSerializerImpl::readPoses(DataStreamPtr& stream, Mesh* pMesh)
2167        {
2168                unsigned short streamID;
2169
2170                // Find all substreams
2171                if (!stream->eof())
2172                {
2173                        streamID = readChunk(stream);
2174                        while(!stream->eof() &&
2175                                (streamID == M_POSE))
2176                        {
2177                                switch(streamID)
2178                                {
2179                                case M_POSE:
2180                                        readPose(stream, pMesh);
2181                                        break;
2182
2183                                }
2184
2185                                if (!stream->eof())
2186                                {
2187                                        streamID = readChunk(stream);
2188                                }
2189
2190                        }
2191                        if (!stream->eof())
2192                        {
2193                                // Backpedal back to start of stream
2194                                stream->skip(-STREAM_OVERHEAD_SIZE);
2195                        }
2196                }
2197        }
2198        //---------------------------------------------------------------------
2199        void MeshSerializerImpl::readPose(DataStreamPtr& stream, Mesh* pMesh)
2200        {
2201                // char* name (may be blank)
2202                String name = readString(stream);
2203                // unsigned short target
2204                unsigned short target;
2205                readShorts(stream, &target, 1);
2206
2207                Pose* pose = pMesh->createPose(target, name);
2208
2209                // Find all substreams
2210                unsigned short streamID;
2211                if (!stream->eof())
2212                {
2213                        streamID = readChunk(stream);
2214                        while(!stream->eof() &&
2215                                (streamID == M_POSE_VERTEX))
2216                        {
2217                                switch(streamID)
2218                                {
2219                                case M_POSE_VERTEX:
2220                                        // create vertex offset
2221                                        uint32 vertIndex;
2222                                        Vector3 offset;
2223                                        // unsigned long vertexIndex
2224                                        readInts(stream, &vertIndex, 1);
2225                                        // float xoffset, yoffset, zoffset
2226                                        readFloats(stream, offset.ptr(), 3);
2227
2228                                        pose->addVertex(vertIndex, offset);
2229                                        break;
2230
2231                                }
2232
2233                                if (!stream->eof())
2234                                {
2235                                        streamID = readChunk(stream);
2236                                }
2237
2238                        }
2239                        if (!stream->eof())
2240                        {
2241                                // Backpedal back to start of stream
2242                                stream->skip(-STREAM_OVERHEAD_SIZE);
2243                        }
2244                }
2245
2246        }
2247        //---------------------------------------------------------------------
2248        void MeshSerializerImpl::readAnimations(DataStreamPtr& stream, Mesh* pMesh)
2249        {
2250                unsigned short streamID;
2251
2252                // Find all substreams
2253                if (!stream->eof())
2254                {
2255                        streamID = readChunk(stream);
2256                        while(!stream->eof() &&
2257                                (streamID == M_ANIMATION))
2258                        {
2259                                switch(streamID)
2260                                {
2261                                case M_ANIMATION:
2262                                        readAnimation(stream, pMesh);
2263                                        break;
2264
2265                                }
2266
2267                                if (!stream->eof())
2268                                {
2269                                        streamID = readChunk(stream);
2270                                }
2271
2272                        }
2273                        if (!stream->eof())
2274                        {
2275                                // Backpedal back to start of stream
2276                                stream->skip(-STREAM_OVERHEAD_SIZE);
2277                        }
2278                }
2279
2280
2281        }
2282        //---------------------------------------------------------------------
2283        void MeshSerializerImpl::readAnimation(DataStreamPtr& stream, Mesh* pMesh)
2284        {
2285
2286                // char* name
2287                String name = readString(stream);
2288                // float length
2289                float len;
2290                readFloats(stream, &len, 1);
2291
2292                Animation* anim = pMesh->createAnimation(name, len);
2293
2294                // tracks
2295                unsigned short streamID;
2296
2297                if (!stream->eof())
2298                {
2299                        streamID = readChunk(stream);
2300                        while(!stream->eof() &&
2301                                streamID == M_ANIMATION_TRACK)
2302                        {
2303                                switch(streamID)
2304                                {
2305                                case M_ANIMATION_TRACK:
2306                                        readAnimationTrack(stream, anim, pMesh);
2307                                        break;
2308                                };
2309                                if (!stream->eof())
2310                                {
2311                                        streamID = readChunk(stream);
2312                                }
2313
2314                        }
2315                        if (!stream->eof())
2316                        {
2317                                // Backpedal back to start of stream
2318                                stream->skip(-STREAM_OVERHEAD_SIZE);
2319                        }
2320                }
2321        }
2322        //---------------------------------------------------------------------
2323        void MeshSerializerImpl::readAnimationTrack(DataStreamPtr& stream,
2324                Animation* anim, Mesh* pMesh)
2325        {
2326                // ushort type
2327                uint16 inAnimType;
2328                readShorts(stream, &inAnimType, 1);
2329                VertexAnimationType animType = (VertexAnimationType)inAnimType;
2330
2331                // unsigned short target
2332                uint16 target;
2333                readShorts(stream, &target, 1);
2334
2335                VertexAnimationTrack* track = anim->createVertexTrack(target,
2336                        pMesh->getVertexDataByTrackHandle(target), animType);
2337
2338                // keyframes
2339                unsigned short streamID;
2340
2341                if (!stream->eof())
2342                {
2343                        streamID = readChunk(stream);
2344                        while(!stream->eof() &&
2345                                (streamID == M_ANIMATION_MORPH_KEYFRAME ||
2346                                 streamID == M_ANIMATION_POSE_KEYFRAME))
2347                        {
2348                                switch(streamID)
2349                                {
2350                                case M_ANIMATION_MORPH_KEYFRAME:
2351                                        readMorphKeyFrame(stream, track);
2352                                        break;
2353                                case M_ANIMATION_POSE_KEYFRAME:
2354                                        readPoseKeyFrame(stream, track);
2355                                        break;
2356                                };
2357                                if (!stream->eof())
2358                                {
2359                                        streamID = readChunk(stream);
2360                                }
2361
2362                        }
2363                        if (!stream->eof())
2364                        {
2365                                // Backpedal back to start of stream
2366                                stream->skip(-STREAM_OVERHEAD_SIZE);
2367                        }
2368                }
2369
2370        }
2371        //---------------------------------------------------------------------
2372        void MeshSerializerImpl::readMorphKeyFrame(DataStreamPtr& stream, VertexAnimationTrack* track)
2373        {
2374                // float time
2375                float timePos;
2376                readFloats(stream, &timePos, 1);
2377
2378                VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(timePos);
2379
2380                // Create buffer, allow read and use shadow buffer
2381                size_t vertexCount = track->getAssociatedVertexData()->vertexCount;
2382                HardwareVertexBufferSharedPtr vbuf =
2383                        HardwareBufferManager::getSingleton().createVertexBuffer(
2384                                VertexElement::getTypeSize(VET_FLOAT3), vertexCount,
2385                                HardwareBuffer::HBU_STATIC, true);
2386                // float x,y,z                  // repeat by number of vertices in original geometry
2387                float* pDst = static_cast<float*>(
2388                        vbuf->lock(HardwareBuffer::HBL_DISCARD));
2389                readFloats(stream, pDst, vertexCount * 3);
2390                vbuf->unlock();
2391                kf->setVertexBuffer(vbuf);
2392
2393        }
2394        //---------------------------------------------------------------------
2395        void MeshSerializerImpl::readPoseKeyFrame(DataStreamPtr& stream, VertexAnimationTrack* track)
2396        {
2397                // float time
2398                float timePos;
2399                readFloats(stream, &timePos, 1);
2400
2401                // Create keyframe
2402                VertexPoseKeyFrame* kf = track->createVertexPoseKeyFrame(timePos);
2403
2404                unsigned short streamID;
2405
2406                if (!stream->eof())
2407                {
2408                        streamID = readChunk(stream);
2409                        while(!stream->eof() &&
2410                                streamID == M_ANIMATION_POSE_REF)
2411                        {
2412                                switch(streamID)
2413                                {
2414                                case M_ANIMATION_POSE_REF:
2415                                        uint16 poseIndex;
2416                                        float influence;
2417                                        // unsigned short poseIndex
2418                                        readShorts(stream, &poseIndex, 1);
2419                                        // float influence
2420                                        readFloats(stream, &influence, 1);
2421
2422                                        kf->addPoseReference(poseIndex, influence);
2423
2424                                        break;
2425                                };
2426                                if (!stream->eof())
2427                                {
2428                                        streamID = readChunk(stream);
2429                                }
2430
2431                        }
2432                        if (!stream->eof())
2433                        {
2434                                // Backpedal back to start of stream
2435                                stream->skip(-STREAM_OVERHEAD_SIZE);
2436                        }
2437                }
2438
2439        }
2440    //---------------------------------------------------------------------
2441    //---------------------------------------------------------------------
2442    //---------------------------------------------------------------------
2443    MeshSerializerImpl_v1_3::MeshSerializerImpl_v1_3()
2444    {
2445        // Version number
2446        mVersion = "[MeshSerializer_v1.30]";
2447    }
2448    //---------------------------------------------------------------------
2449    MeshSerializerImpl_v1_3::~MeshSerializerImpl_v1_3()
2450    {
2451    }
2452    //---------------------------------------------------------------------
2453    void MeshSerializerImpl_v1_3::readEdgeListLodInfo(DataStreamPtr& stream,
2454        EdgeData* edgeData)
2455    {
2456        // unsigned long numTriangles
2457        uint32 numTriangles;
2458        readInts(stream, &numTriangles, 1);
2459        // Allocate correct amount of memory
2460        edgeData->triangles.resize(numTriangles);
2461        edgeData->triangleFaceNormals.resize(numTriangles);
2462        edgeData->triangleLightFacings.resize(numTriangles);
2463        // unsigned long numEdgeGroups
2464        uint32 numEdgeGroups;
2465        readInts(stream, &numEdgeGroups, 1);
2466        // Allocate correct amount of memory
2467        edgeData->edgeGroups.resize(numEdgeGroups);
2468        // Triangle* triangleList
2469        uint32 tmp[3];
2470        for (size_t t = 0; t < numTriangles; ++t)
2471        {
2472            EdgeData::Triangle& tri = edgeData->triangles[t];
2473            // unsigned long indexSet
2474            readInts(stream, tmp, 1);
2475            tri.indexSet = tmp[0];
2476            // unsigned long vertexSet
2477            readInts(stream, tmp, 1);
2478            tri.vertexSet = tmp[0];
2479            // unsigned long vertIndex[3]
2480            readInts(stream, tmp, 3);
2481            tri.vertIndex[0] = tmp[0];
2482            tri.vertIndex[1] = tmp[1];
2483            tri.vertIndex[2] = tmp[2];
2484            // unsigned long sharedVertIndex[3]
2485            readInts(stream, tmp, 3);
2486            tri.sharedVertIndex[0] = tmp[0];
2487            tri.sharedVertIndex[1] = tmp[1];
2488            tri.sharedVertIndex[2] = tmp[2];
2489            // float normal[4]
2490            readFloats(stream, &(edgeData->triangleFaceNormals[t].x), 4);
2491
2492        }
2493
2494        // Assume the mesh is closed, it will update later
2495        edgeData->isClosed = true;
2496
2497        for (uint32 eg = 0; eg < numEdgeGroups; ++eg)
2498        {
2499            unsigned short streamID = readChunk(stream);
2500            if (streamID != M_EDGE_GROUP)
2501            {
2502                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
2503                    "Missing M_EDGE_GROUP stream",
2504                    "MeshSerializerImpl_v1_3::readEdgeListLodInfo");
2505            }
2506            EdgeData::EdgeGroup& edgeGroup = edgeData->edgeGroups[eg];
2507
2508            // unsigned long vertexSet
2509            readInts(stream, tmp, 1);
2510            edgeGroup.vertexSet = tmp[0];
2511            // unsigned long numEdges
2512            uint32 numEdges;
2513            readInts(stream, &numEdges, 1);
2514            edgeGroup.edges.resize(numEdges);
2515            // Edge* edgeList
2516            for (uint32 e = 0; e < numEdges; ++e)
2517            {
2518                EdgeData::Edge& edge = edgeGroup.edges[e];
2519                // unsigned long  triIndex[2]
2520                readInts(stream, tmp, 2);
2521                edge.triIndex[0] = tmp[0];
2522                edge.triIndex[1] = tmp[1];
2523                // unsigned long  vertIndex[2]
2524                readInts(stream, tmp, 2);
2525                edge.vertIndex[0] = tmp[0];
2526                edge.vertIndex[1] = tmp[1];
2527                // unsigned long  sharedVertIndex[2]
2528                readInts(stream, tmp, 2);
2529                edge.sharedVertIndex[0] = tmp[0];
2530                edge.sharedVertIndex[1] = tmp[1];
2531                // bool degenerate
2532                readBools(stream, &(edge.degenerate), 1);
2533
2534                // The mesh is closed only if no degenerate edge here
2535                if (edge.degenerate)
2536                {
2537                    edgeData->isClosed = false;
2538                }
2539            }
2540        }
2541
2542        reorganiseTriangles(edgeData);
2543    }
2544    //---------------------------------------------------------------------
2545    void MeshSerializerImpl_v1_3::reorganiseTriangles(EdgeData* edgeData)
2546    {
2547        size_t numTriangles = edgeData->triangles.size();
2548
2549        if (edgeData->edgeGroups.size() == 1)
2550        {
2551            // Special case for only one edge group in the edge list, which occuring
2552            // most time. In this case, all triangles belongs to that group.
2553            edgeData->edgeGroups.front().triStart = 0;
2554            edgeData->edgeGroups.front().triCount = numTriangles;
2555        }
2556        else
2557        {
2558            EdgeData::EdgeGroupList::iterator egi, egend;
2559            egend = edgeData->edgeGroups.end();
2560
2561            // Calculate number of triangles for edge groups
2562
2563            for (egi = edgeData->edgeGroups.begin(); egi != egend; ++egi)
2564            {
2565                egi->triStart = 0;
2566                egi->triCount = 0;
2567            }
2568
2569            bool isGrouped = true;
2570            EdgeData::EdgeGroup* lastEdgeGroup = 0;
2571            for (size_t t = 0; t < numTriangles; ++t)
2572            {
2573                // Gets the edge group that the triangle belongs to
2574                const EdgeData::Triangle& tri = edgeData->triangles[t];
2575                EdgeData::EdgeGroup* edgeGroup = &edgeData->edgeGroups[tri.vertexSet];
2576
2577                // Does edge group changes from last edge group?
2578                if (isGrouped && edgeGroup != lastEdgeGroup)
2579                {
2580                    // Remember last edge group
2581                    lastEdgeGroup = edgeGroup;
2582
2583                    // Is't first time encounter this edge group?
2584                    if (!edgeGroup->triCount && !edgeGroup->triStart)
2585                    {
2586                        // setup first triangle of this edge group
2587                        edgeGroup->triStart = t;
2588                    }
2589                    else
2590                    {
2591                        // original triangles doesn't grouping by edge group
2592                        isGrouped = false;
2593                    }
2594                }
2595
2596                // Count number of triangles for this edge group
2597                ++edgeGroup->triCount;
2598            }
2599
2600            //
2601            // Note that triangles has been sorted by vertex set for a long time,
2602            // but never stored to old version mesh file.
2603            //
2604            // Adopt this fact to avoid remap triangles here.
2605            //
2606
2607            // Does triangles grouped by vertex set?
2608            if (!isGrouped)
2609            {
2610                // Ok, the triangles of this edge list isn't grouped by vertex set
2611                // perfectly, seems ancient mesh file.
2612                //
2613                // We need work hardly to group triangles by vertex set.
2614                //
2615
2616                // Calculate triStart and reset triCount to zero for each edge group first
2617                size_t triStart = 0;
2618                for (egi = edgeData->edgeGroups.begin(); egi != egend; ++egi)
2619                {
2620                    egi->triStart = triStart;
2621                    triStart += egi->triCount;
2622                    egi->triCount = 0;
2623                }
2624
2625                // The map used to mapping original triangle index to new index
2626                typedef std::vector<size_t> TriangleIndexRemap;
2627                TriangleIndexRemap triangleIndexRemap(numTriangles);
2628
2629                // New triangles information that should be group by vertex set.
2630                EdgeData::TriangleList newTriangles(numTriangles);
2631                EdgeData::TriangleFaceNormalList newTriangleFaceNormals(numTriangles);
2632
2633                // Calculate triangle index map and organise triangles information
2634                for (size_t t = 0; t < numTriangles; ++t)
2635                {
2636                    // Gets the edge group that the triangle belongs to
2637                    const EdgeData::Triangle& tri = edgeData->triangles[t];
2638                    EdgeData::EdgeGroup& edgeGroup = edgeData->edgeGroups[tri.vertexSet];
2639
2640                    // Calculate new index
2641                    size_t newIndex = edgeGroup.triStart + edgeGroup.triCount;
2642                    ++edgeGroup.triCount;
2643
2644                    // Setup triangle index mapping entry
2645                    triangleIndexRemap[t] = newIndex;
2646
2647                    // Copy triangle info to new placement
2648                    newTriangles[newIndex] = tri;
2649                    newTriangleFaceNormals[newIndex] = edgeData->triangleFaceNormals[t];
2650                }
2651
2652                // Replace with new triangles information
2653                edgeData->triangles.swap(newTriangles);
2654                edgeData->triangleFaceNormals.swap(newTriangleFaceNormals);
2655
2656                // Now, update old triangle indices to new index
2657                for (egi = edgeData->edgeGroups.begin(); egi != egend; ++egi)
2658                {
2659                    EdgeData::EdgeList::iterator ei, eend;
2660                    eend = egi->edges.end();
2661                    for (ei = egi->edges.begin(); ei != eend; ++ei)
2662                    {
2663                        ei->triIndex[0] = triangleIndexRemap[ei->triIndex[0]];
2664                        if (!ei->degenerate)
2665                        {
2666                            ei->triIndex[1] = triangleIndexRemap[ei->triIndex[1]];
2667                        }
2668                    }
2669                }
2670            }
2671        }
2672    }
2673        //---------------------------------------------------------------------
2674        void MeshSerializerImpl::readExtremes(DataStreamPtr& stream, Mesh *pMesh)
2675        {
2676                unsigned short idx;
2677                readShorts(stream, &idx, 1);
2678
2679                SubMesh *sm = pMesh->getSubMesh (idx);
2680
2681                int n_floats = (mCurrentstreamLen - STREAM_OVERHEAD_SIZE -
2682                                                sizeof (unsigned short)) / sizeof (float);
2683
2684        assert ((n_floats % 3) == 0);
2685
2686        float *vert = new float[n_floats];
2687                readFloats(stream, vert, n_floats);
2688
2689        for (int i = 0; i < n_floats; i += 3)
2690                        sm->extremityPoints.push_back(Vector3(vert [i], vert [i + 1], vert [i + 2]));
2691
2692        delete [] vert;
2693        }
2694        //---------------------------------------------------------------------
2695    //---------------------------------------------------------------------
2696    //---------------------------------------------------------------------
2697    MeshSerializerImpl_v1_2::MeshSerializerImpl_v1_2()
2698    {
2699        // Version number
2700        mVersion = "[MeshSerializer_v1.20]";
2701    }
2702    //---------------------------------------------------------------------
2703    MeshSerializerImpl_v1_2::~MeshSerializerImpl_v1_2()
2704    {
2705    }
2706    //---------------------------------------------------------------------
2707    void MeshSerializerImpl_v1_2::readMesh(DataStreamPtr& stream, Mesh* pMesh)
2708    {
2709        MeshSerializerImpl::readMesh(stream, pMesh);
2710        // Always automatically build edge lists for this version
2711        pMesh->mAutoBuildEdgeLists = true;
2712
2713    }
2714    //---------------------------------------------------------------------
2715    void MeshSerializerImpl_v1_2::readGeometry(DataStreamPtr& stream, Mesh* pMesh,
2716        VertexData* dest)
2717    {
2718        unsigned short texCoordSet = 0;
2719
2720        unsigned short bindIdx = 0;
2721
2722        dest->vertexStart = 0;
2723
2724        unsigned int vertexCount = 0;
2725        readInts(stream, &vertexCount, 1);
2726        dest->vertexCount = vertexCount;
2727
2728        // Vertex buffers
2729
2730        readGeometryPositions(bindIdx, stream, pMesh, dest);
2731        ++bindIdx;
2732
2733        // Find optional geometry streams
2734        if (!stream->eof())
2735        {
2736            unsigned short streamID = readChunk(stream);
2737            while(!stream->eof() &&
2738                (streamID == M_GEOMETRY_NORMALS ||
2739                 streamID == M_GEOMETRY_COLOURS ||
2740                 streamID == M_GEOMETRY_TEXCOORDS ))
2741            {
2742                switch (streamID)
2743                {
2744                case M_GEOMETRY_NORMALS:
2745                    readGeometryNormals(bindIdx++, stream, pMesh, dest);
2746                    break;
2747                case M_GEOMETRY_COLOURS:
2748                    readGeometryColours(bindIdx++, stream, pMesh, dest);
2749                    break;
2750                case M_GEOMETRY_TEXCOORDS:
2751                    readGeometryTexCoords(bindIdx++, stream, pMesh, dest, texCoordSet++);
2752                    break;
2753                }
2754                // Get next stream
2755                if (!stream->eof())
2756                {
2757                    streamID = readChunk(stream);
2758                }
2759            }
2760            if (!stream->eof())
2761            {
2762                // Backpedal back to start of non-submesh stream
2763                stream->skip(-STREAM_OVERHEAD_SIZE);
2764            }
2765        }
2766    }
2767    //---------------------------------------------------------------------
2768    void MeshSerializerImpl_v1_2::readGeometryPositions(unsigned short bindIdx,
2769        DataStreamPtr& stream, Mesh* pMesh, VertexData* dest)
2770    {
2771        float *pFloat = 0;
2772        HardwareVertexBufferSharedPtr vbuf;
2773        // float* pVertices (x, y, z order x numVertices)
2774        dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_POSITION);
2775        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
2776            dest->vertexDeclaration->getVertexSize(bindIdx),
2777            dest->vertexCount,
2778            pMesh->mVertexBufferUsage,
2779                        pMesh->mIndexBufferShadowBuffer);
2780        pFloat = static_cast<float*>(
2781            vbuf->lock(HardwareBuffer::HBL_DISCARD));
2782        readFloats(stream, pFloat, dest->vertexCount * 3);
2783        vbuf->unlock();
2784        dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
2785    }
2786    //---------------------------------------------------------------------
2787    void MeshSerializerImpl_v1_2::readGeometryNormals(unsigned short bindIdx,
2788        DataStreamPtr& stream, Mesh* pMesh, VertexData* dest)
2789    {
2790        float *pFloat = 0;
2791        HardwareVertexBufferSharedPtr vbuf;
2792        // float* pNormals (x, y, z order x numVertices)
2793        dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_NORMAL);
2794        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
2795            dest->vertexDeclaration->getVertexSize(bindIdx),
2796            dest->vertexCount,
2797            pMesh->mVertexBufferUsage,
2798                        pMesh->mVertexBufferShadowBuffer);
2799        pFloat = static_cast<float*>(
2800            vbuf->lock(HardwareBuffer::HBL_DISCARD));
2801        readFloats(stream, pFloat, dest->vertexCount * 3);
2802        vbuf->unlock();
2803        dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
2804    }
2805    //---------------------------------------------------------------------
2806    void MeshSerializerImpl_v1_2::readGeometryColours(unsigned short bindIdx,
2807        DataStreamPtr& stream, Mesh* pMesh, VertexData* dest)
2808    {
2809        RGBA* pRGBA = 0;
2810        HardwareVertexBufferSharedPtr vbuf;
2811        // unsigned long* pColours (RGBA 8888 format x numVertices)
2812        dest->vertexDeclaration->addElement(bindIdx, 0, VET_COLOUR, VES_DIFFUSE);
2813        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
2814            dest->vertexDeclaration->getVertexSize(bindIdx),
2815            dest->vertexCount,
2816            pMesh->mVertexBufferUsage,
2817                        pMesh->mVertexBufferShadowBuffer);
2818        pRGBA = static_cast<RGBA*>(
2819            vbuf->lock(HardwareBuffer::HBL_DISCARD));
2820        readInts(stream, pRGBA, dest->vertexCount);
2821        vbuf->unlock();
2822        dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
2823    }
2824    //---------------------------------------------------------------------
2825    void MeshSerializerImpl_v1_2::readGeometryTexCoords(unsigned short bindIdx,
2826        DataStreamPtr& stream, Mesh* pMesh, VertexData* dest, unsigned short texCoordSet)
2827    {
2828        float *pFloat = 0;
2829        HardwareVertexBufferSharedPtr vbuf;
2830        // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
2831        unsigned short dim;
2832        readShorts(stream, &dim, 1);
2833        // float* pTexCoords  (u [v] [w] order, dimensions x numVertices)
2834        dest->vertexDeclaration->addElement(
2835            bindIdx,
2836            0,
2837            VertexElement::multiplyTypeCount(VET_FLOAT1, dim),
2838            VES_TEXTURE_COORDINATES,
2839            texCoordSet);
2840        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
2841            dest->vertexDeclaration->getVertexSize(bindIdx),
2842            dest->vertexCount,
2843            pMesh->mVertexBufferUsage,
2844                        pMesh->mVertexBufferShadowBuffer);
2845        pFloat = static_cast<float*>(
2846            vbuf->lock(HardwareBuffer::HBL_DISCARD));
2847        readFloats(stream, pFloat, dest->vertexCount * dim);
2848        vbuf->unlock();
2849        dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
2850    }
2851    //---------------------------------------------------------------------
2852    //---------------------------------------------------------------------
2853    //---------------------------------------------------------------------
2854    MeshSerializerImpl_v1_1::MeshSerializerImpl_v1_1()
2855    {
2856        // Version number
2857        mVersion = "[MeshSerializer_v1.10]";
2858    }
2859    //---------------------------------------------------------------------
2860    MeshSerializerImpl_v1_1::~MeshSerializerImpl_v1_1()
2861    {
2862    }
2863    //---------------------------------------------------------------------
2864    void MeshSerializerImpl_v1_1::readGeometryTexCoords(unsigned short bindIdx,
2865        DataStreamPtr& stream, Mesh* pMesh, VertexData* dest, unsigned short texCoordSet)
2866    {
2867        float *pFloat = 0;
2868        HardwareVertexBufferSharedPtr vbuf;
2869        // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
2870        unsigned short dim;
2871        readShorts(stream, &dim, 1);
2872        // float* pTexCoords  (u [v] [w] order, dimensions x numVertices)
2873        dest->vertexDeclaration->addElement(
2874            bindIdx,
2875            0,
2876            VertexElement::multiplyTypeCount(VET_FLOAT1, dim),
2877            VES_TEXTURE_COORDINATES,
2878            texCoordSet);
2879        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
2880            dest->vertexDeclaration->getVertexSize(bindIdx),
2881            dest->vertexCount,
2882            pMesh->getVertexBufferUsage(),
2883                        pMesh->isVertexBufferShadowed());
2884        pFloat = static_cast<float*>(
2885            vbuf->lock(HardwareBuffer::HBL_DISCARD));
2886        readFloats(stream, pFloat, dest->vertexCount * dim);
2887
2888        // Adjust individual v values to (1 - v)
2889        if (dim == 2)
2890        {
2891            for (size_t i = 0; i < dest->vertexCount; ++i)
2892            {
2893                ++pFloat; // skip u
2894                *pFloat = 1.0 - *pFloat; // v = 1 - v
2895                ++pFloat;
2896            }
2897
2898        }
2899        vbuf->unlock();
2900        dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
2901    }
2902    //---------------------------------------------------------------------
2903    //---------------------------------------------------------------------
2904    //---------------------------------------------------------------------
2905
2906
2907
2908
2909}
2910
Note: See TracBrowser for help on using the repository browser.