diff options
Diffstat (limited to 'src/3rdparty/assimp/code/OgreBinarySerializer.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/OgreBinarySerializer.cpp | 1675 |
1 files changed, 837 insertions, 838 deletions
diff --git a/src/3rdparty/assimp/code/OgreBinarySerializer.cpp b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp index 6674f4cee..ce17cea6a 100644 --- a/src/3rdparty/assimp/code/OgreBinarySerializer.cpp +++ b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp @@ -2,11 +2,11 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2012, assimp team +Copyright (c) 2006-2016, assimp team All rights reserved. -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above @@ -23,16 +23,16 @@ following conditions are met: derived from this software without specific prior written permission of the assimp team. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- @@ -43,6 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "OgreParsingUtils.h" #include "TinyFormatter.h" +#include <assimp/DefaultLogger.hpp> + #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER @@ -64,1044 +66,1041 @@ const long MSTREAM_OVERHEAD_SIZE = sizeof(uint16_t) + const long MSTREAM_BONE_SIZE_WITHOUT_SCALE = MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) + (sizeof(float) * 7); const long MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE = MSTREAM_OVERHEAD_SIZE + (sizeof(float) * 8); -template<> +template<> inline bool OgreBinarySerializer::Read<bool>() { - return (m_reader->GetU1() > 0); + return (m_reader->GetU1() > 0); } -template<> +template<> inline char OgreBinarySerializer::Read<char>() { - return static_cast<char>(m_reader->GetU1()); + return static_cast<char>(m_reader->GetU1()); } -template<> +template<> inline uint8_t OgreBinarySerializer::Read<uint8_t>() { - return m_reader->GetU1(); + return m_reader->GetU1(); } -template<> +template<> inline uint16_t OgreBinarySerializer::Read<uint16_t>() { - return m_reader->GetU2(); + return m_reader->GetU2(); } -template<> +template<> inline uint32_t OgreBinarySerializer::Read<uint32_t>() { - return m_reader->GetU4(); + return m_reader->GetU4(); } -template<> +template<> inline float OgreBinarySerializer::Read<float>() { - return m_reader->GetF4(); + return m_reader->GetF4(); } void OgreBinarySerializer::ReadBytes(char *dest, size_t numBytes) { - ReadBytes(static_cast<void*>(dest), numBytes); + ReadBytes(static_cast<void*>(dest), numBytes); } void OgreBinarySerializer::ReadBytes(uint8_t *dest, size_t numBytes) { - ReadBytes(static_cast<void*>(dest), numBytes); + ReadBytes(static_cast<void*>(dest), numBytes); } void OgreBinarySerializer::ReadBytes(void *dest, size_t numBytes) { - m_reader->CopyAndAdvance(dest, numBytes); + m_reader->CopyAndAdvance(dest, numBytes); } uint8_t *OgreBinarySerializer::ReadBytes(size_t numBytes) { - uint8_t *bytes = new uint8_t[numBytes]; - ReadBytes(bytes, numBytes); - return bytes; + uint8_t *bytes = new uint8_t[numBytes]; + ReadBytes(bytes, numBytes); + return bytes; } void OgreBinarySerializer::ReadVector(aiVector3D &vec) { - m_reader->CopyAndAdvance(&vec.x, sizeof(float)*3); + m_reader->CopyAndAdvance(&vec.x, sizeof(float)*3); } void OgreBinarySerializer::ReadQuaternion(aiQuaternion &quat) { - float temp[4]; - m_reader->CopyAndAdvance(temp, sizeof(float)*4); - quat.x = temp[0]; - quat.y = temp[1]; - quat.z = temp[2]; - quat.w = temp[3]; + float temp[4]; + m_reader->CopyAndAdvance(temp, sizeof(float)*4); + quat.x = temp[0]; + quat.y = temp[1]; + quat.z = temp[2]; + quat.w = temp[3]; } bool OgreBinarySerializer::AtEnd() const { - return (m_reader->GetRemainingSize() == 0); + return (m_reader->GetRemainingSize() == 0); } std::string OgreBinarySerializer::ReadString(size_t len) { - std::string str; - str.resize(len); - ReadBytes(&str[0], len); - return str; + std::string str; + str.resize(len); + ReadBytes(&str[0], len); + return str; } std::string OgreBinarySerializer::ReadLine() { - std::string str; - while(!AtEnd()) - { - char c = Read<char>(); - if (c == '\n') - break; - str += c; - } - return str; + std::string str; + while(!AtEnd()) + { + char c = Read<char>(); + if (c == '\n') + break; + str += c; + } + return str; } uint16_t OgreBinarySerializer::ReadHeader(bool readLen) { - uint16_t id = Read<uint16_t>(); - if (readLen) - m_currentLen = Read<uint32_t>(); + uint16_t id = Read<uint16_t>(); + if (readLen) + m_currentLen = Read<uint32_t>(); #if (OGRE_BINARY_SERIALIZER_DEBUG == 1) - if (id != HEADER_CHUNK_ID) - { - DefaultLogger::get()->debug(Formatter::format() << (assetMode == AM_Mesh - ? MeshHeaderToString(static_cast<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(id)))); - } + if (id != HEADER_CHUNK_ID) + { + DefaultLogger::get()->debug(Formatter::format() << (assetMode == AM_Mesh + ? MeshHeaderToString(static_cast<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(id)))); + } #endif - return id; + return id; } void OgreBinarySerializer::RollbackHeader() { - m_reader->IncPtr(-MSTREAM_OVERHEAD_SIZE); + m_reader->IncPtr(-MSTREAM_OVERHEAD_SIZE); } void OgreBinarySerializer::SkipBytes(size_t numBytes) { #if (OGRE_BINARY_SERIALIZER_DEBUG == 1) - DefaultLogger::get()->debug(Formatter::format() << "Skipping " << numBytes << " bytes"); + DefaultLogger::get()->debug(Formatter::format() << "Skipping " << numBytes << " bytes"); #endif - m_reader->IncPtr(numBytes); + m_reader->IncPtr(numBytes); } // Mesh Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream) { - OgreBinarySerializer serializer(stream, OgreBinarySerializer::AM_Mesh); - - uint16_t id = serializer.ReadHeader(false); - if (id != HEADER_CHUNK_ID) { - throw DeadlyExportError("Invalid Ogre Mesh file header."); - } - - /// @todo Check what we can actually support. - std::string version = serializer.ReadLine(); - if (version != MESH_VERSION_1_8) - { - throw DeadlyExportError(Formatter::format() << "Mesh version " << version << " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again." - << " Supported versions: " << MESH_VERSION_1_8); - } - - Mesh *mesh = new Mesh(); - while (!serializer.AtEnd()) - { - id = serializer.ReadHeader(); - switch(id) - { - case M_MESH: - { - serializer.ReadMesh(mesh); - break; - } - } - } - return mesh; + OgreBinarySerializer serializer(stream, OgreBinarySerializer::AM_Mesh); + + uint16_t id = serializer.ReadHeader(false); + if (id != HEADER_CHUNK_ID) { + throw DeadlyExportError("Invalid Ogre Mesh file header."); + } + + /// @todo Check what we can actually support. + std::string version = serializer.ReadLine(); + if (version != MESH_VERSION_1_8) + { + throw DeadlyExportError(Formatter::format() << "Mesh version " << version << " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again." + << " Supported versions: " << MESH_VERSION_1_8); + } + + Mesh *mesh = new Mesh(); + while (!serializer.AtEnd()) + { + id = serializer.ReadHeader(); + switch(id) + { + case M_MESH: + { + serializer.ReadMesh(mesh); + break; + } + } + } + return mesh; } void OgreBinarySerializer::ReadMesh(Mesh *mesh) { - mesh->hasSkeletalAnimations = Read<bool>(); - - DefaultLogger::get()->debug("Reading Mesh"); - DefaultLogger::get()->debug(Formatter::format() << " - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false")); - - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && - (id == M_GEOMETRY || - id == M_SUBMESH || - id == M_MESH_SKELETON_LINK || - id == M_MESH_BONE_ASSIGNMENT || - id == M_MESH_LOD || - id == M_MESH_BOUNDS || - id == M_SUBMESH_NAME_TABLE || - id == M_EDGE_LISTS || - id == M_POSES || - id == M_ANIMATIONS || - id == M_TABLE_EXTREMES)) - { - switch(id) - { - case M_GEOMETRY: - { - mesh->sharedVertexData = new VertexData(); - ReadGeometry(mesh->sharedVertexData); - break; - } - case M_SUBMESH: - { - ReadSubMesh(mesh); - break; - } - case M_MESH_SKELETON_LINK: - { - ReadMeshSkeletonLink(mesh); - break; - } - case M_MESH_BONE_ASSIGNMENT: - { - ReadBoneAssignment(mesh->sharedVertexData); - break; - } - case M_MESH_LOD: - { - ReadMeshLodInfo(mesh); - break; - } - case M_MESH_BOUNDS: - { - ReadMeshBounds(mesh); - break; - } - case M_SUBMESH_NAME_TABLE: - { - ReadSubMeshNames(mesh); - break; - } - case M_EDGE_LISTS: - { - ReadEdgeList(mesh); - break; - } - case M_POSES: - { - ReadPoses(mesh); - break; - } - case M_ANIMATIONS: - { - ReadAnimations(mesh); - break; - } - case M_TABLE_EXTREMES: - { - ReadMeshExtremes(mesh); - break; - } - } - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } - - NormalizeBoneWeights(mesh->sharedVertexData); + mesh->hasSkeletalAnimations = Read<bool>(); + + DefaultLogger::get()->debug("Reading Mesh"); + DefaultLogger::get()->debug(Formatter::format() << " - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false")); + + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && + (id == M_GEOMETRY || + id == M_SUBMESH || + id == M_MESH_SKELETON_LINK || + id == M_MESH_BONE_ASSIGNMENT || + id == M_MESH_LOD || + id == M_MESH_BOUNDS || + id == M_SUBMESH_NAME_TABLE || + id == M_EDGE_LISTS || + id == M_POSES || + id == M_ANIMATIONS || + id == M_TABLE_EXTREMES)) + { + switch(id) + { + case M_GEOMETRY: + { + mesh->sharedVertexData = new VertexData(); + ReadGeometry(mesh->sharedVertexData); + break; + } + case M_SUBMESH: + { + ReadSubMesh(mesh); + break; + } + case M_MESH_SKELETON_LINK: + { + ReadMeshSkeletonLink(mesh); + break; + } + case M_MESH_BONE_ASSIGNMENT: + { + ReadBoneAssignment(mesh->sharedVertexData); + break; + } + case M_MESH_LOD: + { + ReadMeshLodInfo(mesh); + break; + } + case M_MESH_BOUNDS: + { + ReadMeshBounds(mesh); + break; + } + case M_SUBMESH_NAME_TABLE: + { + ReadSubMeshNames(mesh); + break; + } + case M_EDGE_LISTS: + { + ReadEdgeList(mesh); + break; + } + case M_POSES: + { + ReadPoses(mesh); + break; + } + case M_ANIMATIONS: + { + ReadAnimations(mesh); + break; + } + case M_TABLE_EXTREMES: + { + ReadMeshExtremes(mesh); + break; + } + } + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } + + NormalizeBoneWeights(mesh->sharedVertexData); } void OgreBinarySerializer::ReadMeshLodInfo(Mesh *mesh) { - // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped. - // @todo Put this stuff to scene/mesh custom properties. If manual mesh the app can use the information. - ReadLine(); // strategy name - uint16_t numLods = Read<uint16_t>(); - bool manual = Read<bool>(); - - /// @note Main mesh is considered as LOD 0, start from index 1. - for (size_t i=1; i<numLods; ++i) - { - uint16_t id = ReadHeader(); - if (id != M_MESH_LOD_USAGE) { - throw DeadlyImportError("M_MESH_LOD does not contain a M_MESH_LOD_USAGE for each LOD level"); - } - - m_reader->IncPtr(sizeof(float)); // user value - - if (manual) - { - id = ReadHeader(); - if (id != M_MESH_LOD_MANUAL) { - throw DeadlyImportError("Manual M_MESH_LOD_USAGE does not contain M_MESH_LOD_MANUAL"); - } - - ReadLine(); // manual mesh name (ref to another mesh) - } - else - { - for(size_t si=0, silen=mesh->NumSubMeshes(); si<silen; ++si) - { - id = ReadHeader(); - if (id != M_MESH_LOD_GENERATED) { - throw DeadlyImportError("Generated M_MESH_LOD_USAGE does not contain M_MESH_LOD_GENERATED"); - } - - uint32_t indexCount = Read<uint32_t>(); - bool is32bit = Read<bool>(); - - if (indexCount > 0) - { - uint32_t len = indexCount * (is32bit ? sizeof(uint32_t) : sizeof(uint16_t)); - m_reader->IncPtr(len); - } - } - } - } + // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped. + // @todo Put this stuff to scene/mesh custom properties. If manual mesh the app can use the information. + ReadLine(); // strategy name + uint16_t numLods = Read<uint16_t>(); + bool manual = Read<bool>(); + + /// @note Main mesh is considered as LOD 0, start from index 1. + for (size_t i=1; i<numLods; ++i) + { + uint16_t id = ReadHeader(); + if (id != M_MESH_LOD_USAGE) { + throw DeadlyImportError("M_MESH_LOD does not contain a M_MESH_LOD_USAGE for each LOD level"); + } + + m_reader->IncPtr(sizeof(float)); // user value + + if (manual) + { + id = ReadHeader(); + if (id != M_MESH_LOD_MANUAL) { + throw DeadlyImportError("Manual M_MESH_LOD_USAGE does not contain M_MESH_LOD_MANUAL"); + } + + ReadLine(); // manual mesh name (ref to another mesh) + } + else + { + for(size_t si=0, silen=mesh->NumSubMeshes(); si<silen; ++si) + { + id = ReadHeader(); + if (id != M_MESH_LOD_GENERATED) { + throw DeadlyImportError("Generated M_MESH_LOD_USAGE does not contain M_MESH_LOD_GENERATED"); + } + + uint32_t indexCount = Read<uint32_t>(); + bool is32bit = Read<bool>(); + + if (indexCount > 0) + { + uint32_t len = indexCount * (is32bit ? sizeof(uint32_t) : sizeof(uint16_t)); + m_reader->IncPtr(len); + } + } + } + } } void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh) { - mesh->skeletonRef = ReadLine(); + mesh->skeletonRef = ReadLine(); } -void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh) +void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/) { - // Skip bounds, not compatible with Assimp. - // 2x float vec3 + 1x float sphere radius - SkipBytes(sizeof(float) * 7); + // Skip bounds, not compatible with Assimp. + // 2x float vec3 + 1x float sphere radius + SkipBytes(sizeof(float) * 7); } -void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh) +void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/) { - // Skip extremes, not compatible with Assimp. - size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE; - SkipBytes(numBytes); + // Skip extremes, not compatible with Assimp. + size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE; + SkipBytes(numBytes); } void OgreBinarySerializer::ReadBoneAssignment(VertexData *dest) { - if (!dest) { - throw DeadlyImportError("Cannot read bone assignments, vertex data is null."); - } - - VertexBoneAssignment ba; - ba.vertexIndex = Read<uint32_t>(); - ba.boneIndex = Read<uint16_t>(); - ba.weight = Read<float>(); - - dest->boneAssignments.push_back(ba); + if (!dest) { + throw DeadlyImportError("Cannot read bone assignments, vertex data is null."); + } + + VertexBoneAssignment ba; + ba.vertexIndex = Read<uint32_t>(); + ba.boneIndex = Read<uint16_t>(); + ba.weight = Read<float>(); + + dest->boneAssignments.push_back(ba); } void OgreBinarySerializer::ReadSubMesh(Mesh *mesh) { - uint16_t id = 0; - - SubMesh *submesh = new SubMesh(); - submesh->materialRef = ReadLine(); - submesh->usesSharedVertexData = Read<bool>(); - - submesh->indexData->count = Read<uint32_t>(); - submesh->indexData->faceCount = static_cast<uint32_t>(submesh->indexData->count / 3); - submesh->indexData->is32bit = Read<bool>(); - - DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size()); - DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'"); - DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false")); - - // Index buffer - if (submesh->indexData->count > 0) - { - uint32_t numBytes = submesh->indexData->count * (submesh->indexData->is32bit ? sizeof(uint32_t) : sizeof(uint16_t)); - uint8_t *indexBuffer = ReadBytes(numBytes); - submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true)); - - DefaultLogger::get()->debug(Formatter::format() << " - " << submesh->indexData->faceCount - << " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit") - << " indexes of " << numBytes << " bytes"); - } - - // Vertex buffer if not referencing the shared geometry - if (!submesh->usesSharedVertexData) - { - id = ReadHeader(); - if (id != M_GEOMETRY) { - throw DeadlyImportError("M_SUBMESH does not contain M_GEOMETRY, but shader geometry is set to false"); - } - - submesh->vertexData = new VertexData(); - ReadGeometry(submesh->vertexData); - } - - // Bone assignment, submesh operation and texture aliases - if (!AtEnd()) - { - id = ReadHeader(); - while (!AtEnd() && - (id == M_SUBMESH_OPERATION || - id == M_SUBMESH_BONE_ASSIGNMENT || - id == M_SUBMESH_TEXTURE_ALIAS)) - { - switch(id) - { - case M_SUBMESH_OPERATION: - { - ReadSubMeshOperation(submesh); - break; - } - case M_SUBMESH_BONE_ASSIGNMENT: - { - ReadBoneAssignment(submesh->vertexData); - break; - } - case M_SUBMESH_TEXTURE_ALIAS: - { - ReadSubMeshTextureAlias(submesh); - break; - } - } - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } - - NormalizeBoneWeights(submesh->vertexData); - - submesh->index = mesh->subMeshes.size(); - mesh->subMeshes.push_back(submesh); + uint16_t id = 0; + + SubMesh *submesh = new SubMesh(); + submesh->materialRef = ReadLine(); + submesh->usesSharedVertexData = Read<bool>(); + + submesh->indexData->count = Read<uint32_t>(); + submesh->indexData->faceCount = static_cast<uint32_t>(submesh->indexData->count / 3); + submesh->indexData->is32bit = Read<bool>(); + + DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size()); + DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'"); + DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false")); + + // Index buffer + if (submesh->indexData->count > 0) + { + uint32_t numBytes = submesh->indexData->count * (submesh->indexData->is32bit ? sizeof(uint32_t) : sizeof(uint16_t)); + uint8_t *indexBuffer = ReadBytes(numBytes); + submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true)); + + DefaultLogger::get()->debug(Formatter::format() << " - " << submesh->indexData->faceCount + << " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit") + << " indexes of " << numBytes << " bytes"); + } + + // Vertex buffer if not referencing the shared geometry + if (!submesh->usesSharedVertexData) + { + id = ReadHeader(); + if (id != M_GEOMETRY) { + throw DeadlyImportError("M_SUBMESH does not contain M_GEOMETRY, but shader geometry is set to false"); + } + + submesh->vertexData = new VertexData(); + ReadGeometry(submesh->vertexData); + } + + // Bone assignment, submesh operation and texture aliases + if (!AtEnd()) + { + id = ReadHeader(); + while (!AtEnd() && + (id == M_SUBMESH_OPERATION || + id == M_SUBMESH_BONE_ASSIGNMENT || + id == M_SUBMESH_TEXTURE_ALIAS)) + { + switch(id) + { + case M_SUBMESH_OPERATION: + { + ReadSubMeshOperation(submesh); + break; + } + case M_SUBMESH_BONE_ASSIGNMENT: + { + ReadBoneAssignment(submesh->vertexData); + break; + } + case M_SUBMESH_TEXTURE_ALIAS: + { + ReadSubMeshTextureAlias(submesh); + break; + } + } + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } + + NormalizeBoneWeights(submesh->vertexData); + + submesh->index = mesh->subMeshes.size(); + mesh->subMeshes.push_back(submesh); } void OgreBinarySerializer::NormalizeBoneWeights(VertexData *vertexData) const { - if (!vertexData || vertexData->boneAssignments.empty()) - return; - - std::set<uint32_t> influencedVertices; - for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) { - influencedVertices.insert(baIter->vertexIndex); - } - - /** Normalize bone weights. - Some exporters wont care if the sum of all bone weights - for a single vertex equals 1 or not, so validate here. */ - const float epsilon = 0.05f; - for(std::set<uint32_t>::const_iterator iter=influencedVertices.begin(), end=influencedVertices.end(); iter != end; ++iter) - { - const uint32_t vertexIndex = (*iter); - - float sum = 0.0f; - for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) - { - if (baIter->vertexIndex == vertexIndex) - sum += baIter->weight; - } - if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon))) - { - for (VertexBoneAssignmentList::iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) - { - if (baIter->vertexIndex == vertexIndex) - baIter->weight /= sum; - } - } - } + if (!vertexData || vertexData->boneAssignments.empty()) + return; + + std::set<uint32_t> influencedVertices; + for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) { + influencedVertices.insert(baIter->vertexIndex); + } + + /** Normalize bone weights. + Some exporters wont care if the sum of all bone weights + for a single vertex equals 1 or not, so validate here. */ + const float epsilon = 0.05f; + for (const uint32_t vertexIndex : influencedVertices) + { + float sum = 0.0f; + for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) + { + if (baIter->vertexIndex == vertexIndex) + sum += baIter->weight; + } + if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon))) + { + for (auto &boneAssign : vertexData->boneAssignments) + { + if (boneAssign.vertexIndex == vertexIndex) + boneAssign.weight /= sum; + } + } + } } void OgreBinarySerializer::ReadSubMeshOperation(SubMesh *submesh) { - submesh->operationType = static_cast<SubMesh::OperationType>(Read<uint16_t>()); + submesh->operationType = static_cast<SubMesh::OperationType>(Read<uint16_t>()); } void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh) { - submesh->textureAliasName = ReadLine(); - submesh->textureAliasRef = ReadLine(); + submesh->textureAliasName = ReadLine(); + submesh->textureAliasRef = ReadLine(); } void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) { - uint16_t id = 0; - uint16_t submeshIndex = 0; - - if (!AtEnd()) - { - id = ReadHeader(); - while (!AtEnd() && id == M_SUBMESH_NAME_TABLE_ELEMENT) - { - uint16_t submeshIndex = Read<uint16_t>(); - SubMesh *submesh = mesh->GetSubMesh(submeshIndex); - if (!submesh) { - throw DeadlyImportError(Formatter::format() << "Ogre Mesh does not include submesh " << submeshIndex << " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file."); - } - - submesh->name = ReadLine(); - DefaultLogger::get()->debug(Formatter::format() << " - SubMesh " << submesh->index << " name '" << submesh->name << "'"); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + uint16_t id = 0; + + if (!AtEnd()) + { + id = ReadHeader(); + while (!AtEnd() && id == M_SUBMESH_NAME_TABLE_ELEMENT) + { + uint16_t submeshIndex = Read<uint16_t>(); + SubMesh *submesh = mesh->GetSubMesh(submeshIndex); + if (!submesh) { + throw DeadlyImportError(Formatter::format() << "Ogre Mesh does not include submesh " << submeshIndex << " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file."); + } + + submesh->name = ReadLine(); + DefaultLogger::get()->debug(Formatter::format() << " - SubMesh " << submesh->index << " name '" << submesh->name << "'"); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadGeometry(VertexData *dest) { - dest->count = Read<uint32_t>(); - - DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices"); - - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && - (id == M_GEOMETRY_VERTEX_DECLARATION || - id == M_GEOMETRY_VERTEX_BUFFER)) - { - switch(id) - { - case M_GEOMETRY_VERTEX_DECLARATION: - { - ReadGeometryVertexDeclaration(dest); - break; - } - case M_GEOMETRY_VERTEX_BUFFER: - { - ReadGeometryVertexBuffer(dest); - break; - } - } - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + dest->count = Read<uint32_t>(); + + DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices"); + + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && + (id == M_GEOMETRY_VERTEX_DECLARATION || + id == M_GEOMETRY_VERTEX_BUFFER)) + { + switch(id) + { + case M_GEOMETRY_VERTEX_DECLARATION: + { + ReadGeometryVertexDeclaration(dest); + break; + } + case M_GEOMETRY_VERTEX_BUFFER: + { + ReadGeometryVertexBuffer(dest); + break; + } + } + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadGeometryVertexDeclaration(VertexData *dest) { - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && id == M_GEOMETRY_VERTEX_ELEMENT) - { - ReadGeometryVertexElement(dest); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && id == M_GEOMETRY_VERTEX_ELEMENT) + { + ReadGeometryVertexElement(dest); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadGeometryVertexElement(VertexData *dest) { - VertexElement element; - element.source = Read<uint16_t>(); - element.type = static_cast<VertexElement::Type>(Read<uint16_t>()); - element.semantic = static_cast<VertexElement::Semantic>(Read<uint16_t>()); - element.offset = Read<uint16_t>(); - element.index = Read<uint16_t>(); + VertexElement element; + element.source = Read<uint16_t>(); + element.type = static_cast<VertexElement::Type>(Read<uint16_t>()); + element.semantic = static_cast<VertexElement::Semantic>(Read<uint16_t>()); + element.offset = Read<uint16_t>(); + element.index = Read<uint16_t>(); - DefaultLogger::get()->debug(Formatter::format() << " - Vertex element " << element.SemanticToString() << " of type " - << element.TypeToString() << " index=" << element.index << " source=" << element.source); + DefaultLogger::get()->debug(Formatter::format() << " - Vertex element " << element.SemanticToString() << " of type " + << element.TypeToString() << " index=" << element.index << " source=" << element.source); - dest->vertexElements.push_back(element); + dest->vertexElements.push_back(element); } void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest) { - uint16_t bindIndex = Read<uint16_t>(); - uint16_t vertexSize = Read<uint16_t>(); - - uint16_t id = ReadHeader(); - if (id != M_GEOMETRY_VERTEX_BUFFER_DATA) - throw DeadlyImportError("M_GEOMETRY_VERTEX_BUFFER_DATA not found in M_GEOMETRY_VERTEX_BUFFER"); - - if (dest->VertexSize(bindIndex) != vertexSize) - throw DeadlyImportError("Vertex buffer size does not agree with vertex declaration in M_GEOMETRY_VERTEX_BUFFER"); - - size_t numBytes = dest->count * vertexSize; - uint8_t *vertexBuffer = ReadBytes(numBytes); - dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true)); - - DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes"); + uint16_t bindIndex = Read<uint16_t>(); + uint16_t vertexSize = Read<uint16_t>(); + + uint16_t id = ReadHeader(); + if (id != M_GEOMETRY_VERTEX_BUFFER_DATA) + throw DeadlyImportError("M_GEOMETRY_VERTEX_BUFFER_DATA not found in M_GEOMETRY_VERTEX_BUFFER"); + + if (dest->VertexSize(bindIndex) != vertexSize) + throw DeadlyImportError("Vertex buffer size does not agree with vertex declaration in M_GEOMETRY_VERTEX_BUFFER"); + + size_t numBytes = dest->count * vertexSize; + uint8_t *vertexBuffer = ReadBytes(numBytes); + dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true)); + + DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes"); } -void OgreBinarySerializer::ReadEdgeList(Mesh *mesh) +void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/) { - // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped. - - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && id == M_EDGE_LIST_LOD) - { - m_reader->IncPtr(sizeof(uint16_t)); // lod index - bool manual = Read<bool>(); - - if (!manual) - { - m_reader->IncPtr(sizeof(uint8_t)); - uint32_t numTriangles = Read<uint32_t>(); - uint32_t numEdgeGroups = Read<uint32_t>(); - - size_t skipBytes = (sizeof(uint32_t) * 8 + sizeof(float) * 4) * numTriangles; - m_reader->IncPtr(skipBytes); - - for (size_t i=0; i<numEdgeGroups; ++i) - { - uint16_t id = ReadHeader(); - if (id != M_EDGE_GROUP) - throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD"); - - m_reader->IncPtr(sizeof(uint32_t) * 3); - uint32_t numEdges = Read<uint32_t>(); - for (size_t j=0; j<numEdges; ++j) - { - m_reader->IncPtr(sizeof(uint32_t) * 6 + sizeof(uint8_t)); - } - } - } - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped. + + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && id == M_EDGE_LIST_LOD) + { + m_reader->IncPtr(sizeof(uint16_t)); // lod index + bool manual = Read<bool>(); + + if (!manual) + { + m_reader->IncPtr(sizeof(uint8_t)); + uint32_t numTriangles = Read<uint32_t>(); + uint32_t numEdgeGroups = Read<uint32_t>(); + + size_t skipBytes = (sizeof(uint32_t) * 8 + sizeof(float) * 4) * numTriangles; + m_reader->IncPtr(skipBytes); + + for (size_t i=0; i<numEdgeGroups; ++i) + { + uint16_t id = ReadHeader(); + if (id != M_EDGE_GROUP) + throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD"); + + m_reader->IncPtr(sizeof(uint32_t) * 3); + uint32_t numEdges = Read<uint32_t>(); + for (size_t j=0; j<numEdges; ++j) + { + m_reader->IncPtr(sizeof(uint32_t) * 6 + sizeof(uint8_t)); + } + } + } + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadPoses(Mesh *mesh) { - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && id == M_POSE) - { - Pose *pose = new Pose(); - pose->name = ReadLine(); - pose->target = Read<uint16_t>(); - pose->hasNormals = Read<bool>(); - - ReadPoseVertices(pose); - - mesh->poses.push_back(pose); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && id == M_POSE) + { + Pose *pose = new Pose(); + pose->name = ReadLine(); + pose->target = Read<uint16_t>(); + pose->hasNormals = Read<bool>(); + + ReadPoseVertices(pose); + + mesh->poses.push_back(pose); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadPoseVertices(Pose *pose) { - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && id == M_POSE_VERTEX) - { - Pose::Vertex v; - v.index = Read<uint32_t>(); - ReadVector(v.offset); - if (pose->hasNormals) - ReadVector(v.normal); - - pose->vertices[v.index] = v; - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && id == M_POSE_VERTEX) + { + Pose::Vertex v; + v.index = Read<uint32_t>(); + ReadVector(v.offset); + if (pose->hasNormals) + ReadVector(v.normal); + + pose->vertices[v.index] = v; + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadAnimations(Mesh *mesh) { - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && id == M_ANIMATION) - { - Animation *anim = new Animation(mesh); - anim->name = ReadLine(); - anim->length = Read<float>(); - - ReadAnimation(anim); - - mesh->animations.push_back(anim); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && id == M_ANIMATION) + { + Animation *anim = new Animation(mesh); + anim->name = ReadLine(); + anim->length = Read<float>(); + + ReadAnimation(anim); + + mesh->animations.push_back(anim); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadAnimation(Animation *anim) -{ - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - if (id == M_ANIMATION_BASEINFO) - { - anim->baseName = ReadLine(); - anim->baseTime = Read<float>(); - - // Advance to first track - id = ReadHeader(); - } - - while (!AtEnd() && id == M_ANIMATION_TRACK) - { - VertexAnimationTrack track; - track.type = static_cast<VertexAnimationTrack::Type>(Read<uint16_t>()); - track.target = Read<uint16_t>(); - - ReadAnimationKeyFrames(anim, &track); - - anim->tracks.push_back(track); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } +{ + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + if (id == M_ANIMATION_BASEINFO) + { + anim->baseName = ReadLine(); + anim->baseTime = Read<float>(); + + // Advance to first track + id = ReadHeader(); + } + + while (!AtEnd() && id == M_ANIMATION_TRACK) + { + VertexAnimationTrack track; + track.type = static_cast<VertexAnimationTrack::Type>(Read<uint16_t>()); + track.target = Read<uint16_t>(); + + ReadAnimationKeyFrames(anim, &track); + + anim->tracks.push_back(track); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } void OgreBinarySerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track) { - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - while (!AtEnd() && - (id == M_ANIMATION_MORPH_KEYFRAME || - id == M_ANIMATION_POSE_KEYFRAME)) - { - if (id == M_ANIMATION_MORPH_KEYFRAME) - { - MorphKeyFrame kf; - kf.timePos = Read<float>(); - bool hasNormals = Read<bool>(); - - size_t vertexCount = anim->AssociatedVertexData(track)->count; - size_t vertexSize = sizeof(float) * (hasNormals ? 6 : 3); - size_t numBytes = vertexCount * vertexSize; - - uint8_t *morphBuffer = ReadBytes(numBytes); - kf.buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(morphBuffer, numBytes, true)); - - track->morphKeyFrames.push_back(kf); - } - else if (id == M_ANIMATION_POSE_KEYFRAME) - { - PoseKeyFrame kf; - kf.timePos = Read<float>(); - - if (!AtEnd()) - { - id = ReadHeader(); - while (!AtEnd() && id == M_ANIMATION_POSE_REF) - { - PoseRef pr; - pr.index = Read<uint16_t>(); - pr.influence = Read<float>(); - kf.references.push_back(pr); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } - - track->poseKeyFrames.push_back(kf); - } - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + while (!AtEnd() && + (id == M_ANIMATION_MORPH_KEYFRAME || + id == M_ANIMATION_POSE_KEYFRAME)) + { + if (id == M_ANIMATION_MORPH_KEYFRAME) + { + MorphKeyFrame kf; + kf.timePos = Read<float>(); + bool hasNormals = Read<bool>(); + + size_t vertexCount = anim->AssociatedVertexData(track)->count; + size_t vertexSize = sizeof(float) * (hasNormals ? 6 : 3); + size_t numBytes = vertexCount * vertexSize; + + uint8_t *morphBuffer = ReadBytes(numBytes); + kf.buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(morphBuffer, numBytes, true)); + + track->morphKeyFrames.push_back(kf); + } + else if (id == M_ANIMATION_POSE_KEYFRAME) + { + PoseKeyFrame kf; + kf.timePos = Read<float>(); + + if (!AtEnd()) + { + id = ReadHeader(); + while (!AtEnd() && id == M_ANIMATION_POSE_REF) + { + PoseRef pr; + pr.index = Read<uint16_t>(); + pr.influence = Read<float>(); + kf.references.push_back(pr); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } + + track->poseKeyFrames.push_back(kf); + } + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } } // Skeleton bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) { - if (!mesh || mesh->skeletonRef.empty()) - return false; - - // Highly unusual to see in read world cases but support - // binary mesh referencing a XML skeleton file. - if (EndsWith(mesh->skeletonRef, ".skeleton.xml", false)) - { - OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh); - return false; - } - - MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef); - - Skeleton *skeleton = new Skeleton(); - OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton); - serializer.ReadSkeleton(skeleton); - mesh->skeleton = skeleton; - return true; + if (!mesh || mesh->skeletonRef.empty()) + return false; + + // Highly unusual to see in read world cases but support + // binary mesh referencing a XML skeleton file. + if (EndsWith(mesh->skeletonRef, ".skeleton.xml", false)) + { + OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh); + return false; + } + + MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef); + + Skeleton *skeleton = new Skeleton(); + OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton); + serializer.ReadSkeleton(skeleton); + mesh->skeleton = skeleton; + return true; } bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh) { - if (!mesh || mesh->skeletonRef.empty()) - return false; - - MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef); - if (!reader.get()) - return false; - - Skeleton *skeleton = new Skeleton(); - OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton); - serializer.ReadSkeleton(skeleton); - mesh->skeleton = skeleton; - return true; + if (!mesh || mesh->skeletonRef.empty()) + return false; + + MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef); + if (!reader.get()) + return false; + + Skeleton *skeleton = new Skeleton(); + OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton); + serializer.ReadSkeleton(skeleton); + mesh->skeleton = skeleton; + return true; } MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) { - if (!EndsWith(filename, ".skeleton", false)) - { - DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file."); - return MemoryStreamReaderPtr(); - } - - if (!pIOHandler->Exists(filename)) - { - DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh."); - return MemoryStreamReaderPtr(); - } - - IOStream *f = pIOHandler->Open(filename, "rb"); - if (!f) { - throw DeadlyImportError("Failed to open skeleton file " + filename); - } - - return MemoryStreamReaderPtr(new MemoryStreamReader(f)); + if (!EndsWith(filename, ".skeleton", false)) + { + DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file."); + return MemoryStreamReaderPtr(); + } + + if (!pIOHandler->Exists(filename)) + { + DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh."); + return MemoryStreamReaderPtr(); + } + + IOStream *f = pIOHandler->Open(filename, "rb"); + if (!f) { + throw DeadlyImportError("Failed to open skeleton file " + filename); + } + + return MemoryStreamReaderPtr(new MemoryStreamReader(f)); } void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { - uint16_t id = ReadHeader(false); - if (id != HEADER_CHUNK_ID) { - throw DeadlyExportError("Invalid Ogre Skeleton file header."); - } - - // This deserialization supports both versions of the skeleton spec - std::string version = ReadLine(); - if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1) - { - throw DeadlyExportError(Formatter::format() << "Skeleton version " << version << " not supported by this importer." - << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1); - } - - DefaultLogger::get()->debug("Reading Skeleton"); - - bool firstBone = true; - bool firstAnim = true; - - while (!AtEnd()) - { - id = ReadHeader(); - switch(id) - { - case SKELETON_BLENDMODE: - { - skeleton->blendMode = static_cast<Skeleton::BlendMode>(Read<uint16_t>()); - break; - } - case SKELETON_BONE: - { - if (firstBone) - { - DefaultLogger::get()->debug(" - Bones"); - firstBone = false; - } - - ReadBone(skeleton); - break; - } - case SKELETON_BONE_PARENT: - { - ReadBoneParent(skeleton); - break; - } - case SKELETON_ANIMATION: - { - if (firstAnim) - { - DefaultLogger::get()->debug(" - Animations"); - firstAnim = false; - } - - ReadSkeletonAnimation(skeleton); - break; - } - case SKELETON_ANIMATION_LINK: - { - ReadSkeletonAnimationLink(skeleton); - break; - } - } - } - - // Calculate bone matrices for root bones. Recursively calculates their children. - for (size_t i=0, len=skeleton->bones.size(); i<len; ++i) - { - Bone *bone = skeleton->bones[i]; - if (!bone->IsParented()) - bone->CalculateWorldMatrixAndDefaultPose(skeleton); - } + uint16_t id = ReadHeader(false); + if (id != HEADER_CHUNK_ID) { + throw DeadlyExportError("Invalid Ogre Skeleton file header."); + } + + // This deserialization supports both versions of the skeleton spec + std::string version = ReadLine(); + if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1) + { + throw DeadlyExportError(Formatter::format() << "Skeleton version " << version << " not supported by this importer." + << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1); + } + + DefaultLogger::get()->debug("Reading Skeleton"); + + bool firstBone = true; + bool firstAnim = true; + + while (!AtEnd()) + { + id = ReadHeader(); + switch(id) + { + case SKELETON_BLENDMODE: + { + skeleton->blendMode = static_cast<Skeleton::BlendMode>(Read<uint16_t>()); + break; + } + case SKELETON_BONE: + { + if (firstBone) + { + DefaultLogger::get()->debug(" - Bones"); + firstBone = false; + } + + ReadBone(skeleton); + break; + } + case SKELETON_BONE_PARENT: + { + ReadBoneParent(skeleton); + break; + } + case SKELETON_ANIMATION: + { + if (firstAnim) + { + DefaultLogger::get()->debug(" - Animations"); + firstAnim = false; + } + + ReadSkeletonAnimation(skeleton); + break; + } + case SKELETON_ANIMATION_LINK: + { + ReadSkeletonAnimationLink(skeleton); + break; + } + } + } + + // Calculate bone matrices for root bones. Recursively calculates their children. + for (size_t i=0, len=skeleton->bones.size(); i<len; ++i) + { + Bone *bone = skeleton->bones[i]; + if (!bone->IsParented()) + bone->CalculateWorldMatrixAndDefaultPose(skeleton); + } } void OgreBinarySerializer::ReadBone(Skeleton *skeleton) { - Bone *bone = new Bone(); - bone->name = ReadLine(); - bone->id = Read<uint16_t>(); + Bone *bone = new Bone(); + bone->name = ReadLine(); + bone->id = Read<uint16_t>(); - // Pos and rot - ReadVector(bone->position); - ReadQuaternion(bone->rotation); + // Pos and rot + ReadVector(bone->position); + ReadQuaternion(bone->rotation); - // Scale (optional) - if (m_currentLen > MSTREAM_BONE_SIZE_WITHOUT_SCALE) - ReadVector(bone->scale); + // Scale (optional) + if (m_currentLen > MSTREAM_BONE_SIZE_WITHOUT_SCALE) + ReadVector(bone->scale); - // Bone indexes need to start from 0 and be contiguous - if (bone->id != skeleton->bones.size()) { - throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id); - } + // Bone indexes need to start from 0 and be contiguous + if (bone->id != skeleton->bones.size()) { + throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id); + } - DefaultLogger::get()->debug(Formatter::format() << " " << bone->id << " " << bone->name); + DefaultLogger::get()->debug(Formatter::format() << " " << bone->id << " " << bone->name); - skeleton->bones.push_back(bone); + skeleton->bones.push_back(bone); } void OgreBinarySerializer::ReadBoneParent(Skeleton *skeleton) { - uint16_t childId = Read<uint16_t>(); - uint16_t parentId = Read<uint16_t>(); - - Bone *child = skeleton->BoneById(childId); - Bone *parent = skeleton->BoneById(parentId); - - if (child && parent) - parent->AddChild(child); - else - throw DeadlyImportError(Formatter::format() << "Failed to find bones for parenting: Child id " << childId << " for parent id " << parentId); + uint16_t childId = Read<uint16_t>(); + uint16_t parentId = Read<uint16_t>(); + + Bone *child = skeleton->BoneById(childId); + Bone *parent = skeleton->BoneById(parentId); + + if (child && parent) + parent->AddChild(child); + else + throw DeadlyImportError(Formatter::format() << "Failed to find bones for parenting: Child id " << childId << " for parent id " << parentId); } void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton) { - Animation *anim = new Animation(skeleton); - anim->name = ReadLine(); - anim->length = Read<float>(); - - if (!AtEnd()) - { - uint16_t id = ReadHeader(); - if (id == SKELETON_ANIMATION_BASEINFO) - { - anim->baseName = ReadLine(); - anim->baseTime = Read<float>(); - - // Advance to first track - id = ReadHeader(); - } - - while (!AtEnd() && id == SKELETON_ANIMATION_TRACK) - { - ReadSkeletonAnimationTrack(skeleton, anim); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - } - - skeleton->animations.push_back(anim); - - DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)"); + Animation *anim = new Animation(skeleton); + anim->name = ReadLine(); + anim->length = Read<float>(); + + if (!AtEnd()) + { + uint16_t id = ReadHeader(); + if (id == SKELETON_ANIMATION_BASEINFO) + { + anim->baseName = ReadLine(); + anim->baseTime = Read<float>(); + + // Advance to first track + id = ReadHeader(); + } + + while (!AtEnd() && id == SKELETON_ANIMATION_TRACK) + { + ReadSkeletonAnimationTrack(skeleton, anim); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + } + + skeleton->animations.push_back(anim); + + DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)"); } -void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest) +void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest) { - uint16_t boneId = Read<uint16_t>(); - Bone *bone = dest->parentSkeleton->BoneById(boneId); - if (!bone) { - throw DeadlyImportError(Formatter::format() << "Cannot read animation track, target bone " << boneId << " not in target Skeleton"); - } - - VertexAnimationTrack track; - track.type = VertexAnimationTrack::VAT_TRANSFORM; - track.boneName = bone->name; - - uint16_t id = ReadHeader(); - while (!AtEnd() && id == SKELETON_ANIMATION_TRACK_KEYFRAME) - { - ReadSkeletonAnimationKeyFrame(&track); - - if (!AtEnd()) - id = ReadHeader(); - } - if (!AtEnd()) - RollbackHeader(); - - dest->tracks.push_back(track); + uint16_t boneId = Read<uint16_t>(); + Bone *bone = dest->parentSkeleton->BoneById(boneId); + if (!bone) { + throw DeadlyImportError(Formatter::format() << "Cannot read animation track, target bone " << boneId << " not in target Skeleton"); + } + + VertexAnimationTrack track; + track.type = VertexAnimationTrack::VAT_TRANSFORM; + track.boneName = bone->name; + + uint16_t id = ReadHeader(); + while (!AtEnd() && id == SKELETON_ANIMATION_TRACK_KEYFRAME) + { + ReadSkeletonAnimationKeyFrame(&track); + + if (!AtEnd()) + id = ReadHeader(); + } + if (!AtEnd()) + RollbackHeader(); + + dest->tracks.push_back(track); } void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest) { - TransformKeyFrame keyframe; - keyframe.timePos = Read<float>(); - - // Rot and pos - ReadQuaternion(keyframe.rotation); - ReadVector(keyframe.position); - - // Scale (optional) - if (m_currentLen > MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE) - ReadVector(keyframe.scale); - - dest->transformKeyFrames.push_back(keyframe); + TransformKeyFrame keyframe; + keyframe.timePos = Read<float>(); + + // Rot and pos + ReadQuaternion(keyframe.rotation); + ReadVector(keyframe.position); + + // Scale (optional) + if (m_currentLen > MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE) + ReadVector(keyframe.scale); + + dest->transformKeyFrames.push_back(keyframe); } -void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton) +void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/) { - // Skip bounds, not compatible with Assimp. - ReadLine(); // skeleton name - SkipBytes(sizeof(float) * 3); // scale + // Skip bounds, not compatible with Assimp. + ReadLine(); // skeleton name + SkipBytes(sizeof(float) * 3); // scale } } // Ogre |