lugre_meshloader.cpp

Go to the documentation of this file.
00001 // inspired by Ogre::MeshSerializerImpl
00002 
00003 #include <OgreStableHeaders.h>
00004 #include <OgreMeshFileFormat.h>
00005 #include <OgreMesh.h>
00006 #include <OgreSubMesh.h>
00007 #include <OgreException.h>
00008 #include <OgreLogManager.h>
00009 #include <OgreSkeleton.h>
00010 #include <OgreHardwareBufferManager.h>
00011 #include <OgreMaterial.h>
00012 #include <OgreTechnique.h>
00013 #include <OgrePass.h>
00014 #include <OgreAnimation.h>
00015 #include <OgreAnimationTrack.h>
00016 #include <OgreKeyFrame.h>
00017 #include <OgreRoot.h>
00018         
00019 #include "lugre_prefix.h"
00020 #include "lugre_meshbuffer.h"
00021 #include "lugre_meshloader.h"
00022 #undef min
00023 #undef max
00024 #include <Ogre.h>
00025 #include <map>
00026 #include <string>
00027 #include <iostream>
00028 #include <fstream>
00029 #include "lugre_meshshape.h"
00030 using namespace Ogre;
00031 
00032 #define MESHLOAD_SKIP
00033 // #define ENABLE_LUGRE_MESH_LOADER   // uncomment this to enable compiling of the code below
00034 
00035 namespace Lugre {
00036     
00037 void    MeshLoader_LoadFile     (const char* szFilePath,cBufferedMesh* pDest) {
00038     #ifdef ENABLE_LUGRE_MESH_LOADER
00039     std::ifstream fp;
00040     fp.open(szFilePath, std::ios::in | std::ios::binary);
00041     if (!fp) { printf("MeshLoader_LoadFile:error opening file %s\n",szFilePath); return; }
00042     Ogre::DataStreamPtr stream(new FileStreamDataStream(szFilePath, &fp, false));
00043     cMeshLoader myloader;
00044     myloader.importMesh(stream,pDest);
00045     #endif
00046 }
00047     
00048     
00049     
00050     
00051     
00052 #ifdef ENABLE_LUGRE_MESH_LOADER
00054 const long STREAM_OVERHEAD_SIZE = sizeof(uint16) + sizeof(uint32);
00055 //---------------------------------------------------------------------
00056 cMeshLoader::cMeshLoader()
00057 {
00058     // Version number
00059     mVersion = "[Lugre_cMeshLoader_v1.40]";
00060 }
00061 //---------------------------------------------------------------------
00062 cMeshLoader::~cMeshLoader()
00063 {
00064 }
00065 
00066 
00067 //---------------------------------------------------------------------
00068 void cMeshLoader::importMesh(DataStreamPtr& stream, Mesh* pMesh)
00069 {
00070     // Determine endianness (must be the first thing we do!)
00071     determineEndianness(stream);
00072 
00073     // Check header
00074     readFileHeader(stream);
00075 
00076     unsigned short streamID;
00077     while(!stream->eof())
00078     {
00079         streamID = readChunk(stream);
00080         switch (streamID)
00081         {
00082         case M_MESH:
00083             readMesh(stream, pMesh);
00084             break;
00085         }
00086 
00087     }
00088 }
00089 //---------------------------------------------------------------------
00090 //---------------------------------------------------------------------
00091 void cMeshLoader::readGeometry(DataStreamPtr& stream, Mesh* pMesh,
00092     VertexData* dest)
00093 {
00094 
00095     dest->vertexStart = 0;
00096 
00097     unsigned int vertexCount = 0;
00098     readInts(stream, &vertexCount, 1);
00099     dest->vertexCount = vertexCount;
00100 
00101     // Find optional geometry streams
00102     if (!stream->eof())
00103     {
00104         unsigned short streamID = readChunk(stream);
00105         while(!stream->eof() &&
00106             (streamID == M_GEOMETRY_VERTEX_DECLARATION ||
00107              streamID == M_GEOMETRY_VERTEX_BUFFER ))
00108         {
00109             switch (streamID)
00110             {
00111             case M_GEOMETRY_VERTEX_DECLARATION:
00112                 readGeometryVertexDeclaration(stream, pMesh, dest);
00113                 break;
00114             case M_GEOMETRY_VERTEX_BUFFER:
00115                 readGeometryVertexBuffer(stream, pMesh, dest);
00116                 break;
00117             }
00118             // Get next stream
00119             if (!stream->eof())
00120             {
00121                 streamID = readChunk(stream);
00122             }
00123         }
00124         if (!stream->eof())
00125         {
00126             // Backpedal back to start of non-submesh stream
00127             stream->skip(-STREAM_OVERHEAD_SIZE);
00128         }
00129     }
00130 
00131     // Perform any necessary colour conversion for an active rendersystem
00132     if (Root::getSingletonPtr() && Root::getSingleton().getRenderSystem())
00133     {
00134         // We don't know the source type if it's VET_COLOUR, but assume ARGB
00135         // since that's the most common. Won't get used unless the mesh is
00136         // ambiguous anyway, which will have been warned about in the log
00137         dest->convertPackedColour(VET_COLOUR_ARGB, 
00138             VertexElement::getBestColourVertexElementType());
00139     }
00140 }
00141 //---------------------------------------------------------------------
00142 void cMeshLoader::readGeometryVertexDeclaration(DataStreamPtr& stream,
00143     Mesh* pMesh, VertexData* dest)
00144 {
00145     // Find optional geometry streams
00146     if (!stream->eof())
00147     {
00148         unsigned short streamID = readChunk(stream);
00149         while(!stream->eof() &&
00150             (streamID == M_GEOMETRY_VERTEX_ELEMENT ))
00151         {
00152             switch (streamID)
00153             {
00154             case M_GEOMETRY_VERTEX_ELEMENT:
00155                 readGeometryVertexElement(stream, pMesh, dest);
00156                 break;
00157             }
00158             // Get next stream
00159             if (!stream->eof())
00160             {
00161                 streamID = readChunk(stream);
00162             }
00163         }
00164         if (!stream->eof())
00165         {
00166             // Backpedal back to start of non-submesh stream
00167             stream->skip(-STREAM_OVERHEAD_SIZE);
00168         }
00169     }
00170 
00171 }
00172 //---------------------------------------------------------------------
00173 void cMeshLoader::readGeometryVertexElement(DataStreamPtr& stream,
00174     Mesh* pMesh, VertexData* dest)
00175 {
00176     unsigned short source, offset, index, tmp;
00177     VertexElementType vType;
00178     VertexElementSemantic vSemantic;
00179     // unsigned short source;   // buffer bind source
00180     readShorts(stream, &source, 1);
00181     // unsigned short type;     // VertexElementType
00182     readShorts(stream, &tmp, 1);
00183     vType = static_cast<VertexElementType>(tmp);
00184     // unsigned short semantic; // VertexElementSemantic
00185     readShorts(stream, &tmp, 1);
00186     vSemantic = static_cast<VertexElementSemantic>(tmp);
00187     // unsigned short offset;   // start offset in buffer in bytes
00188     readShorts(stream, &offset, 1);
00189     // unsigned short index;    // index of the semantic
00190     readShorts(stream, &index, 1);
00191 
00192     dest->vertexDeclaration->addElement(source, offset, vType, vSemantic, index);
00193 
00194     if (vType == VET_COLOUR)
00195     {
00196         StringUtil::StrStreamType s;
00197         s << "Warning: VET_COLOUR element type is deprecated, you should use "
00198             << "one of the more specific types to indicate the byte order. "
00199             << "Use OgreMeshUpgrade on " << pMesh->getName() << " as soon as possible. ";
00200         LogManager::getSingleton().logMessage(s.str());
00201     }
00202 
00203 }
00204 //---------------------------------------------------------------------
00205 void cMeshLoader::readGeometryVertexBuffer(DataStreamPtr& stream,
00206     Mesh* pMesh, VertexData* dest)
00207 {
00208     unsigned short bindIndex, vertexSize;
00209     // unsigned short bindIndex;    // Index to bind this buffer to
00210     readShorts(stream, &bindIndex, 1);
00211     // unsigned short vertexSize;   // Per-vertex size, must agree with declaration at this index
00212     readShorts(stream, &vertexSize, 1);
00213 
00214     // Check for vertex data header
00215     unsigned short headerID;
00216     headerID = readChunk(stream);
00217     if (headerID != M_GEOMETRY_VERTEX_BUFFER_DATA)
00218     {
00219         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Can't find vertex buffer data area",
00220             "cMeshLoader::readGeometryVertexBuffer");
00221     }
00222     // Check that vertex size agrees
00223     if (dest->vertexDeclaration->getVertexSize(bindIndex) != vertexSize)
00224     {
00225         OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Buffer vertex size does not agree with vertex declaration",
00226             "cMeshLoader::readGeometryVertexBuffer");
00227     }
00228 
00229     #ifdef MESHLOAD_SKIP 
00230     stream->skip(dest->vertexCount * vertexSize);
00231     #else
00232     // Create / populate vertex buffer
00233     HardwareVertexBufferSharedPtr vbuf;
00234     vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
00235         vertexSize,
00236         dest->vertexCount,
00237         pMesh->mVertexBufferUsage,
00238         pMesh->mVertexBufferShadowBuffer);
00239     void* pBuf = vbuf->lock(HardwareBuffer::HBL_DISCARD);
00240     stream->read(pBuf, dest->vertexCount * vertexSize);
00241 
00242     // endian conversion for OSX
00243     flipFromLittleEndian(
00244         pBuf,
00245         dest->vertexCount,
00246         vertexSize,
00247         dest->vertexDeclaration->findElementsBySource(bindIndex));
00248     vbuf->unlock();
00249 
00250     // Set binding
00251     dest->vertexBufferBinding->setBinding(bindIndex, vbuf);
00252     #endif
00253 }
00254 //---------------------------------------------------------------------
00255 void cMeshLoader::readSubMeshNameTable(DataStreamPtr& stream, Mesh* pMesh)
00256 {
00257     // The map for
00258     std::map<unsigned short, String> subMeshNames;
00259     unsigned short streamID, subMeshIndex;
00260 
00261     // Need something to store the index, and the objects name
00262     // This table is a method that imported meshes can retain their naming
00263     // so that the names established in the modelling software can be used
00264     // to get the sub-meshes by name. The exporter must support exporting
00265     // the optional stream M_SUBMESH_NAME_TABLE.
00266 
00267     // Read in all the sub-streams. Each sub-stream should contain an index and Ogre::String for the name.
00268     if (!stream->eof())
00269     {
00270         streamID = readChunk(stream);
00271         while(!stream->eof() && (streamID == M_SUBMESH_NAME_TABLE_ELEMENT ))
00272         {
00273             // Read in the index of the submesh.
00274             readShorts(stream, &subMeshIndex, 1);
00275             // Read in the String and map it to its index.
00276             subMeshNames[subMeshIndex] = readString(stream);
00277 
00278             // If we're not end of file get the next stream ID
00279             if (!stream->eof())
00280                 streamID = readChunk(stream);
00281         }
00282         if (!stream->eof())
00283         {
00284             // Backpedal back to start of stream
00285             stream->skip(-STREAM_OVERHEAD_SIZE);
00286         }
00287     }
00288 
00289     // Set all the submeshes names
00290     // ?
00291 
00292     // Loop through and save out the index and names.
00293     std::map<unsigned short, String>::const_iterator it = subMeshNames.begin();
00294 
00295     while(it != subMeshNames.end())
00296     {
00297         // Name this submesh to the stored name.
00298         pMesh->nameSubMesh(it->second, it->first);
00299         ++it;
00300     }
00301 
00302 
00303 
00304 }
00305 //---------------------------------------------------------------------
00306 void cMeshLoader::readMesh(DataStreamPtr& stream, Mesh* pMesh)
00307 {
00308     unsigned short streamID;
00309 
00310     // Never automatically build edge lists for this version
00311     // expect them in the file or not at all
00312     pMesh->mAutoBuildEdgeLists = false;
00313 
00314     // bool skeletallyAnimated
00315     bool skeletallyAnimated;
00316     readBools(stream, &skeletallyAnimated, 1);
00317 
00318     // Find all substreams
00319     if (!stream->eof())
00320     {
00321         streamID = readChunk(stream);
00322         while(!stream->eof() &&
00323             (streamID == M_GEOMETRY ||
00324              streamID == M_SUBMESH ||
00325              streamID == M_MESH_SKELETON_LINK ||
00326              streamID == M_MESH_BONE_ASSIGNMENT ||
00327              streamID == M_MESH_LOD ||
00328              streamID == M_MESH_BOUNDS ||
00329              streamID == M_SUBMESH_NAME_TABLE ||
00330              streamID == M_EDGE_LISTS ||
00331              streamID == M_POSES ||
00332              streamID == M_ANIMATIONS ||
00333              streamID == M_TABLE_EXTREMES))
00334         {
00335             switch(streamID)
00336             {
00337             case M_GEOMETRY:
00338                 pMesh->sharedVertexData = new VertexData();
00339                 try {
00340                     readGeometry(stream, pMesh, pMesh->sharedVertexData);
00341                 }
00342                 catch (Exception& e)
00343                 {
00344                     if (e.getNumber() == Exception::ERR_ITEM_NOT_FOUND)
00345                     {
00346                         // duff geometry data entry with 0 vertices
00347                         delete pMesh->sharedVertexData;
00348                         pMesh->sharedVertexData = 0;
00349                         // Skip this stream (pointer will have been returned to just after header)
00350                         stream->skip(mCurrentstreamLen - STREAM_OVERHEAD_SIZE);
00351                     }
00352                     else
00353                     {
00354                         throw;
00355                     }
00356                 }
00357                 break;
00358             case M_SUBMESH:
00359                 readSubMesh(stream, pMesh);
00360                 break;
00361             case M_MESH_SKELETON_LINK:
00362                 readSkeletonLink(stream, pMesh);
00363                 break;
00364             case M_MESH_BONE_ASSIGNMENT:
00365                 readMeshBoneAssignment(stream, pMesh);
00366                 break;
00367             case M_MESH_LOD:
00368                 readMeshLodInfo(stream, pMesh);
00369                 break;
00370             case M_MESH_BOUNDS:
00371                 readBoundsInfo(stream, pMesh);
00372                 break;
00373             case M_SUBMESH_NAME_TABLE:
00374                 readSubMeshNameTable(stream, pMesh);
00375                 break;
00376             case M_EDGE_LISTS:
00377                 readEdgeList(stream, pMesh);
00378                 break;
00379             case M_POSES:
00380                 readPoses(stream, pMesh);
00381                 break;
00382             case M_ANIMATIONS:
00383                 readAnimations(stream, pMesh);
00384                 break;
00385             case M_TABLE_EXTREMES:
00386                 readExtremes(stream, pMesh);
00387                 break;
00388             }
00389 
00390             if (!stream->eof())
00391             {
00392                 streamID = readChunk(stream);
00393             }
00394 
00395         }
00396         if (!stream->eof())
00397         {
00398             // Backpedal back to start of stream
00399             stream->skip(-STREAM_OVERHEAD_SIZE);
00400         }
00401     }
00402 
00403 }
00404 //---------------------------------------------------------------------
00405 void cMeshLoader::readSubMesh(DataStreamPtr& stream, Mesh* pMesh)
00406 {
00407     unsigned short streamID;
00408 
00409     SubMesh* sm = pMesh->createSubMesh();
00410     // char* materialName
00411     String materialName = readString(stream);
00412     sm->setMaterialName(materialName);
00413     // bool useSharedVertices
00414     readBools(stream,&sm->useSharedVertices, 1);
00415 
00416     sm->indexData->indexStart = 0;
00417     unsigned int indexCount = 0;
00418     readInts(stream, &indexCount, 1);
00419     sm->indexData->indexCount = indexCount;
00420 
00421     HardwareIndexBufferSharedPtr ibuf;
00422     // bool indexes32Bit
00423     bool idx32bit;
00424     readBools(stream, &idx32bit, 1);
00425     if (idx32bit)
00426     {
00427         ibuf = HardwareBufferManager::getSingleton().
00428             createIndexBuffer(
00429                 HardwareIndexBuffer::IT_32BIT,
00430                 sm->indexData->indexCount,
00431                 pMesh->mIndexBufferUsage,
00432                 pMesh->mIndexBufferShadowBuffer);
00433         // unsigned int* faceVertexIndices
00434         unsigned int* pIdx = static_cast<unsigned int*>(
00435             ibuf->lock(HardwareBuffer::HBL_DISCARD)
00436             );
00437         readInts(stream, pIdx, sm->indexData->indexCount);
00438         ibuf->unlock();
00439 
00440     }
00441     else // 16-bit
00442     {
00443         ibuf = HardwareBufferManager::getSingleton().
00444             createIndexBuffer(
00445                 HardwareIndexBuffer::IT_16BIT,
00446                 sm->indexData->indexCount,
00447                 pMesh->mIndexBufferUsage,
00448                 pMesh->mIndexBufferShadowBuffer);
00449         // unsigned short* faceVertexIndices
00450         unsigned short* pIdx = static_cast<unsigned short*>(
00451             ibuf->lock(HardwareBuffer::HBL_DISCARD)
00452             );
00453         readShorts(stream, pIdx, sm->indexData->indexCount);
00454         ibuf->unlock();
00455     }
00456     sm->indexData->indexBuffer = ibuf;
00457 
00458     // M_GEOMETRY stream (Optional: present only if useSharedVertices = false)
00459     if (!sm->useSharedVertices)
00460     {
00461         streamID = readChunk(stream);
00462         if (streamID != M_GEOMETRY)
00463         {
00464             OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Missing geometry data in mesh file",
00465                 "cMeshLoader::readSubMesh");
00466         }
00467         sm->vertexData = new VertexData();
00468         readGeometry(stream, pMesh, sm->vertexData);
00469     }
00470 
00471 
00472     // Find all bone assignments, submesh operation, and texture aliases (if present)
00473     if (!stream->eof())
00474     {
00475         streamID = readChunk(stream);
00476         while(!stream->eof() &&
00477             (streamID == M_SUBMESH_BONE_ASSIGNMENT ||
00478              streamID == M_SUBMESH_OPERATION ||
00479              streamID == M_SUBMESH_TEXTURE_ALIAS))
00480         {
00481             switch(streamID)
00482             {
00483             case M_SUBMESH_OPERATION:
00484                 readSubMeshOperation(stream, pMesh, sm);
00485                 break;
00486             case M_SUBMESH_BONE_ASSIGNMENT:
00487                 readSubMeshBoneAssignment(stream, pMesh, sm);
00488                 break;
00489             case M_SUBMESH_TEXTURE_ALIAS:
00490                 readSubMeshTextureAlias(stream, pMesh, sm);
00491                 break;
00492             }
00493 
00494             if (!stream->eof())
00495             {
00496                 streamID = readChunk(stream);
00497             }
00498 
00499         }
00500         if (!stream->eof())
00501         {
00502             // Backpedal back to start of stream
00503             stream->skip(-STREAM_OVERHEAD_SIZE);
00504         }
00505     }
00506 
00507 
00508 }
00509 //---------------------------------------------------------------------
00510 void cMeshLoader::readSubMeshOperation(DataStreamPtr& stream,
00511     Mesh* pMesh, SubMesh* sm)
00512 {
00513     // unsigned short operationType
00514     unsigned short opType;
00515     readShorts(stream, &opType, 1);
00516     sm->operationType = static_cast<RenderOperation::OperationType>(opType);
00517 }
00518 //---------------------------------------------------------------------
00519 void cMeshLoader::readSubMeshTextureAlias(DataStreamPtr& stream, Mesh* pMesh, SubMesh* sub)
00520 {
00521     String aliasName = readString(stream);
00522     String textureName = readString(stream);
00523     sub->addTextureAlias(aliasName, textureName);
00524 }
00525 //---------------------------------------------------------------------
00526 //---------------------------------------------------------------------
00527 void cMeshLoader::readSkeletonLink(DataStreamPtr& stream, Mesh* pMesh)
00528 {
00529     String skelName = readString(stream);
00530     pMesh->setSkeletonName(skelName);
00531 }
00532 //---------------------------------------------------------------------
00533 void cMeshLoader::readTextureLayer(DataStreamPtr& stream, Mesh* pMesh,
00534     MaterialPtr& pMat)
00535 {
00536     // Material definition section phased out of 1.1
00537 }
00538 //---------------------------------------------------------------------
00539 //---------------------------------------------------------------------
00540 void cMeshLoader::readMeshBoneAssignment(DataStreamPtr& stream, Mesh* pMesh)
00541 {
00542     VertexBoneAssignment assign;
00543 
00544     // unsigned int vertexIndex;
00545     readInts(stream, &(assign.vertexIndex),1);
00546     // unsigned short boneIndex;
00547     readShorts(stream, &(assign.boneIndex),1);
00548     // float weight;
00549     readFloats(stream, &(assign.weight), 1);
00550 
00551     pMesh->addBoneAssignment(assign);
00552 
00553 }
00554 //---------------------------------------------------------------------
00555 void cMeshLoader::readSubMeshBoneAssignment(DataStreamPtr& stream,
00556     Mesh* pMesh, SubMesh* sub)
00557 {
00558     VertexBoneAssignment assign;
00559 
00560     // unsigned int vertexIndex;
00561     readInts(stream, &(assign.vertexIndex),1);
00562     // unsigned short boneIndex;
00563     readShorts(stream, &(assign.boneIndex),1);
00564     // float weight;
00565     readFloats(stream, &(assign.weight), 1);
00566 
00567     sub->addBoneAssignment(assign);
00568 
00569 }
00570 //---------------------------------------------------------------------
00571 //---------------------------------------------------------------------
00572 //---------------------------------------------------------------------
00573 void cMeshLoader::readBoundsInfo(DataStreamPtr& stream, Mesh* pMesh)
00574 {
00575     Vector3 min, max;
00576     // float minx, miny, minz
00577     readFloats(stream, &min.x, 1);
00578     readFloats(stream, &min.y, 1);
00579     readFloats(stream, &min.z, 1);
00580     // float maxx, maxy, maxz
00581     readFloats(stream, &max.x, 1);
00582     readFloats(stream, &max.y, 1);
00583     readFloats(stream, &max.z, 1);
00584     AxisAlignedBox box(min, max);
00585     pMesh->_setBounds(box, true);
00586     // float radius
00587     float radius;
00588     readFloats(stream, &radius, 1);
00589     pMesh->_setBoundingSphereRadius(radius);
00590 
00591 
00592 
00593 }
00594 //---------------------------------------------------------------------
00595 void cMeshLoader::readMeshLodInfo(DataStreamPtr& stream, Mesh* pMesh)
00596 {
00597     unsigned short streamID, i;
00598 
00599     // unsigned short numLevels;
00600     readShorts(stream, &(pMesh->mNumLods), 1);
00601     // bool manual;  (true for manual alternate meshes, false for generated)
00602     readBools(stream, &(pMesh->mIsLodManual), 1);
00603 
00604     // Preallocate submesh lod face data if not manual
00605     if (!pMesh->mIsLodManual)
00606     {
00607         unsigned short numsubs = pMesh->getNumSubMeshes();
00608         for (i = 0; i < numsubs; ++i)
00609         {
00610             SubMesh* sm = pMesh->getSubMesh(i);
00611             sm->mLodFaceList.resize(pMesh->mNumLods-1);
00612         }
00613     }
00614 
00615     // Loop from 1 rather than 0 (full detail index is not in file)
00616     for (i = 1; i < pMesh->getNumLodLevels(); ++i)
00617     {
00618         streamID = readChunk(stream);
00619         if (streamID != M_MESH_LOD_USAGE)
00620         {
00621             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
00622                 "Missing M_MESH_LOD_USAGE stream in " + pMesh->getName(),
00623                 "cMeshLoader::readMeshLodInfo");
00624         }
00625         // Read depth
00626         MeshLodUsage usage;
00627         readFloats(stream, &(usage.fromDepthSquared), 1);
00628 
00629         if (pMesh->isLodManual())
00630         {
00631             readMeshLodUsageManual(stream, pMesh, i, usage);
00632         }
00633         else //(!pMesh->isLodManual)
00634         {
00635             readMeshLodUsageGenerated(stream, pMesh, i, usage);
00636         }
00637         usage.edgeData = NULL;
00638 
00639         // Save usage
00640         #ifdef MESHLOAD_SKIP 
00641         #else
00642         pMesh->mMeshLodUsageList.push_back(usage);
00643         #endif
00644     }
00645 
00646 
00647 }
00648 //---------------------------------------------------------------------
00649 void cMeshLoader::readMeshLodUsageManual(DataStreamPtr& stream,
00650     Mesh* pMesh, unsigned short lodNum, MeshLodUsage& usage)
00651 {
00652     unsigned long streamID;
00653     // Read detail stream
00654     streamID = readChunk(stream);
00655     if (streamID != M_MESH_LOD_MANUAL)
00656     {
00657         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
00658             "Missing M_MESH_LOD_MANUAL stream in " + pMesh->getName(),
00659             "cMeshLoader::readMeshLodUsageManual");
00660     }
00661 
00662     usage.manualName = readString(stream);
00663     usage.manualMesh.setNull(); // will trigger load later
00664 }
00665 //---------------------------------------------------------------------
00666 void cMeshLoader::readMeshLodUsageGenerated(DataStreamPtr& stream,
00667     Mesh* pMesh, unsigned short lodNum, MeshLodUsage& usage)
00668 {
00669     usage.manualName = "";
00670     usage.manualMesh.setNull();
00671 
00672     // Get one set of detail per SubMesh
00673     unsigned short numSubs, i;
00674     unsigned long streamID;
00675     numSubs = pMesh->getNumSubMeshes();
00676     for (i = 0; i < numSubs; ++i)
00677     {
00678         streamID = readChunk(stream);
00679         if (streamID != M_MESH_LOD_GENERATED)
00680         {
00681             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
00682                 "Missing M_MESH_LOD_GENERATED stream in " + pMesh->getName(),
00683                 "cMeshLoader::readMeshLodUsageGenerated");
00684         }
00685 
00686         SubMesh* sm = pMesh->getSubMesh(i);
00687         // lodNum - 1 because SubMesh doesn't store full detail LOD
00688         sm->mLodFaceList[lodNum - 1] = new IndexData();
00689         IndexData* indexData = sm->mLodFaceList[lodNum - 1];
00690         // unsigned int numIndexes
00691         unsigned int numIndexes;
00692         readInts(stream, &numIndexes, 1);
00693         indexData->indexCount = static_cast<size_t>(numIndexes);
00694         // bool indexes32Bit
00695         bool idx32Bit;
00696         readBools(stream, &idx32Bit, 1);
00697         // unsigned short*/int* faceIndexes;  ((v1, v2, v3) * numFaces)
00698         if (idx32Bit)
00699         {
00700             #ifdef MESHLOAD_SKIP 
00701             stream->skip(indexData->indexCount * sizeof(int));
00702             #else
00703             indexData->indexBuffer = HardwareBufferManager::getSingleton().
00704                 createIndexBuffer(HardwareIndexBuffer::IT_32BIT, indexData->indexCount,
00705                 pMesh->mIndexBufferUsage, pMesh->mIndexBufferShadowBuffer);
00706             unsigned int* pIdx = static_cast<unsigned int*>(
00707                 indexData->indexBuffer->lock(
00708                     0,
00709                     indexData->indexBuffer->getSizeInBytes(),
00710                     HardwareBuffer::HBL_DISCARD) );
00711 
00712             readInts(stream, pIdx, indexData->indexCount);
00713             indexData->indexBuffer->unlock();
00714             #endif
00715         }
00716         else
00717         {
00718             #ifdef MESHLOAD_SKIP 
00719             stream->skip(indexData->indexCount * sizeof(short));
00720             #else
00721             indexData->indexBuffer = HardwareBufferManager::getSingleton().
00722                 createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount,
00723                 pMesh->mIndexBufferUsage, pMesh->mIndexBufferShadowBuffer);
00724             unsigned short* pIdx = static_cast<unsigned short*>(
00725                 indexData->indexBuffer->lock(
00726                     0,
00727                     indexData->indexBuffer->getSizeInBytes(),
00728                     HardwareBuffer::HBL_DISCARD) );
00729             readShorts(stream, pIdx, indexData->indexCount);
00730             indexData->indexBuffer->unlock();
00731             #endif
00732         }
00733 
00734     }
00735 }
00736 //---------------------------------------------------------------------
00737 void cMeshLoader::flipFromLittleEndian(void* pData, size_t vertexCount,
00738     size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
00739 {
00740     if (mFlipEndian)
00741     {
00742         flipEndian(pData, vertexCount, vertexSize, elems);
00743     }
00744 }
00745 //---------------------------------------------------------------------
00746 void cMeshLoader::flipToLittleEndian(void* pData, size_t vertexCount,
00747         size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
00748 {
00749     if (mFlipEndian)
00750     {
00751         flipEndian(pData, vertexCount, vertexSize, elems);
00752     }
00753 }
00754 //---------------------------------------------------------------------
00755 void cMeshLoader::flipEndian(void* pData, size_t vertexCount,
00756     size_t vertexSize, const VertexDeclaration::VertexElementList& elems)
00757 {
00758     void *pBase = pData;
00759     for (size_t v = 0; v < vertexCount; ++v)
00760     {
00761         VertexDeclaration::VertexElementList::const_iterator ei, eiend;
00762         eiend = elems.end();
00763         for (ei = elems.begin(); ei != eiend; ++ei)
00764         {
00765             void *pElem;
00766             // re-base pointer to the element
00767             (*ei).baseVertexPointerToElement(pBase, &pElem);
00768             // Flip the endian based on the type
00769             size_t typeSize = 0;
00770             switch (VertexElement::getBaseType((*ei).getType()))
00771             {
00772                 case VET_FLOAT1:
00773                     typeSize = sizeof(float);
00774                     break;
00775                 case VET_SHORT1:
00776                     typeSize = sizeof(short);
00777                     break;
00778                 case VET_COLOUR:
00779                 case VET_COLOUR_ABGR:
00780                 case VET_COLOUR_ARGB:
00781                     typeSize = sizeof(RGBA);
00782                     break;
00783                 case VET_UBYTE4:
00784                     typeSize = 0; // NO FLIPPING
00785                     break;
00786                 default:
00787                     assert(false); // Should never happen
00788             };
00789             Serializer::flipEndian(pElem, typeSize,
00790                 VertexElement::getTypeCount((*ei).getType()));
00791 
00792         }
00793 
00794         pBase = static_cast<void*>(
00795             static_cast<unsigned char*>(pBase) + vertexSize);
00796 
00797     }
00798 }
00799 //---------------------------------------------------------------------
00800 //---------------------------------------------------------------------
00801 //---------------------------------------------------------------------
00802 void cMeshLoader::readEdgeList(DataStreamPtr& stream, Mesh* pMesh)
00803 {
00804     unsigned short streamID;
00805 
00806     if (!stream->eof())
00807     {
00808         streamID = readChunk(stream);
00809         while(!stream->eof() &&
00810             streamID == M_EDGE_LIST_LOD)
00811         {
00812             // Process single LOD
00813 
00814             // unsigned short lodIndex
00815             unsigned short lodIndex;
00816             readShorts(stream, &lodIndex, 1);
00817 
00818             // bool isManual            // If manual, no edge data here, loaded from manual mesh
00819             bool isManual;
00820             readBools(stream, &isManual, 1);
00821             // Only load in non-manual levels; others will be connected up by Mesh on demand
00822             if (!isManual)
00823             {
00824                 MeshLodUsage& usage = const_cast<MeshLodUsage&>(pMesh->getLodLevel(lodIndex));
00825 
00826                 usage.edgeData = new EdgeData();
00827 
00828                 // Read detail information of the edge list
00829                 readEdgeListLodInfo(stream, usage.edgeData);
00830 
00831                 // Postprocessing edge groups
00832                 EdgeData::EdgeGroupList::iterator egi, egend;
00833                 egend = usage.edgeData->edgeGroups.end();
00834                 for (egi = usage.edgeData->edgeGroups.begin(); egi != egend; ++egi)
00835                 {
00836                     EdgeData::EdgeGroup& edgeGroup = *egi;
00837                     // Populate edgeGroup.vertexData pointers
00838                     // If there is shared vertex data, vertexSet 0 is that,
00839                     // otherwise 0 is first dedicated
00840                     if (pMesh->sharedVertexData)
00841                     {
00842                         if (edgeGroup.vertexSet == 0)
00843                         {
00844                             edgeGroup.vertexData = pMesh->sharedVertexData;
00845                         }
00846                         else
00847                         {
00848                             edgeGroup.vertexData = pMesh->getSubMesh(
00849                                 edgeGroup.vertexSet-1)->vertexData;
00850                         }
00851                     }
00852                     else
00853                     {
00854                         edgeGroup.vertexData = pMesh->getSubMesh(
00855                             edgeGroup.vertexSet)->vertexData;
00856                     }
00857                 }
00858             }
00859 
00860             if (!stream->eof())
00861             {
00862                 streamID = readChunk(stream);
00863             }
00864 
00865         }
00866         if (!stream->eof())
00867         {
00868             // Backpedal back to start of stream
00869             stream->skip(-STREAM_OVERHEAD_SIZE);
00870         }
00871     }
00872 
00873     #ifdef MESHLOAD_SKIP 
00874     #else
00875     pMesh->mEdgeListsBuilt = true;
00876     #endif
00877 }
00878 //---------------------------------------------------------------------
00879 void cMeshLoader::readEdgeListLodInfo(DataStreamPtr& stream,
00880     EdgeData* edgeData)
00881 {
00882     // bool isClosed
00883     readBools(stream, &edgeData->isClosed, 1);
00884     // unsigned long numTriangles
00885     uint32 numTriangles;
00886     readInts(stream, &numTriangles, 1);
00887     // Allocate correct amount of memory
00888     edgeData->triangles.resize(numTriangles);
00889     edgeData->triangleFaceNormals.resize(numTriangles);
00890     edgeData->triangleLightFacings.resize(numTriangles);
00891     // unsigned long numEdgeGroups
00892     uint32 numEdgeGroups;
00893     readInts(stream, &numEdgeGroups, 1);
00894     // Allocate correct amount of memory
00895     edgeData->edgeGroups.resize(numEdgeGroups);
00896     // Triangle* triangleList
00897     uint32 tmp[3];
00898     for (size_t t = 0; t < numTriangles; ++t)
00899     {
00900         EdgeData::Triangle& tri = edgeData->triangles[t];
00901         // unsigned long indexSet
00902         readInts(stream, tmp, 1);
00903         tri.indexSet = tmp[0];
00904         // unsigned long vertexSet
00905         readInts(stream, tmp, 1);
00906         tri.vertexSet = tmp[0];
00907         // unsigned long vertIndex[3]
00908         readInts(stream, tmp, 3);
00909         tri.vertIndex[0] = tmp[0];
00910         tri.vertIndex[1] = tmp[1];
00911         tri.vertIndex[2] = tmp[2];
00912         // unsigned long sharedVertIndex[3]
00913         readInts(stream, tmp, 3);
00914         tri.sharedVertIndex[0] = tmp[0];
00915         tri.sharedVertIndex[1] = tmp[1];
00916         tri.sharedVertIndex[2] = tmp[2];
00917         // float normal[4]
00918         readFloats(stream, &(edgeData->triangleFaceNormals[t].x), 4);
00919 
00920     }
00921 
00922     for (uint32 eg = 0; eg < numEdgeGroups; ++eg)
00923     {
00924         unsigned short streamID = readChunk(stream);
00925         if (streamID != M_EDGE_GROUP)
00926         {
00927             OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
00928                 "Missing M_EDGE_GROUP stream",
00929                 "cMeshLoader::readEdgeListLodInfo");
00930         }
00931         EdgeData::EdgeGroup& edgeGroup = edgeData->edgeGroups[eg];
00932 
00933         // unsigned long vertexSet
00934         readInts(stream, tmp, 1);
00935         edgeGroup.vertexSet = tmp[0];
00936         // unsigned long triStart
00937         readInts(stream, tmp, 1);
00938         edgeGroup.triStart = tmp[0];
00939         // unsigned long triCount
00940         readInts(stream, tmp, 1);
00941         edgeGroup.triCount = tmp[0];
00942         // unsigned long numEdges
00943         uint32 numEdges;
00944         readInts(stream, &numEdges, 1);
00945         edgeGroup.edges.resize(numEdges);
00946         // Edge* edgeList
00947         for (uint32 e = 0; e < numEdges; ++e)
00948         {
00949             EdgeData::Edge& edge = edgeGroup.edges[e];
00950             // unsigned long  triIndex[2]
00951             readInts(stream, tmp, 2);
00952             edge.triIndex[0] = tmp[0];
00953             edge.triIndex[1] = tmp[1];
00954             // unsigned long  vertIndex[2]
00955             readInts(stream, tmp, 2);
00956             edge.vertIndex[0] = tmp[0];
00957             edge.vertIndex[1] = tmp[1];
00958             // unsigned long  sharedVertIndex[2]
00959             readInts(stream, tmp, 2);
00960             edge.sharedVertIndex[0] = tmp[0];
00961             edge.sharedVertIndex[1] = tmp[1];
00962             // bool degenerate
00963             readBools(stream, &(edge.degenerate), 1);
00964         }
00965     }
00966 }
00967 //---------------------------------------------------------------------
00968 //---------------------------------------------------------------------
00969 void cMeshLoader::readPoses(DataStreamPtr& stream, Mesh* pMesh)
00970 {
00971     unsigned short streamID;
00972 
00973     // Find all substreams
00974     if (!stream->eof())
00975     {
00976         streamID = readChunk(stream);
00977         while(!stream->eof() &&
00978             (streamID == M_POSE))
00979         {
00980             switch(streamID)
00981             {
00982             case M_POSE:
00983                 readPose(stream, pMesh);
00984                 break;
00985 
00986             }
00987 
00988             if (!stream->eof())
00989             {
00990                 streamID = readChunk(stream);
00991             }
00992 
00993         }
00994         if (!stream->eof())
00995         {
00996             // Backpedal back to start of stream
00997             stream->skip(-STREAM_OVERHEAD_SIZE);
00998         }
00999     }
01000 }
01001 //---------------------------------------------------------------------
01002 void cMeshLoader::readPose(DataStreamPtr& stream, Mesh* pMesh)
01003 {
01004     // char* name (may be blank)
01005     String name = readString(stream);
01006     // unsigned short target
01007     unsigned short target;
01008     readShorts(stream, &target, 1);
01009 
01010     Pose* pose = pMesh->createPose(target, name);
01011 
01012     // Find all substreams
01013     unsigned short streamID;
01014     if (!stream->eof())
01015     {
01016         streamID = readChunk(stream);
01017         while(!stream->eof() &&
01018             (streamID == M_POSE_VERTEX))
01019         {
01020             switch(streamID)
01021             {
01022             case M_POSE_VERTEX:
01023                 // create vertex offset
01024                 uint32 vertIndex;
01025                 Vector3 offset;
01026                 // unsigned long vertexIndex
01027                 readInts(stream, &vertIndex, 1);
01028                 // float xoffset, yoffset, zoffset
01029                 readFloats(stream, offset.ptr(), 3);
01030 
01031                 pose->addVertex(vertIndex, offset);
01032                 break;
01033 
01034             }
01035 
01036             if (!stream->eof())
01037             {
01038                 streamID = readChunk(stream);
01039             }
01040 
01041         }
01042         if (!stream->eof())
01043         {
01044             // Backpedal back to start of stream
01045             stream->skip(-STREAM_OVERHEAD_SIZE);
01046         }
01047     }
01048 
01049 }
01050 //---------------------------------------------------------------------
01051 void cMeshLoader::readAnimations(DataStreamPtr& stream, Mesh* pMesh)
01052 {
01053     unsigned short streamID;
01054 
01055     // Find all substreams
01056     if (!stream->eof())
01057     {
01058         streamID = readChunk(stream);
01059         while(!stream->eof() &&
01060             (streamID == M_ANIMATION))
01061         {
01062             switch(streamID)
01063             {
01064             case M_ANIMATION:
01065                 readAnimation(stream, pMesh);
01066                 break;
01067 
01068             }
01069 
01070             if (!stream->eof())
01071             {
01072                 streamID = readChunk(stream);
01073             }
01074 
01075         }
01076         if (!stream->eof())
01077         {
01078             // Backpedal back to start of stream
01079             stream->skip(-STREAM_OVERHEAD_SIZE);
01080         }
01081     }
01082 
01083 
01084 }
01085 //---------------------------------------------------------------------
01086 void cMeshLoader::readAnimation(DataStreamPtr& stream, Mesh* pMesh)
01087 {
01088 
01089     // char* name
01090     String name = readString(stream);
01091     // float length
01092     float len;
01093     readFloats(stream, &len, 1);
01094 
01095     Animation* anim = pMesh->createAnimation(name, len);
01096 
01097     // tracks
01098     unsigned short streamID;
01099 
01100     if (!stream->eof())
01101     {
01102         streamID = readChunk(stream);
01103         while(!stream->eof() &&
01104             streamID == M_ANIMATION_TRACK)
01105         {
01106             switch(streamID)
01107             {
01108             case M_ANIMATION_TRACK:
01109                 readAnimationTrack(stream, anim, pMesh);
01110                 break;
01111             };
01112             if (!stream->eof())
01113             {
01114                 streamID = readChunk(stream);
01115             }
01116 
01117         }
01118         if (!stream->eof())
01119         {
01120             // Backpedal back to start of stream
01121             stream->skip(-STREAM_OVERHEAD_SIZE);
01122         }
01123     }
01124 }
01125 //---------------------------------------------------------------------
01126 void cMeshLoader::readAnimationTrack(DataStreamPtr& stream,
01127     Animation* anim, Mesh* pMesh)
01128 {
01129     // ushort type
01130     uint16 inAnimType;
01131     readShorts(stream, &inAnimType, 1);
01132     VertexAnimationType animType = (VertexAnimationType)inAnimType;
01133 
01134     // unsigned short target
01135     uint16 target;
01136     readShorts(stream, &target, 1);
01137 
01138     VertexAnimationTrack* track = anim->createVertexTrack(target,
01139         pMesh->getVertexDataByTrackHandle(target), animType);
01140 
01141     // keyframes
01142     unsigned short streamID;
01143 
01144     if (!stream->eof())
01145     {
01146         streamID = readChunk(stream);
01147         while(!stream->eof() &&
01148             (streamID == M_ANIMATION_MORPH_KEYFRAME ||
01149              streamID == M_ANIMATION_POSE_KEYFRAME))
01150         {
01151             switch(streamID)
01152             {
01153             case M_ANIMATION_MORPH_KEYFRAME:
01154                 readMorphKeyFrame(stream, track);
01155                 break;
01156             case M_ANIMATION_POSE_KEYFRAME:
01157                 readPoseKeyFrame(stream, track);
01158                 break;
01159             };
01160             if (!stream->eof())
01161             {
01162                 streamID = readChunk(stream);
01163             }
01164 
01165         }
01166         if (!stream->eof())
01167         {
01168             // Backpedal back to start of stream
01169             stream->skip(-STREAM_OVERHEAD_SIZE);
01170         }
01171     }
01172 
01173 }
01174 //---------------------------------------------------------------------
01175 void cMeshLoader::readMorphKeyFrame(DataStreamPtr& stream, VertexAnimationTrack* track)
01176 {
01177     // float time
01178     float timePos;
01179     readFloats(stream, &timePos, 1);
01180 
01181     VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(timePos);
01182 
01183     // Create buffer, allow read and use shadow buffer
01184     size_t vertexCount = track->getAssociatedVertexData()->vertexCount;
01185     HardwareVertexBufferSharedPtr vbuf =
01186         HardwareBufferManager::getSingleton().createVertexBuffer(
01187             VertexElement::getTypeSize(VET_FLOAT3), vertexCount,
01188             HardwareBuffer::HBU_STATIC, true);
01189     // float x,y,z          // repeat by number of vertices in original geometry
01190     float* pDst = static_cast<float*>(
01191         vbuf->lock(HardwareBuffer::HBL_DISCARD));
01192     readFloats(stream, pDst, vertexCount * 3);
01193     vbuf->unlock();
01194     kf->setVertexBuffer(vbuf);
01195 
01196 }
01197 //---------------------------------------------------------------------
01198 void cMeshLoader::readPoseKeyFrame(DataStreamPtr& stream, VertexAnimationTrack* track)
01199 {
01200     // float time
01201     float timePos;
01202     readFloats(stream, &timePos, 1);
01203 
01204     // Create keyframe
01205     VertexPoseKeyFrame* kf = track->createVertexPoseKeyFrame(timePos);
01206 
01207     unsigned short streamID;
01208 
01209     if (!stream->eof())
01210     {
01211         streamID = readChunk(stream);
01212         while(!stream->eof() &&
01213             streamID == M_ANIMATION_POSE_REF)
01214         {
01215             switch(streamID)
01216             {
01217             case M_ANIMATION_POSE_REF:
01218                 uint16 poseIndex;
01219                 float influence;
01220                 // unsigned short poseIndex
01221                 readShorts(stream, &poseIndex, 1);
01222                 // float influence
01223                 readFloats(stream, &influence, 1);
01224 
01225                 kf->addPoseReference(poseIndex, influence);
01226 
01227                 break;
01228             };
01229             if (!stream->eof())
01230             {
01231                 streamID = readChunk(stream);
01232             }
01233 
01234         }
01235         if (!stream->eof())
01236         {
01237             // Backpedal back to start of stream
01238             stream->skip(-STREAM_OVERHEAD_SIZE);
01239         }
01240     }
01241 
01242 }
01243 //---------------------------------------------------------------------
01244 
01245 void cMeshLoader::readExtremes(DataStreamPtr& stream, Mesh *pMesh)
01246 {
01247     unsigned short idx;
01248     readShorts(stream, &idx, 1);
01249 
01250     SubMesh *sm = pMesh->getSubMesh (idx);
01251 
01252     int n_floats = (mCurrentstreamLen - STREAM_OVERHEAD_SIZE -
01253                     sizeof (unsigned short)) / sizeof (float);
01254 
01255     assert ((n_floats % 3) == 0);
01256 
01257     float *vert = new float[n_floats];
01258     readFloats(stream, vert, n_floats);
01259 
01260     for (int i = 0; i < n_floats; i += 3)
01261         sm->extremityPoints.push_back(Vector3(vert [i], vert [i + 1], vert [i + 2]));
01262 
01263     delete [] vert;
01264 }
01265 //---------------------------------------------------------------------
01266 //---------------------------------------------------------------------
01267 //---------------------------------------------------------------------
01268 
01269 #endif
01270 
01271 }
01272 

Generated on Wed May 23 06:00:14 2012 for cpp by  doxygen 1.5.6