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