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

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:35 2004