1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4     (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #include "OgreStableHeaders.h"
29 
30 #include "OgreMeshSerializerImpl.h"
31 #include "OgreMeshFileFormat.h"
32 #include "OgreMeshSerializer.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 #include "OgreLodStrategyManager.h"
47 #include "OgreDistanceLodStrategy.h"
48 
49 #if OGRE_COMPILER == OGRE_COMPILER_MSVC
50 // Disable conversion warnings, we do a lot of them, intentionally
51 #   pragma warning (disable : 4267)
52 #endif
53 
54 
55 namespace Ogre {
56 
57     /// stream overhead = ID + size
58     const long MSTREAM_OVERHEAD_SIZE = sizeof(uint16) + sizeof(uint32);
59     //---------------------------------------------------------------------
MeshSerializerImpl()60     MeshSerializerImpl::MeshSerializerImpl()
61     {
62 
63         // Version number
64         mVersion = "[MeshSerializer_v1.8]";
65     }
66     //---------------------------------------------------------------------
~MeshSerializerImpl()67     MeshSerializerImpl::~MeshSerializerImpl()
68     {
69     }
70     //---------------------------------------------------------------------
exportMesh(const Mesh * pMesh,DataStreamPtr stream,Endian endianMode)71     void MeshSerializerImpl::exportMesh(const Mesh* pMesh,
72 		DataStreamPtr stream, Endian endianMode)
73     {
74         LogManager::getSingleton().logMessage("MeshSerializer writing mesh data to stream " + stream->getName() + "...");
75 
76 		// Decide on endian mode
77 		determineEndianness(endianMode);
78 
79         // Check that the mesh has it's bounds set
80         if (pMesh->getBounds().isNull() || pMesh->getBoundingSphereRadius() == 0.0f)
81         {
82             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The Mesh you have supplied does not have its"
83                 " bounds completely defined. Define them first before exporting.",
84                 "MeshSerializerImpl::exportMesh");
85         }
86         mStream = stream;
87 		if (!stream->isWriteable())
88 		{
89 			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
90 				"Unable to use stream " + stream->getName() + " for writing",
91 				"MeshSerializerImpl::exportMesh");
92 		}
93 
94         writeFileHeader();
95         LogManager::getSingleton().logMessage("File header written.");
96 
97 
98         LogManager::getSingleton().logMessage("Writing mesh data...");
99         writeMesh(pMesh);
100         LogManager::getSingleton().logMessage("Mesh data exported.");
101 
102         LogManager::getSingleton().logMessage("MeshSerializer export successful.");
103     }
104     //---------------------------------------------------------------------
importMesh(DataStreamPtr & stream,Mesh * pMesh,MeshSerializerListener * listener)105     void MeshSerializerImpl::importMesh(DataStreamPtr& stream, Mesh* pMesh, MeshSerializerListener *listener)
106     {
107 		// Determine endianness (must be the first thing we do!)
108 		determineEndianness(stream);
109 
110         // Check header
111         readFileHeader(stream);
112 
113         while(!stream->eof())
114         {
115             unsigned short streamID = readChunk(stream);
116             switch (streamID)
117             {
118             case M_MESH:
119                 readMesh(stream, pMesh, listener);
120                 break;
121 			}
122 
123         }
124     }
125     //---------------------------------------------------------------------
writeMesh(const Mesh * pMesh)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 (unsigned short 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
writeSubMeshNameTable(const Mesh * pMesh)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, MSTREAM_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     //---------------------------------------------------------------------
writeSubMesh(const SubMesh * s)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 = static_cast<unsigned int>(s->indexData->indexCount);
244         writeInts(&indexCount, 1);
245 
246         // bool indexes32Bit
247         bool idx32bit = (!s->indexData->indexBuffer.isNull() &&
248 			s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
249         writeBools(&idx32bit, 1);
250 
251 		if (indexCount > 0)
252 		{
253 			// unsigned short* faceVertexIndices ((indexCount)
254 			HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer;
255 			void* pIdx = ibuf->lock(HardwareBuffer::HBL_READ_ONLY);
256 			if (idx32bit)
257 			{
258 				unsigned int* pIdx32 = static_cast<unsigned int*>(pIdx);
259 				writeInts(pIdx32, s->indexData->indexCount);
260 			}
261 			else
262 			{
263 				unsigned short* pIdx16 = static_cast<unsigned short*>(pIdx);
264 				writeShorts(pIdx16, s->indexData->indexCount);
265 			}
266 			ibuf->unlock();
267 		}
268 
269         // M_GEOMETRY stream (Optional: present only if useSharedVertices = false)
270         if (!s->useSharedVertices)
271         {
272             writeGeometry(s->vertexData);
273         }
274 
275         // end of sub mesh chunk
276 
277         // write out texture alias chunks
278         writeSubMeshTextureAliases(s);
279 
280         // Operation type
281         writeSubMeshOperation(s);
282 
283         // Bone assignments
284         if (!s->mBoneAssignments.empty())
285         {
286             LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");
287 
288             SubMesh::VertexBoneAssignmentList::const_iterator vi;
289             for (vi = s->mBoneAssignments.begin();
290             vi != s->mBoneAssignments.end(); ++vi)
291             {
292                 writeSubMeshBoneAssignment(vi->second);
293             }
294 
295             LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported.");
296         }
297 
298 
299     }
300     //---------------------------------------------------------------------
writeExtremes(const Mesh * pMesh)301     void MeshSerializerImpl::writeExtremes(const Mesh *pMesh)
302     {
303         bool has_extremes = false;
304         for (unsigned short i = 0; i < pMesh->getNumSubMeshes(); ++i)
305         {
306             SubMesh *sm = pMesh->getSubMesh(i);
307             if (sm->extremityPoints.empty())
308                 continue;
309             if (!has_extremes)
310             {
311                 has_extremes = true;
312                 LogManager::getSingleton().logMessage("Writing submesh extremes...");
313             }
314             writeSubMeshExtremes(i, sm);
315         }
316         if (has_extremes)
317             LogManager::getSingleton().logMessage("Extremes exported.");
318     }
319     //---------------------------------------------------------------------
writeSubMeshExtremes(unsigned short idx,const SubMesh * s)320     void MeshSerializerImpl::writeSubMeshExtremes(unsigned short idx, const SubMesh* s)
321     {
322         size_t chunkSize = MSTREAM_OVERHEAD_SIZE + sizeof (unsigned short) +
323             s->extremityPoints.size () * sizeof (float) * 3;
324         writeChunkHeader(M_TABLE_EXTREMES, chunkSize);
325 
326         writeShorts(&idx, 1);
327 
328         float *vertices = OGRE_ALLOC_T(float, s->extremityPoints.size() * 3, MEMCATEGORY_GEOMETRY);
329 		float *pVert = vertices;
330 
331         for (vector<Vector3>::type::const_iterator i = s->extremityPoints.begin();
332              i != s->extremityPoints.end(); ++i)
333         {
334 			*pVert++ = i->x;
335 			*pVert++ = i->y;
336 			*pVert++ = i->z;
337         }
338 
339         writeFloats(vertices, s->extremityPoints.size () * 3);
340         OGRE_FREE(vertices, MEMCATEGORY_GEOMETRY);
341     }
342     //---------------------------------------------------------------------
writeSubMeshTextureAliases(const SubMesh * s)343     void MeshSerializerImpl::writeSubMeshTextureAliases(const SubMesh* s)
344     {
345         AliasTextureNamePairList::const_iterator i;
346 
347 		LogManager::getSingleton().logMessage("Exporting submesh texture aliases...");
348 
349         // iterate through texture aliases and write them out as a chunk
350         for (i = s->mTextureAliases.begin(); i != s->mTextureAliases.end(); ++i)
351         {
352             // calculate chunk size based on string length + 1.  Add 1 for the line feed.
353             size_t chunkSize = MSTREAM_OVERHEAD_SIZE + i->first.length() + i->second.length() + 2;
354 			writeChunkHeader(M_SUBMESH_TEXTURE_ALIAS, chunkSize);
355             // write out alias name
356             writeString(i->first);
357             // write out texture name
358             writeString(i->second);
359         }
360 
361 		LogManager::getSingleton().logMessage("Submesh texture aliases exported.");
362     }
363 
364     //---------------------------------------------------------------------
writeSubMeshOperation(const SubMesh * sm)365     void MeshSerializerImpl::writeSubMeshOperation(const SubMesh* sm)
366     {
367         // Header
368         writeChunkHeader(M_SUBMESH_OPERATION, calcSubMeshOperationSize(sm));
369 
370         // unsigned short operationType
371         unsigned short opType = static_cast<unsigned short>(sm->operationType);
372         writeShorts(&opType, 1);
373     }
374     //---------------------------------------------------------------------
writeGeometry(const VertexData * vertexData)375     void MeshSerializerImpl::writeGeometry(const VertexData* vertexData)
376     {
377 		// calc size
378         const VertexDeclaration::VertexElementList& elemList =
379             vertexData->vertexDeclaration->getElements();
380         const VertexBufferBinding::VertexBufferBindingMap& bindings =
381             vertexData->vertexBufferBinding->getBindings();
382         VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbiend;
383 
384 		size_t size = MSTREAM_OVERHEAD_SIZE + sizeof(unsigned int) + // base
385 			(MSTREAM_OVERHEAD_SIZE + elemList.size() * (MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5)); // elements
386         vbiend = bindings.end();
387 		for (vbi = bindings.begin(); vbi != vbiend; ++vbi)
388 		{
389 			const HardwareVertexBufferSharedPtr& vbuf = vbi->second;
390 			size += (MSTREAM_OVERHEAD_SIZE * 2) + (sizeof(unsigned short) * 2) + vbuf->getSizeInBytes();
391 		}
392 
393 		// Header
394         writeChunkHeader(M_GEOMETRY, size);
395 
396         unsigned int vertexCount = static_cast<unsigned int>(vertexData->vertexCount);
397         writeInts(&vertexCount, 1);
398 
399 		// Vertex declaration
400 		size = MSTREAM_OVERHEAD_SIZE + elemList.size() * (MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5);
401 		writeChunkHeader(M_GEOMETRY_VERTEX_DECLARATION, size);
402 
403         VertexDeclaration::VertexElementList::const_iterator vei, veiend;
404 		veiend = elemList.end();
405 		unsigned short tmp;
406 		size = MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5;
407 		for (vei = elemList.begin(); vei != veiend; ++vei)
408 		{
409 			const VertexElement& elem = *vei;
410 			writeChunkHeader(M_GEOMETRY_VERTEX_ELEMENT, size);
411 			// unsigned short source;  	// buffer bind source
412 			tmp = elem.getSource();
413 			writeShorts(&tmp, 1);
414 			// unsigned short type;    	// VertexElementType
415 			tmp = static_cast<unsigned short>(elem.getType());
416 			writeShorts(&tmp, 1);
417 			// unsigned short semantic; // VertexElementSemantic
418 			tmp = static_cast<unsigned short>(elem.getSemantic());
419 			writeShorts(&tmp, 1);
420 			// unsigned short offset;	// start offset in buffer in bytes
421 			tmp = static_cast<unsigned short>(elem.getOffset());
422 			writeShorts(&tmp, 1);
423 			// unsigned short index;	// index of the semantic (for colours and texture coords)
424 			tmp = elem.getIndex();
425 			writeShorts(&tmp, 1);
426 
427 		}
428 
429 		// Buffers and bindings
430 		vbiend = bindings.end();
431 		for (vbi = bindings.begin(); vbi != vbiend; ++vbi)
432 		{
433 			const HardwareVertexBufferSharedPtr& vbuf = vbi->second;
434 			size = (MSTREAM_OVERHEAD_SIZE * 2) + (sizeof(unsigned short) * 2) + vbuf->getSizeInBytes();
435 			writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER,  size);
436 			// unsigned short bindIndex;	// Index to bind this buffer to
437 			tmp = vbi->first;
438 			writeShorts(&tmp, 1);
439 			// unsigned short vertexSize;	// Per-vertex size, must agree with declaration at this index
440 			tmp = (unsigned short)vbuf->getVertexSize();
441 			writeShorts(&tmp, 1);
442 
443 			// Data
444 			size = MSTREAM_OVERHEAD_SIZE + vbuf->getSizeInBytes();
445 			writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
446 			void* pBuf = vbuf->lock(HardwareBuffer::HBL_READ_ONLY);
447 
448 			if (mFlipEndian)
449 			{
450 				// endian conversion
451 				// Copy data
452 				unsigned char* tempData = OGRE_ALLOC_T(unsigned char, vbuf->getSizeInBytes(), MEMCATEGORY_GEOMETRY);
453 				memcpy(tempData, pBuf, vbuf->getSizeInBytes());
454 				flipToLittleEndian(
455 					tempData,
456 					vertexData->vertexCount,
457 					vbuf->getVertexSize(),
458 					vertexData->vertexDeclaration->findElementsBySource(vbi->first));
459 				writeData(tempData, vbuf->getVertexSize(), vertexData->vertexCount);
460 				OGRE_FREE(tempData, MEMCATEGORY_GEOMETRY);
461 			}
462 			else
463 			{
464 				writeData(pBuf, vbuf->getVertexSize(), vertexData->vertexCount);
465 			}
466             vbuf->unlock();
467 		}
468 
469 
470     }
471     //---------------------------------------------------------------------
calcSubMeshNameTableSize(const Mesh * pMesh)472 	size_t MeshSerializerImpl::calcSubMeshNameTableSize(const Mesh* pMesh)
473 	{
474 		size_t size = MSTREAM_OVERHEAD_SIZE;
475 		// Figure out the size of the Name table.
476 		// Iterate through the subMeshList & add up the size of the indexes and names.
477 		Mesh::SubMeshNameMap::const_iterator it = pMesh->mSubMeshNameMap.begin();
478 		while(it != pMesh->mSubMeshNameMap.end())
479 		{
480 			// size of the index + header size for each element chunk
481 			size += MSTREAM_OVERHEAD_SIZE + sizeof(uint16);
482 			// name
483 			size += it->first.length() + 1;
484 
485 			++it;
486 		}
487 
488 		// size of the sub-mesh name table.
489 		return size;
490 	}
491     //---------------------------------------------------------------------
calcMeshSize(const Mesh * pMesh)492     size_t MeshSerializerImpl::calcMeshSize(const Mesh* pMesh)
493     {
494         size_t size = MSTREAM_OVERHEAD_SIZE;
495 
496         // Num shared vertices
497         size += sizeof(uint32);
498 
499         // Geometry
500         if (pMesh->sharedVertexData && pMesh->sharedVertexData->vertexCount > 0)
501         {
502             size += calcGeometrySize(pMesh->sharedVertexData);
503         }
504 
505         // Submeshes
506         for (unsigned short i = 0; i < pMesh->getNumSubMeshes(); ++i)
507         {
508             size += calcSubMeshSize(pMesh->getSubMesh(i));
509         }
510 
511         // Skeleton link
512         if (pMesh->hasSkeleton())
513         {
514             size += calcSkeletonLinkSize(pMesh->getSkeletonName());
515         }
516 
517 		// Submesh name table
518 		size += calcSubMeshNameTableSize(pMesh);
519 
520 		// Edge list
521 		if (pMesh->isEdgeListBuilt())
522 		{
523 			size += calcEdgeListSize(pMesh);
524 		}
525 
526 		// Animations
527 		for (unsigned short a = 0; a < pMesh->getNumAnimations(); ++a)
528 		{
529 			Animation* anim = pMesh->getAnimation(a);
530 			size += calcAnimationSize(anim);
531 		}
532 
533 		return size;
534     }
535     //---------------------------------------------------------------------
calcSubMeshSize(const SubMesh * pSub)536     size_t MeshSerializerImpl::calcSubMeshSize(const SubMesh* pSub)
537     {
538         size_t size = MSTREAM_OVERHEAD_SIZE;
539 
540 		bool idx32bit = (!pSub->indexData->indexBuffer.isNull() &&
541 						 pSub->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
542 
543         // Material name
544         size += pSub->getMaterialName().length() + 1;
545 
546         // bool useSharedVertices
547         size += sizeof(bool);
548         // unsigned int indexCount
549         size += sizeof(unsigned int);
550         // bool indexes32bit
551         size += sizeof(bool);
552         // unsigned int* / unsigned short* faceVertexIndices
553 		if (idx32bit)
554 			size += sizeof(unsigned int) * pSub->indexData->indexCount;
555 		else
556 			size += sizeof(unsigned short) * pSub->indexData->indexCount;
557         // Geometry
558         if (!pSub->useSharedVertices)
559         {
560             size += calcGeometrySize(pSub->vertexData);
561         }
562 
563         size += calcSubMeshTextureAliasesSize(pSub);
564         size += calcSubMeshOperationSize(pSub);
565 
566         // Bone assignments
567         if (!pSub->mBoneAssignments.empty())
568         {
569             SubMesh::VertexBoneAssignmentList::const_iterator vi;
570             for (vi = pSub->mBoneAssignments.begin();
571                  vi != pSub->mBoneAssignments.end(); ++vi)
572             {
573                 size += calcBoneAssignmentSize();
574             }
575         }
576 
577         return size;
578     }
579     //---------------------------------------------------------------------
calcSubMeshOperationSize(const SubMesh * pSub)580     size_t MeshSerializerImpl::calcSubMeshOperationSize(const SubMesh* pSub)
581     {
582         return MSTREAM_OVERHEAD_SIZE + sizeof(uint16);
583     }
584     //---------------------------------------------------------------------
calcSubMeshTextureAliasesSize(const SubMesh * pSub)585     size_t MeshSerializerImpl::calcSubMeshTextureAliasesSize(const SubMesh* pSub)
586     {
587         size_t chunkSize = 0;
588         AliasTextureNamePairList::const_iterator i;
589 
590         // iterate through texture alias map and calc size of strings
591         for (i = pSub->mTextureAliases.begin(); i != pSub->mTextureAliases.end(); ++i)
592         {
593             // calculate chunk size based on string length + 1.  Add 1 for the line feed.
594             chunkSize += MSTREAM_OVERHEAD_SIZE + i->first.length() + i->second.length() + 2;
595         }
596 
597         return chunkSize;
598     }
599     //---------------------------------------------------------------------
calcGeometrySize(const VertexData * vertexData)600     size_t MeshSerializerImpl::calcGeometrySize(const VertexData* vertexData)
601     {
602         size_t size = MSTREAM_OVERHEAD_SIZE;
603 
604         // Num vertices
605         size += sizeof(unsigned int);
606 
607         const VertexDeclaration::VertexElementList& elems =
608             vertexData->vertexDeclaration->getElements();
609 
610         // Vertex declaration
611 		size += MSTREAM_OVERHEAD_SIZE + elems.size() * (MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5);
612 
613         VertexDeclaration::VertexElementList::const_iterator i, iend;
614         iend = elems.end();
615         for (i = elems.begin(); i != iend; ++i)
616         {
617             // Vertex element header
618             size += MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) * 5;
619 
620             const VertexElement& elem = *i;
621             // Vertex element
622             size += VertexElement::getTypeSize(elem.getType()) * vertexData->vertexCount;
623         }
624         return size;
625     }
626     //---------------------------------------------------------------------
readGeometry(DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)627     void MeshSerializerImpl::readGeometry(DataStreamPtr& stream, Mesh* pMesh,
628         VertexData* dest)
629     {
630 
631         dest->vertexStart = 0;
632 
633         unsigned int vertexCount = 0;
634         readInts(stream, &vertexCount, 1);
635         dest->vertexCount = vertexCount;
636 
637         // Find optional geometry streams
638         if (!stream->eof())
639         {
640             unsigned short streamID = readChunk(stream);
641             while(!stream->eof() &&
642                 (streamID == M_GEOMETRY_VERTEX_DECLARATION ||
643                  streamID == M_GEOMETRY_VERTEX_BUFFER ))
644             {
645                 switch (streamID)
646                 {
647                 case M_GEOMETRY_VERTEX_DECLARATION:
648                     readGeometryVertexDeclaration(stream, pMesh, dest);
649                     break;
650                 case M_GEOMETRY_VERTEX_BUFFER:
651                     readGeometryVertexBuffer(stream, pMesh, dest);
652                     break;
653                 }
654                 // Get next stream
655                 if (!stream->eof())
656                 {
657                     streamID = readChunk(stream);
658                 }
659             }
660             if (!stream->eof())
661             {
662                 // Backpedal back to start of non-submesh stream
663                 stream->skip(-MSTREAM_OVERHEAD_SIZE);
664             }
665         }
666 
667 		// Perform any necessary colour conversion for an active rendersystem
668 		if (Root::getSingletonPtr() && Root::getSingleton().getRenderSystem())
669 		{
670 			// We don't know the source type if it's VET_COLOUR, but assume ARGB
671 			// since that's the most common. Won't get used unless the mesh is
672 			// ambiguous anyway, which will have been warned about in the log
673 			dest->convertPackedColour(VET_COLOUR_ARGB,
674 				VertexElement::getBestColourVertexElementType());
675 		}
676     }
677     //---------------------------------------------------------------------
readGeometryVertexDeclaration(DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)678     void MeshSerializerImpl::readGeometryVertexDeclaration(DataStreamPtr& stream,
679         Mesh* pMesh, VertexData* dest)
680     {
681         // Find optional geometry streams
682         if (!stream->eof())
683         {
684             unsigned short streamID = readChunk(stream);
685             while(!stream->eof() &&
686                 (streamID == M_GEOMETRY_VERTEX_ELEMENT ))
687             {
688                 switch (streamID)
689                 {
690                 case M_GEOMETRY_VERTEX_ELEMENT:
691                     readGeometryVertexElement(stream, pMesh, dest);
692                     break;
693                 }
694                 // Get next stream
695                 if (!stream->eof())
696                 {
697                     streamID = readChunk(stream);
698                 }
699             }
700             if (!stream->eof())
701             {
702                 // Backpedal back to start of non-submesh stream
703                 stream->skip(-MSTREAM_OVERHEAD_SIZE);
704             }
705         }
706 
707 	}
708     //---------------------------------------------------------------------
readGeometryVertexElement(DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)709     void MeshSerializerImpl::readGeometryVertexElement(DataStreamPtr& stream,
710         Mesh* pMesh, VertexData* dest)
711     {
712 		unsigned short source, offset, index, tmp;
713 		VertexElementType vType;
714 		VertexElementSemantic vSemantic;
715 		// unsigned short source;  	// buffer bind source
716 		readShorts(stream, &source, 1);
717 		// unsigned short type;    	// VertexElementType
718 		readShorts(stream, &tmp, 1);
719 		vType = static_cast<VertexElementType>(tmp);
720 		// unsigned short semantic; // VertexElementSemantic
721 		readShorts(stream, &tmp, 1);
722 		vSemantic = static_cast<VertexElementSemantic>(tmp);
723 		// unsigned short offset;	// start offset in buffer in bytes
724 		readShorts(stream, &offset, 1);
725 		// unsigned short index;	// index of the semantic
726 		readShorts(stream, &index, 1);
727 
728 		dest->vertexDeclaration->addElement(source, offset, vType, vSemantic, index);
729 
730 		if (vType == VET_COLOUR)
731 		{
732 			LogManager::getSingleton().stream()
733 				<< "Warning: VET_COLOUR element type is deprecated, you should use "
734 				<< "one of the more specific types to indicate the byte order. "
735 				<< "Use OgreMeshUpgrade on " << pMesh->getName() << " as soon as possible. ";
736 		}
737 
738 	}
739     //---------------------------------------------------------------------
readGeometryVertexBuffer(DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)740     void MeshSerializerImpl::readGeometryVertexBuffer(DataStreamPtr& stream,
741         Mesh* pMesh, VertexData* dest)
742     {
743 		unsigned short bindIndex, vertexSize;
744 		// unsigned short bindIndex;	// Index to bind this buffer to
745 		readShorts(stream, &bindIndex, 1);
746 		// unsigned short vertexSize;	// Per-vertex size, must agree with declaration at this index
747 		readShorts(stream, &vertexSize, 1);
748 
749 		// Check for vertex data header
750 		unsigned short headerID;
751 		headerID = readChunk(stream);
752 		if (headerID != M_GEOMETRY_VERTEX_BUFFER_DATA)
753 		{
754 			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Can't find vertex buffer data area",
755             	"MeshSerializerImpl::readGeometryVertexBuffer");
756 		}
757 		// Check that vertex size agrees
758 		if (dest->vertexDeclaration->getVertexSize(bindIndex) != vertexSize)
759 		{
760 			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Buffer vertex size does not agree with vertex declaration",
761             	"MeshSerializerImpl::readGeometryVertexBuffer");
762 		}
763 
764 		// Create / populate vertex buffer
765 		HardwareVertexBufferSharedPtr vbuf;
766         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
767             vertexSize,
768             dest->vertexCount,
769             pMesh->mVertexBufferUsage,
770 			pMesh->mVertexBufferShadowBuffer);
771         void* pBuf = vbuf->lock(HardwareBuffer::HBL_DISCARD);
772         stream->read(pBuf, dest->vertexCount * vertexSize);
773 
774 		// endian conversion for OSX
775 		flipFromLittleEndian(
776 			pBuf,
777 			dest->vertexCount,
778 			vertexSize,
779 			dest->vertexDeclaration->findElementsBySource(bindIndex));
780         vbuf->unlock();
781 
782 		// Set binding
783         dest->vertexBufferBinding->setBinding(bindIndex, vbuf);
784 
785 	}
786     //---------------------------------------------------------------------
readSubMeshNameTable(DataStreamPtr & stream,Mesh * pMesh)787 	void MeshSerializerImpl::readSubMeshNameTable(DataStreamPtr& stream, Mesh* pMesh)
788 	{
789 		// The map for
790 		map<unsigned short, String>::type subMeshNames;
791 		unsigned short subMeshIndex;
792 
793 		// Need something to store the index, and the objects name
794 		// This table is a method that imported meshes can retain their naming
795 		// so that the names established in the modelling software can be used
796 		// to get the sub-meshes by name. The exporter must support exporting
797 		// the optional stream M_SUBMESH_NAME_TABLE.
798 
799         // Read in all the sub-streams. Each sub-stream should contain an index and Ogre::String for the name.
800 		if (!stream->eof())
801 		{
802 			unsigned short streamID = readChunk(stream);
803 			while(!stream->eof() && (streamID == M_SUBMESH_NAME_TABLE_ELEMENT ))
804 			{
805 				// Read in the index of the submesh.
806 				readShorts(stream, &subMeshIndex, 1);
807 				// Read in the String and map it to its index.
808 				subMeshNames[subMeshIndex] = readString(stream);
809 
810 				// If we're not end of file get the next stream ID
811 				if (!stream->eof())
812 					streamID = readChunk(stream);
813 			}
814 			if (!stream->eof())
815 			{
816 				// Backpedal back to start of stream
817 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
818 			}
819 		}
820 
821 		// Set all the submeshes names
822 		// ?
823 
824 		// Loop through and save out the index and names.
825 		map<unsigned short, String>::type::const_iterator it = subMeshNames.begin();
826 
827 		while(it != subMeshNames.end())
828 		{
829 			// Name this submesh to the stored name.
830 			pMesh->nameSubMesh(it->second, it->first);
831 			++it;
832 		}
833 
834 
835 
836 	}
837     //---------------------------------------------------------------------
readMesh(DataStreamPtr & stream,Mesh * pMesh,MeshSerializerListener * listener)838     void MeshSerializerImpl::readMesh(DataStreamPtr& stream, Mesh* pMesh, MeshSerializerListener *listener)
839     {
840         // Never automatically build edge lists for this version
841         // expect them in the file or not at all
842         pMesh->mAutoBuildEdgeLists = false;
843 
844 		// bool skeletallyAnimated
845 		bool skeletallyAnimated;
846 		readBools(stream, &skeletallyAnimated, 1);
847 
848         // Find all substreams
849         if (!stream->eof())
850         {
851             unsigned short streamID = readChunk(stream);
852             while(!stream->eof() &&
853                 (streamID == M_GEOMETRY ||
854 				 streamID == M_SUBMESH ||
855                  streamID == M_MESH_SKELETON_LINK ||
856                  streamID == M_MESH_BONE_ASSIGNMENT ||
857 				 streamID == M_MESH_LOD ||
858                  streamID == M_MESH_BOUNDS ||
859 				 streamID == M_SUBMESH_NAME_TABLE ||
860 				 streamID == M_EDGE_LISTS ||
861 				 streamID == M_POSES ||
862 				 streamID == M_ANIMATIONS ||
863 				 streamID == M_TABLE_EXTREMES))
864             {
865                 switch(streamID)
866                 {
867 				case M_GEOMETRY:
868 					pMesh->sharedVertexData = OGRE_NEW VertexData();
869 					try {
870 						readGeometry(stream, pMesh, pMesh->sharedVertexData);
871 					}
872 					catch (Exception& e)
873 					{
874 						if (e.getNumber() == Exception::ERR_ITEM_NOT_FOUND)
875 						{
876 							// duff geometry data entry with 0 vertices
877 							OGRE_DELETE pMesh->sharedVertexData;
878 							pMesh->sharedVertexData = 0;
879 							// Skip this stream (pointer will have been returned to just after header)
880 							stream->skip(mCurrentstreamLen - MSTREAM_OVERHEAD_SIZE);
881 						}
882 						else
883 						{
884 							throw;
885 						}
886 					}
887 					break;
888                 case M_SUBMESH:
889                     readSubMesh(stream, pMesh, listener);
890                     break;
891                 case M_MESH_SKELETON_LINK:
892                     readSkeletonLink(stream, pMesh, listener);
893                     break;
894                 case M_MESH_BONE_ASSIGNMENT:
895                     readMeshBoneAssignment(stream, pMesh);
896                     break;
897                 case M_MESH_LOD:
898 					readMeshLodInfo(stream, pMesh);
899 					break;
900                 case M_MESH_BOUNDS:
901                     readBoundsInfo(stream, pMesh);
902                     break;
903 				case M_SUBMESH_NAME_TABLE:
904     	            readSubMeshNameTable(stream, pMesh);
905 					break;
906                 case M_EDGE_LISTS:
907                     readEdgeList(stream, pMesh);
908                     break;
909 				case M_POSES:
910 					readPoses(stream, pMesh);
911 					break;
912 				case M_ANIMATIONS:
913 					readAnimations(stream, pMesh);
914                     break;
915                 case M_TABLE_EXTREMES:
916                     readExtremes(stream, pMesh);
917                     break;
918                 }
919 
920                 if (!stream->eof())
921                 {
922                     streamID = readChunk(stream);
923                 }
924 
925             }
926             if (!stream->eof())
927             {
928                 // Backpedal back to start of stream
929                 stream->skip(-MSTREAM_OVERHEAD_SIZE);
930             }
931         }
932 
933     }
934     //---------------------------------------------------------------------
readSubMesh(DataStreamPtr & stream,Mesh * pMesh,MeshSerializerListener * listener)935     void MeshSerializerImpl::readSubMesh(DataStreamPtr& stream, Mesh* pMesh, MeshSerializerListener *listener)
936     {
937         unsigned short streamID;
938 
939         SubMesh* sm = pMesh->createSubMesh();
940 
941         // char* materialName
942         String materialName = readString(stream);
943 		if(listener)
944 			listener->processMaterialName(pMesh, &materialName);
945         sm->setMaterialName(materialName, pMesh->getGroup());
946 
947         // bool useSharedVertices
948         readBools(stream,&sm->useSharedVertices, 1);
949 
950         sm->indexData->indexStart = 0;
951         unsigned int indexCount = 0;
952         readInts(stream, &indexCount, 1);
953         sm->indexData->indexCount = indexCount;
954 
955         HardwareIndexBufferSharedPtr ibuf;
956         // bool indexes32Bit
957         bool idx32bit;
958         readBools(stream, &idx32bit, 1);
959         if (indexCount > 0)
960         {
961             if (idx32bit)
962             {
963                 ibuf = HardwareBufferManager::getSingleton().
964                     createIndexBuffer(
965                         HardwareIndexBuffer::IT_32BIT,
966                         sm->indexData->indexCount,
967                         pMesh->mIndexBufferUsage,
968 					    pMesh->mIndexBufferShadowBuffer);
969                 // unsigned int* faceVertexIndices
970                 unsigned int* pIdx = static_cast<unsigned int*>(
971                     ibuf->lock(HardwareBuffer::HBL_DISCARD)
972                     );
973                 readInts(stream, pIdx, sm->indexData->indexCount);
974                 ibuf->unlock();
975 
976             }
977             else // 16-bit
978             {
979                 ibuf = HardwareBufferManager::getSingleton().
980                     createIndexBuffer(
981                         HardwareIndexBuffer::IT_16BIT,
982                         sm->indexData->indexCount,
983                         pMesh->mIndexBufferUsage,
984 					    pMesh->mIndexBufferShadowBuffer);
985                 // unsigned short* faceVertexIndices
986                 unsigned short* pIdx = static_cast<unsigned short*>(
987                     ibuf->lock(HardwareBuffer::HBL_DISCARD)
988                     );
989                 readShorts(stream, pIdx, sm->indexData->indexCount);
990                 ibuf->unlock();
991             }
992         }
993         sm->indexData->indexBuffer = ibuf;
994 
995         // M_GEOMETRY stream (Optional: present only if useSharedVertices = false)
996         if (!sm->useSharedVertices)
997         {
998             streamID = readChunk(stream);
999             if (streamID != M_GEOMETRY)
1000             {
1001                 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Missing geometry data in mesh file",
1002                     "MeshSerializerImpl::readSubMesh");
1003             }
1004             sm->vertexData = OGRE_NEW VertexData();
1005             readGeometry(stream, pMesh, sm->vertexData);
1006         }
1007 
1008 
1009         // Find all bone assignments, submesh operation, and texture aliases (if present)
1010         if (!stream->eof())
1011         {
1012             streamID = readChunk(stream);
1013             while(!stream->eof() &&
1014                 (streamID == M_SUBMESH_BONE_ASSIGNMENT ||
1015                  streamID == M_SUBMESH_OPERATION ||
1016                  streamID == M_SUBMESH_TEXTURE_ALIAS))
1017             {
1018                 switch(streamID)
1019                 {
1020                 case M_SUBMESH_OPERATION:
1021                     readSubMeshOperation(stream, pMesh, sm);
1022                     break;
1023                 case M_SUBMESH_BONE_ASSIGNMENT:
1024                     readSubMeshBoneAssignment(stream, pMesh, sm);
1025                     break;
1026                 case M_SUBMESH_TEXTURE_ALIAS:
1027                     readSubMeshTextureAlias(stream, pMesh, sm);
1028                     break;
1029                 }
1030 
1031                 if (!stream->eof())
1032                 {
1033                     streamID = readChunk(stream);
1034                 }
1035 
1036             }
1037             if (!stream->eof())
1038             {
1039                 // Backpedal back to start of stream
1040                 stream->skip(-MSTREAM_OVERHEAD_SIZE);
1041             }
1042         }
1043 
1044 
1045     }
1046     //---------------------------------------------------------------------
readSubMeshOperation(DataStreamPtr & stream,Mesh * pMesh,SubMesh * sm)1047     void MeshSerializerImpl::readSubMeshOperation(DataStreamPtr& stream,
1048         Mesh* pMesh, SubMesh* sm)
1049     {
1050         // unsigned short operationType
1051         unsigned short opType;
1052         readShorts(stream, &opType, 1);
1053         sm->operationType = static_cast<RenderOperation::OperationType>(opType);
1054     }
1055     //---------------------------------------------------------------------
readSubMeshTextureAlias(DataStreamPtr & stream,Mesh * pMesh,SubMesh * sub)1056     void MeshSerializerImpl::readSubMeshTextureAlias(DataStreamPtr& stream, Mesh* pMesh, SubMesh* sub)
1057     {
1058         String aliasName = readString(stream);
1059         String textureName = readString(stream);
1060         sub->addTextureAlias(aliasName, textureName);
1061     }
1062     //---------------------------------------------------------------------
writeSkeletonLink(const String & skelName)1063     void MeshSerializerImpl::writeSkeletonLink(const String& skelName)
1064     {
1065         writeChunkHeader(M_MESH_SKELETON_LINK, calcSkeletonLinkSize(skelName));
1066 
1067         writeString(skelName);
1068 
1069     }
1070     //---------------------------------------------------------------------
readSkeletonLink(DataStreamPtr & stream,Mesh * pMesh,MeshSerializerListener * listener)1071     void MeshSerializerImpl::readSkeletonLink(DataStreamPtr& stream, Mesh* pMesh, MeshSerializerListener *listener)
1072     {
1073         String skelName = readString(stream);
1074 
1075 		if(listener)
1076 			listener->processSkeletonName(pMesh, &skelName);
1077 
1078         pMesh->setSkeletonName(skelName);
1079     }
1080     //---------------------------------------------------------------------
readTextureLayer(DataStreamPtr & stream,Mesh * pMesh,MaterialPtr & pMat)1081     void MeshSerializerImpl::readTextureLayer(DataStreamPtr& stream, Mesh* pMesh,
1082         MaterialPtr& pMat)
1083     {
1084         // Material definition section phased out of 1.1
1085     }
1086     //---------------------------------------------------------------------
calcSkeletonLinkSize(const String & skelName)1087     size_t MeshSerializerImpl::calcSkeletonLinkSize(const String& skelName)
1088     {
1089         size_t size = MSTREAM_OVERHEAD_SIZE;
1090 
1091         size += skelName.length() + 1;
1092 
1093         return size;
1094 
1095     }
1096     //---------------------------------------------------------------------
writeMeshBoneAssignment(const VertexBoneAssignment & assign)1097     void MeshSerializerImpl::writeMeshBoneAssignment(const VertexBoneAssignment& assign)
1098     {
1099         writeChunkHeader(M_MESH_BONE_ASSIGNMENT, calcBoneAssignmentSize());
1100 
1101         // unsigned int vertexIndex;
1102         writeInts(&(assign.vertexIndex), 1);
1103         // unsigned short boneIndex;
1104         writeShorts(&(assign.boneIndex), 1);
1105         // float weight;
1106         writeFloats(&(assign.weight), 1);
1107     }
1108     //---------------------------------------------------------------------
writeSubMeshBoneAssignment(const VertexBoneAssignment & assign)1109     void MeshSerializerImpl::writeSubMeshBoneAssignment(const VertexBoneAssignment& assign)
1110     {
1111         writeChunkHeader(M_SUBMESH_BONE_ASSIGNMENT, calcBoneAssignmentSize());
1112 
1113         // unsigned int vertexIndex;
1114         writeInts(&(assign.vertexIndex), 1);
1115         // unsigned short boneIndex;
1116         writeShorts(&(assign.boneIndex), 1);
1117         // float weight;
1118         writeFloats(&(assign.weight), 1);
1119     }
1120     //---------------------------------------------------------------------
readMeshBoneAssignment(DataStreamPtr & stream,Mesh * pMesh)1121     void MeshSerializerImpl::readMeshBoneAssignment(DataStreamPtr& stream, Mesh* pMesh)
1122     {
1123         VertexBoneAssignment assign;
1124 
1125         // unsigned int vertexIndex;
1126         readInts(stream, &(assign.vertexIndex),1);
1127         // unsigned short boneIndex;
1128         readShorts(stream, &(assign.boneIndex),1);
1129         // float weight;
1130         readFloats(stream, &(assign.weight), 1);
1131 
1132         pMesh->addBoneAssignment(assign);
1133 
1134     }
1135     //---------------------------------------------------------------------
readSubMeshBoneAssignment(DataStreamPtr & stream,Mesh * pMesh,SubMesh * sub)1136     void MeshSerializerImpl::readSubMeshBoneAssignment(DataStreamPtr& stream,
1137         Mesh* pMesh, SubMesh* sub)
1138     {
1139         VertexBoneAssignment assign;
1140 
1141         // unsigned int vertexIndex;
1142         readInts(stream, &(assign.vertexIndex),1);
1143         // unsigned short boneIndex;
1144         readShorts(stream, &(assign.boneIndex),1);
1145         // float weight;
1146         readFloats(stream, &(assign.weight), 1);
1147 
1148         sub->addBoneAssignment(assign);
1149 
1150     }
1151     //---------------------------------------------------------------------
calcBoneAssignmentSize(void)1152     size_t MeshSerializerImpl::calcBoneAssignmentSize(void)
1153     {
1154         size_t size = MSTREAM_OVERHEAD_SIZE;
1155 
1156         // Vert index
1157         size += sizeof(unsigned int);
1158         // Bone index
1159         size += sizeof(unsigned short);
1160         // weight
1161         size += sizeof(float);
1162 
1163         return size;
1164     }
1165     //---------------------------------------------------------------------
writeLodInfo(const Mesh * pMesh)1166     void MeshSerializerImpl::writeLodInfo(const Mesh* pMesh)
1167     {
1168         const LodStrategy *strategy = pMesh->getLodStrategy();
1169         unsigned short numLods = pMesh->getNumLodLevels();
1170         bool manual = pMesh->isLodManual();
1171         writeLodSummary(numLods, manual, strategy);
1172 
1173 		// Loop from LOD 1 (not 0, this is full detail)
1174         for (unsigned short i = 1; i < numLods; ++i)
1175         {
1176 			const MeshLodUsage& usage = pMesh->getLodLevel(i);
1177 			if (manual)
1178 			{
1179 				writeLodUsageManual(usage);
1180 			}
1181 			else
1182 			{
1183 				writeLodUsageGenerated(pMesh, usage, i);
1184 			}
1185 
1186         }
1187 
1188 
1189     }
1190     //---------------------------------------------------------------------
writeLodSummary(unsigned short numLevels,bool manual,const LodStrategy * strategy)1191     void MeshSerializerImpl::writeLodSummary(unsigned short numLevels, bool manual, const LodStrategy *strategy)
1192     {
1193         // Header
1194         size_t size = MSTREAM_OVERHEAD_SIZE;
1195         // unsigned short numLevels;
1196         size += sizeof(unsigned short);
1197         // bool manual;  (true for manual alternate meshes, false for generated)
1198         size += sizeof(bool);
1199         writeChunkHeader(M_MESH_LOD, size);
1200 
1201         // Details
1202         // string strategyName;
1203         writeString(strategy->getName());
1204         // unsigned short numLevels;
1205         writeShorts(&numLevels, 1);
1206         // bool manual;  (true for manual alternate meshes, false for generated)
1207         writeBools(&manual, 1);
1208 
1209 
1210     }
1211     //---------------------------------------------------------------------
writeLodUsageManual(const MeshLodUsage & usage)1212     void MeshSerializerImpl::writeLodUsageManual(const MeshLodUsage& usage)
1213     {
1214         // Header
1215         size_t size = MSTREAM_OVERHEAD_SIZE;
1216         size_t manualSize = MSTREAM_OVERHEAD_SIZE;
1217         // float lodValue;
1218         size += sizeof(float);
1219         // Manual part size
1220 
1221         // String manualMeshName;
1222         manualSize += usage.manualName.length() + 1;
1223 
1224         size += manualSize;
1225 
1226         writeChunkHeader(M_MESH_LOD_USAGE, size);
1227         writeFloats(&(usage.userValue), 1);
1228 
1229         writeChunkHeader(M_MESH_LOD_MANUAL, manualSize);
1230         writeString(usage.manualName);
1231 
1232 
1233     }
1234     //---------------------------------------------------------------------
writeLodUsageGenerated(const Mesh * pMesh,const MeshLodUsage & usage,unsigned short lodNum)1235     void MeshSerializerImpl::writeLodUsageGenerated(const Mesh* pMesh, const MeshLodUsage& usage,
1236 		unsigned short lodNum)
1237     {
1238 		// Usage Header
1239         size_t size = MSTREAM_OVERHEAD_SIZE;
1240 		unsigned short subidx;
1241 
1242         // float fromDepthSquared;
1243         size += sizeof(float);
1244 
1245         // Calc generated SubMesh sections size
1246 		for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
1247 		{
1248 			// header
1249 			size += MSTREAM_OVERHEAD_SIZE;
1250 			// unsigned int numFaces;
1251 			size += sizeof(unsigned int);
1252 			SubMesh* sm = pMesh->getSubMesh(subidx);
1253             const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
1254 
1255             // bool indexes32Bit
1256 			size += sizeof(bool);
1257 			// unsigned short*/int* faceIndexes;
1258             if (!indexData->indexBuffer.isNull() &&
1259 				indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
1260             {
1261 			    size += static_cast<unsigned long>(
1262                     sizeof(unsigned int) * indexData->indexCount);
1263             }
1264             else
1265             {
1266 			    size += static_cast<unsigned long>(
1267                     sizeof(unsigned short) * indexData->indexCount);
1268             }
1269 
1270 		}
1271 
1272         writeChunkHeader(M_MESH_LOD_USAGE, size);
1273         writeFloats(&(usage.userValue), 1);
1274 
1275 		// Now write sections
1276         // Calc generated SubMesh sections size
1277 		for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
1278 		{
1279 			size = MSTREAM_OVERHEAD_SIZE;
1280 			// unsigned int numFaces;
1281 			size += sizeof(unsigned int);
1282 			SubMesh* sm = pMesh->getSubMesh(subidx);
1283             const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
1284             // bool indexes32Bit
1285 			size += sizeof(bool);
1286 			// Lock index buffer to write
1287 			HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
1288 			// bool indexes32bit
1289 			bool idx32 = (!ibuf.isNull() && ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
1290 			// unsigned short*/int* faceIndexes;
1291             if (idx32)
1292             {
1293 			    size += static_cast<unsigned long>(
1294                     sizeof(unsigned int) * indexData->indexCount);
1295             }
1296             else
1297             {
1298 			    size += static_cast<unsigned long>(
1299                     sizeof(unsigned short) * indexData->indexCount);
1300             }
1301 
1302 			writeChunkHeader(M_MESH_LOD_GENERATED, size);
1303 			unsigned int idxCount = static_cast<unsigned int>(indexData->indexCount);
1304 			writeInts(&idxCount, 1);
1305 			writeBools(&idx32, 1);
1306 
1307 			if (idxCount > 0)
1308 			{
1309 				if (idx32)
1310 				{
1311 					unsigned int* pIdx = static_cast<unsigned int*>(
1312 						ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1313 					writeInts(pIdx, indexData->indexCount);
1314 					ibuf->unlock();
1315 				}
1316 				else
1317 				{
1318 					unsigned short* pIdx = static_cast<unsigned short*>(
1319 						ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
1320 					writeShorts(pIdx, indexData->indexCount);
1321 					ibuf->unlock();
1322 				}
1323 			}
1324 		}
1325 
1326 
1327     }
1328     //---------------------------------------------------------------------
writeBoundsInfo(const Mesh * pMesh)1329     void MeshSerializerImpl::writeBoundsInfo(const Mesh* pMesh)
1330     {
1331 		// Usage Header
1332         unsigned long size = MSTREAM_OVERHEAD_SIZE;
1333 
1334         size += sizeof(float) * 7;
1335         writeChunkHeader(M_MESH_BOUNDS, size);
1336 
1337         // float minx, miny, minz
1338         const Vector3& min = pMesh->mAABB.getMinimum();
1339         const Vector3& max = pMesh->mAABB.getMaximum();
1340         writeFloats(&min.x, 1);
1341         writeFloats(&min.y, 1);
1342         writeFloats(&min.z, 1);
1343         // float maxx, maxy, maxz
1344         writeFloats(&max.x, 1);
1345         writeFloats(&max.y, 1);
1346         writeFloats(&max.z, 1);
1347         // float radius
1348         writeFloats(&pMesh->mBoundRadius, 1);
1349 
1350     }
1351     //---------------------------------------------------------------------
readBoundsInfo(DataStreamPtr & stream,Mesh * pMesh)1352     void MeshSerializerImpl::readBoundsInfo(DataStreamPtr& stream, Mesh* pMesh)
1353     {
1354         Vector3 min, max;
1355         // float minx, miny, minz
1356         readFloats(stream, &min.x, 1);
1357         readFloats(stream, &min.y, 1);
1358         readFloats(stream, &min.z, 1);
1359         // float maxx, maxy, maxz
1360         readFloats(stream, &max.x, 1);
1361         readFloats(stream, &max.y, 1);
1362         readFloats(stream, &max.z, 1);
1363         AxisAlignedBox box(min, max);
1364         pMesh->_setBounds(box, true);
1365         // float radius
1366         float radius;
1367         readFloats(stream, &radius, 1);
1368         pMesh->_setBoundingSphereRadius(radius);
1369 
1370 
1371 
1372     }
1373     //---------------------------------------------------------------------
readMeshLodInfo(DataStreamPtr & stream,Mesh * pMesh)1374 	void MeshSerializerImpl::readMeshLodInfo(DataStreamPtr& stream, Mesh* pMesh)
1375 	{
1376 		unsigned short i;
1377 
1378         // Read the strategy to be used for this mesh
1379         String strategyName = readString(stream);
1380         LodStrategy *strategy = LodStrategyManager::getSingleton().getStrategy(strategyName);
1381 
1382         // Check that valid strategy name was given, otherwise use default
1383         if (strategy == 0)
1384             strategy = LodStrategyManager::getSingleton().getDefaultStrategy();
1385 
1386         pMesh->setLodStrategy(strategy);
1387 
1388         // unsigned short numLevels;
1389 		readShorts(stream, &(pMesh->mNumLods), 1);
1390         // bool manual;  (true for manual alternate meshes, false for generated)
1391 		readBools(stream, &(pMesh->mIsLodManual), 1);
1392 
1393 		// Preallocate submesh LOD face data if not manual
1394 		if (!pMesh->mIsLodManual)
1395 		{
1396 			unsigned short numsubs = pMesh->getNumSubMeshes();
1397 			for (i = 0; i < numsubs; ++i)
1398 			{
1399 				SubMesh* sm = pMesh->getSubMesh(i);
1400 				sm->mLodFaceList.resize(pMesh->mNumLods-1);
1401 			}
1402 		}
1403 
1404 		// Loop from 1 rather than 0 (full detail index is not in file)
1405 		for (i = 1; i < pMesh->mNumLods; ++i)
1406 		{
1407 			unsigned short streamID = readChunk(stream);
1408 			if (streamID != M_MESH_LOD_USAGE)
1409 			{
1410 				OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1411 					"Missing M_MESH_LOD_USAGE stream in " + pMesh->getName(),
1412 					"MeshSerializerImpl::readMeshLodInfo");
1413 			}
1414 			// Read depth
1415 			MeshLodUsage usage;
1416 			readFloats(stream, &(usage.userValue), 1);
1417 
1418 			if (pMesh->isLodManual())
1419 			{
1420 				readMeshLodUsageManual(stream, pMesh, i, usage);
1421 			}
1422 			else //(!pMesh->isLodManual)
1423 			{
1424 				readMeshLodUsageGenerated(stream, pMesh, i, usage);
1425 			}
1426             usage.edgeData = NULL;
1427 
1428 			// Save usage
1429 			pMesh->mMeshLodUsageList.push_back(usage);
1430 		}
1431 
1432 
1433 	}
1434     //---------------------------------------------------------------------
readMeshLodUsageManual(DataStreamPtr & stream,Mesh * pMesh,unsigned short lodNum,MeshLodUsage & usage)1435 	void MeshSerializerImpl::readMeshLodUsageManual(DataStreamPtr& stream,
1436         Mesh* pMesh, unsigned short lodNum, MeshLodUsage& usage)
1437 	{
1438 		unsigned long streamID;
1439 		// Read detail stream
1440 		streamID = readChunk(stream);
1441 		if (streamID != M_MESH_LOD_MANUAL)
1442 		{
1443 			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1444 				"Missing M_MESH_LOD_MANUAL stream in " + pMesh->getName(),
1445 				"MeshSerializerImpl::readMeshLodUsageManual");
1446 		}
1447 
1448 		usage.manualName = readString(stream);
1449 		usage.manualMesh.setNull(); // will trigger load later
1450 	}
1451     //---------------------------------------------------------------------
readMeshLodUsageGenerated(DataStreamPtr & stream,Mesh * pMesh,unsigned short lodNum,MeshLodUsage & usage)1452 	void MeshSerializerImpl::readMeshLodUsageGenerated(DataStreamPtr& stream,
1453         Mesh* pMesh, unsigned short lodNum, MeshLodUsage& usage)
1454 	{
1455 		usage.manualName = "";
1456 		usage.manualMesh.setNull();
1457 
1458 		// Get one set of detail per SubMesh
1459 		unsigned short numSubs, i;
1460 		numSubs = pMesh->getNumSubMeshes();
1461 		for (i = 0; i < numSubs; ++i)
1462 		{
1463 			unsigned short streamID = readChunk(stream);
1464 			if (streamID != M_MESH_LOD_GENERATED)
1465 			{
1466 				OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1467 					"Missing M_MESH_LOD_GENERATED stream in " + pMesh->getName(),
1468 					"MeshSerializerImpl::readMeshLodUsageGenerated");
1469 			}
1470 
1471 			SubMesh* sm = pMesh->getSubMesh(i);
1472 			// lodNum - 1 because SubMesh doesn't store full detail LOD
1473             sm->mLodFaceList[lodNum - 1] = OGRE_NEW IndexData();
1474 			IndexData* indexData = sm->mLodFaceList[lodNum - 1];
1475             // unsigned int numIndexes
1476             unsigned int numIndexes;
1477 			readInts(stream, &numIndexes, 1);
1478             indexData->indexCount = static_cast<size_t>(numIndexes);
1479             // bool indexes32Bit
1480             bool idx32Bit;
1481             readBools(stream, &idx32Bit, 1);
1482             // unsigned short*/int* faceIndexes;  ((v1, v2, v3) * numFaces)
1483             if (idx32Bit)
1484             {
1485                 indexData->indexBuffer = HardwareBufferManager::getSingleton().
1486                     createIndexBuffer(HardwareIndexBuffer::IT_32BIT, indexData->indexCount,
1487                     pMesh->mIndexBufferUsage, pMesh->mIndexBufferShadowBuffer);
1488                 unsigned int* pIdx = static_cast<unsigned int*>(
1489                     indexData->indexBuffer->lock(
1490                         0,
1491                         indexData->indexBuffer->getSizeInBytes(),
1492                         HardwareBuffer::HBL_DISCARD) );
1493 
1494 			    readInts(stream, pIdx, indexData->indexCount);
1495                 indexData->indexBuffer->unlock();
1496 
1497             }
1498             else
1499             {
1500                 indexData->indexBuffer = HardwareBufferManager::getSingleton().
1501                     createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount,
1502                     pMesh->mIndexBufferUsage, pMesh->mIndexBufferShadowBuffer);
1503                 unsigned short* pIdx = static_cast<unsigned short*>(
1504                     indexData->indexBuffer->lock(
1505                         0,
1506                         indexData->indexBuffer->getSizeInBytes(),
1507                         HardwareBuffer::HBL_DISCARD) );
1508 			    readShorts(stream, pIdx, indexData->indexCount);
1509                 indexData->indexBuffer->unlock();
1510 
1511             }
1512 
1513 		}
1514 	}
1515     //---------------------------------------------------------------------
flipFromLittleEndian(void * pData,size_t vertexCount,size_t vertexSize,const VertexDeclaration::VertexElementList & elems)1516     void MeshSerializerImpl::flipFromLittleEndian(void* pData, size_t vertexCount,
1517         size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
1518 	{
1519 		if (mFlipEndian)
1520 		{
1521 	        flipEndian(pData, vertexCount, vertexSize, elems);
1522 		}
1523     }
1524     //---------------------------------------------------------------------
flipToLittleEndian(void * pData,size_t vertexCount,size_t vertexSize,const VertexDeclaration::VertexElementList & elems)1525     void MeshSerializerImpl::flipToLittleEndian(void* pData, size_t vertexCount,
1526 			size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
1527 	{
1528 		if (mFlipEndian)
1529 		{
1530 	        flipEndian(pData, vertexCount, vertexSize, elems);
1531 		}
1532 	}
1533     //---------------------------------------------------------------------
flipEndian(void * pData,size_t vertexCount,size_t vertexSize,const VertexDeclaration::VertexElementList & elems)1534     void MeshSerializerImpl::flipEndian(void* pData, size_t vertexCount,
1535         size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
1536 	{
1537 		void *pBase = pData;
1538 		for (size_t v = 0; v < vertexCount; ++v)
1539 		{
1540 			VertexDeclaration::VertexElementList::const_iterator ei, eiend;
1541 			eiend = elems.end();
1542 			for (ei = elems.begin(); ei != eiend; ++ei)
1543 			{
1544 				void *pElem;
1545 				// re-base pointer to the element
1546 				(*ei).baseVertexPointerToElement(pBase, &pElem);
1547 				// Flip the endian based on the type
1548 				size_t typeSize = 0;
1549 				switch (VertexElement::getBaseType((*ei).getType()))
1550 				{
1551 					case VET_FLOAT1:
1552 						typeSize = sizeof(float);
1553 						break;
1554 					case VET_DOUBLE1:
1555 						typeSize = sizeof(double);
1556 						break;
1557 					case VET_SHORT1:
1558 						typeSize = sizeof(short);
1559 						break;
1560 					case VET_USHORT1:
1561 						typeSize = sizeof(unsigned short);
1562 						break;
1563 					case VET_INT1:
1564 						typeSize = sizeof(int);
1565 						break;
1566 					case VET_UINT1:
1567 						typeSize = sizeof(unsigned int);
1568 						break;
1569 					case VET_COLOUR:
1570 					case VET_COLOUR_ABGR:
1571 					case VET_COLOUR_ARGB:
1572 						typeSize = sizeof(RGBA);
1573 						break;
1574 					case VET_UBYTE4:
1575 						typeSize = 0; // NO FLIPPING
1576 						break;
1577 					default:
1578 						assert(false); // Should never happen
1579 				};
1580                 Serializer::flipEndian(pElem, typeSize,
1581 					VertexElement::getTypeCount((*ei).getType()));
1582 
1583 			}
1584 
1585 			pBase = static_cast<void*>(
1586 				static_cast<unsigned char*>(pBase) + vertexSize);
1587 
1588 		}
1589 	}
1590     //---------------------------------------------------------------------
calcEdgeListSize(const Mesh * pMesh)1591 	size_t MeshSerializerImpl::calcEdgeListSize(const Mesh* pMesh)
1592 	{
1593         size_t size = MSTREAM_OVERHEAD_SIZE;
1594 
1595         for (ushort i = 0; i < pMesh->getNumLodLevels(); ++i)
1596         {
1597 
1598             const EdgeData* edgeData = pMesh->getEdgeList(i);
1599             bool isManual = pMesh->isLodManual() && (i > 0);
1600 
1601             size += calcEdgeListLodSize(edgeData, isManual);
1602 
1603         }
1604 
1605         return size;
1606 	}
1607     //---------------------------------------------------------------------
calcEdgeListLodSize(const EdgeData * edgeData,bool isManual)1608     size_t MeshSerializerImpl::calcEdgeListLodSize(const EdgeData* edgeData, bool isManual)
1609     {
1610         size_t size = MSTREAM_OVERHEAD_SIZE;
1611 
1612         // unsigned short lodIndex
1613         size += sizeof(uint16);
1614 
1615         // bool isManual			// If manual, no edge data here, loaded from manual mesh
1616         size += sizeof(bool);
1617         if (!isManual)
1618         {
1619             // bool isClosed
1620             size += sizeof(bool);
1621             // unsigned long numTriangles
1622             size += sizeof(uint32);
1623             // unsigned long numEdgeGroups
1624             size += sizeof(uint32);
1625             // Triangle* triangleList
1626             size_t triSize = 0;
1627             // unsigned long indexSet
1628             // unsigned long vertexSet
1629             // unsigned long vertIndex[3]
1630             // unsigned long sharedVertIndex[3]
1631             // float normal[4]
1632             triSize += sizeof(uint32) * 8
1633                     + sizeof(float) * 4;
1634 
1635             size += triSize * edgeData->triangles.size();
1636             // Write the groups
1637             for (EdgeData::EdgeGroupList::const_iterator gi = edgeData->edgeGroups.begin();
1638                 gi != edgeData->edgeGroups.end(); ++gi)
1639             {
1640                 const EdgeData::EdgeGroup& edgeGroup = *gi;
1641                 size += calcEdgeGroupSize(edgeGroup);
1642             }
1643 
1644         }
1645 
1646         return size;
1647     }
1648     //---------------------------------------------------------------------
calcEdgeGroupSize(const EdgeData::EdgeGroup & group)1649     size_t MeshSerializerImpl::calcEdgeGroupSize(const EdgeData::EdgeGroup& group)
1650     {
1651         size_t size = MSTREAM_OVERHEAD_SIZE;
1652 
1653         // unsigned long vertexSet
1654         size += sizeof(uint32);
1655         // unsigned long triStart
1656         size += sizeof(uint32);
1657         // unsigned long triCount
1658         size += sizeof(uint32);
1659         // unsigned long numEdges
1660         size += sizeof(uint32);
1661         // Edge* edgeList
1662         size_t edgeSize = 0;
1663         // unsigned long  triIndex[2]
1664         // unsigned long  vertIndex[2]
1665         // unsigned long  sharedVertIndex[2]
1666         // bool degenerate
1667         edgeSize += sizeof(uint32) * 6 + sizeof(bool);
1668         size += edgeSize * group.edges.size();
1669 
1670         return size;
1671     }
1672     //---------------------------------------------------------------------
writeEdgeList(const Mesh * pMesh)1673 	void MeshSerializerImpl::writeEdgeList(const Mesh* pMesh)
1674 	{
1675         writeChunkHeader(M_EDGE_LISTS, calcEdgeListSize(pMesh));
1676 
1677         for (ushort i = 0; i < pMesh->getNumLodLevels(); ++i)
1678         {
1679             const EdgeData* edgeData = pMesh->getEdgeList(i);
1680             bool isManual = pMesh->isLodManual() && (i > 0);
1681             writeChunkHeader(M_EDGE_LIST_LOD, calcEdgeListLodSize(edgeData, isManual));
1682 
1683             // unsigned short lodIndex
1684             writeShorts(&i, 1);
1685 
1686             // bool isManual			// If manual, no edge data here, loaded from manual mesh
1687             writeBools(&isManual, 1);
1688             if (!isManual)
1689             {
1690                 // bool isClosed
1691                 writeBools(&edgeData->isClosed, 1);
1692                 // unsigned long  numTriangles
1693                 uint32 count = static_cast<uint32>(edgeData->triangles.size());
1694                 writeInts(&count, 1);
1695                 // unsigned long numEdgeGroups
1696                 count = static_cast<uint32>(edgeData->edgeGroups.size());
1697                 writeInts(&count, 1);
1698                 // Triangle* triangleList
1699                 // Iterate rather than writing en-masse to allow endian conversion
1700                 EdgeData::TriangleList::const_iterator t = edgeData->triangles.begin();
1701                 EdgeData::TriangleFaceNormalList::const_iterator fni = edgeData->triangleFaceNormals.begin();
1702                 for ( ; t != edgeData->triangles.end(); ++t, ++fni)
1703                 {
1704                     const EdgeData::Triangle& tri = *t;
1705                     // unsigned long indexSet;
1706                     uint32 tmp[3];
1707                     tmp[0] = static_cast<uint32>(tri.indexSet);
1708                     writeInts(tmp, 1);
1709                     // unsigned long vertexSet;
1710                     tmp[0] = static_cast<uint32>(tri.vertexSet);
1711                     writeInts(tmp, 1);
1712                     // unsigned long vertIndex[3];
1713                     tmp[0] = static_cast<uint32>(tri.vertIndex[0]);
1714                     tmp[1] = static_cast<uint32>(tri.vertIndex[1]);
1715                     tmp[2] = static_cast<uint32>(tri.vertIndex[2]);
1716                     writeInts(tmp, 3);
1717                     // unsigned long sharedVertIndex[3];
1718                     tmp[0] = static_cast<uint32>(tri.sharedVertIndex[0]);
1719                     tmp[1] = static_cast<uint32>(tri.sharedVertIndex[1]);
1720                     tmp[2] = static_cast<uint32>(tri.sharedVertIndex[2]);
1721                     writeInts(tmp, 3);
1722                     // float normal[4];
1723                     writeFloats(&(fni->x), 4);
1724 
1725                 }
1726                 // Write the groups
1727                 for (EdgeData::EdgeGroupList::const_iterator gi = edgeData->edgeGroups.begin();
1728                     gi != edgeData->edgeGroups.end(); ++gi)
1729                 {
1730                     const EdgeData::EdgeGroup& edgeGroup = *gi;
1731                     writeChunkHeader(M_EDGE_GROUP, calcEdgeGroupSize(edgeGroup));
1732                     // unsigned long vertexSet
1733                     uint32 vertexSet = static_cast<uint32>(edgeGroup.vertexSet);
1734                     writeInts(&vertexSet, 1);
1735                     // unsigned long triStart
1736                     uint32 triStart = static_cast<uint32>(edgeGroup.triStart);
1737                     writeInts(&triStart, 1);
1738                     // unsigned long triCount
1739                     uint32 triCount = static_cast<uint32>(edgeGroup.triCount);
1740                     writeInts(&triCount, 1);
1741                     // unsigned long numEdges
1742                     count = static_cast<uint32>(edgeGroup.edges.size());
1743                     writeInts(&count, 1);
1744                     // Edge* edgeList
1745                     // Iterate rather than writing en-masse to allow endian conversion
1746                     for (EdgeData::EdgeList::const_iterator ei = edgeGroup.edges.begin();
1747                         ei != edgeGroup.edges.end(); ++ei)
1748                     {
1749                         const EdgeData::Edge& edge = *ei;
1750                         uint32 tmp[2];
1751                         // unsigned long  triIndex[2]
1752                         tmp[0] = static_cast<uint32>(edge.triIndex[0]);
1753                         tmp[1] = static_cast<uint32>(edge.triIndex[1]);
1754                         writeInts(tmp, 2);
1755                         // unsigned long  vertIndex[2]
1756                         tmp[0] = static_cast<uint32>(edge.vertIndex[0]);
1757                         tmp[1] = static_cast<uint32>(edge.vertIndex[1]);
1758                         writeInts(tmp, 2);
1759                         // unsigned long  sharedVertIndex[2]
1760                         tmp[0] = static_cast<uint32>(edge.sharedVertIndex[0]);
1761                         tmp[1] = static_cast<uint32>(edge.sharedVertIndex[1]);
1762                         writeInts(tmp, 2);
1763                         // bool degenerate
1764                         writeBools(&(edge.degenerate), 1);
1765                     }
1766 
1767                 }
1768 
1769             }
1770 
1771         }
1772 	}
1773     //---------------------------------------------------------------------
readEdgeList(DataStreamPtr & stream,Mesh * pMesh)1774 	void MeshSerializerImpl::readEdgeList(DataStreamPtr& stream, Mesh* pMesh)
1775 	{
1776         if (!stream->eof())
1777         {
1778             unsigned short streamID = readChunk(stream);
1779             while(!stream->eof() &&
1780                 streamID == M_EDGE_LIST_LOD)
1781             {
1782                 // Process single LOD
1783 
1784                 // unsigned short lodIndex
1785                 unsigned short lodIndex;
1786                 readShorts(stream, &lodIndex, 1);
1787 
1788                 // bool isManual			// If manual, no edge data here, loaded from manual mesh
1789                 bool isManual;
1790                 readBools(stream, &isManual, 1);
1791                 // Only load in non-manual levels; others will be connected up by Mesh on demand
1792                 if (!isManual)
1793                 {
1794                     MeshLodUsage& usage = const_cast<MeshLodUsage&>(pMesh->getLodLevel(lodIndex));
1795 
1796                     usage.edgeData = OGRE_NEW EdgeData();
1797 
1798                     // Read detail information of the edge list
1799                     readEdgeListLodInfo(stream, usage.edgeData);
1800 
1801                     // Postprocessing edge groups
1802                     EdgeData::EdgeGroupList::iterator egi, egend;
1803                     egend = usage.edgeData->edgeGroups.end();
1804                     for (egi = usage.edgeData->edgeGroups.begin(); egi != egend; ++egi)
1805                     {
1806                         EdgeData::EdgeGroup& edgeGroup = *egi;
1807                         // Populate edgeGroup.vertexData pointers
1808                         // If there is shared vertex data, vertexSet 0 is that,
1809                         // otherwise 0 is first dedicated
1810                         if (pMesh->sharedVertexData)
1811                         {
1812                             if (edgeGroup.vertexSet == 0)
1813                             {
1814                                 edgeGroup.vertexData = pMesh->sharedVertexData;
1815                             }
1816                             else
1817                             {
1818                                 edgeGroup.vertexData = pMesh->getSubMesh(
1819                                     (unsigned short)edgeGroup.vertexSet-1)->vertexData;
1820                             }
1821                         }
1822                         else
1823                         {
1824                             edgeGroup.vertexData = pMesh->getSubMesh(
1825                                 (unsigned short)edgeGroup.vertexSet)->vertexData;
1826                         }
1827                     }
1828                 }
1829 
1830                 if (!stream->eof())
1831                 {
1832                     streamID = readChunk(stream);
1833                 }
1834 
1835             }
1836             if (!stream->eof())
1837             {
1838                 // Backpedal back to start of stream
1839                 stream->skip(-MSTREAM_OVERHEAD_SIZE);
1840             }
1841         }
1842 
1843         pMesh->mEdgeListsBuilt = true;
1844 	}
1845 	//---------------------------------------------------------------------
readEdgeListLodInfo(DataStreamPtr & stream,EdgeData * edgeData)1846     void MeshSerializerImpl::readEdgeListLodInfo(DataStreamPtr& stream,
1847         EdgeData* edgeData)
1848     {
1849         // bool isClosed
1850         readBools(stream, &edgeData->isClosed, 1);
1851         // unsigned long numTriangles
1852         uint32 numTriangles;
1853         readInts(stream, &numTriangles, 1);
1854         // Allocate correct amount of memory
1855         edgeData->triangles.resize(numTriangles);
1856         edgeData->triangleFaceNormals.resize(numTriangles);
1857         edgeData->triangleLightFacings.resize(numTriangles);
1858         // unsigned long numEdgeGroups
1859         uint32 numEdgeGroups;
1860         readInts(stream, &numEdgeGroups, 1);
1861         // Allocate correct amount of memory
1862         edgeData->edgeGroups.resize(numEdgeGroups);
1863         // Triangle* triangleList
1864         uint32 tmp[3];
1865         for (size_t t = 0; t < numTriangles; ++t)
1866         {
1867             EdgeData::Triangle& tri = edgeData->triangles[t];
1868             // unsigned long indexSet
1869             readInts(stream, tmp, 1);
1870             tri.indexSet = tmp[0];
1871             // unsigned long vertexSet
1872             readInts(stream, tmp, 1);
1873             tri.vertexSet = tmp[0];
1874             // unsigned long vertIndex[3]
1875             readInts(stream, tmp, 3);
1876             tri.vertIndex[0] = tmp[0];
1877             tri.vertIndex[1] = tmp[1];
1878             tri.vertIndex[2] = tmp[2];
1879             // unsigned long sharedVertIndex[3]
1880             readInts(stream, tmp, 3);
1881             tri.sharedVertIndex[0] = tmp[0];
1882             tri.sharedVertIndex[1] = tmp[1];
1883             tri.sharedVertIndex[2] = tmp[2];
1884             // float normal[4]
1885             readFloats(stream, &(edgeData->triangleFaceNormals[t].x), 4);
1886 
1887         }
1888 
1889         for (uint32 eg = 0; eg < numEdgeGroups; ++eg)
1890         {
1891             unsigned short streamID = readChunk(stream);
1892             if (streamID != M_EDGE_GROUP)
1893             {
1894                 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
1895                     "Missing M_EDGE_GROUP stream",
1896                     "MeshSerializerImpl::readEdgeListLodInfo");
1897             }
1898             EdgeData::EdgeGroup& edgeGroup = edgeData->edgeGroups[eg];
1899 
1900             // unsigned long vertexSet
1901             readInts(stream, tmp, 1);
1902             edgeGroup.vertexSet = tmp[0];
1903             // unsigned long triStart
1904             readInts(stream, tmp, 1);
1905             edgeGroup.triStart = tmp[0];
1906             // unsigned long triCount
1907             readInts(stream, tmp, 1);
1908             edgeGroup.triCount = tmp[0];
1909             // unsigned long numEdges
1910             uint32 numEdges;
1911             readInts(stream, &numEdges, 1);
1912             edgeGroup.edges.resize(numEdges);
1913             // Edge* edgeList
1914             for (uint32 e = 0; e < numEdges; ++e)
1915             {
1916                 EdgeData::Edge& edge = edgeGroup.edges[e];
1917                 // unsigned long  triIndex[2]
1918                 readInts(stream, tmp, 2);
1919                 edge.triIndex[0] = tmp[0];
1920                 edge.triIndex[1] = tmp[1];
1921                 // unsigned long  vertIndex[2]
1922                 readInts(stream, tmp, 2);
1923                 edge.vertIndex[0] = tmp[0];
1924                 edge.vertIndex[1] = tmp[1];
1925                 // unsigned long  sharedVertIndex[2]
1926                 readInts(stream, tmp, 2);
1927                 edge.sharedVertIndex[0] = tmp[0];
1928                 edge.sharedVertIndex[1] = tmp[1];
1929                 // bool degenerate
1930                 readBools(stream, &(edge.degenerate), 1);
1931             }
1932         }
1933     }
1934 	//---------------------------------------------------------------------
calcAnimationsSize(const Mesh * pMesh)1935 	size_t MeshSerializerImpl::calcAnimationsSize(const Mesh* pMesh)
1936 	{
1937 		size_t size = MSTREAM_OVERHEAD_SIZE;
1938 
1939 		for (unsigned short a = 0; a < pMesh->getNumAnimations(); ++a)
1940 		{
1941 			Animation* anim = pMesh->getAnimation(a);
1942 			size += calcAnimationSize(anim);
1943 		}
1944 		return size;
1945 
1946 	}
1947 	//---------------------------------------------------------------------
calcAnimationSize(const Animation * anim)1948 	size_t MeshSerializerImpl::calcAnimationSize(const Animation* anim)
1949 	{
1950 		size_t size = MSTREAM_OVERHEAD_SIZE;
1951 		// char* name
1952 		size += anim->getName().length() + 1;
1953 
1954 		// float length
1955 		size += sizeof(float);
1956 
1957 		Animation::VertexTrackIterator trackIt = anim->getVertexTrackIterator();
1958 		while (trackIt.hasMoreElements())
1959 		{
1960 			VertexAnimationTrack* vt = trackIt.getNext();
1961 			size += calcAnimationTrackSize(vt);
1962 		}
1963 
1964 		return size;
1965 	}
1966 	//---------------------------------------------------------------------
calcAnimationTrackSize(const VertexAnimationTrack * track)1967 	size_t MeshSerializerImpl::calcAnimationTrackSize(const VertexAnimationTrack* track)
1968 	{
1969 		size_t size = MSTREAM_OVERHEAD_SIZE;
1970 		// uint16 type
1971 		size += sizeof(uint16);
1972 		// unsigned short target		// 0 for shared geometry,
1973 		size += sizeof(unsigned short);
1974 
1975 		if (track->getAnimationType() == VAT_MORPH)
1976 		{
1977 			for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
1978 			{
1979 				VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(i);
1980 				size += calcMorphKeyframeSize(kf, track->getAssociatedVertexData()->vertexCount);
1981 			}
1982 		}
1983 		else
1984 		{
1985 			for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
1986 			{
1987 				VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(i);
1988 				size += calcPoseKeyframeSize(kf);
1989 			}
1990 		}
1991 		return size;
1992 	}
1993 	//---------------------------------------------------------------------
calcMorphKeyframeSize(const VertexMorphKeyFrame * kf,size_t vertexCount)1994 	size_t MeshSerializerImpl::calcMorphKeyframeSize(const VertexMorphKeyFrame* kf,
1995 		size_t vertexCount)
1996 	{
1997 		size_t size = MSTREAM_OVERHEAD_SIZE;
1998 		// float time
1999 		size += sizeof(float);
2000 		// float x,y,z[,nx,ny,nz]
2001 		bool includesNormals = kf->getVertexBuffer()->getVertexSize() > (sizeof(float) * 3);
2002 		size += sizeof(float) * (includesNormals ? 6 : 3) * vertexCount;
2003 
2004 		return size;
2005 	}
2006 	//---------------------------------------------------------------------
calcPoseKeyframeSize(const VertexPoseKeyFrame * kf)2007 	size_t MeshSerializerImpl::calcPoseKeyframeSize(const VertexPoseKeyFrame* kf)
2008 	{
2009 		size_t size = MSTREAM_OVERHEAD_SIZE;
2010 
2011 		// float time
2012 		size += sizeof(float);
2013 
2014 		size += calcPoseKeyframePoseRefSize() * kf->getPoseReferences().size();
2015 
2016 		return size;
2017 
2018 	}
2019 	//---------------------------------------------------------------------
calcPoseKeyframePoseRefSize(void)2020 	size_t MeshSerializerImpl::calcPoseKeyframePoseRefSize(void)
2021 	{
2022 		size_t size = MSTREAM_OVERHEAD_SIZE;
2023 		// unsigned short poseIndex
2024 		size += sizeof(uint16);
2025 		// float influence
2026 		size += sizeof(float);
2027 
2028 		return size;
2029 
2030 	}
2031 	//---------------------------------------------------------------------
calcPosesSize(const Mesh * pMesh)2032 	size_t MeshSerializerImpl::calcPosesSize(const Mesh* pMesh)
2033 	{
2034 		size_t size = MSTREAM_OVERHEAD_SIZE;
2035 
2036 		Mesh::ConstPoseIterator poseIt = pMesh->getPoseIterator();
2037 		while (poseIt.hasMoreElements())
2038 		{
2039 			size += calcPoseSize(poseIt.getNext());
2040 		}
2041 		return size;
2042 	}
2043 	//---------------------------------------------------------------------
calcPoseSize(const Pose * pose)2044 	size_t MeshSerializerImpl::calcPoseSize(const Pose* pose)
2045 	{
2046 		size_t size = MSTREAM_OVERHEAD_SIZE;
2047 
2048 		// char* name (may be blank)
2049 		size += pose->getName().length() + 1;
2050 		// unsigned short target
2051 		size += sizeof(uint16);
2052 		// bool includesNormals
2053 		size += sizeof(bool);
2054 
2055 		// vertex offsets
2056 		size += pose->getVertexOffsets().size() * calcPoseVertexSize(pose);
2057 
2058 		return size;
2059 
2060 	}
2061 	//---------------------------------------------------------------------
calcPoseVertexSize(const Pose * pose)2062 	size_t MeshSerializerImpl::calcPoseVertexSize(const Pose* pose)
2063 	{
2064 		size_t size = MSTREAM_OVERHEAD_SIZE;
2065 		// unsigned long vertexIndex
2066 		size += sizeof(uint32);
2067 		// float xoffset, yoffset, zoffset
2068 		size += sizeof(float) * 3;
2069 		// optional normals
2070 		if (!pose->getNormals().empty())
2071 			size += sizeof(float) * 3;
2072 
2073 		return size;
2074 	}
2075 	//---------------------------------------------------------------------
writePoses(const Mesh * pMesh)2076 	void MeshSerializerImpl::writePoses(const Mesh* pMesh)
2077 	{
2078 		Mesh::ConstPoseIterator poseIterator = pMesh->getPoseIterator();
2079 		if (poseIterator.hasMoreElements())
2080 		{
2081 			writeChunkHeader(M_POSES, calcPosesSize(pMesh));
2082 			while (poseIterator.hasMoreElements())
2083 			{
2084 				writePose(poseIterator.getNext());
2085 			}
2086 		}
2087 
2088 	}
2089 	//---------------------------------------------------------------------
writePose(const Pose * pose)2090 	void MeshSerializerImpl::writePose(const Pose* pose)
2091 	{
2092 		writeChunkHeader(M_POSE, calcPoseSize(pose));
2093 
2094 		// char* name (may be blank)
2095 		writeString(pose->getName());
2096 
2097 		// unsigned short target
2098 		ushort val = pose->getTarget();
2099 		writeShorts(&val, 1);
2100 
2101 		// bool includesNormals
2102 		bool includesNormals = !pose->getNormals().empty();
2103 		writeBools(&includesNormals, 1);
2104 
2105 		size_t vertexSize = calcPoseVertexSize(pose);
2106 		Pose::ConstVertexOffsetIterator vit = pose->getVertexOffsetIterator();
2107 		Pose::ConstNormalsIterator nit = pose->getNormalsIterator();
2108 		while (vit.hasMoreElements())
2109 		{
2110 			uint32 vertexIndex = (uint32)vit.peekNextKey();
2111 			Vector3 offset = vit.getNext();
2112 			writeChunkHeader(M_POSE_VERTEX, vertexSize);
2113 			// unsigned long vertexIndex
2114 			writeInts(&vertexIndex, 1);
2115 			// float xoffset, yoffset, zoffset
2116 			writeFloats(offset.ptr(), 3);
2117 			if (includesNormals)
2118 			{
2119 				Vector3 normal = nit.getNext();
2120 				// float xnormal, ynormal, znormal
2121 				writeFloats(normal.ptr(), 3);
2122 			}
2123 		}
2124 
2125 
2126 	}
2127 	//---------------------------------------------------------------------
writeAnimations(const Mesh * pMesh)2128 	void MeshSerializerImpl::writeAnimations(const Mesh* pMesh)
2129 	{
2130 		writeChunkHeader(M_ANIMATIONS, calcAnimationsSize(pMesh));
2131 
2132 		for (unsigned short a = 0; a < pMesh->getNumAnimations(); ++a)
2133 		{
2134 			Animation* anim = pMesh->getAnimation(a);
2135 			LogManager::getSingleton().logMessage("Exporting animation " + anim->getName());
2136 			writeAnimation(anim);
2137 			LogManager::getSingleton().logMessage("Animation exported.");
2138 		}
2139 	}
2140 	//---------------------------------------------------------------------
writeAnimation(const Animation * anim)2141 	void MeshSerializerImpl::writeAnimation(const Animation* anim)
2142 	{
2143 		writeChunkHeader(M_ANIMATION, calcAnimationSize(anim));
2144 		// char* name
2145 		writeString(anim->getName());
2146 		// float length
2147 		float len = anim->getLength();
2148 		writeFloats(&len, 1);
2149 
2150 		if (anim->getUseBaseKeyFrame())
2151 		{
2152 			size_t size = MSTREAM_OVERHEAD_SIZE;
2153 			// char* baseAnimationName (including terminator)
2154 			size += anim->getBaseKeyFrameAnimationName().length() + 1;
2155 			// float baseKeyFrameTime
2156 			size += sizeof(float);
2157 
2158 			writeChunkHeader(M_ANIMATION_BASEINFO, size);
2159 
2160 			// char* baseAnimationName (blank for self)
2161 			writeString(anim->getBaseKeyFrameAnimationName());
2162 
2163 			// float baseKeyFrameTime
2164 			float t = (float)anim->getBaseKeyFrameTime();
2165 			writeFloats(&t, 1);
2166 		}
2167 
2168 		// tracks
2169 		Animation::VertexTrackIterator trackIt = anim->getVertexTrackIterator();
2170 		while (trackIt.hasMoreElements())
2171 		{
2172 			VertexAnimationTrack* vt = trackIt.getNext();
2173 			writeAnimationTrack(vt);
2174 		}
2175 
2176 
2177 	}
2178     //---------------------------------------------------------------------
writeAnimationTrack(const VertexAnimationTrack * track)2179 	void MeshSerializerImpl::writeAnimationTrack(const VertexAnimationTrack* track)
2180 	{
2181 		writeChunkHeader(M_ANIMATION_TRACK, calcAnimationTrackSize(track));
2182 		// unsigned short type			// 1 == morph, 2 == pose
2183 		uint16 animType = (uint16)track->getAnimationType();
2184 		writeShorts(&animType, 1);
2185 		// unsigned short target
2186 		uint16 target = track->getHandle();
2187 		writeShorts(&target, 1);
2188 
2189 		if (track->getAnimationType() == VAT_MORPH)
2190 		{
2191 			for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
2192 			{
2193 				VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(i);
2194 				writeMorphKeyframe(kf, track->getAssociatedVertexData()->vertexCount);
2195 			}
2196 		}
2197 		else // VAT_POSE
2198 		{
2199 			for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
2200 			{
2201 				VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(i);
2202 				writePoseKeyframe(kf);
2203 			}
2204 		}
2205 
2206 	}
2207 	//---------------------------------------------------------------------
writeMorphKeyframe(const VertexMorphKeyFrame * kf,size_t vertexCount)2208 	void MeshSerializerImpl::writeMorphKeyframe(const VertexMorphKeyFrame* kf, size_t vertexCount)
2209 	{
2210 		writeChunkHeader(M_ANIMATION_MORPH_KEYFRAME, calcMorphKeyframeSize(kf, vertexCount));
2211 		// float time
2212 		float timePos = kf->getTime();
2213 		writeFloats(&timePos, 1);
2214 		// bool includeNormals
2215 		bool includeNormals = kf->getVertexBuffer()->getVertexSize() > (sizeof(float) * 3);
2216 		writeBools(&includeNormals, 1);
2217 		// float x,y,z			// repeat by number of vertices in original geometry
2218 		float* pSrc = static_cast<float*>(
2219 			kf->getVertexBuffer()->lock(HardwareBuffer::HBL_READ_ONLY));
2220 		writeFloats(pSrc, vertexCount * (includeNormals ? 6 : 3));
2221 		kf->getVertexBuffer()->unlock();
2222 	}
2223 	//---------------------------------------------------------------------
writePoseKeyframe(const VertexPoseKeyFrame * kf)2224 	void MeshSerializerImpl::writePoseKeyframe(const VertexPoseKeyFrame* kf)
2225 	{
2226 		writeChunkHeader(M_ANIMATION_POSE_KEYFRAME, calcPoseKeyframeSize(kf));
2227 		// float time
2228 		float timePos = kf->getTime();
2229 		writeFloats(&timePos, 1);
2230 
2231 		// pose references
2232 		VertexPoseKeyFrame::ConstPoseRefIterator poseRefIt =
2233 			kf->getPoseReferenceIterator();
2234 		while (poseRefIt.hasMoreElements())
2235 		{
2236 			writePoseKeyframePoseRef(poseRefIt.getNext());
2237 		}
2238 
2239 
2240 
2241 	}
2242 	//---------------------------------------------------------------------
writePoseKeyframePoseRef(const VertexPoseKeyFrame::PoseRef & poseRef)2243 	void MeshSerializerImpl::writePoseKeyframePoseRef(
2244 		const VertexPoseKeyFrame::PoseRef& poseRef)
2245 	{
2246 		writeChunkHeader(M_ANIMATION_POSE_REF, calcPoseKeyframePoseRefSize());
2247 		// unsigned short poseIndex
2248 		writeShorts(&(poseRef.poseIndex), 1);
2249 		// float influence
2250 		writeFloats(&(poseRef.influence), 1);
2251 	}
2252 	//---------------------------------------------------------------------
readPoses(DataStreamPtr & stream,Mesh * pMesh)2253 	void MeshSerializerImpl::readPoses(DataStreamPtr& stream, Mesh* pMesh)
2254 	{
2255 		// Find all substreams
2256 		if (!stream->eof())
2257 		{
2258 			unsigned short streamID = readChunk(stream);
2259 			while(!stream->eof() &&
2260 				(streamID == M_POSE))
2261 			{
2262 				switch(streamID)
2263 				{
2264 				case M_POSE:
2265 					readPose(stream, pMesh);
2266 					break;
2267 
2268 				}
2269 
2270 				if (!stream->eof())
2271 				{
2272 					streamID = readChunk(stream);
2273 				}
2274 
2275 			}
2276 			if (!stream->eof())
2277 			{
2278 				// Backpedal back to start of stream
2279 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
2280 			}
2281 		}
2282 	}
2283 	//---------------------------------------------------------------------
readPose(DataStreamPtr & stream,Mesh * pMesh)2284 	void MeshSerializerImpl::readPose(DataStreamPtr& stream, Mesh* pMesh)
2285 	{
2286 		// char* name (may be blank)
2287 		String name = readString(stream);
2288 		// unsigned short target
2289 		unsigned short target;
2290 		readShorts(stream, &target, 1);
2291 
2292 		// bool includesNormals
2293 		bool includesNormals;
2294 		readBools(stream, &includesNormals, 1);
2295 
2296 		Pose* pose = pMesh->createPose(target, name);
2297 
2298 		// Find all substreams
2299 		if (!stream->eof())
2300 		{
2301 			unsigned short streamID = readChunk(stream);
2302 			while(!stream->eof() &&
2303 				(streamID == M_POSE_VERTEX))
2304 			{
2305 				switch(streamID)
2306 				{
2307 				case M_POSE_VERTEX:
2308 					// create vertex offset
2309 					uint32 vertIndex;
2310 					Vector3 offset, normal;
2311 					// unsigned long vertexIndex
2312 					readInts(stream, &vertIndex, 1);
2313 					// float xoffset, yoffset, zoffset
2314 					readFloats(stream, offset.ptr(), 3);
2315 
2316 					if (includesNormals)
2317 					{
2318 						readFloats(stream, normal.ptr(), 3);
2319 						pose->addVertex(vertIndex, offset, normal);
2320 					}
2321 					else
2322 					{
2323 						pose->addVertex(vertIndex, offset);
2324 					}
2325 
2326 
2327 					break;
2328 
2329 				}
2330 
2331 				if (!stream->eof())
2332 				{
2333 					streamID = readChunk(stream);
2334 				}
2335 
2336 			}
2337 			if (!stream->eof())
2338 			{
2339 				// Backpedal back to start of stream
2340 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
2341 			}
2342 		}
2343 
2344 	}
2345 	//---------------------------------------------------------------------
readAnimations(DataStreamPtr & stream,Mesh * pMesh)2346 	void MeshSerializerImpl::readAnimations(DataStreamPtr& stream, Mesh* pMesh)
2347 	{
2348 		// Find all substreams
2349 		if (!stream->eof())
2350 		{
2351 			unsigned short streamID = readChunk(stream);
2352 			while(!stream->eof() &&
2353 				(streamID == M_ANIMATION))
2354 			{
2355 				switch(streamID)
2356 				{
2357 				case M_ANIMATION:
2358 					readAnimation(stream, pMesh);
2359 					break;
2360 
2361 				}
2362 
2363 				if (!stream->eof())
2364 				{
2365 					streamID = readChunk(stream);
2366 				}
2367 
2368 			}
2369 			if (!stream->eof())
2370 			{
2371 				// Backpedal back to start of stream
2372 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
2373 			}
2374 		}
2375 
2376 
2377 	}
2378 	//---------------------------------------------------------------------
readAnimation(DataStreamPtr & stream,Mesh * pMesh)2379 	void MeshSerializerImpl::readAnimation(DataStreamPtr& stream, Mesh* pMesh)
2380 	{
2381 
2382 		// char* name
2383 		String name = readString(stream);
2384 		// float length
2385 		float len;
2386 		readFloats(stream, &len, 1);
2387 
2388 		Animation* anim = pMesh->createAnimation(name, len);
2389 
2390 		// tracks
2391 		if (!stream->eof())
2392 		{
2393 			unsigned short streamID = readChunk(stream);
2394 
2395 			// Optional base info is possible
2396 			if (streamID == M_ANIMATION_BASEINFO)
2397 			{
2398 				// char baseAnimationName
2399 				String baseAnimName = readString(stream);
2400 				// float baseKeyFrameTime
2401 				float baseKeyTime;
2402 				readFloats(stream, &baseKeyTime, 1);
2403 
2404 				anim->setUseBaseKeyFrame(true, baseKeyTime, baseAnimName);
2405 
2406                 if (!stream->eof())
2407                 {
2408                     // Get next stream
2409                     streamID = readChunk(stream);
2410                 }
2411 			}
2412 
2413 			while(!stream->eof() &&
2414 				streamID == M_ANIMATION_TRACK)
2415 			{
2416 				switch(streamID)
2417 				{
2418 				case M_ANIMATION_TRACK:
2419 					readAnimationTrack(stream, anim, pMesh);
2420 					break;
2421 				};
2422 				if (!stream->eof())
2423 				{
2424 					streamID = readChunk(stream);
2425 				}
2426 
2427 			}
2428 			if (!stream->eof())
2429 			{
2430 				// Backpedal back to start of stream
2431 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
2432 			}
2433 		}
2434 	}
2435 	//---------------------------------------------------------------------
readAnimationTrack(DataStreamPtr & stream,Animation * anim,Mesh * pMesh)2436 	void MeshSerializerImpl::readAnimationTrack(DataStreamPtr& stream,
2437 		Animation* anim, Mesh* pMesh)
2438 	{
2439 		// ushort type
2440 		uint16 inAnimType;
2441 		readShorts(stream, &inAnimType, 1);
2442 		VertexAnimationType animType = (VertexAnimationType)inAnimType;
2443 
2444 		// unsigned short target
2445 		uint16 target;
2446 		readShorts(stream, &target, 1);
2447 
2448 		VertexAnimationTrack* track = anim->createVertexTrack(target,
2449 			pMesh->getVertexDataByTrackHandle(target), animType);
2450 
2451 		// keyframes
2452 		if (!stream->eof())
2453 		{
2454 			unsigned short streamID = readChunk(stream);
2455 			while(!stream->eof() &&
2456 				(streamID == M_ANIMATION_MORPH_KEYFRAME ||
2457 				 streamID == M_ANIMATION_POSE_KEYFRAME))
2458 			{
2459 				switch(streamID)
2460 				{
2461 				case M_ANIMATION_MORPH_KEYFRAME:
2462 					readMorphKeyFrame(stream, track);
2463 					break;
2464 				case M_ANIMATION_POSE_KEYFRAME:
2465 					readPoseKeyFrame(stream, track);
2466 					break;
2467 				};
2468 				if (!stream->eof())
2469 				{
2470 					streamID = readChunk(stream);
2471 				}
2472 
2473 			}
2474 			if (!stream->eof())
2475 			{
2476 				// Backpedal back to start of stream
2477 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
2478 			}
2479 		}
2480 
2481 	}
2482 	//---------------------------------------------------------------------
readMorphKeyFrame(DataStreamPtr & stream,VertexAnimationTrack * track)2483 	void MeshSerializerImpl::readMorphKeyFrame(DataStreamPtr& stream, VertexAnimationTrack* track)
2484 	{
2485 		// float time
2486 		float timePos;
2487 		readFloats(stream, &timePos, 1);
2488 
2489 		// bool includesNormals
2490 		bool includesNormals;
2491 		readBools(stream, &includesNormals, 1);
2492 
2493 		VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(timePos);
2494 
2495 		// Create buffer, allow read and use shadow buffer
2496 		size_t vertexCount = track->getAssociatedVertexData()->vertexCount;
2497 		size_t vertexSize = sizeof(float) * (includesNormals ? 6 : 3);
2498 		HardwareVertexBufferSharedPtr vbuf =
2499 			HardwareBufferManager::getSingleton().createVertexBuffer(
2500 				vertexSize, vertexCount,
2501 				HardwareBuffer::HBU_STATIC, true);
2502 		// float x,y,z			// repeat by number of vertices in original geometry
2503 		float* pDst = static_cast<float*>(
2504 			vbuf->lock(HardwareBuffer::HBL_DISCARD));
2505 		readFloats(stream, pDst, vertexCount * (includesNormals ? 6 : 3));
2506 		vbuf->unlock();
2507 		kf->setVertexBuffer(vbuf);
2508 
2509 	}
2510 	//---------------------------------------------------------------------
readPoseKeyFrame(DataStreamPtr & stream,VertexAnimationTrack * track)2511 	void MeshSerializerImpl::readPoseKeyFrame(DataStreamPtr& stream, VertexAnimationTrack* track)
2512 	{
2513 		// float time
2514 		float timePos;
2515 		readFloats(stream, &timePos, 1);
2516 
2517 		// Create keyframe
2518 		VertexPoseKeyFrame* kf = track->createVertexPoseKeyFrame(timePos);
2519 
2520 		if (!stream->eof())
2521 		{
2522 			unsigned short streamID = readChunk(stream);
2523 			while(!stream->eof() &&
2524 				streamID == M_ANIMATION_POSE_REF)
2525 			{
2526 				switch(streamID)
2527 				{
2528 				case M_ANIMATION_POSE_REF:
2529 					uint16 poseIndex;
2530 					float influence;
2531 					// unsigned short poseIndex
2532 					readShorts(stream, &poseIndex, 1);
2533 					// float influence
2534 					readFloats(stream, &influence, 1);
2535 
2536 					kf->addPoseReference(poseIndex, influence);
2537 
2538 					break;
2539 				};
2540 				if (!stream->eof())
2541 				{
2542 					streamID = readChunk(stream);
2543 				}
2544 
2545 			}
2546 			if (!stream->eof())
2547 			{
2548 				// Backpedal back to start of stream
2549 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
2550 			}
2551 		}
2552 
2553 	}
2554 	//---------------------------------------------------------------------
readExtremes(DataStreamPtr & stream,Mesh * pMesh)2555 	void MeshSerializerImpl::readExtremes(DataStreamPtr& stream, Mesh *pMesh)
2556 	{
2557 		unsigned short idx;
2558 		readShorts(stream, &idx, 1);
2559 
2560 		SubMesh *sm = pMesh->getSubMesh (idx);
2561 
2562 		int n_floats = (mCurrentstreamLen - MSTREAM_OVERHEAD_SIZE -
2563 						sizeof (unsigned short)) / sizeof (float);
2564 
2565         assert ((n_floats % 3) == 0);
2566 
2567         float *vert = OGRE_ALLOC_T(float, n_floats, MEMCATEGORY_GEOMETRY);
2568 		readFloats(stream, vert, n_floats);
2569 
2570         for (int i = 0; i < n_floats; i += 3)
2571 			sm->extremityPoints.push_back(Vector3(vert [i], vert [i + 1], vert [i + 2]));
2572 
2573         OGRE_FREE(vert, MEMCATEGORY_GEOMETRY);
2574 	}
2575     //---------------------------------------------------------------------
2576     //---------------------------------------------------------------------
2577     //---------------------------------------------------------------------
MeshSerializerImpl_v1_41()2578 	MeshSerializerImpl_v1_41::MeshSerializerImpl_v1_41()
2579 	{
2580         // Version number
2581         mVersion = "[MeshSerializer_v1.41]";
2582 	}
2583     //---------------------------------------------------------------------
~MeshSerializerImpl_v1_41()2584 	MeshSerializerImpl_v1_41::~MeshSerializerImpl_v1_41()
2585 	{
2586 	}
2587     //---------------------------------------------------------------------
writeMorphKeyframe(const VertexMorphKeyFrame * kf,size_t vertexCount)2588 	void MeshSerializerImpl_v1_41::writeMorphKeyframe(const VertexMorphKeyFrame* kf, size_t vertexCount)
2589 	{
2590 		writeChunkHeader(M_ANIMATION_MORPH_KEYFRAME, calcMorphKeyframeSize(kf, vertexCount));
2591 		// float time
2592 		float timePos = kf->getTime();
2593 		writeFloats(&timePos, 1);
2594 		// float x,y,z			// repeat by number of vertices in original geometry
2595 		float* pSrc = static_cast<float*>(
2596 			kf->getVertexBuffer()->lock(HardwareBuffer::HBL_READ_ONLY));
2597 		writeFloats(pSrc, vertexCount * 3);
2598 		kf->getVertexBuffer()->unlock();
2599 	}
2600     //---------------------------------------------------------------------
readMorphKeyFrame(DataStreamPtr & stream,VertexAnimationTrack * track)2601 	void MeshSerializerImpl_v1_41::readMorphKeyFrame(DataStreamPtr& stream, VertexAnimationTrack* track)
2602 	{
2603 		// float time
2604 		float timePos;
2605 		readFloats(stream, &timePos, 1);
2606 
2607 		VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(timePos);
2608 
2609 		// Create buffer, allow read and use shadow buffer
2610 		size_t vertexCount = track->getAssociatedVertexData()->vertexCount;
2611 		HardwareVertexBufferSharedPtr vbuf =
2612 			HardwareBufferManager::getSingleton().createVertexBuffer(
2613 				VertexElement::getTypeSize(VET_FLOAT3), vertexCount,
2614 				HardwareBuffer::HBU_STATIC, true);
2615 		// float x,y,z			// repeat by number of vertices in original geometry
2616 		float* pDst = static_cast<float*>(
2617 			vbuf->lock(HardwareBuffer::HBL_DISCARD));
2618 		readFloats(stream, pDst, vertexCount * 3);
2619 		vbuf->unlock();
2620 		kf->setVertexBuffer(vbuf);
2621 	}
2622     //---------------------------------------------------------------------
writePose(const Pose * pose)2623 	void MeshSerializerImpl_v1_41::writePose(const Pose* pose)
2624 	{
2625 		writeChunkHeader(M_POSE, calcPoseSize(pose));
2626 
2627 		// char* name (may be blank)
2628 		writeString(pose->getName());
2629 
2630 		// unsigned short target
2631 		ushort val = pose->getTarget();
2632 		writeShorts(&val, 1);
2633 
2634 		size_t vertexSize = calcPoseVertexSize();
2635 		Pose::ConstVertexOffsetIterator vit = pose->getVertexOffsetIterator();
2636 		while (vit.hasMoreElements())
2637 		{
2638 			uint32 vertexIndex = (uint32)vit.peekNextKey();
2639 			Vector3 offset = vit.getNext();
2640 			writeChunkHeader(M_POSE_VERTEX, vertexSize);
2641 			// unsigned long vertexIndex
2642 			writeInts(&vertexIndex, 1);
2643 			// float xoffset, yoffset, zoffset
2644 			writeFloats(offset.ptr(), 3);
2645 		}
2646 	}
2647     //---------------------------------------------------------------------
readPose(DataStreamPtr & stream,Mesh * pMesh)2648 	void MeshSerializerImpl_v1_41::readPose(DataStreamPtr& stream, Mesh* pMesh)
2649 	{
2650 		// char* name (may be blank)
2651 		String name = readString(stream);
2652 		// unsigned short target
2653 		unsigned short target;
2654 		readShorts(stream, &target, 1);
2655 
2656 		Pose* pose = pMesh->createPose(target, name);
2657 
2658 		// Find all substreams
2659 		if (!stream->eof())
2660 		{
2661 			unsigned short streamID = readChunk(stream);
2662 			while(!stream->eof() &&
2663 				(streamID == M_POSE_VERTEX))
2664 			{
2665 				switch(streamID)
2666 				{
2667 				case M_POSE_VERTEX:
2668 					// create vertex offset
2669 					uint32 vertIndex;
2670 					Vector3 offset;
2671 					// unsigned long vertexIndex
2672 					readInts(stream, &vertIndex, 1);
2673 					// float xoffset, yoffset, zoffset
2674 					readFloats(stream, offset.ptr(), 3);
2675 
2676 					pose->addVertex(vertIndex, offset);
2677 					break;
2678 
2679 				}
2680 
2681 				if (!stream->eof())
2682 				{
2683 					streamID = readChunk(stream);
2684 				}
2685 
2686 			}
2687 			if (!stream->eof())
2688 			{
2689 				// Backpedal back to start of stream
2690 				stream->skip(-MSTREAM_OVERHEAD_SIZE);
2691 			}
2692 		}
2693 	}
2694 	//---------------------------------------------------------------------
calcPoseSize(const Pose * pose)2695 	size_t MeshSerializerImpl_v1_41::calcPoseSize(const Pose* pose)
2696 	{
2697 		size_t size = MSTREAM_OVERHEAD_SIZE;
2698 
2699 		// char* name (may be blank)
2700 		size += pose->getName().length() + 1;
2701 		// unsigned short target
2702 		size += sizeof(uint16);
2703 
2704 		// vertex offsets
2705 		size += pose->getVertexOffsets().size() * calcPoseVertexSize();
2706 
2707 		return size;
2708 
2709 	}
2710 	//---------------------------------------------------------------------
calcPoseVertexSize(void)2711 	size_t MeshSerializerImpl_v1_41::calcPoseVertexSize(void)
2712 	{
2713 		size_t size = MSTREAM_OVERHEAD_SIZE;
2714 		// unsigned long vertexIndex
2715 		size += sizeof(uint32);
2716 		// float xoffset, yoffset, zoffset
2717 		size += sizeof(float) * 3;
2718 
2719 		return size;
2720 	}
2721 	//---------------------------------------------------------------------
calcMorphKeyframeSize(const VertexMorphKeyFrame * kf,size_t vertexCount)2722 	size_t MeshSerializerImpl_v1_41::calcMorphKeyframeSize(const VertexMorphKeyFrame* kf,
2723 		size_t vertexCount)
2724 	{
2725 		size_t size = MSTREAM_OVERHEAD_SIZE;
2726 		// float time
2727 		size += sizeof(float);
2728 		// float x,y,z
2729 		size += sizeof(float) * 3 * vertexCount;
2730 
2731 		return size;
2732 	}
2733 
2734     //---------------------------------------------------------------------
2735     //---------------------------------------------------------------------
MeshSerializerImpl_v1_4()2736     MeshSerializerImpl_v1_4::MeshSerializerImpl_v1_4()
2737     {
2738         // Version number
2739         mVersion = "[MeshSerializer_v1.40]";
2740     }
2741     //---------------------------------------------------------------------
~MeshSerializerImpl_v1_4()2742     MeshSerializerImpl_v1_4::~MeshSerializerImpl_v1_4()
2743     {
2744     }
2745     //---------------------------------------------------------------------
writeLodSummary(unsigned short numLevels,bool manual,const LodStrategy * strategy)2746     void MeshSerializerImpl_v1_4::writeLodSummary(unsigned short numLevels, bool manual, const LodStrategy *strategy)
2747     {
2748         // Header
2749         size_t size = MSTREAM_OVERHEAD_SIZE;
2750         // unsigned short numLevels;
2751         size += sizeof(unsigned short);
2752         // bool manual;  (true for manual alternate meshes, false for generated)
2753         size += sizeof(bool);
2754         writeChunkHeader(M_MESH_LOD, size);
2755 
2756         // Details
2757         // unsigned short numLevels;
2758         writeShorts(&numLevels, 1);
2759         // bool manual;  (true for manual alternate meshes, false for generated)
2760         writeBools(&manual, 1);
2761 
2762 
2763     }
2764     //---------------------------------------------------------------------
writeLodUsageManual(const MeshLodUsage & usage)2765     void MeshSerializerImpl_v1_4::writeLodUsageManual(const MeshLodUsage& usage)
2766     {
2767         // Header
2768         size_t size = MSTREAM_OVERHEAD_SIZE;
2769         size_t manualSize = MSTREAM_OVERHEAD_SIZE;
2770         // float fromDepthSquared;
2771         size += sizeof(float);
2772         // Manual part size
2773 
2774         // String manualMeshName;
2775         manualSize += usage.manualName.length() + 1;
2776 
2777         size += manualSize;
2778 
2779         writeChunkHeader(M_MESH_LOD_USAGE, size);
2780 		// Main difference to later version here is that we use 'value' (squared depth)
2781 		// rather than 'userValue' which is just depth
2782         writeFloats(&(usage.value), 1);
2783 
2784         writeChunkHeader(M_MESH_LOD_MANUAL, manualSize);
2785         writeString(usage.manualName);
2786 
2787 
2788     }
2789     //---------------------------------------------------------------------
writeLodUsageGenerated(const Mesh * pMesh,const MeshLodUsage & usage,unsigned short lodNum)2790     void MeshSerializerImpl_v1_4::writeLodUsageGenerated(const Mesh* pMesh, const MeshLodUsage& usage,
2791 													unsigned short lodNum)
2792     {
2793 		// Usage Header
2794         size_t size = MSTREAM_OVERHEAD_SIZE;
2795 		unsigned short subidx;
2796 
2797         // float fromDepthSquared;
2798         size += sizeof(float);
2799 
2800         // Calc generated SubMesh sections size
2801 		for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
2802 		{
2803 			// header
2804 			size += MSTREAM_OVERHEAD_SIZE;
2805 			// unsigned int numFaces;
2806 			size += sizeof(unsigned int);
2807 			SubMesh* sm = pMesh->getSubMesh(subidx);
2808             const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
2809 
2810             // bool indexes32Bit
2811 			size += sizeof(bool);
2812 			// unsigned short*/int* faceIndexes;
2813             if (!indexData->indexBuffer.isNull() &&
2814 				indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
2815             {
2816 			    size += static_cast<unsigned long>(
2817 												   sizeof(unsigned int) * indexData->indexCount);
2818             }
2819             else
2820             {
2821 			    size += static_cast<unsigned long>(
2822 												   sizeof(unsigned short) * indexData->indexCount);
2823             }
2824 
2825 		}
2826 
2827         writeChunkHeader(M_MESH_LOD_USAGE, size);
2828 		// Main difference to later version here is that we use 'value' (squared depth)
2829 		// rather than 'userValue' which is just depth
2830         writeFloats(&(usage.value), 1);
2831 
2832 		// Now write sections
2833         // Calc generated SubMesh sections size
2834 		for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
2835 		{
2836 			size = MSTREAM_OVERHEAD_SIZE;
2837 			// unsigned int numFaces;
2838 			size += sizeof(unsigned int);
2839 			SubMesh* sm = pMesh->getSubMesh(subidx);
2840             const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
2841             // bool indexes32Bit
2842 			size += sizeof(bool);
2843 			// Lock index buffer to write
2844 			HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
2845 			// bool indexes32bit
2846 			bool idx32 = (!ibuf.isNull() && ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
2847 			// unsigned short*/int* faceIndexes;
2848             if (idx32)
2849             {
2850 			    size += static_cast<unsigned long>(
2851 												   sizeof(unsigned int) * indexData->indexCount);
2852             }
2853             else
2854             {
2855 			    size += static_cast<unsigned long>(
2856 												   sizeof(unsigned short) * indexData->indexCount);
2857             }
2858 
2859 			writeChunkHeader(M_MESH_LOD_GENERATED, size);
2860 			unsigned int idxCount = static_cast<unsigned int>(indexData->indexCount);
2861 			writeInts(&idxCount, 1);
2862 			writeBools(&idx32, 1);
2863 
2864 			if (idxCount > 0)
2865 			{
2866 				if (idx32)
2867 				{
2868 					unsigned int* pIdx = static_cast<unsigned int*>(
2869 																	ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
2870 					writeInts(pIdx, indexData->indexCount);
2871 					ibuf->unlock();
2872 				}
2873 				else
2874 				{
2875 					unsigned short* pIdx = static_cast<unsigned short*>(
2876 																		ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
2877 					writeShorts(pIdx, indexData->indexCount);
2878 					ibuf->unlock();
2879 				}
2880 			}
2881 		}
2882 
2883 
2884     }
2885     //---------------------------------------------------------------------
readMeshLodInfo(DataStreamPtr & stream,Mesh * pMesh)2886     void MeshSerializerImpl_v1_4::readMeshLodInfo(DataStreamPtr& stream, Mesh* pMesh)
2887     {
2888         unsigned short i;
2889 
2890         // Use the old strategy for this mesh
2891         LodStrategy *strategy = DistanceLodSphereStrategy::getSingletonPtr();
2892         pMesh->setLodStrategy(strategy);
2893 
2894         // unsigned short numLevels;
2895         readShorts(stream, &(pMesh->mNumLods), 1);
2896         // bool manual;  (true for manual alternate meshes, false for generated)
2897         readBools(stream, &(pMesh->mIsLodManual), 1);
2898 
2899         // Preallocate submesh LOD face data if not manual
2900         if (!pMesh->mIsLodManual)
2901         {
2902             unsigned short numsubs = pMesh->getNumSubMeshes();
2903             for (i = 0; i < numsubs; ++i)
2904             {
2905                 SubMesh* sm = pMesh->getSubMesh(i);
2906                 sm->mLodFaceList.resize(pMesh->mNumLods-1);
2907             }
2908         }
2909 
2910         // Loop from 1 rather than 0 (full detail index is not in file)
2911         for (i = 1; i < pMesh->mNumLods; ++i)
2912         {
2913             unsigned short streamID = readChunk(stream);
2914             if (streamID != M_MESH_LOD_USAGE)
2915             {
2916                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
2917                     "Missing M_MESH_LOD_USAGE stream in " + pMesh->getName(),
2918                     "MeshSerializerImpl::readMeshLodInfo");
2919             }
2920             // Read depth
2921             MeshLodUsage usage;
2922             readFloats(stream, &(usage.value), 1);
2923             usage.userValue = Math::Sqrt(usage.value);
2924 
2925             if (pMesh->isLodManual())
2926             {
2927                 readMeshLodUsageManual(stream, pMesh, i, usage);
2928             }
2929             else //(!pMesh->isLodManual)
2930             {
2931                 readMeshLodUsageGenerated(stream, pMesh, i, usage);
2932             }
2933             usage.edgeData = NULL;
2934 
2935             // Save usage
2936             pMesh->mMeshLodUsageList.push_back(usage);
2937         }
2938 
2939 
2940 	}
2941     //---------------------------------------------------------------------
2942     //---------------------------------------------------------------------
2943     //---------------------------------------------------------------------
MeshSerializerImpl_v1_3()2944     MeshSerializerImpl_v1_3::MeshSerializerImpl_v1_3()
2945     {
2946         // Version number
2947         mVersion = "[MeshSerializer_v1.30]";
2948     }
2949     //---------------------------------------------------------------------
~MeshSerializerImpl_v1_3()2950     MeshSerializerImpl_v1_3::~MeshSerializerImpl_v1_3()
2951     {
2952     }
2953     //---------------------------------------------------------------------
readEdgeListLodInfo(DataStreamPtr & stream,EdgeData * edgeData)2954     void MeshSerializerImpl_v1_3::readEdgeListLodInfo(DataStreamPtr& stream,
2955         EdgeData* edgeData)
2956     {
2957         // unsigned long numTriangles
2958         uint32 numTriangles;
2959         readInts(stream, &numTriangles, 1);
2960         // Allocate correct amount of memory
2961         edgeData->triangles.resize(numTriangles);
2962         edgeData->triangleFaceNormals.resize(numTriangles);
2963         edgeData->triangleLightFacings.resize(numTriangles);
2964         // unsigned long numEdgeGroups
2965         uint32 numEdgeGroups;
2966         readInts(stream, &numEdgeGroups, 1);
2967         // Allocate correct amount of memory
2968         edgeData->edgeGroups.resize(numEdgeGroups);
2969         // Triangle* triangleList
2970         uint32 tmp[3];
2971         for (size_t t = 0; t < numTriangles; ++t)
2972         {
2973             EdgeData::Triangle& tri = edgeData->triangles[t];
2974             // unsigned long indexSet
2975             readInts(stream, tmp, 1);
2976             tri.indexSet = tmp[0];
2977             // unsigned long vertexSet
2978             readInts(stream, tmp, 1);
2979             tri.vertexSet = tmp[0];
2980             // unsigned long vertIndex[3]
2981             readInts(stream, tmp, 3);
2982             tri.vertIndex[0] = tmp[0];
2983             tri.vertIndex[1] = tmp[1];
2984             tri.vertIndex[2] = tmp[2];
2985             // unsigned long sharedVertIndex[3]
2986             readInts(stream, tmp, 3);
2987             tri.sharedVertIndex[0] = tmp[0];
2988             tri.sharedVertIndex[1] = tmp[1];
2989             tri.sharedVertIndex[2] = tmp[2];
2990             // float normal[4]
2991             readFloats(stream, &(edgeData->triangleFaceNormals[t].x), 4);
2992 
2993         }
2994 
2995         // Assume the mesh is closed, it will update later
2996         edgeData->isClosed = true;
2997 
2998         for (uint32 eg = 0; eg < numEdgeGroups; ++eg)
2999         {
3000             unsigned short streamID = readChunk(stream);
3001             if (streamID != M_EDGE_GROUP)
3002             {
3003                 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
3004                     "Missing M_EDGE_GROUP stream",
3005                     "MeshSerializerImpl_v1_3::readEdgeListLodInfo");
3006             }
3007             EdgeData::EdgeGroup& edgeGroup = edgeData->edgeGroups[eg];
3008 
3009             // unsigned long vertexSet
3010             readInts(stream, tmp, 1);
3011             edgeGroup.vertexSet = tmp[0];
3012             // unsigned long numEdges
3013             uint32 numEdges;
3014             readInts(stream, &numEdges, 1);
3015             edgeGroup.edges.resize(numEdges);
3016             // Edge* edgeList
3017             for (uint32 e = 0; e < numEdges; ++e)
3018             {
3019                 EdgeData::Edge& edge = edgeGroup.edges[e];
3020                 // unsigned long  triIndex[2]
3021                 readInts(stream, tmp, 2);
3022                 edge.triIndex[0] = tmp[0];
3023                 edge.triIndex[1] = tmp[1];
3024                 // unsigned long  vertIndex[2]
3025                 readInts(stream, tmp, 2);
3026                 edge.vertIndex[0] = tmp[0];
3027                 edge.vertIndex[1] = tmp[1];
3028                 // unsigned long  sharedVertIndex[2]
3029                 readInts(stream, tmp, 2);
3030                 edge.sharedVertIndex[0] = tmp[0];
3031                 edge.sharedVertIndex[1] = tmp[1];
3032                 // bool degenerate
3033                 readBools(stream, &(edge.degenerate), 1);
3034 
3035                 // The mesh is closed only if no degenerate edge here
3036                 if (edge.degenerate)
3037                 {
3038                     edgeData->isClosed = false;
3039                 }
3040             }
3041         }
3042 
3043         reorganiseTriangles(edgeData);
3044     }
3045     //---------------------------------------------------------------------
reorganiseTriangles(EdgeData * edgeData)3046     void MeshSerializerImpl_v1_3::reorganiseTriangles(EdgeData* edgeData)
3047     {
3048         size_t numTriangles = edgeData->triangles.size();
3049 
3050         if (edgeData->edgeGroups.size() == 1)
3051         {
3052             // Special case for only one edge group in the edge list, which occurring
3053             // most time. In this case, all triangles belongs to that group.
3054             edgeData->edgeGroups.front().triStart = 0;
3055             edgeData->edgeGroups.front().triCount = numTriangles;
3056         }
3057         else
3058         {
3059             EdgeData::EdgeGroupList::iterator egi, egend;
3060             egend = edgeData->edgeGroups.end();
3061 
3062             // Calculate number of triangles for edge groups
3063 
3064             for (egi = edgeData->edgeGroups.begin(); egi != egend; ++egi)
3065             {
3066                 egi->triStart = 0;
3067                 egi->triCount = 0;
3068             }
3069 
3070             bool isGrouped = true;
3071             EdgeData::EdgeGroup* lastEdgeGroup = 0;
3072             for (size_t t = 0; t < numTriangles; ++t)
3073             {
3074                 // Gets the edge group that the triangle belongs to
3075                 const EdgeData::Triangle& tri = edgeData->triangles[t];
3076                 EdgeData::EdgeGroup* edgeGroup = &edgeData->edgeGroups[tri.vertexSet];
3077 
3078                 // Does edge group changes from last edge group?
3079                 if (isGrouped && edgeGroup != lastEdgeGroup)
3080                 {
3081                     // Remember last edge group
3082                     lastEdgeGroup = edgeGroup;
3083 
3084                     // Is't first time encounter this edge group?
3085                     if (!edgeGroup->triCount && !edgeGroup->triStart)
3086                     {
3087                         // setup first triangle of this edge group
3088                         edgeGroup->triStart = t;
3089                     }
3090                     else
3091                     {
3092                         // original triangles doesn't grouping by edge group
3093                         isGrouped = false;
3094                     }
3095                 }
3096 
3097                 // Count number of triangles for this edge group
3098                 if(edgeGroup)
3099                     ++edgeGroup->triCount;
3100             }
3101 
3102             //
3103             // Note that triangles has been sorted by vertex set for a long time,
3104             // but never stored to old version mesh file.
3105             //
3106             // Adopt this fact to avoid remap triangles here.
3107             //
3108 
3109             // Does triangles grouped by vertex set?
3110             if (!isGrouped)
3111             {
3112                 // Ok, the triangles of this edge list isn't grouped by vertex set
3113                 // perfectly, seems ancient mesh file.
3114                 //
3115                 // We need work hardly to group triangles by vertex set.
3116                 //
3117 
3118                 // Calculate triStart and reset triCount to zero for each edge group first
3119                 size_t triStart = 0;
3120                 for (egi = edgeData->edgeGroups.begin(); egi != egend; ++egi)
3121                 {
3122                     egi->triStart = triStart;
3123                     triStart += egi->triCount;
3124                     egi->triCount = 0;
3125                 }
3126 
3127                 // The map used to mapping original triangle index to new index
3128                 typedef vector<size_t>::type TriangleIndexRemap;
3129                 TriangleIndexRemap triangleIndexRemap(numTriangles);
3130 
3131                 // New triangles information that should be group by vertex set.
3132                 EdgeData::TriangleList newTriangles(numTriangles);
3133                 EdgeData::TriangleFaceNormalList newTriangleFaceNormals(numTriangles);
3134 
3135                 // Calculate triangle index map and organise triangles information
3136                 for (size_t t = 0; t < numTriangles; ++t)
3137                 {
3138                     // Gets the edge group that the triangle belongs to
3139                     const EdgeData::Triangle& tri = edgeData->triangles[t];
3140                     EdgeData::EdgeGroup& edgeGroup = edgeData->edgeGroups[tri.vertexSet];
3141 
3142                     // Calculate new index
3143                     size_t newIndex = edgeGroup.triStart + edgeGroup.triCount;
3144                     ++edgeGroup.triCount;
3145 
3146                     // Setup triangle index mapping entry
3147                     triangleIndexRemap[t] = newIndex;
3148 
3149                     // Copy triangle info to new placement
3150                     newTriangles[newIndex] = tri;
3151                     newTriangleFaceNormals[newIndex] = edgeData->triangleFaceNormals[t];
3152                 }
3153 
3154                 // Replace with new triangles information
3155                 edgeData->triangles.swap(newTriangles);
3156                 edgeData->triangleFaceNormals.swap(newTriangleFaceNormals);
3157 
3158                 // Now, update old triangle indices to new index
3159                 for (egi = edgeData->edgeGroups.begin(); egi != egend; ++egi)
3160                 {
3161                     EdgeData::EdgeList::iterator ei, eend;
3162                     eend = egi->edges.end();
3163                     for (ei = egi->edges.begin(); ei != eend; ++ei)
3164                     {
3165                         ei->triIndex[0] = triangleIndexRemap[ei->triIndex[0]];
3166                         if (!ei->degenerate)
3167                         {
3168                             ei->triIndex[1] = triangleIndexRemap[ei->triIndex[1]];
3169                         }
3170                     }
3171                 }
3172             }
3173         }
3174     }
3175     //---------------------------------------------------------------------
writeEdgeList(const Mesh * pMesh)3176 	void MeshSerializerImpl_v1_3::writeEdgeList(const Mesh* pMesh)
3177 	{
3178         writeChunkHeader(M_EDGE_LISTS, calcEdgeListSize(pMesh));
3179 
3180         for (ushort i = 0; i < pMesh->getNumLodLevels(); ++i)
3181         {
3182             const EdgeData* edgeData = pMesh->getEdgeList(i);
3183             bool isManual = pMesh->isLodManual() && (i > 0);
3184             writeChunkHeader(M_EDGE_LIST_LOD, calcEdgeListLodSize(edgeData, isManual));
3185 
3186             // unsigned short lodIndex
3187             writeShorts(&i, 1);
3188 
3189             // bool isManual			// If manual, no edge data here, loaded from manual mesh
3190             writeBools(&isManual, 1);
3191             if (!isManual)
3192             {
3193                 // unsigned long  numTriangles
3194                 uint32 count = static_cast<uint32>(edgeData->triangles.size());
3195                 writeInts(&count, 1);
3196                 // unsigned long numEdgeGroups
3197                 count = static_cast<uint32>(edgeData->edgeGroups.size());
3198                 writeInts(&count, 1);
3199                 // Triangle* triangleList
3200                 // Iterate rather than writing en-masse to allow endian conversion
3201                 EdgeData::TriangleList::const_iterator t = edgeData->triangles.begin();
3202                 EdgeData::TriangleFaceNormalList::const_iterator fni = edgeData->triangleFaceNormals.begin();
3203                 for ( ; t != edgeData->triangles.end(); ++t, ++fni)
3204                 {
3205                     const EdgeData::Triangle& tri = *t;
3206                     // unsigned long indexSet;
3207                     uint32 tmp[3];
3208                     tmp[0] = static_cast<uint32>(tri.indexSet);
3209                     writeInts(tmp, 1);
3210                     // unsigned long vertexSet;
3211                     tmp[0] = static_cast<uint32>(tri.vertexSet);
3212                     writeInts(tmp, 1);
3213                     // unsigned long vertIndex[3];
3214                     tmp[0] = static_cast<uint32>(tri.vertIndex[0]);
3215                     tmp[1] = static_cast<uint32>(tri.vertIndex[1]);
3216                     tmp[2] = static_cast<uint32>(tri.vertIndex[2]);
3217                     writeInts(tmp, 3);
3218                     // unsigned long sharedVertIndex[3];
3219                     tmp[0] = static_cast<uint32>(tri.sharedVertIndex[0]);
3220                     tmp[1] = static_cast<uint32>(tri.sharedVertIndex[1]);
3221                     tmp[2] = static_cast<uint32>(tri.sharedVertIndex[2]);
3222                     writeInts(tmp, 3);
3223                     // float normal[4];
3224                     writeFloats(&(fni->x), 4);
3225 
3226                 }
3227                 // Write the groups
3228                 for (EdgeData::EdgeGroupList::const_iterator gi = edgeData->edgeGroups.begin();
3229 					 gi != edgeData->edgeGroups.end(); ++gi)
3230                 {
3231                     const EdgeData::EdgeGroup& edgeGroup = *gi;
3232                     writeChunkHeader(M_EDGE_GROUP, calcEdgeGroupSize(edgeGroup));
3233                     // unsigned long vertexSet
3234                     uint32 vertexSet = static_cast<uint32>(edgeGroup.vertexSet);
3235                     writeInts(&vertexSet, 1);
3236                     // unsigned long numEdges
3237                     count = static_cast<uint32>(edgeGroup.edges.size());
3238                     writeInts(&count, 1);
3239                     // Edge* edgeList
3240                     // Iterate rather than writing en-masse to allow endian conversion
3241                     for (EdgeData::EdgeList::const_iterator ei = edgeGroup.edges.begin();
3242 						 ei != edgeGroup.edges.end(); ++ei)
3243                     {
3244                         const EdgeData::Edge& edge = *ei;
3245                         uint32 tmp[2];
3246                         // unsigned long  triIndex[2]
3247                         tmp[0] = static_cast<uint32>(edge.triIndex[0]);
3248                         tmp[1] = static_cast<uint32>(edge.triIndex[1]);
3249                         writeInts(tmp, 2);
3250                         // unsigned long  vertIndex[2]
3251                         tmp[0] = static_cast<uint32>(edge.vertIndex[0]);
3252                         tmp[1] = static_cast<uint32>(edge.vertIndex[1]);
3253                         writeInts(tmp, 2);
3254                         // unsigned long  sharedVertIndex[2]
3255                         tmp[0] = static_cast<uint32>(edge.sharedVertIndex[0]);
3256                         tmp[1] = static_cast<uint32>(edge.sharedVertIndex[1]);
3257                         writeInts(tmp, 2);
3258                         // bool degenerate
3259                         writeBools(&(edge.degenerate), 1);
3260                     }
3261 
3262                 }
3263 
3264             }
3265 
3266         }
3267 	}
3268 	//---------------------------------------------------------------------
3269     //---------------------------------------------------------------------
3270     //---------------------------------------------------------------------
MeshSerializerImpl_v1_2()3271     MeshSerializerImpl_v1_2::MeshSerializerImpl_v1_2()
3272     {
3273         // Version number
3274         mVersion = "[MeshSerializer_v1.20]";
3275     }
3276     //---------------------------------------------------------------------
~MeshSerializerImpl_v1_2()3277     MeshSerializerImpl_v1_2::~MeshSerializerImpl_v1_2()
3278     {
3279     }
3280     //---------------------------------------------------------------------
readMesh(DataStreamPtr & stream,Mesh * pMesh,MeshSerializerListener * listener)3281     void MeshSerializerImpl_v1_2::readMesh(DataStreamPtr& stream, Mesh* pMesh, MeshSerializerListener *listener)
3282     {
3283         MeshSerializerImpl::readMesh(stream, pMesh, listener);
3284         // Always automatically build edge lists for this version
3285         pMesh->mAutoBuildEdgeLists = true;
3286 
3287     }
3288     //---------------------------------------------------------------------
readGeometry(DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)3289     void MeshSerializerImpl_v1_2::readGeometry(DataStreamPtr& stream, Mesh* pMesh,
3290         VertexData* dest)
3291     {
3292         unsigned short bindIdx = 0;
3293 
3294         dest->vertexStart = 0;
3295 
3296         unsigned int vertexCount = 0;
3297         readInts(stream, &vertexCount, 1);
3298         dest->vertexCount = vertexCount;
3299 
3300         // Vertex buffers
3301 
3302         readGeometryPositions(bindIdx, stream, pMesh, dest);
3303         ++bindIdx;
3304 
3305         // Find optional geometry streams
3306         if (!stream->eof())
3307         {
3308             unsigned short streamID = readChunk(stream);
3309             unsigned short texCoordSet = 0;
3310 
3311             while(!stream->eof() &&
3312                 (streamID == M_GEOMETRY_NORMALS ||
3313                  streamID == M_GEOMETRY_COLOURS ||
3314                  streamID == M_GEOMETRY_TEXCOORDS ))
3315             {
3316                 switch (streamID)
3317                 {
3318                 case M_GEOMETRY_NORMALS:
3319                     readGeometryNormals(bindIdx++, stream, pMesh, dest);
3320                     break;
3321                 case M_GEOMETRY_COLOURS:
3322                     readGeometryColours(bindIdx++, stream, pMesh, dest);
3323                     break;
3324                 case M_GEOMETRY_TEXCOORDS:
3325                     readGeometryTexCoords(bindIdx++, stream, pMesh, dest, texCoordSet++);
3326                     break;
3327                 }
3328                 // Get next stream
3329                 if (!stream->eof())
3330                 {
3331                     streamID = readChunk(stream);
3332                 }
3333             }
3334             if (!stream->eof())
3335             {
3336                 // Backpedal back to start of non-submesh stream
3337                 stream->skip(-MSTREAM_OVERHEAD_SIZE);
3338             }
3339         }
3340     }
3341     //---------------------------------------------------------------------
readGeometryPositions(unsigned short bindIdx,DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)3342     void MeshSerializerImpl_v1_2::readGeometryPositions(unsigned short bindIdx,
3343         DataStreamPtr& stream, Mesh* pMesh, VertexData* dest)
3344     {
3345         float *pFloat = 0;
3346         HardwareVertexBufferSharedPtr vbuf;
3347         // float* pVertices (x, y, z order x numVertices)
3348         dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_POSITION);
3349         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
3350             dest->vertexDeclaration->getVertexSize(bindIdx),
3351             dest->vertexCount,
3352             pMesh->mVertexBufferUsage,
3353 			pMesh->mVertexBufferShadowBuffer);
3354         pFloat = static_cast<float*>(
3355             vbuf->lock(HardwareBuffer::HBL_DISCARD));
3356         readFloats(stream, pFloat, dest->vertexCount * 3);
3357         vbuf->unlock();
3358         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
3359     }
3360     //---------------------------------------------------------------------
readGeometryNormals(unsigned short bindIdx,DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)3361     void MeshSerializerImpl_v1_2::readGeometryNormals(unsigned short bindIdx,
3362         DataStreamPtr& stream, Mesh* pMesh, VertexData* dest)
3363     {
3364         float *pFloat = 0;
3365         HardwareVertexBufferSharedPtr vbuf;
3366         // float* pNormals (x, y, z order x numVertices)
3367         dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_NORMAL);
3368         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
3369             dest->vertexDeclaration->getVertexSize(bindIdx),
3370             dest->vertexCount,
3371             pMesh->mVertexBufferUsage,
3372 			pMesh->mVertexBufferShadowBuffer);
3373         pFloat = static_cast<float*>(
3374             vbuf->lock(HardwareBuffer::HBL_DISCARD));
3375         readFloats(stream, pFloat, dest->vertexCount * 3);
3376         vbuf->unlock();
3377         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
3378     }
3379     //---------------------------------------------------------------------
readGeometryColours(unsigned short bindIdx,DataStreamPtr & stream,Mesh * pMesh,VertexData * dest)3380     void MeshSerializerImpl_v1_2::readGeometryColours(unsigned short bindIdx,
3381         DataStreamPtr& stream, Mesh* pMesh, VertexData* dest)
3382     {
3383         RGBA* pRGBA = 0;
3384         HardwareVertexBufferSharedPtr vbuf;
3385         // unsigned long* pColours (RGBA 8888 format x numVertices)
3386         dest->vertexDeclaration->addElement(bindIdx, 0, VET_COLOUR, VES_DIFFUSE);
3387         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
3388             dest->vertexDeclaration->getVertexSize(bindIdx),
3389             dest->vertexCount,
3390             pMesh->mVertexBufferUsage,
3391 			pMesh->mVertexBufferShadowBuffer);
3392         pRGBA = static_cast<RGBA*>(
3393             vbuf->lock(HardwareBuffer::HBL_DISCARD));
3394         readInts(stream, pRGBA, dest->vertexCount);
3395         vbuf->unlock();
3396         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
3397     }
3398     //---------------------------------------------------------------------
readGeometryTexCoords(unsigned short bindIdx,DataStreamPtr & stream,Mesh * pMesh,VertexData * dest,unsigned short texCoordSet)3399     void MeshSerializerImpl_v1_2::readGeometryTexCoords(unsigned short bindIdx,
3400         DataStreamPtr& stream, Mesh* pMesh, VertexData* dest, unsigned short texCoordSet)
3401     {
3402         float *pFloat = 0;
3403         HardwareVertexBufferSharedPtr vbuf;
3404         // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
3405         unsigned short dim;
3406         readShorts(stream, &dim, 1);
3407         // float* pTexCoords  (u [v] [w] order, dimensions x numVertices)
3408         dest->vertexDeclaration->addElement(
3409             bindIdx,
3410             0,
3411             VertexElement::multiplyTypeCount(VET_FLOAT1, dim),
3412             VES_TEXTURE_COORDINATES,
3413             texCoordSet);
3414         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
3415             dest->vertexDeclaration->getVertexSize(bindIdx),
3416             dest->vertexCount,
3417             pMesh->mVertexBufferUsage,
3418 			pMesh->mVertexBufferShadowBuffer);
3419         pFloat = static_cast<float*>(
3420             vbuf->lock(HardwareBuffer::HBL_DISCARD));
3421         readFloats(stream, pFloat, dest->vertexCount * dim);
3422         vbuf->unlock();
3423         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
3424     }
3425     //---------------------------------------------------------------------
3426     //---------------------------------------------------------------------
3427     //---------------------------------------------------------------------
MeshSerializerImpl_v1_1()3428     MeshSerializerImpl_v1_1::MeshSerializerImpl_v1_1()
3429     {
3430         // Version number
3431         mVersion = "[MeshSerializer_v1.10]";
3432     }
3433     //---------------------------------------------------------------------
~MeshSerializerImpl_v1_1()3434     MeshSerializerImpl_v1_1::~MeshSerializerImpl_v1_1()
3435     {
3436     }
3437     //---------------------------------------------------------------------
readGeometryTexCoords(unsigned short bindIdx,DataStreamPtr & stream,Mesh * pMesh,VertexData * dest,unsigned short texCoordSet)3438     void MeshSerializerImpl_v1_1::readGeometryTexCoords(unsigned short bindIdx,
3439         DataStreamPtr& stream, Mesh* pMesh, VertexData* dest, unsigned short texCoordSet)
3440     {
3441         float *pFloat = 0;
3442         HardwareVertexBufferSharedPtr vbuf;
3443         // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
3444         unsigned short dim;
3445         readShorts(stream, &dim, 1);
3446         // float* pTexCoords  (u [v] [w] order, dimensions x numVertices)
3447         dest->vertexDeclaration->addElement(
3448             bindIdx,
3449             0,
3450             VertexElement::multiplyTypeCount(VET_FLOAT1, dim),
3451             VES_TEXTURE_COORDINATES,
3452             texCoordSet);
3453         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
3454             dest->vertexDeclaration->getVertexSize(bindIdx),
3455             dest->vertexCount,
3456             pMesh->getVertexBufferUsage(),
3457 			pMesh->isVertexBufferShadowed());
3458         pFloat = static_cast<float*>(
3459             vbuf->lock(HardwareBuffer::HBL_DISCARD));
3460         readFloats(stream, pFloat, dest->vertexCount * dim);
3461 
3462         // Adjust individual v values to (1 - v)
3463         if (dim == 2)
3464         {
3465             for (size_t i = 0; i < dest->vertexCount; ++i)
3466             {
3467                 ++pFloat; // skip u
3468                 *pFloat = 1.0f - *pFloat; // v = 1 - v
3469                 ++pFloat;
3470             }
3471 
3472         }
3473         vbuf->unlock();
3474         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
3475     }
3476     //---------------------------------------------------------------------
3477     //---------------------------------------------------------------------
3478     //---------------------------------------------------------------------
3479 
3480 
3481 
3482 
3483 }
3484 
3485 
3486