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