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