Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreMeshSerializerImpl.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreStableHeaders.h"
00026 
00027 #include "OgreMeshSerializerImpl.h"
00028 #include "OgreMeshFileFormat.h"
00029 #include "OgreMesh.h"
00030 #include "OgreSubMesh.h"
00031 #include "OgreException.h"
00032 #include "OgreMaterialManager.h"
00033 #include "OgreLogManager.h"
00034 #include "OgreSkeleton.h"
00035 #include "OgreHardwareBufferManager.h"
00036 #include "OgreMaterial.h"
00037 #include "OgreTechnique.h"
00038 #include "OgrePass.h"
00039 
00040 
00041 namespace Ogre {
00042 
00044     const unsigned long CHUNK_OVERHEAD_SIZE = sizeof(unsigned short) + sizeof(unsigned long);
00045     //---------------------------------------------------------------------
00046     MeshSerializerImpl::MeshSerializerImpl()
00047     {
00048         mpMesh = 0;
00049 
00050         // Version number
00051         mVersion = "[MeshSerializer_v1.20]";
00052     }
00053     //---------------------------------------------------------------------
00054     MeshSerializerImpl::~MeshSerializerImpl()
00055     {
00056     }
00057     //---------------------------------------------------------------------
00058     void MeshSerializerImpl::exportMesh(const Mesh* pMesh, const String& filename)
00059     {
00060         LogManager::getSingleton().logMessage("MeshSerializer writing mesh data to " + filename + "...");
00061 
00062         // Check that the mesh has it's bounds set
00063         if (pMesh->getBounds().isNull() || pMesh->getBoundingSphereRadius() == 0.0f)
00064         {
00065             Except(Exception::ERR_INVALIDPARAMS, "The Mesh you have supplied does not have its"
00066                 " bounds completely defined. Define them first before exporting.", 
00067                 "MeshSerializerImpl::exportMesh");
00068         }
00069         mpfFile = fopen(filename, "wb");
00070 
00071         writeFileHeader();
00072         LogManager::getSingleton().logMessage("File header written.");
00073 
00074 
00075         LogManager::getSingleton().logMessage("Writing mesh data...");
00076         writeMesh(pMesh);
00077         LogManager::getSingleton().logMessage("Mesh data exported.");
00078 
00079         // Added by DrEvil
00080         LogManager::getSingleton().logMessage("Writing submesh name table...");
00081 
00082         writeSubMeshNameTable(pMesh);
00083         LogManager::getSingleton().logMessage("Done writing submesh name table");
00084 
00085 
00086         fclose(mpfFile);
00087         LogManager::getSingleton().logMessage("MeshSerializer export successful.");
00088     }
00089     //---------------------------------------------------------------------
00090     void MeshSerializerImpl::importMesh(DataChunk& chunk, Mesh* pDest)
00091     {
00092         mpMesh = pDest;
00093 
00094         // Check header
00095         readFileHeader(chunk);
00096 
00097         unsigned short chunkID;
00098         while(!chunk.isEOF())
00099         {
00100             chunkID = readChunk(chunk);
00101             switch (chunkID)
00102             {
00103             case M_MESH:
00104                 readMesh(chunk);
00105                 break;
00106             case M_MATERIAL:     // removed in 1.1 but still present in 1.0
00107                  readMaterial(chunk);    
00108                  break;                
00109 
00110             // Added by DrEvil optional chunk which lists submesh indexes & their names.
00111             case M_SUBMESH_NAME_TABLE:
00112                 readSubMeshNameTable(chunk);
00113             }
00114         }
00115     }
00116     //---------------------------------------------------------------------
00117     void MeshSerializerImpl::writeMesh(const Mesh* pMesh)
00118     {
00119         // Header
00120         writeChunkHeader(M_MESH, calcMeshSize(pMesh));
00121 
00122         // bool skeletallyAnimated
00123         bool skelAnim = pMesh->hasSkeleton();
00124         writeBools(&skelAnim, 1);
00125 
00126         // Write shared geometry
00127         if (pMesh->sharedVertexData)
00128             writeGeometry(pMesh->sharedVertexData);
00129 
00130         // Write Submeshes
00131         for (int i = 0; i < pMesh->getNumSubMeshes(); ++i)
00132         {
00133             LogManager::getSingleton().logMessage("Writing submesh...");
00134             writeSubMesh(pMesh->getSubMesh(i));
00135             LogManager::getSingleton().logMessage("Submesh exported.");
00136         }
00137 
00138         // Write skeleton info if required
00139         if (pMesh->hasSkeleton())
00140         {
00141             LogManager::getSingleton().logMessage("Exporting skeleton link...");
00142             // Write skeleton link
00143             writeSkeletonLink(pMesh->getSkeletonName());
00144             LogManager::getSingleton().logMessage("Skeleton link exported.");
00145 
00146             // Write bone assignments
00147             if (!pMesh->mBoneAssignments.empty())
00148             {
00149                 LogManager::getSingleton().logMessage("Exporting shared geometry bone assignments...");
00150 
00151                 Mesh::VertexBoneAssignmentList::const_iterator vi;
00152                 for (vi = pMesh->mBoneAssignments.begin(); 
00153                 vi != pMesh->mBoneAssignments.end(); ++vi)
00154                 {
00155                     writeMeshBoneAssignment(&(vi->second));
00156                 }
00157 
00158                 LogManager::getSingleton().logMessage("Shared geometry bone assignments exported.");
00159             }
00160         }
00161 
00162         // Write LOD data if any
00163         if (pMesh->getNumLodLevels() > 1)
00164         {
00165             LogManager::getSingleton().logMessage("Exporting LOD information....");
00166             writeLodInfo(pMesh);
00167             LogManager::getSingleton().logMessage("LOD information exported.");
00168             
00169         }
00170         // Write bounds information
00171         LogManager::getSingleton().logMessage("Exporting bounds information....");
00172         writeBoundsInfo(pMesh);
00173         LogManager::getSingleton().logMessage("Bounds information exported.");
00174 
00175 
00176     }
00177     //---------------------------------------------------------------------
00178     // Added by DrEvil
00179     void MeshSerializerImpl::writeSubMeshNameTable(const Mesh* pMesh)
00180     {
00181         // Header
00182         writeChunkHeader(M_SUBMESH_NAME_TABLE, calcSubMeshNameTableSize(pMesh));
00183 
00184         // Loop through and save out the index and names.
00185         Mesh::SubMeshNameMap::const_iterator it = pMesh->mSubMeshNameMap.begin();
00186 
00187         while(it != pMesh->mSubMeshNameMap.end())
00188         {
00189             // Header
00190             writeChunkHeader(M_SUBMESH_NAME_TABLE_ELEMENT, CHUNK_OVERHEAD_SIZE + 
00191                 sizeof(unsigned short) + (unsigned long)it->first.length() + 1);
00192 
00193             // write the index
00194             writeShorts(&it->second, 1);
00195             // name
00196             writeString(it->first);
00197 
00198             ++it;
00199         }
00200     }
00201     //---------------------------------------------------------------------
00202     void MeshSerializerImpl::writeSubMesh(const SubMesh* s)
00203     {
00204         // Header
00205         writeChunkHeader(M_SUBMESH, calcSubMeshSize(s));
00206 
00207         // char* materialName
00208         writeString(s->getMaterialName());
00209 
00210         // bool useSharedVertices
00211         writeBools(&s->useSharedVertices, 1);
00212 
00213         // unsigned int indexCount
00214         writeInts(&s->indexData->indexCount, 1);
00215 
00216         // bool indexes32Bit
00217         bool idx32bit = (s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);
00218         writeBools(&idx32bit, 1);
00219 
00220         // unsigned short* faceVertexIndices ((indexCount)
00221         HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer;
00222         void* pIdx = ibuf->lock(HardwareBuffer::HBL_READ_ONLY);
00223         if (idx32bit)
00224         {
00225             unsigned int* pIdx32 = static_cast<unsigned int*>(pIdx);
00226             writeInts(pIdx32, s->indexData->indexCount);
00227         }
00228         else
00229         {
00230             unsigned short* pIdx16 = static_cast<unsigned short*>(pIdx);
00231             writeShorts(pIdx16, s->indexData->indexCount);
00232         }
00233         ibuf->unlock();
00234 
00235         // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
00236         if (!s->useSharedVertices)
00237         {
00238             writeGeometry(s->vertexData);
00239         }
00240         
00241         // Operation type
00242         writeSubMeshOperation(s);
00243 
00244         // Bone assignments
00245         if (!s->mBoneAssignments.empty())
00246         {
00247             LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");
00248 
00249             SubMesh::VertexBoneAssignmentList::const_iterator vi;
00250             for (vi = s->mBoneAssignments.begin(); 
00251             vi != s->mBoneAssignments.end(); ++vi)
00252             {
00253                 writeSubMeshBoneAssignment(&(vi->second));
00254             }
00255 
00256             LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported.");
00257         }
00258 
00259 
00260     }
00261     //---------------------------------------------------------------------
00262     void MeshSerializerImpl::writeSubMeshOperation(const SubMesh* sm)
00263     {
00264         // Header
00265         writeChunkHeader(M_SUBMESH_OPERATION, calcSubMeshOperationSize(sm));
00266 
00267         // unsigned short operationType
00268         unsigned short opType = static_cast<unsigned short>(sm->operationType);
00269         writeShorts(&opType, 1);
00270     }
00271     //---------------------------------------------------------------------
00272     void MeshSerializerImpl::writeCondensedVertexBuffer(HardwareVertexBufferSharedPtr vbuf, 
00273         const VertexElement* elem, size_t vertexCount)
00274     {
00275         // Hacky method, turns shared buffers into unshared
00276         // Needed because for now the mesh format only supports unshared for simplicity
00277         // This will probably be upgraded in the next version, but there were enough
00278         // changes going on as it is!
00279         void* pVert = vbuf->lock(HardwareBuffer::HBL_READ_ONLY);
00280 
00281         // Check see if already unshared
00282         if (vbuf->getVertexSize() == elem->getSize())
00283         {
00284             // Bulk copy
00285             writeReals(static_cast<Real*>(pVert), vertexCount * VertexElement::getTypeCount(elem->getType()));
00286         }
00287         else
00288         {
00289             // Do it the hard way
00290             Real* pReal;
00291             while (vertexCount--)
00292             {
00293                 elem->baseVertexPointerToElement(pVert, &pReal);
00294                 writeReals(pReal, VertexElement::getTypeCount(elem->getType()));
00295                 pVert = static_cast<void*>(
00296                     static_cast<unsigned char*>(pVert) + vbuf->getVertexSize() );
00297             }
00298         }
00299         
00300         vbuf->unlock();
00301     }
00302     //---------------------------------------------------------------------
00303     void MeshSerializerImpl::writeGeometry(const VertexData* vertexData)
00304     {
00305         // Header
00306         writeChunkHeader(M_GEOMETRY, calcGeometrySize(vertexData));
00307 
00308         // unsigned int numVertices
00309         writeInts(&vertexData->vertexCount, 1);
00310 
00311         // Real* pVertices (x, y, z order x numVertices)
00312         const VertexElement* elem = 
00313             vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
00314         if (!elem)
00315         {
00316             Except(Exception::ERR_ITEM_NOT_FOUND, "Can't find position elements in the "
00317             "mesh to be written!", "MeshSerializerImpl::writeGeometry");
00318         }
00319         HardwareVertexBufferSharedPtr vbuf = 
00320             vertexData->vertexBufferBinding->getBuffer(elem->getSource());
00321         writeCondensedVertexBuffer(vbuf, elem, vertexData->vertexCount);
00322         //writeReals(pReal, vertexData->vertexCount * 3);
00323 
00324         elem = vertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL);
00325         if (elem)
00326         {
00327             writeChunkHeader(M_GEOMETRY_NORMALS, 
00328                 static_cast<unsigned long>(elem->getSize() * vertexData->vertexCount));
00329 
00330             // Real* pNormals (x, y, z order x numVertices)
00331             vbuf = vertexData->vertexBufferBinding->getBuffer(elem->getSource());
00332             writeCondensedVertexBuffer(vbuf, elem, vertexData->vertexCount);
00333         }
00334 
00335         elem = vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE);
00336         if (elem)
00337         {
00338             writeChunkHeader(M_GEOMETRY_COLOURS, 
00339                 static_cast<unsigned long>(elem->getSize() * vertexData->vertexCount));
00340             // unsigned long* pColours (RGBA 8888 format x numVertices)
00341             vbuf = vertexData->vertexBufferBinding->getBuffer(elem->getSource());
00342             writeCondensedVertexBuffer(vbuf, elem, vertexData->vertexCount);
00343         }
00344 
00345         for (int t = 0; t < OGRE_MAX_TEXTURE_COORD_SETS; ++t)
00346         {
00347             elem = vertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, t);
00348             if (elem)
00349             {
00350                 writeChunkHeader(M_GEOMETRY_TEXCOORDS, 
00351                     static_cast<unsigned long>(elem->getSize() * vertexData->vertexCount));
00352                 vbuf = vertexData->vertexBufferBinding->getBuffer(elem->getSource());
00353                 // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
00354                 unsigned short dims = VertexElement::getTypeCount(elem->getType());
00355                 writeShorts(&dims, 1);
00356                 // Real* pTexCoords  (u [v] [w] order, dimensions x numVertices)
00357                 writeCondensedVertexBuffer(vbuf, elem, vertexData->vertexCount);
00358             }
00359 
00360         }
00361 
00362 
00363     }
00364     //---------------------------------------------------------------------
00365     // Added by DrEvil
00366     unsigned long MeshSerializerImpl::calcSubMeshNameTableSize(const Mesh *pMesh)
00367     {
00368         size_t size = CHUNK_OVERHEAD_SIZE;
00369         // Figure out the size of the Name table.
00370         // Iterate through the subMeshList & add up the size of the indexes and names.
00371         Mesh::SubMeshNameMap::const_iterator it = pMesh->mSubMeshNameMap.begin();       
00372         while(it != pMesh->mSubMeshNameMap.end())
00373         {
00374             // size of the index
00375             size += sizeof(unsigned short);
00376             // name
00377             size += (unsigned long)it->first.length() + 1;
00378 
00379             ++it;
00380         }               
00381 
00382         // size of the sub-mesh name table.
00383         return (unsigned long)size;
00384     }
00385     //---------------------------------------------------------------------
00386     unsigned long MeshSerializerImpl::calcMeshSize(const Mesh* pMesh)
00387     {
00388         unsigned long size = CHUNK_OVERHEAD_SIZE;
00389 
00390         // Num shared vertices
00391         size += sizeof(unsigned int);
00392 
00393         // Geometry
00394         if (pMesh->sharedVertexData && pMesh->sharedVertexData->vertexCount > 0)
00395         {
00396             size += calcGeometrySize(pMesh->sharedVertexData);
00397         }
00398 
00399         // Submeshes
00400         for (int i = 0; i < pMesh->getNumSubMeshes(); ++i)
00401         {
00402             size += calcSubMeshSize(pMesh->getSubMesh(i));
00403         }
00404 
00405         // Skeleton link
00406         if (pMesh->hasSkeleton())
00407         {
00408             size += calcSkeletonLinkSize(pMesh->getSkeletonName());
00409         }
00410 
00411         return size;
00412 
00413     }
00414     //---------------------------------------------------------------------
00415     unsigned long MeshSerializerImpl::calcSubMeshSize(const SubMesh* pSub)
00416     {
00417         size_t size = CHUNK_OVERHEAD_SIZE;
00418 
00419         // Material name
00420         size += (unsigned long)pSub->getMaterialName().length() + 1;
00421 
00422         // bool useSharedVertices
00423         size += sizeof(bool);
00424         // unsigned int indexCount
00425         size += sizeof(unsigned int);
00426         // bool indexes32bit
00427         size += sizeof(bool);
00428         // unsigned int* faceVertexIndices 
00429         size += sizeof(unsigned int) * pSub->indexData->indexCount;
00430 
00431         // Geometry
00432         if (!pSub->useSharedVertices)
00433         {
00434             size += calcGeometrySize(pSub->vertexData);
00435         }
00436 
00437         return static_cast<unsigned long>(size);
00438     }
00439     //---------------------------------------------------------------------
00440     unsigned long MeshSerializerImpl::calcSubMeshOperationSize(const SubMesh* pSub)
00441     {
00442         return CHUNK_OVERHEAD_SIZE + sizeof(unsigned short);
00443     }
00444     //---------------------------------------------------------------------
00445     unsigned long MeshSerializerImpl::calcGeometrySize(const VertexData* vertexData)
00446     {
00447         size_t size = CHUNK_OVERHEAD_SIZE;
00448 
00449         // Num vertices
00450         size += sizeof(unsigned int);
00451 
00452         const VertexDeclaration::VertexElementList& elems = 
00453             vertexData->vertexDeclaration->getElements();
00454 
00455         VertexDeclaration::VertexElementList::const_iterator i, iend;
00456         iend = elems.end();
00457         for (i = elems.begin(); i != iend; ++i)
00458         {
00459             const VertexElement& elem = *i;
00460             // Vertex element
00461             size += VertexElement::getTypeSize(elem.getType()) * vertexData->vertexCount;
00462         }
00463         return static_cast<unsigned long>(size);
00464     }
00465     //---------------------------------------------------------------------
00466     // Added by DrEvil
00467     void MeshSerializerImpl::readSubMeshNameTable(DataChunk& chunk)
00468     {
00469         // The map for
00470         std::map<unsigned short, String> subMeshNames;
00471         unsigned short chunkID, subMeshIndex;
00472 
00473         // Need something to store the index, and the objects name
00474         // This table is a method that imported meshes can retain their naming
00475         // so that the names established in the modelling software can be used
00476         // to get the sub-meshes by name. The exporter must support exporting
00477         // the optional chunk M_SUBMESH_NAME_TABLE.
00478 
00479         // Read in all the sub-chunks. Each sub-chunk should contain an index and Ogre::String for the name.
00480         if (!chunk.isEOF())
00481         {
00482             chunkID = readChunk(chunk);
00483             while(!chunk.isEOF() && (chunkID == M_SUBMESH_NAME_TABLE_ELEMENT ))
00484             {
00485                 // Read in the index of the submesh.
00486                 readShorts(chunk, &subMeshIndex, 1);
00487                 // Read in the String and map it to its index.
00488                 subMeshNames[subMeshIndex] = readString(chunk);                 
00489 
00490                 // If we're not end of file get the next chunk ID
00491                 if (!chunk.isEOF())
00492                     chunkID = readChunk(chunk);
00493             }
00494             if (!chunk.isEOF())
00495             {
00496                 // Backpedal back to start of chunk
00497                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
00498             }
00499         }
00500 
00501         // Set all the submeshes names
00502         // ?
00503 
00504         // Loop through and save out the index and names.
00505         std::map<unsigned short, String>::const_iterator it = subMeshNames.begin();
00506 
00507         while(it != subMeshNames.end())
00508         {           
00509             // Name this submesh to the stored name.
00510             mpMesh->nameSubMesh(it->second, it->first);
00511             ++it;
00512         }
00513 
00514 
00515 
00516     }
00517     //---------------------------------------------------------------------
00518     void MeshSerializerImpl::readMesh(DataChunk& chunk)
00519     {
00520         unsigned short chunkID;
00521 
00522         // bool skeletallyAnimated
00523         readBools(chunk, &mIsSkeletallyAnimated, 1);
00524 
00525         // Find all subchunks 
00526         if (!chunk.isEOF())
00527         {
00528             chunkID = readChunk(chunk);
00529             while(!chunk.isEOF() &&
00530                 (chunkID == M_GEOMETRY ||
00531                  chunkID == M_SUBMESH ||
00532                  chunkID == M_MESH_SKELETON_LINK ||
00533                  chunkID == M_MESH_BONE_ASSIGNMENT ||
00534                  chunkID == M_MESH_LOD ||
00535                  chunkID == M_MESH_BOUNDS))
00536             {
00537                 switch(chunkID)
00538                 {
00539                 case M_GEOMETRY:
00540                     mpMesh->sharedVertexData = new VertexData();
00541                     try {
00542                         readGeometry(chunk, mpMesh->sharedVertexData);
00543                     }
00544                     catch (Exception& e)
00545                     {
00546                         if (e.getNumber() == Exception::ERR_ITEM_NOT_FOUND)
00547                         {
00548                             // duff geometry data entry with 0 vertices
00549                             delete mpMesh->sharedVertexData;
00550                             mpMesh->sharedVertexData = 0;
00551                             // Skip this chunk (pointer will have been returned to just after header)
00552                             chunk.skip(mCurrentChunkLen - CHUNK_OVERHEAD_SIZE);
00553                         }
00554                         else
00555                         {
00556                             throw;
00557                         }
00558                     }
00559                     break;
00560                 case M_SUBMESH:
00561                     readSubMesh(chunk);
00562                     break;
00563                 case M_MESH_SKELETON_LINK:
00564                     readSkeletonLink(chunk);
00565                     break;
00566                 case M_MESH_BONE_ASSIGNMENT:
00567                     readMeshBoneAssignment(chunk);
00568                     break;
00569                 case M_MESH_LOD:
00570                     readMeshLodInfo(chunk);
00571                     break;
00572                 case M_MESH_BOUNDS:
00573                     readBoundsInfo(chunk);
00574                     break;
00575                 }
00576 
00577                 if (!chunk.isEOF())
00578                 {
00579                     chunkID = readChunk(chunk);
00580                 }
00581 
00582             }
00583             if (!chunk.isEOF())
00584             {
00585                 // Backpedal back to start of chunk
00586                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
00587             }
00588         }
00589 
00590     }
00591     //---------------------------------------------------------------------
00592     void MeshSerializerImpl::readSubMesh(DataChunk& chunk)
00593     {
00594         unsigned short chunkID;
00595 
00596         SubMesh* sm = mpMesh->createSubMesh();
00597         // char* materialName
00598         String materialName = readString(chunk);
00599         sm->setMaterialName(materialName);
00600 
00601         // bool useSharedVertices
00602         readBools(chunk,&sm->useSharedVertices, 1);
00603 
00604         // unsigned int indexCount
00605         sm->indexData->indexStart = 0;
00606         readInts(chunk, &sm->indexData->indexCount, 1);
00607 
00608         HardwareIndexBufferSharedPtr ibuf;
00609         // bool indexes32Bit
00610         bool idx32bit;
00611         readBools(chunk, &idx32bit, 1);
00612         if (idx32bit)
00613         {
00614             ibuf = HardwareBufferManager::getSingleton().
00615                 createIndexBuffer(
00616                     HardwareIndexBuffer::IT_32BIT, 
00617                     sm->indexData->indexCount, 
00618                     mpMesh->mIndexBufferUsage,
00619                     mpMesh->mIndexBufferShadowBuffer);
00620             // unsigned int* faceVertexIndices 
00621             unsigned int* pIdx = static_cast<unsigned int*>(
00622                 ibuf->lock(HardwareBuffer::HBL_DISCARD)
00623                 );
00624             readInts(chunk, pIdx, sm->indexData->indexCount);
00625             ibuf->unlock();
00626 
00627         }
00628         else // 16-bit
00629         {
00630             ibuf = HardwareBufferManager::getSingleton().
00631                 createIndexBuffer(
00632                     HardwareIndexBuffer::IT_16BIT, 
00633                     sm->indexData->indexCount, 
00634                     mpMesh->mIndexBufferUsage,
00635                     mpMesh->mIndexBufferShadowBuffer);
00636             // unsigned short* faceVertexIndices 
00637             unsigned short* pIdx = static_cast<unsigned short*>(
00638                 ibuf->lock(HardwareBuffer::HBL_DISCARD)
00639                 );
00640             readShorts(chunk, pIdx, sm->indexData->indexCount);
00641             ibuf->unlock();
00642         }
00643         sm->indexData->indexBuffer = ibuf;
00644 
00645         // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
00646         if (!sm->useSharedVertices)
00647         {
00648             chunkID = readChunk(chunk);
00649             if (chunkID != M_GEOMETRY)
00650             {
00651                 Except(Exception::ERR_INTERNAL_ERROR, "Missing geometry data in mesh file", 
00652                     "MeshSerializerImpl::readSubMesh");
00653             }
00654             sm->vertexData = new VertexData();
00655             readGeometry(chunk, sm->vertexData);
00656         }
00657 
00658 
00659         // Find all bone assignments (if present) 
00660         if (!chunk.isEOF())
00661         {
00662             chunkID = readChunk(chunk);
00663             while(!chunk.isEOF() &&
00664                 (chunkID == M_SUBMESH_BONE_ASSIGNMENT ||
00665                  chunkID == M_SUBMESH_OPERATION))
00666             {
00667                 switch(chunkID)
00668                 {
00669                 case M_SUBMESH_OPERATION:
00670                     readSubMeshOperation(chunk, sm);
00671                     break;
00672                 case M_SUBMESH_BONE_ASSIGNMENT:
00673                     readSubMeshBoneAssignment(chunk, sm);
00674                     break;
00675                 }
00676 
00677                 if (!chunk.isEOF())
00678                 {
00679                     chunkID = readChunk(chunk);
00680                 }
00681 
00682             }
00683             if (!chunk.isEOF())
00684             {
00685                 // Backpedal back to start of chunk
00686                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
00687             }
00688         }
00689     
00690 
00691     }
00692     //---------------------------------------------------------------------
00693     void MeshSerializerImpl::readSubMeshOperation(DataChunk& chunk, SubMesh* sm)
00694     {
00695         // unsigned short operationType
00696         unsigned short opType;
00697         readShorts(chunk, &opType, 1);
00698         sm->operationType = static_cast<RenderOperation::OperationType>(opType);
00699     }
00700     //---------------------------------------------------------------------
00701     void MeshSerializerImpl::readGeometry(DataChunk& chunk, VertexData* dest)
00702     {
00703         unsigned short texCoordSet = 0;
00704         
00705         unsigned short bindIdx = 0;
00706 
00707         dest->vertexStart = 0;
00708 
00709         // unsigned int numVertices
00710         readInts(chunk, &dest->vertexCount, 1);
00711 
00712         // Vertex buffers
00713         // TODO: consider redesigning this so vertex buffers can be combined
00714 
00715         readGeometryPositions(bindIdx, chunk, dest);
00716         ++bindIdx;
00717 
00718         // Find optional geometry chunks
00719         if (!chunk.isEOF())
00720         {
00721             unsigned short chunkID = readChunk(chunk);
00722             while(!chunk.isEOF() && 
00723                 (chunkID == M_GEOMETRY_NORMALS || 
00724                  chunkID == M_GEOMETRY_COLOURS ||
00725                  chunkID == M_GEOMETRY_TEXCOORDS ))
00726             {
00727                 switch (chunkID)
00728                 {
00729                 case M_GEOMETRY_NORMALS:
00730                     readGeometryNormals(bindIdx++, chunk, dest);
00731                     break;
00732                 case M_GEOMETRY_COLOURS:
00733                     readGeometryColours(bindIdx++, chunk, dest);
00734                     break;
00735                 case M_GEOMETRY_TEXCOORDS:
00736                     readGeometryTexCoords(bindIdx++, chunk, dest, texCoordSet++);
00737                     break;
00738                 }
00739                 // Get next chunk
00740                 if (!chunk.isEOF())
00741                 {
00742                     chunkID = readChunk(chunk);
00743                 }
00744             }
00745             if (!chunk.isEOF())
00746             {
00747                 // Backpedal back to start of non-submesh chunk
00748                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
00749             }
00750         }
00751     }
00752     //---------------------------------------------------------------------
00753     void MeshSerializerImpl::readGeometryPositions(unsigned short bindIdx, 
00754         DataChunk& chunk, VertexData* dest)
00755     {
00756         Real *pReal = 0;
00757         HardwareVertexBufferSharedPtr vbuf;
00758         // Real* pVertices (x, y, z order x numVertices)
00759         dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_POSITION);
00760         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
00761             dest->vertexDeclaration->getVertexSize(bindIdx),
00762             dest->vertexCount,
00763             mpMesh->mVertexBufferUsage, 
00764             mpMesh->mIndexBufferShadowBuffer);
00765         pReal = static_cast<Real*>(
00766             vbuf->lock(HardwareBuffer::HBL_DISCARD));
00767         readReals(chunk, pReal, dest->vertexCount * 3);
00768         vbuf->unlock();
00769         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
00770     }
00771     //---------------------------------------------------------------------
00772     void MeshSerializerImpl::readGeometryNormals(unsigned short bindIdx, 
00773         DataChunk& chunk, VertexData* dest)
00774     {
00775         Real *pReal = 0;
00776         HardwareVertexBufferSharedPtr vbuf;
00777         // Real* pNormals (x, y, z order x numVertices)
00778         dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_NORMAL);
00779         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
00780             dest->vertexDeclaration->getVertexSize(bindIdx),
00781             dest->vertexCount,
00782             mpMesh->mVertexBufferUsage,
00783             mpMesh->mVertexBufferShadowBuffer);
00784         pReal = static_cast<Real*>(
00785             vbuf->lock(HardwareBuffer::HBL_DISCARD));
00786         readReals(chunk, pReal, dest->vertexCount * 3);
00787         vbuf->unlock();
00788         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
00789     }
00790     //---------------------------------------------------------------------
00791     void MeshSerializerImpl::readGeometryColours(unsigned short bindIdx, 
00792         DataChunk& chunk, VertexData* dest)
00793     {
00794         RGBA* pRGBA = 0;
00795         HardwareVertexBufferSharedPtr vbuf;
00796         // unsigned long* pColours (RGBA 8888 format x numVertices)
00797         dest->vertexDeclaration->addElement(bindIdx, 0, VET_COLOUR, VES_DIFFUSE);
00798         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
00799             dest->vertexDeclaration->getVertexSize(bindIdx),
00800             dest->vertexCount,
00801             mpMesh->mVertexBufferUsage,
00802             mpMesh->mVertexBufferShadowBuffer);
00803         pRGBA = static_cast<RGBA*>(
00804             vbuf->lock(HardwareBuffer::HBL_DISCARD));
00805         readLongs(chunk, pRGBA, dest->vertexCount);
00806         vbuf->unlock();
00807         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
00808     }
00809     //---------------------------------------------------------------------
00810     void MeshSerializerImpl::readGeometryTexCoords(unsigned short bindIdx, 
00811         DataChunk& chunk, VertexData* dest, unsigned short texCoordSet)
00812     {
00813         Real *pReal = 0;
00814         HardwareVertexBufferSharedPtr vbuf;
00815         // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
00816         unsigned short dim;
00817         readShorts(chunk, &dim, 1);
00818         // Real* pTexCoords  (u [v] [w] order, dimensions x numVertices)
00819         dest->vertexDeclaration->addElement(
00820             bindIdx, 
00821             0, 
00822             VertexElement::multiplyTypeCount(VET_FLOAT1, dim), 
00823             VES_TEXTURE_COORDINATES,
00824             texCoordSet);
00825         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
00826             dest->vertexDeclaration->getVertexSize(bindIdx),
00827             dest->vertexCount,
00828             mpMesh->mVertexBufferUsage,
00829             mpMesh->mVertexBufferShadowBuffer);
00830         pReal = static_cast<Real*>(
00831             vbuf->lock(HardwareBuffer::HBL_DISCARD));
00832         readReals(chunk, pReal, dest->vertexCount * dim);
00833         vbuf->unlock();
00834         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
00835     }
00836     //---------------------------------------------------------------------
00837     void MeshSerializerImpl::writeSkeletonLink(const String& skelName)
00838     {
00839         writeChunkHeader(M_MESH_SKELETON_LINK, calcSkeletonLinkSize(skelName));
00840 
00841         writeString(skelName);
00842 
00843     }
00844     //---------------------------------------------------------------------
00845     void MeshSerializerImpl::readSkeletonLink(DataChunk &chunk)
00846     {
00847         String skelName = readString(chunk);
00848         mpMesh->setSkeletonName(skelName);
00849     }
00850     //---------------------------------------------------------------------
00851     void MeshSerializerImpl::readMaterial(DataChunk& chunk)
00852     {
00853 
00854         // Material definition section phased out of 1.1
00855 
00856     }
00857     //---------------------------------------------------------------------
00858     void MeshSerializerImpl::readTextureLayer(DataChunk& chunk, Material* pMat)
00859     {
00860         // Material definition section phased out of 1.1
00861     }
00862     //---------------------------------------------------------------------
00863     unsigned long MeshSerializerImpl::calcSkeletonLinkSize(const String& skelName)
00864     {
00865         unsigned long size = CHUNK_OVERHEAD_SIZE;
00866 
00867         size += (unsigned long)skelName.length() + 1;
00868 
00869         return size;
00870 
00871     }
00872     //---------------------------------------------------------------------
00873     void MeshSerializerImpl::writeMeshBoneAssignment(const VertexBoneAssignment* assign)
00874     {
00875         writeChunkHeader(M_MESH_BONE_ASSIGNMENT, calcBoneAssignmentSize());
00876 
00877         // unsigned int vertexIndex;
00878         writeInts(&(assign->vertexIndex), 1);
00879         // unsigned short boneIndex;
00880         writeShorts(&(assign->boneIndex), 1);
00881         // Real weight;
00882         writeReals(&(assign->weight), 1);
00883     }
00884     //---------------------------------------------------------------------
00885     void MeshSerializerImpl::writeSubMeshBoneAssignment(const VertexBoneAssignment* assign)
00886     {
00887         writeChunkHeader(M_SUBMESH_BONE_ASSIGNMENT, calcBoneAssignmentSize());
00888 
00889         // unsigned int vertexIndex;
00890         writeInts(&(assign->vertexIndex), 1);
00891         // unsigned short boneIndex;
00892         writeShorts(&(assign->boneIndex), 1);
00893         // Real weight;
00894         writeReals(&(assign->weight), 1);
00895     }
00896     //---------------------------------------------------------------------
00897     void MeshSerializerImpl::readMeshBoneAssignment(DataChunk& chunk)
00898     {
00899         VertexBoneAssignment assign;
00900 
00901         // unsigned int vertexIndex;
00902         readInts(chunk, &(assign.vertexIndex),1);
00903         // unsigned short boneIndex;
00904         readShorts(chunk, &(assign.boneIndex),1);
00905         // Real weight;
00906         readReals(chunk, &(assign.weight), 1);
00907 
00908         mpMesh->addBoneAssignment(assign);
00909 
00910     }
00911     //---------------------------------------------------------------------
00912     void MeshSerializerImpl::readSubMeshBoneAssignment(DataChunk& chunk, SubMesh* sub)
00913     {
00914         VertexBoneAssignment assign;
00915 
00916         // unsigned int vertexIndex;
00917         readInts(chunk, &(assign.vertexIndex),1);
00918         // unsigned short boneIndex;
00919         readShorts(chunk, &(assign.boneIndex),1);
00920         // Real weight;
00921         readReals(chunk, &(assign.weight), 1);
00922 
00923         sub->addBoneAssignment(assign);
00924 
00925     }
00926     //---------------------------------------------------------------------
00927     unsigned long MeshSerializerImpl::calcBoneAssignmentSize(void)
00928     {
00929         unsigned long size;
00930 
00931         size = CHUNK_OVERHEAD_SIZE;
00932 
00933         // Vert index
00934         size += sizeof(unsigned int);
00935         // Bone index
00936         size += sizeof(unsigned short);
00937         // weight
00938         size += sizeof(Real);
00939 
00940         return size;
00941     }
00942     //---------------------------------------------------------------------
00943     void MeshSerializerImpl::writeLodInfo(const Mesh* pMesh)
00944     {
00945         unsigned short numLods = pMesh->getNumLodLevels();
00946         bool manual = pMesh->isLodManual();
00947         writeLodSummary(numLods, manual);
00948 
00949         // Loop from LOD 1 (not 0, this is full detail)
00950         for (unsigned short i = 1; i < numLods; ++i)
00951         {
00952             const Mesh::MeshLodUsage& usage = pMesh->getLodLevel(i);
00953             if (manual)
00954             {
00955                 writeLodUsageManual(usage);
00956             }
00957             else
00958             {
00959                 writeLodUsageGenerated(pMesh, usage, i);
00960             }
00961             
00962         }
00963         
00964 
00965     }
00966     //---------------------------------------------------------------------
00967     void MeshSerializerImpl::writeLodSummary(unsigned short numLevels, bool manual)
00968     {
00969         // Header
00970         unsigned long size = CHUNK_OVERHEAD_SIZE;
00971         // unsigned short numLevels;
00972         size += sizeof(unsigned short);
00973         // bool manual;  (true for manual alternate meshes, false for generated)
00974         size += sizeof(bool);
00975         writeChunkHeader(M_MESH_LOD, size);
00976 
00977         // Details
00978         // unsigned short numLevels;
00979         writeShorts(&numLevels, 1);
00980         // bool manual;  (true for manual alternate meshes, false for generated)
00981         writeBools(&manual, 1);
00982 
00983         
00984     }
00985     //---------------------------------------------------------------------
00986     void MeshSerializerImpl::writeLodUsageManual(const Mesh::MeshLodUsage& usage)
00987     {
00988         // Header
00989         unsigned long size = CHUNK_OVERHEAD_SIZE;
00990         unsigned long manualSize = CHUNK_OVERHEAD_SIZE;
00991         // Real fromDepthSquared;
00992         size += sizeof(Real);
00993         // Manual part size
00994 
00995         // String manualMeshName;
00996         manualSize += static_cast<unsigned long>(usage.manualName.length() + 1);
00997 
00998         size += manualSize;
00999 
01000         writeChunkHeader(M_MESH_LOD_USAGE, size);
01001         writeReals(&(usage.fromDepthSquared), 1);
01002 
01003         writeChunkHeader(M_MESH_LOD_MANUAL, manualSize);
01004         writeString(usage.manualName);
01005         
01006 
01007     }
01008     //---------------------------------------------------------------------
01009     void MeshSerializerImpl::writeLodUsageGenerated(const Mesh* pMesh, const Mesh::MeshLodUsage& usage,
01010         unsigned short lodNum)
01011     {
01012         // Usage Header
01013         unsigned long size = CHUNK_OVERHEAD_SIZE;
01014         unsigned short subidx;
01015 
01016         // Real fromDepthSquared;
01017         size += sizeof(Real);
01018 
01019         // Calc generated SubMesh sections size
01020         for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
01021         {
01022             // header
01023             size += CHUNK_OVERHEAD_SIZE;
01024             // unsigned int numFaces;
01025             size += sizeof(unsigned int);
01026             SubMesh* sm = pMesh->getSubMesh(subidx);
01027             const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
01028 
01029             // bool indexes32Bit
01030             size += sizeof(bool);
01031             // unsigned short*/int* faceIndexes;  
01032             if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
01033             {
01034                 size += static_cast<unsigned long>(
01035                     sizeof(unsigned int) * indexData->indexCount);
01036             }
01037             else
01038             {
01039                 size += static_cast<unsigned long>(
01040                     sizeof(unsigned short) * indexData->indexCount);
01041             }
01042 
01043         }
01044 
01045         writeChunkHeader(M_MESH_LOD_USAGE, size);
01046         writeReals(&(usage.fromDepthSquared), 1);
01047 
01048         // Now write sections
01049         // Calc generated SubMesh sections size
01050         for(subidx = 0; subidx < pMesh->getNumSubMeshes(); ++subidx)
01051         {
01052             size = CHUNK_OVERHEAD_SIZE;
01053             // unsigned int numFaces;
01054             size += sizeof(unsigned int);
01055             SubMesh* sm = pMesh->getSubMesh(subidx);
01056             const IndexData* indexData = sm->mLodFaceList[lodNum - 1];
01057             // bool indexes32Bit
01058             size += sizeof(bool);
01059             // unsigned short*/int* faceIndexes;  
01060             if (indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT)
01061             {
01062                 size += static_cast<unsigned long>(
01063                     sizeof(unsigned int) * indexData->indexCount);
01064             }
01065             else
01066             {
01067                 size += static_cast<unsigned long>(
01068                     sizeof(unsigned short) * indexData->indexCount);
01069             }
01070 
01071             writeChunkHeader(M_MESH_LOD_GENERATED, size);
01072             unsigned int idxCount = static_cast<unsigned int>(indexData->indexCount);
01073             writeInts(&idxCount, 1);
01074             // Lock index buffer to write
01075             HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
01076             // bool indexes32bit
01077             bool idx32 = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
01078             writeBools(&idx32, 1);
01079             if (idx32)
01080             {
01081                 unsigned int* pIdx = static_cast<unsigned int*>(
01082                     ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
01083                 writeInts(pIdx, indexData->indexCount);
01084                 ibuf->unlock();
01085             }
01086             else
01087             {
01088                 unsigned short* pIdx = static_cast<unsigned short*>(
01089                     ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
01090                 writeShorts(pIdx, indexData->indexCount);
01091                 ibuf->unlock();
01092             }
01093         }
01094     
01095 
01096     }
01097     //---------------------------------------------------------------------
01098     void MeshSerializerImpl::writeBoundsInfo(const Mesh* pMesh)
01099     {
01100         // Usage Header
01101         unsigned long size = CHUNK_OVERHEAD_SIZE;
01102 
01103         size += sizeof(Real) * 7;
01104         writeChunkHeader(M_MESH_BOUNDS, size);
01105 
01106         // Real minx, miny, minz
01107         const Vector3& min = pMesh->mAABB.getMinimum();
01108         const Vector3& max = pMesh->mAABB.getMaximum();
01109         writeReals(&min.x, 1);
01110         writeReals(&min.y, 1);
01111         writeReals(&min.z, 1);
01112         // Real maxx, maxy, maxz
01113         writeReals(&max.x, 1);
01114         writeReals(&max.y, 1);
01115         writeReals(&max.z, 1);
01116         // Real radius
01117         writeReals(&pMesh->mBoundRadius, 1);
01118 
01119     }
01120     //---------------------------------------------------------------------
01121     void MeshSerializerImpl::readBoundsInfo(DataChunk& chunk)
01122     {
01123         Vector3 min, max;
01124         // Real minx, miny, minz
01125         readReals(chunk, &min.x, 1);
01126         readReals(chunk, &min.y, 1);
01127         readReals(chunk, &min.z, 1);
01128         // Real maxx, maxy, maxz
01129         readReals(chunk, &max.x, 1);
01130         readReals(chunk, &max.y, 1);
01131         readReals(chunk, &max.z, 1);
01132         AxisAlignedBox box(min, max);
01133         mpMesh->_setBounds(box);
01134         // Real radius
01135         Real radius;
01136         readReals(chunk, &radius, 1);
01137         mpMesh->_setBoundingSphereRadius(radius);
01138 
01139 
01140 
01141     }
01142     //---------------------------------------------------------------------
01143     void MeshSerializerImpl::readMeshLodInfo(DataChunk& chunk)
01144     {
01145         unsigned short chunkID, i;
01146 
01147         // unsigned short numLevels;
01148         readShorts(chunk, &(mpMesh->mNumLods), 1);
01149         // bool manual;  (true for manual alternate meshes, false for generated)
01150         readBools(chunk, &(mpMesh->mIsLodManual), 1);
01151 
01152         // Preallocate submesh lod face data if not manual
01153         if (!mpMesh->mIsLodManual)
01154         {
01155             unsigned short numsubs = mpMesh->getNumSubMeshes();
01156             for (i = 0; i < numsubs; ++i)
01157             {
01158                 SubMesh* sm = mpMesh->getSubMesh(i);
01159                 sm->mLodFaceList.resize(mpMesh->mNumLods-1);
01160             }
01161         }
01162 
01163         // Loop from 1 rather than 0 (full detail index is not in file)
01164         for (i = 1; i < mpMesh->mNumLods; ++i)
01165         {
01166             chunkID = readChunk(chunk);
01167             if (chunkID != M_MESH_LOD_USAGE)
01168             {
01169                 Except(Exception::ERR_ITEM_NOT_FOUND, 
01170                     "Missing M_MESH_LOD_USAGE chunk in " + mpMesh->getName(), 
01171                     "MeshSerializerImpl::readMeshLodInfo");
01172             }
01173             // Read depth
01174             Mesh::MeshLodUsage usage;
01175             readReals(chunk, &(usage.fromDepthSquared), 1);
01176 
01177             if (mpMesh->isLodManual())
01178             {
01179                 readMeshLodUsageManual(chunk, i, usage);
01180             }
01181             else //(!mpMesh->isLodManual)
01182             {
01183                 readMeshLodUsageGenerated(chunk, i, usage);
01184             }
01185             usage.edgeData = NULL;
01186 
01187             // Save usage
01188             mpMesh->mMeshLodUsageList.push_back(usage);
01189         }
01190 
01191 
01192     }
01193     //---------------------------------------------------------------------
01194     void MeshSerializerImpl::readMeshLodUsageManual(DataChunk& chunk, 
01195         unsigned short lodNum, Mesh::MeshLodUsage& usage)
01196     {
01197         unsigned long chunkID;
01198         // Read detail chunk
01199         chunkID = readChunk(chunk);
01200         if (chunkID != M_MESH_LOD_MANUAL)
01201         {
01202             Except(Exception::ERR_ITEM_NOT_FOUND, 
01203                 "Missing M_MESH_LOD_MANUAL chunk in " + mpMesh->getName(),
01204                 "MeshSerializerImpl::readMeshLodUsageManual");
01205         }
01206 
01207         usage.manualName = readString(chunk);
01208         usage.manualMesh = NULL; // will trigger load later
01209     }
01210     //---------------------------------------------------------------------
01211     void MeshSerializerImpl::readMeshLodUsageGenerated(DataChunk& chunk, 
01212         unsigned short lodNum, Mesh::MeshLodUsage& usage)
01213     {
01214         usage.manualName = "";
01215         usage.manualMesh = 0;
01216 
01217         // Get one set of detail per SubMesh
01218         unsigned short numSubs, i;
01219         unsigned long chunkID;
01220         numSubs = mpMesh->getNumSubMeshes();
01221         for (i = 0; i < numSubs; ++i)
01222         {
01223             chunkID = readChunk(chunk);
01224             if (chunkID != M_MESH_LOD_GENERATED)
01225             {
01226                 Except(Exception::ERR_ITEM_NOT_FOUND, 
01227                     "Missing M_MESH_LOD_GENERATED chunk in " + mpMesh->getName(),
01228                     "MeshSerializerImpl::readMeshLodUsageGenerated");
01229             }
01230 
01231             SubMesh* sm = mpMesh->getSubMesh(i);
01232             // lodNum - 1 because SubMesh doesn't store full detail LOD
01233             sm->mLodFaceList[lodNum - 1] = new IndexData();
01234             IndexData* indexData = sm->mLodFaceList[lodNum - 1];
01235             // unsigned int numIndexes
01236             unsigned int numIndexes;
01237             readInts(chunk, &numIndexes, 1);
01238             indexData->indexCount = static_cast<size_t>(numIndexes);
01239             // bool indexes32Bit
01240             bool idx32Bit;
01241             readBools(chunk, &idx32Bit, 1);
01242             // unsigned short*/int* faceIndexes;  ((v1, v2, v3) * numFaces)
01243             if (idx32Bit)
01244             {
01245                 indexData->indexBuffer = HardwareBufferManager::getSingleton().
01246                     createIndexBuffer(HardwareIndexBuffer::IT_32BIT, indexData->indexCount,
01247                     mpMesh->mIndexBufferUsage, mpMesh->mIndexBufferShadowBuffer);
01248                 unsigned int* pIdx = static_cast<unsigned int*>(
01249                     indexData->indexBuffer->lock(
01250                         0, 
01251                         indexData->indexBuffer->getSizeInBytes(), 
01252                         HardwareBuffer::HBL_DISCARD) );
01253 
01254                 readInts(chunk, pIdx, indexData->indexCount);
01255                 indexData->indexBuffer->unlock();
01256 
01257             }
01258             else
01259             {
01260                 indexData->indexBuffer = HardwareBufferManager::getSingleton().
01261                     createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount,
01262                     mpMesh->mIndexBufferUsage, mpMesh->mIndexBufferShadowBuffer);
01263                 unsigned short* pIdx = static_cast<unsigned short*>(
01264                     indexData->indexBuffer->lock(
01265                         0, 
01266                         indexData->indexBuffer->getSizeInBytes(), 
01267                         HardwareBuffer::HBL_DISCARD) );
01268                 readShorts(chunk, pIdx, indexData->indexCount);
01269                 indexData->indexBuffer->unlock();
01270 
01271             }
01272 
01273         }
01274     }
01275     //---------------------------------------------------------------------
01276     //---------------------------------------------------------------------
01277     //---------------------------------------------------------------------
01278     MeshSerializerImpl_v1_1::MeshSerializerImpl_v1_1()
01279     {
01280         // Version number
01281         mVersion = "[MeshSerializer_v1.10]";
01282     }
01283     //---------------------------------------------------------------------
01284     MeshSerializerImpl_v1_1::~MeshSerializerImpl_v1_1()
01285     {
01286     }
01287     //---------------------------------------------------------------------
01288     void MeshSerializerImpl_v1_1::readGeometryTexCoords(unsigned short bindIdx, 
01289         DataChunk& chunk, VertexData* dest, unsigned short texCoordSet)
01290     {
01291         Real *pReal = 0;
01292         HardwareVertexBufferSharedPtr vbuf;
01293         // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
01294         unsigned short dim;
01295         readShorts(chunk, &dim, 1);
01296         // Real* pTexCoords  (u [v] [w] order, dimensions x numVertices)
01297         dest->vertexDeclaration->addElement(
01298             bindIdx, 
01299             0, 
01300             VertexElement::multiplyTypeCount(VET_FLOAT1, dim), 
01301             VES_TEXTURE_COORDINATES,
01302             texCoordSet);
01303         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
01304             dest->vertexDeclaration->getVertexSize(bindIdx),
01305             dest->vertexCount,
01306             mpMesh->getVertexBufferUsage(),
01307             mpMesh->isVertexBufferShadowed());
01308         pReal = static_cast<Real*>(
01309             vbuf->lock(HardwareBuffer::HBL_DISCARD));
01310         readReals(chunk, pReal, dest->vertexCount * dim);
01311 
01312         // Adjust individual v values to (1 - v)
01313         if (dim == 2)
01314         {
01315             for (size_t i = 0; i < dest->vertexCount; ++i)
01316             {
01317                 ++pReal; // skip u
01318                 *pReal = 1.0 - *pReal; // v = 1 - v
01319                 ++pReal;
01320             }
01321             
01322         }
01323         vbuf->unlock();
01324         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
01325     }
01326     //---------------------------------------------------------------------
01327     //---------------------------------------------------------------------
01328     //---------------------------------------------------------------------
01329     MeshSerializerImpl_v1::MeshSerializerImpl_v1()
01330     {
01331         // Version number
01332         mVersion = "[MeshSerializer_v1.00]";
01333 
01334     }
01335     //---------------------------------------------------------------------
01336     void MeshSerializerImpl_v1::readMesh(DataChunk& chunk)
01337     {
01338         unsigned short chunkID;
01339 
01340         mFirstGeometry = true;
01341         mIsSkeletallyAnimated = false;
01342 
01343         // M_GEOMETRY chunk
01344         chunkID = readChunk(chunk);
01345         if (chunkID == M_GEOMETRY)
01346         {
01347             mpMesh->sharedVertexData = new VertexData();
01348             try {
01349                 readGeometry(chunk, mpMesh->sharedVertexData);
01350             }
01351             catch (Exception& e)
01352             {
01353                 if (e.getNumber() == Exception::ERR_ITEM_NOT_FOUND)
01354                 {
01355                     // duff geometry data entry with 0 vertices
01356                     delete mpMesh->sharedVertexData;
01357                     mpMesh->sharedVertexData = 0;
01358                     // Skip this chunk (pointer will have been returned to just after header)
01359                     chunk.skip(mCurrentChunkLen - CHUNK_OVERHEAD_SIZE);
01360                 }
01361                 else
01362                 {
01363                     throw;
01364                 }
01365             }
01366         }
01367 
01368         // Find all subchunks 
01369         if (!chunk.isEOF())
01370         {
01371             chunkID = readChunk(chunk);
01372             while(!chunk.isEOF() &&
01373                 (chunkID == M_SUBMESH ||
01374                  chunkID == M_MESH_SKELETON_LINK ||
01375                  chunkID == M_MESH_BONE_ASSIGNMENT ||
01376                  chunkID == M_MESH_LOD))
01377             {
01378                 switch(chunkID)
01379                 {
01380                 case M_SUBMESH:
01381                     readSubMesh(chunk);
01382                     break;
01383                 case M_MESH_SKELETON_LINK:
01384                     readSkeletonLink(chunk);
01385                     break;
01386                 case M_MESH_BONE_ASSIGNMENT:
01387                     readMeshBoneAssignment(chunk);
01388                     break;
01389                 case M_MESH_LOD:
01390                     readMeshLodInfo(chunk);
01391                     break;
01392                 }
01393 
01394                 if (!chunk.isEOF())
01395                 {
01396                     chunkID = readChunk(chunk);
01397                 }
01398 
01399             }
01400             if (!chunk.isEOF())
01401             {
01402                 // Backpedal back to start of chunk
01403                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
01404             }
01405         }
01406 
01407     }
01408     //---------------------------------------------------------------------
01409     void MeshSerializerImpl_v1::readSubMesh(DataChunk& chunk)
01410     {
01411         unsigned short chunkID;
01412 
01413         SubMesh* sm = mpMesh->createSubMesh();
01414         // char* materialName
01415         String materialName = readString(chunk);
01416         sm->setMaterialName(materialName);
01417 
01418         // bool useSharedVertices
01419         readBools(chunk,&sm->useSharedVertices, 1);
01420 
01421         // unsigned short faceCount
01422         sm->indexData->indexStart = 0;
01423         unsigned short faceCount;
01424         readShorts(chunk, &faceCount, 1);
01425         sm->indexData->indexCount = faceCount * 3;
01426 
01427         // Indexes always 16-bit in this version
01428         HardwareIndexBufferSharedPtr ibuf;
01429         ibuf = HardwareBufferManager::getSingleton().
01430             createIndexBuffer(
01431                 HardwareIndexBuffer::IT_16BIT, 
01432                 sm->indexData->indexCount, 
01433                 mpMesh->mIndexBufferUsage,
01434                 mpMesh->mIndexBufferShadowBuffer);
01435         sm->indexData->indexBuffer = ibuf;
01436         // unsigned short* faceVertexIndices 
01437         unsigned short* pIdx = static_cast<unsigned short*>(
01438             ibuf->lock(HardwareBuffer::HBL_DISCARD)
01439             );
01440         readShorts(chunk, pIdx, sm->indexData->indexCount);
01441         ibuf->unlock();
01442 
01443         // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
01444         if (!sm->useSharedVertices)
01445         {
01446             chunkID = readChunk(chunk);
01447             if (chunkID != M_GEOMETRY)
01448             {
01449                 Except(Exception::ERR_INTERNAL_ERROR, "Missing geometry data in mesh file", 
01450                     "MeshSerializerImpl::readSubMesh");
01451             }
01452             sm->vertexData = new VertexData();
01453             readGeometry(chunk, sm->vertexData);
01454         }
01455 
01456 
01457         // Find all bone assignments (if present) 
01458         if (!chunk.isEOF())
01459         {
01460             chunkID = readChunk(chunk);
01461             while(!chunk.isEOF() &&
01462                 (chunkID == M_SUBMESH_BONE_ASSIGNMENT))
01463             {
01464                 switch(chunkID)
01465                 {
01466                 case M_SUBMESH_BONE_ASSIGNMENT:
01467                     readSubMeshBoneAssignment(chunk, sm);
01468                     break;
01469                 }
01470 
01471                 if (!chunk.isEOF())
01472                 {
01473                     chunkID = readChunk(chunk);
01474                 }
01475 
01476             }
01477             if (!chunk.isEOF())
01478             {
01479                 // Backpedal back to start of chunk
01480                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
01481             }
01482         }
01483     }
01484     //---------------------------------------------------------------------
01485     void MeshSerializerImpl_v1::readGeometry(DataChunk& chunk, VertexData* dest)
01486     {
01487         unsigned short texCoordSet = 0;
01488         HardwareVertexBufferSharedPtr vbuf;
01489         unsigned short bindIdx = 0;
01490         Real *pReal = 0;
01491         RGBA* pRGBA = 0;
01492 
01493         dest->vertexStart = 0;
01494 
01495         // unsigned short numVertices
01496         unsigned short numVerts;
01497         readShorts(chunk, &numVerts, 1);
01498         dest->vertexCount = numVerts;
01499 
01500         if (dest->vertexCount == 0)
01501         {
01502             // Empty positions
01503             // skip back to where we were
01504             chunk.skip(0 - sizeof(unsigned short));
01505             Except(Exception::ERR_ITEM_NOT_FOUND, "Geometry section found but no "
01506                 "positions defined - you should upgrade this .mesh to the latest version "
01507                 "to eliminate this problem.", "MeshSerializerImpl::readGeometry");
01508         }
01509 
01510         // Vertex buffers
01511         // TODO: consider redesigning this so vertex buffers can be combined
01512 
01513         // Real* pVertices (x, y, z order x numVertices)
01514         dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_POSITION);
01515         vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
01516             dest->vertexDeclaration->getVertexSize(bindIdx),
01517             dest->vertexCount,
01518             mpMesh->mVertexBufferUsage,
01519             mpMesh->mVertexBufferShadowBuffer);
01520         pReal = static_cast<Real*>(
01521             vbuf->lock(HardwareBuffer::HBL_DISCARD));
01522         readReals(chunk, pReal, dest->vertexCount * 3);
01523 
01524         // Since in v1 we did not save mesh bounds, we need to calculate them now
01525         AxisAlignedBox localBox;
01526         Vector3 min, max;
01527         bool first = true;
01528         Real maxSquaredRadius = -1;
01529 
01530         for (size_t vert = 0; vert < dest->vertexCount; ++vert)
01531         {
01532             Vector3 vec(pReal[0], pReal[1], pReal[2]);
01533 
01534             // Update sphere bounds
01535             maxSquaredRadius = std::max(vec.squaredLength(), maxSquaredRadius);
01536 
01537             // Update box
01538             if (first)
01539             {
01540                 min = vec;
01541                 max = vec;
01542                 first = false;
01543             }
01544             else
01545             {
01546                 min.makeFloor(vec);
01547                 max.makeCeil(vec);
01548             }
01549 
01550             pReal += 3;
01551         }
01552         localBox.setExtents(min, max);
01553         
01554         if (mFirstGeometry)
01555         {
01556             mpMesh->_setBounds(localBox);
01557             mpMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
01558             mFirstGeometry = false;
01559         }
01560         else
01561         {
01562             localBox.merge(mpMesh->mAABB);
01563             mpMesh->_setBounds(localBox);
01564             maxSquaredRadius = std::max(maxSquaredRadius, mpMesh->mBoundRadius);
01565             mpMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
01566         }
01567 
01568         vbuf->unlock();
01569         dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
01570         ++bindIdx;
01571 
01572         // Find optional geometry chunks
01573         if (!chunk.isEOF())
01574         {
01575             unsigned short chunkID = readChunk(chunk);
01576             while(!chunk.isEOF() && 
01577                 (chunkID == M_GEOMETRY_NORMALS || 
01578                  chunkID == M_GEOMETRY_COLOURS ||
01579                  chunkID == M_GEOMETRY_TEXCOORDS ))
01580             {
01581                 switch (chunkID)
01582                 {
01583                 case M_GEOMETRY_NORMALS:
01584                     // Real* pNormals (x, y, z order x numVertices)
01585                     dest->vertexDeclaration->addElement(bindIdx, 0, VET_FLOAT3, VES_NORMAL);
01586                     vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
01587                         dest->vertexDeclaration->getVertexSize(bindIdx),
01588                         dest->vertexCount,
01589                         mpMesh->mVertexBufferUsage,
01590                         mpMesh->mVertexBufferShadowBuffer);
01591                     pReal = static_cast<Real*>(
01592                         vbuf->lock(HardwareBuffer::HBL_DISCARD));
01593                     readReals(chunk, pReal, dest->vertexCount * 3);
01594                     vbuf->unlock();
01595                     dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
01596                     ++bindIdx;
01597                     break;
01598                 case M_GEOMETRY_COLOURS:
01599                     // unsigned long* pColours (RGBA 8888 format x numVertices)
01600                     dest->vertexDeclaration->addElement(bindIdx, 0, VET_COLOUR, VES_DIFFUSE);
01601                     vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
01602                         dest->vertexDeclaration->getVertexSize(bindIdx),
01603                         dest->vertexCount,
01604                         mpMesh->mVertexBufferUsage,
01605                         mpMesh->mVertexBufferShadowBuffer);
01606                     pRGBA = static_cast<RGBA*>(
01607                         vbuf->lock(HardwareBuffer::HBL_DISCARD));
01608                     readLongs(chunk, pRGBA, dest->vertexCount);
01609                     vbuf->unlock();
01610                     dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
01611                     ++bindIdx;
01612                     break;
01613                 case M_GEOMETRY_TEXCOORDS:
01614                     // unsigned short dimensions    (1 for 1D, 2 for 2D, 3 for 3D)
01615                     unsigned short dim;
01616                     readShorts(chunk, &dim, 1);
01617                     // Real* pTexCoords  (u [v] [w] order, dimensions x numVertices)
01618                     dest->vertexDeclaration->addElement(
01619                         bindIdx, 
01620                         0, 
01621                         VertexElement::multiplyTypeCount(VET_FLOAT1, dim), 
01622                         VES_TEXTURE_COORDINATES,
01623                         texCoordSet);
01624                     vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
01625                         dest->vertexDeclaration->getVertexSize(bindIdx),
01626                         dest->vertexCount,
01627                         mpMesh->mVertexBufferUsage,
01628                         mpMesh->mVertexBufferShadowBuffer);
01629                     pReal = static_cast<Real*>(
01630                         vbuf->lock(HardwareBuffer::HBL_DISCARD));
01631                     readReals(chunk, pReal, dest->vertexCount * dim);
01632 
01633                     // Adjust individual v values to (1 - v)
01634                     if (dim == 2)
01635                     {
01636                         for (size_t i = 0; i < dest->vertexCount; ++i)
01637                         {
01638                             ++pReal; // skip u
01639                             *pReal = 1.0 - *pReal; // v = 1 - v
01640                             ++pReal;
01641                         }
01642                         
01643                     }
01644 
01645                     vbuf->unlock();
01646                     dest->vertexBufferBinding->setBinding(bindIdx, vbuf);
01647                     ++texCoordSet;
01648                     ++bindIdx;
01649                     break;
01650                 }
01651                 // Get next chunk
01652                 if (!chunk.isEOF())
01653                 {
01654                     chunkID = readChunk(chunk);
01655                 }
01656             }
01657             if (!chunk.isEOF())
01658             {
01659                 // Backpedal back to start of non-submesh chunk
01660                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
01661             }
01662         }
01663     }
01664     //---------------------------------------------------------------------
01665     void MeshSerializerImpl_v1::readMeshBoneAssignment(DataChunk& chunk)
01666     {
01667         VertexBoneAssignment assign;
01668 
01669         // unsigned short vertexIndex;
01670         unsigned short vIndex;
01671         readShorts(chunk, &vIndex,1);
01672         assign.vertexIndex = vIndex;
01673         // unsigned short boneIndex;
01674         readShorts(chunk, &(assign.boneIndex),1);
01675         // Real weight;
01676         readReals(chunk, &(assign.weight), 1);
01677 
01678         mpMesh->addBoneAssignment(assign);
01679 
01680     }
01681     //---------------------------------------------------------------------
01682     void MeshSerializerImpl_v1::readSubMeshBoneAssignment(DataChunk& chunk, SubMesh* sub)
01683     {
01684         VertexBoneAssignment assign;
01685 
01686         // unsigned short vertexIndex;
01687         unsigned short vIndex;
01688         readShorts(chunk, &vIndex,1);
01689         assign.vertexIndex = vIndex;
01690         // unsigned short boneIndex;
01691         readShorts(chunk, &(assign.boneIndex),1);
01692         // Real weight;
01693         readReals(chunk, &(assign.weight), 1);
01694 
01695         sub->addBoneAssignment(assign);
01696     }
01697     //---------------------------------------------------------------------
01698     void MeshSerializerImpl_v1::readMeshLodUsageGenerated(DataChunk& chunk, unsigned short lodNum, Mesh::MeshLodUsage& usage)
01699     {
01700         usage.manualName = "";
01701         usage.manualMesh = 0;
01702 
01703         // Get one set of detail per SubMesh
01704         unsigned short numSubs, i;
01705         unsigned long chunkID;
01706         numSubs = mpMesh->getNumSubMeshes();
01707         for (i = 0; i < numSubs; ++i)
01708         {
01709             chunkID = readChunk(chunk);
01710             if (chunkID != M_MESH_LOD_GENERATED)
01711             {
01712                 Except(Exception::ERR_ITEM_NOT_FOUND, 
01713                     "Missing M_MESH_LOD_GENERATED chunk in " + mpMesh->getName(),
01714                     "MeshSerializerImpl::readMeshLodUsageGenerated");
01715             }
01716 
01717             SubMesh* sm = mpMesh->getSubMesh(i);
01718             // lodNum - 1 because SubMesh doesn't store full detail LOD
01719             sm->mLodFaceList[lodNum - 1] = new IndexData();
01720             IndexData* indexData = sm->mLodFaceList[lodNum - 1];
01721             // unsigned short numFaces
01722             unsigned short numFaces;
01723             readShorts(chunk, &numFaces, 1);
01724             indexData->indexCount = static_cast<size_t>(numFaces * 3);
01725             // unsigned short*/int* faceIndexes;  ((v1, v2, v3) * numFaces)
01726             // Always 16-bit in 1.0
01727             indexData->indexBuffer = HardwareBufferManager::getSingleton().
01728                 createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount,
01729                 mpMesh->mIndexBufferUsage, mpMesh->mIndexBufferShadowBuffer);
01730             unsigned short* pIdx = static_cast<unsigned short*>(
01731                 indexData->indexBuffer->lock(
01732                     0, 
01733                     indexData->indexBuffer->getSizeInBytes(), 
01734                     HardwareBuffer::HBL_DISCARD) );
01735             readShorts(chunk, pIdx, indexData->indexCount);
01736             indexData->indexBuffer->unlock();
01737 
01738         }
01739     }
01740     //---------------------------------------------------------------------
01741     void MeshSerializerImpl_v1::readMaterial(DataChunk& chunk)
01742     {
01743         ColourValue col;
01744         Real rVal;
01745 
01746         // Material definition section phased out of 1.1
01747         LogManager::getSingleton().logMessage(
01748             "Warning: Material definitions are no longer supported in .mesh files, "
01749             "you should move these definitions to a material script when you "
01750             "upgrade this mesh to the latest version. ");
01751 
01752         // char* name 
01753         String name = readString(chunk);
01754 
01755         // Create a new material
01756         Material* pMat;
01757         try 
01758         {
01759             pMat = (Material*)MaterialManager::getSingleton().create(name);
01760             Pass* p = pMat->createTechnique()->createPass();
01761         }
01762         catch (Exception& e)
01763         {
01764             if(e.getNumber() == Exception::ERR_DUPLICATE_ITEM)
01765             {
01766                 // Material already exists
01767                 char msg[256];
01768                 sprintf(msg, "Material '%s' in model '%s' has been ignored "
01769                     "because a material with the same name has already "
01770                     "been registered.", name.c_str(),
01771                     mpMesh->getName().c_str());
01772                 LogManager::getSingleton().logMessage(msg);
01773                 // Skip the rest of this material
01774                 chunk.skip(mCurrentChunkLen - name.length() - 1 - CHUNK_OVERHEAD_SIZE);
01775                 return;
01776 
01777             }
01778             else
01779             {
01780                 throw;
01781             }
01782         }
01783 
01784         // AMBIENT
01785         // Real r, g, b
01786         readReals(chunk, &col.r, 1);
01787         readReals(chunk, &col.g, 1);
01788         readReals(chunk, &col.b, 1);
01789         pMat->setAmbient(col);
01790 
01791         // DIFFUSE
01792         // Real r, g, b
01793         readReals(chunk, &col.r, 1);
01794         readReals(chunk, &col.g, 1);
01795         readReals(chunk, &col.b, 1);
01796         pMat->setDiffuse(col);
01797 
01798         // SPECULAR
01799         // Real r, g, b
01800         readReals(chunk, &col.r, 1);
01801         readReals(chunk, &col.g, 1);
01802         readReals(chunk, &col.b, 1);
01803         pMat->setSpecular(col);
01804 
01805         // SHININESS
01806         // Real val;
01807         readReals(chunk, &rVal, 1);
01808         pMat->setShininess(rVal);
01809 
01810         // Read any texture layers
01811         if (!chunk.isEOF())
01812         {
01813             unsigned short chunkID = readChunk(chunk);
01814             while(chunkID == M_TEXTURE_LAYER && !chunk.isEOF())
01815             {
01816                 readTextureLayer(chunk, pMat);
01817                 if (!chunk.isEOF())
01818                 {
01819                     chunkID = readChunk(chunk);
01820                 }
01821             }
01822             // Get next chunk
01823             if (!chunk.isEOF())
01824             {
01825                 // Backpedal back to start of non-texture layer chunk
01826                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
01827             }
01828         }
01829 
01830     }
01831     //---------------------------------------------------------------------
01832     void MeshSerializerImpl_v1::readTextureLayer(DataChunk& chunk, Material* pMat)
01833     {
01834         // Just name for now
01835         String name = readString(chunk);
01836 
01837         pMat->getTechnique(0)->getPass(0)->createTextureUnitState(name);
01838     }
01839 
01840 
01841 
01842 
01843 }
01844 

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:27 2004