diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:09:44 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:10:02 +0100 |
commit | 77d294db076dac19e8b549b445ffede9f7260c84 (patch) | |
tree | 828ee7a6862ec5c0bd24f97cb540625a2c647376 /src/3rdparty/assimp/code/OgreStructs.cpp | |
parent | 59f8fec8a41606b3185fe3a4e276978e3e1ed5ef (diff) | |
parent | 939b9b4b7591e8a421cf048a0a84ed3e75d81d21 (diff) |
Merge branch 'dev' into wip/animationwip/animation
Change-Id: I6e770609c90a7745d08fa4e2f424e865678c5d6f
Diffstat (limited to 'src/3rdparty/assimp/code/OgreStructs.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/OgreStructs.cpp | 1639 |
1 files changed, 825 insertions, 814 deletions
diff --git a/src/3rdparty/assimp/code/OgreStructs.cpp b/src/3rdparty/assimp/code/OgreStructs.cpp index 3eaf2df01..e2e8c8103 100644 --- a/src/3rdparty/assimp/code/OgreStructs.cpp +++ b/src/3rdparty/assimp/code/OgreStructs.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. ---------------------------------------------------------------------- @@ -42,6 +42,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "OgreStructs.h" #include "TinyFormatter.h" +#include <assimp/scene.h> +#include <assimp/DefaultLogger.hpp> +#include "Exceptional.h" + namespace Assimp { @@ -50,247 +54,245 @@ namespace Ogre // VertexElement -VertexElement::VertexElement() : - index(0), - source(0), - offset(0), - type(VET_FLOAT1), - semantic(VES_POSITION) +VertexElement::VertexElement() : + index(0), + source(0), + offset(0), + type(VET_FLOAT1), + semantic(VES_POSITION) { } size_t VertexElement::Size() const { - return TypeSize(type); + return TypeSize(type); } size_t VertexElement::ComponentCount() const { - return ComponentCount(type); + return ComponentCount(type); } size_t VertexElement::ComponentCount(Type type) { - switch(type) - { - case VET_COLOUR: - case VET_COLOUR_ABGR: - case VET_COLOUR_ARGB: - case VET_FLOAT1: - case VET_DOUBLE1: - case VET_SHORT1: - case VET_USHORT1: - case VET_INT1: - case VET_UINT1: - return 1; - case VET_FLOAT2: - case VET_DOUBLE2: - case VET_SHORT2: - case VET_USHORT2: - case VET_INT2: - case VET_UINT2: - return 2; - case VET_FLOAT3: - case VET_DOUBLE3: - case VET_SHORT3: - case VET_USHORT3: - case VET_INT3: - case VET_UINT3: - return 3; - case VET_FLOAT4: - case VET_DOUBLE4: - case VET_SHORT4: - case VET_USHORT4: - case VET_INT4: - case VET_UINT4: - case VET_UBYTE4: - return 4; - } - return 0; + switch(type) + { + case VET_COLOUR: + case VET_COLOUR_ABGR: + case VET_COLOUR_ARGB: + case VET_FLOAT1: + case VET_DOUBLE1: + case VET_SHORT1: + case VET_USHORT1: + case VET_INT1: + case VET_UINT1: + return 1; + case VET_FLOAT2: + case VET_DOUBLE2: + case VET_SHORT2: + case VET_USHORT2: + case VET_INT2: + case VET_UINT2: + return 2; + case VET_FLOAT3: + case VET_DOUBLE3: + case VET_SHORT3: + case VET_USHORT3: + case VET_INT3: + case VET_UINT3: + return 3; + case VET_FLOAT4: + case VET_DOUBLE4: + case VET_SHORT4: + case VET_USHORT4: + case VET_INT4: + case VET_UINT4: + case VET_UBYTE4: + return 4; + } + return 0; } size_t VertexElement::TypeSize(Type type) { - switch(type) - { - case VET_COLOUR: - case VET_COLOUR_ABGR: - case VET_COLOUR_ARGB: - return sizeof(unsigned int); - case VET_FLOAT1: - return sizeof(float); - case VET_FLOAT2: - return sizeof(float)*2; - case VET_FLOAT3: - return sizeof(float)*3; - case VET_FLOAT4: - return sizeof(float)*4; - case VET_DOUBLE1: - return sizeof(double); - case VET_DOUBLE2: - return sizeof(double)*2; - case VET_DOUBLE3: - return sizeof(double)*3; - case VET_DOUBLE4: - return sizeof(double)*4; - case VET_SHORT1: - return sizeof(short); - case VET_SHORT2: - return sizeof(short)*2; - case VET_SHORT3: - return sizeof(short)*3; - case VET_SHORT4: - return sizeof(short)*4; - case VET_USHORT1: - return sizeof(unsigned short); - case VET_USHORT2: - return sizeof(unsigned short)*2; - case VET_USHORT3: - return sizeof(unsigned short)*3; - case VET_USHORT4: - return sizeof(unsigned short)*4; - case VET_INT1: - return sizeof(int); - case VET_INT2: - return sizeof(int)*2; - case VET_INT3: - return sizeof(int)*3; - case VET_INT4: - return sizeof(int)*4; - case VET_UINT1: - return sizeof(unsigned int); - case VET_UINT2: - return sizeof(unsigned int)*2; - case VET_UINT3: - return sizeof(unsigned int)*3; - case VET_UINT4: - return sizeof(unsigned int)*4; - case VET_UBYTE4: - return sizeof(unsigned char)*4; - } - return 0; + switch(type) + { + case VET_COLOUR: + case VET_COLOUR_ABGR: + case VET_COLOUR_ARGB: + return sizeof(unsigned int); + case VET_FLOAT1: + return sizeof(float); + case VET_FLOAT2: + return sizeof(float)*2; + case VET_FLOAT3: + return sizeof(float)*3; + case VET_FLOAT4: + return sizeof(float)*4; + case VET_DOUBLE1: + return sizeof(double); + case VET_DOUBLE2: + return sizeof(double)*2; + case VET_DOUBLE3: + return sizeof(double)*3; + case VET_DOUBLE4: + return sizeof(double)*4; + case VET_SHORT1: + return sizeof(short); + case VET_SHORT2: + return sizeof(short)*2; + case VET_SHORT3: + return sizeof(short)*3; + case VET_SHORT4: + return sizeof(short)*4; + case VET_USHORT1: + return sizeof(unsigned short); + case VET_USHORT2: + return sizeof(unsigned short)*2; + case VET_USHORT3: + return sizeof(unsigned short)*3; + case VET_USHORT4: + return sizeof(unsigned short)*4; + case VET_INT1: + return sizeof(int); + case VET_INT2: + return sizeof(int)*2; + case VET_INT3: + return sizeof(int)*3; + case VET_INT4: + return sizeof(int)*4; + case VET_UINT1: + return sizeof(unsigned int); + case VET_UINT2: + return sizeof(unsigned int)*2; + case VET_UINT3: + return sizeof(unsigned int)*3; + case VET_UINT4: + return sizeof(unsigned int)*4; + case VET_UBYTE4: + return sizeof(unsigned char)*4; + } + return 0; } std::string VertexElement::TypeToString() { - return TypeToString(type); + return TypeToString(type); } std::string VertexElement::TypeToString(Type type) { - switch(type) - { - case VET_COLOUR: return "COLOUR"; - case VET_COLOUR_ABGR: return "COLOUR_ABGR"; - case VET_COLOUR_ARGB: return "COLOUR_ARGB"; - case VET_FLOAT1: return "FLOAT1"; - case VET_FLOAT2: return "FLOAT2"; - case VET_FLOAT3: return "FLOAT3"; - case VET_FLOAT4: return "FLOAT4"; - case VET_DOUBLE1: return "DOUBLE1"; - case VET_DOUBLE2: return "DOUBLE2"; - case VET_DOUBLE3: return "DOUBLE3"; - case VET_DOUBLE4: return "DOUBLE4"; - case VET_SHORT1: return "SHORT1"; - case VET_SHORT2: return "SHORT2"; - case VET_SHORT3: return "SHORT3"; - case VET_SHORT4: return "SHORT4"; - case VET_USHORT1: return "USHORT1"; - case VET_USHORT2: return "USHORT2"; - case VET_USHORT3: return "USHORT3"; - case VET_USHORT4: return "USHORT4"; - case VET_INT1: return "INT1"; - case VET_INT2: return "INT2"; - case VET_INT3: return "INT3"; - case VET_INT4: return "INT4"; - case VET_UINT1: return "UINT1"; - case VET_UINT2: return "UINT2"; - case VET_UINT3: return "UINT3"; - case VET_UINT4: return "UINT4"; - case VET_UBYTE4: return "UBYTE4"; - } - return "Uknown_VertexElement::Type"; + switch(type) + { + case VET_COLOUR: return "COLOUR"; + case VET_COLOUR_ABGR: return "COLOUR_ABGR"; + case VET_COLOUR_ARGB: return "COLOUR_ARGB"; + case VET_FLOAT1: return "FLOAT1"; + case VET_FLOAT2: return "FLOAT2"; + case VET_FLOAT3: return "FLOAT3"; + case VET_FLOAT4: return "FLOAT4"; + case VET_DOUBLE1: return "DOUBLE1"; + case VET_DOUBLE2: return "DOUBLE2"; + case VET_DOUBLE3: return "DOUBLE3"; + case VET_DOUBLE4: return "DOUBLE4"; + case VET_SHORT1: return "SHORT1"; + case VET_SHORT2: return "SHORT2"; + case VET_SHORT3: return "SHORT3"; + case VET_SHORT4: return "SHORT4"; + case VET_USHORT1: return "USHORT1"; + case VET_USHORT2: return "USHORT2"; + case VET_USHORT3: return "USHORT3"; + case VET_USHORT4: return "USHORT4"; + case VET_INT1: return "INT1"; + case VET_INT2: return "INT2"; + case VET_INT3: return "INT3"; + case VET_INT4: return "INT4"; + case VET_UINT1: return "UINT1"; + case VET_UINT2: return "UINT2"; + case VET_UINT3: return "UINT3"; + case VET_UINT4: return "UINT4"; + case VET_UBYTE4: return "UBYTE4"; + } + return "Uknown_VertexElement::Type"; } std::string VertexElement::SemanticToString() { - return SemanticToString(semantic); + return SemanticToString(semantic); } std::string VertexElement::SemanticToString(Semantic semantic) { - switch(semantic) - { - case VES_POSITION: return "POSITION"; - case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS"; - case VES_BLEND_INDICES: return "BLEND_INDICES"; - case VES_NORMAL: return "NORMAL"; - case VES_DIFFUSE: return "DIFFUSE"; - case VES_SPECULAR: return "SPECULAR"; - case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES"; - case VES_BINORMAL: return "BINORMAL"; - case VES_TANGENT: return "TANGENT"; - } - return "Uknown_VertexElement::Semantic"; + switch(semantic) + { + case VES_POSITION: return "POSITION"; + case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS"; + case VES_BLEND_INDICES: return "BLEND_INDICES"; + case VES_NORMAL: return "NORMAL"; + case VES_DIFFUSE: return "DIFFUSE"; + case VES_SPECULAR: return "SPECULAR"; + case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES"; + case VES_BINORMAL: return "BINORMAL"; + case VES_TANGENT: return "TANGENT"; + } + return "Uknown_VertexElement::Semantic"; } // IVertexData IVertexData::IVertexData() : - count(0) + count(0) { } bool IVertexData::HasBoneAssignments() const { - return !boneAssignments.empty(); + return !boneAssignments.empty(); } void IVertexData::AddVertexMapping(uint32_t oldIndex, uint32_t newIndex) { - BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]); - vertexIndexMapping[oldIndex].push_back(newIndex); + BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]); + vertexIndexMapping[oldIndex].push_back(newIndex); } void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const { - for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end(); - iter!=end; ++iter) - { - if (iter->vertexIndex == currentIndex) - { - VertexBoneAssignment a = (*iter); - a.vertexIndex = newIndex; - dest.push_back(a); - } - } + for (const auto &boneAssign : boneAssignments) + { + if (boneAssign.vertexIndex == currentIndex) + { + VertexBoneAssignment a = boneAssign; + a.vertexIndex = newIndex; + dest.push_back(a); + } + } } AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices) { - AssimpVertexBoneWeightList weights; - for(size_t vi=0; vi<vertices; ++vi) - { - VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[vi]; - for (VertexBoneAssignmentList::const_iterator iter=vertexWeights.begin(), end=vertexWeights.end(); - iter!=end; ++iter) - { - std::vector<aiVertexWeight> &boneWeights = weights[iter->boneIndex]; - boneWeights.push_back(aiVertexWeight(vi, iter->weight)); - } - } - return weights; + AssimpVertexBoneWeightList weights; + for(size_t vi=0; vi<vertices; ++vi) + { + VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[vi]; + for (VertexBoneAssignmentList::const_iterator iter=vertexWeights.begin(), end=vertexWeights.end(); + iter!=end; ++iter) + { + std::vector<aiVertexWeight> &boneWeights = weights[iter->boneIndex]; + boneWeights.push_back(aiVertexWeight(vi, iter->weight)); + } + } + return weights; } std::set<uint16_t> IVertexData::ReferencedBonesByWeights() const { - std::set<uint16_t> referenced; - for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end(); - iter!=end; ++iter) - { - referenced.insert(iter->boneIndex); - } - return referenced; + std::set<uint16_t> referenced; + for (const auto &boneAssign : boneAssignments) + { + referenced.insert(boneAssign.boneIndex); + } + return referenced; } // VertexData @@ -301,43 +303,42 @@ VertexData::VertexData() VertexData::~VertexData() { - Reset(); + Reset(); } void VertexData::Reset() { - // Releases shared ptr memory streams. - vertexBindings.clear(); - vertexElements.clear(); + // Releases shared ptr memory streams. + vertexBindings.clear(); + vertexElements.clear(); } uint32_t VertexData::VertexSize(uint16_t source) const { - uint32_t size = 0; - for(VertexElementList::const_iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter) - { - if (iter->source == source) - size += iter->Size(); - } - return size; + uint32_t size = 0; + for(const auto &element : vertexElements) + { + if (element.source == source) + size += element.Size(); + } + return size; } MemoryStream *VertexData::VertexBuffer(uint16_t source) { - if (vertexBindings.find(source) != vertexBindings.end()) - return vertexBindings[source].get(); - return 0; + if (vertexBindings.find(source) != vertexBindings.end()) + return vertexBindings[source].get(); + return 0; } VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index) { - for(VertexElementList::iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter) - { - VertexElement &element = (*iter); - if (element.semantic == semantic && element.index == index) - return &element; - } - return 0; + for(auto & element : vertexElements) + { + if (element.semantic == semantic && element.index == index) + return &element; + } + return 0; } // VertexDataXml @@ -348,843 +349,853 @@ VertexDataXml::VertexDataXml() bool VertexDataXml::HasPositions() const { - return !positions.empty(); + return !positions.empty(); } bool VertexDataXml::HasNormals() const { - return !normals.empty(); + return !normals.empty(); } bool VertexDataXml::HasTangents() const { - return !tangents.empty(); + return !tangents.empty(); } bool VertexDataXml::HasUvs() const { - return !uvs.empty(); + return !uvs.empty(); } size_t VertexDataXml::NumUvs() const { - return uvs.size(); + return uvs.size(); } // IndexData IndexData::IndexData() : - count(0), - faceCount(0), - is32bit(false) + count(0), + faceCount(0), + is32bit(false) { } IndexData::~IndexData() { - Reset(); + Reset(); } void IndexData::Reset() { - // Release shared ptr memory stream. - buffer.reset(); + // Release shared ptr memory stream. + buffer.reset(); } size_t IndexData::IndexSize() const { - return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t)); + return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t)); } size_t IndexData::FaceSize() const { - return IndexSize() * 3; + return IndexSize() * 3; } // Mesh -Mesh::Mesh() : - sharedVertexData(0), - skeleton(0), - hasSkeletalAnimations(false) +Mesh::Mesh() + : hasSkeletalAnimations(false) + , skeleton(NULL) + , sharedVertexData(NULL) + , subMeshes() + , animations() + , poses() { } Mesh::~Mesh() { - Reset(); + Reset(); } void Mesh::Reset() { - OGRE_SAFE_DELETE(skeleton) - OGRE_SAFE_DELETE(sharedVertexData) + OGRE_SAFE_DELETE(skeleton) + OGRE_SAFE_DELETE(sharedVertexData) - for(size_t i=0, len=subMeshes.size(); i<len; ++i) { - OGRE_SAFE_DELETE(subMeshes[i]) - } - subMeshes.clear(); - for(size_t i=0, len=animations.size(); i<len; ++i) { - OGRE_SAFE_DELETE(animations[i]) - } - animations.clear(); - for(size_t i=0, len=poses.size(); i<len; ++i) { - OGRE_SAFE_DELETE(poses[i]) - } - poses.clear(); + for(auto &mesh : subMeshes) { + OGRE_SAFE_DELETE(mesh) + } + subMeshes.clear(); + for(auto &anim : animations) { + OGRE_SAFE_DELETE(anim) + } + animations.clear(); + for(auto &pose : poses) { + OGRE_SAFE_DELETE(pose) + } + poses.clear(); } size_t Mesh::NumSubMeshes() const { - return subMeshes.size(); + return subMeshes.size(); } -SubMesh *Mesh::GetSubMesh(uint16_t index) const +SubMesh *Mesh::GetSubMesh( size_t index ) const { - for(size_t i=0; i<subMeshes.size(); ++i) - if (subMeshes[i]->index == index) - return subMeshes[i]; - return 0; + for ( size_t i = 0; i < subMeshes.size(); ++i ) { + if ( subMeshes[ i ]->index == index ) { + return subMeshes[ i ]; + } + } + return 0; } void Mesh::ConvertToAssimpScene(aiScene* dest) { - // Setup - dest->mNumMeshes = NumSubMeshes(); - dest->mMeshes = new aiMesh*[dest->mNumMeshes]; - - // Create root node - dest->mRootNode = new aiNode(); - dest->mRootNode->mNumMeshes = dest->mNumMeshes; - dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes]; - - // Export meshes - for(size_t i=0; i<dest->mNumMeshes; ++i) - { - dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this); - dest->mRootNode->mMeshes[i] = i; - } - - // Export skeleton - if (skeleton) - { - // Bones - if (!skeleton->bones.empty()) - { - BoneList rootBones = skeleton->RootBones(); - dest->mRootNode->mNumChildren = rootBones.size(); - dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren]; - - for(size_t i=0, len=rootBones.size(); i<len; ++i) - { - dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode); - } - } - - // Animations - if (!skeleton->animations.empty()) - { - dest->mNumAnimations = skeleton->animations.size(); - dest->mAnimations = new aiAnimation*[dest->mNumAnimations]; - - for(size_t i=0, len=skeleton->animations.size(); i<len; ++i) - { - dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation(); - } - } - } + if ( nullptr == dest ) { + return; + } + + // Setup + dest->mNumMeshes = NumSubMeshes(); + dest->mMeshes = new aiMesh*[dest->mNumMeshes]; + + // Create root node + dest->mRootNode = new aiNode(); + dest->mRootNode->mNumMeshes = dest->mNumMeshes; + dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes]; + + // Export meshes + for(size_t i=0; i<dest->mNumMeshes; ++i) { + dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this); + dest->mRootNode->mMeshes[i] = i; + } + + // Export skeleton + if (skeleton) + { + // Bones + if (!skeleton->bones.empty()) + { + BoneList rootBones = skeleton->RootBones(); + dest->mRootNode->mNumChildren = rootBones.size(); + dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren]; + + for(size_t i=0, len=rootBones.size(); i<len; ++i) + { + dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode); + } + } + + // Animations + if (!skeleton->animations.empty()) + { + dest->mNumAnimations = skeleton->animations.size(); + dest->mAnimations = new aiAnimation*[dest->mNumAnimations]; + + for(size_t i=0, len=skeleton->animations.size(); i<len; ++i) + { + dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation(); + } + } + } } // ISubMesh ISubMesh::ISubMesh() : - index(0), - materialIndex(-1), - usesSharedVertexData(false), - operationType(OT_POINT_LIST) + index(0), + materialIndex(-1), + usesSharedVertexData(false), + operationType(OT_POINT_LIST) { } // SubMesh SubMesh::SubMesh() : - vertexData(0), - indexData(new IndexData()) + vertexData(0), + indexData(new IndexData()) { } SubMesh::~SubMesh() { - Reset(); + Reset(); } void SubMesh::Reset() { - OGRE_SAFE_DELETE(vertexData) - OGRE_SAFE_DELETE(indexData) + OGRE_SAFE_DELETE(vertexData) + OGRE_SAFE_DELETE(indexData) } aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) { - if (operationType != OT_TRIANGLE_LIST) { - throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType); - } - - aiMesh *dest = new aiMesh(); - dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - if (!name.empty()) - dest->mName = name; - - // Material index - if (materialIndex != -1) - dest->mMaterialIndex = materialIndex; - - // Pick source vertex data from shader geometry or from internal geometry. - VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData); - - VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION); - VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL); - VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0); - VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1); - - // Sanity checks - if (!positionsElement) { - throw DeadlyImportError("Failed to import Ogre VertexElement::VES_POSITION. Mesh does not have vertex positions!"); - } else if (positionsElement->type != VertexElement::VET_FLOAT3) { - throw DeadlyImportError("Ogre Mesh position vertex element type != VertexElement::VET_FLOAT3. This is not supported."); - } else if (normalsElement && normalsElement->type != VertexElement::VET_FLOAT3) { - throw DeadlyImportError("Ogre Mesh normal vertex element type != VertexElement::VET_FLOAT3. This is not supported."); - } - - // Faces - dest->mNumFaces = indexData->faceCount; - dest->mFaces = new aiFace[dest->mNumFaces]; - - // Assimp required unique vertices, we need to convert from Ogres shared indexing. - size_t uniqueVertexCount = dest->mNumFaces * 3; - dest->mNumVertices = uniqueVertexCount; - dest->mVertices = new aiVector3D[dest->mNumVertices]; - - // Source streams - MemoryStream *positions = src->VertexBuffer(positionsElement->source); - MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0); - MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0); - MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0); - - // Element size - const size_t sizePosition = positionsElement->Size(); - const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0); - const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0); - const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0); - - // Vertex width - const size_t vWidthPosition = src->VertexSize(positionsElement->source); - const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0); - const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0); - const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0); - - bool boneAssignments = src->HasBoneAssignments(); - - // Prepare normals - if (normals) - dest->mNormals = new aiVector3D[dest->mNumVertices]; - - // Prepare UVs, ignoring incompatible UVs. - if (uv1) - { - if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3) - { - dest->mNumUVComponents[0] = uv1Element->ComponentCount(); - dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices]; - } - else - { - DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); - uv1 = 0; - } - } - if (uv2) - { - if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3) - { - dest->mNumUVComponents[1] = uv2Element->ComponentCount(); - dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices]; - } - else - { - DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); - uv2 = 0; - } - } - - aiVector3D *uv1Dest = (uv1 ? dest->mTextureCoords[0] : 0); - aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0); - - MemoryStream *faces = indexData->buffer.get(); - for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize(); - fi<dest->mNumFaces; ++fi) - { - // Source Ogre face - aiFace ogreFace; - ogreFace.mNumIndices = 3; - ogreFace.mIndices = new unsigned int[3]; - - faces->Seek(fi * fsize, aiOrigin_SET); - if (indexData->is32bit) - { - faces->Read(&ogreFace.mIndices[0], isize, 3); - } - else - { - uint16_t iout = 0; - for (size_t ii=0; ii<3; ++ii) - { - faces->Read(&iout, isize, 1); - ogreFace.mIndices[ii] = static_cast<unsigned int>(iout); - } - } - - // Destination Assimp face - aiFace &face = dest->mFaces[fi]; - face.mNumIndices = 3; - face.mIndices = new unsigned int[3]; - - const size_t pos = fi * 3; - for (size_t v=0; v<3; ++v) - { - const size_t newIndex = pos + v; - - // Write face index - face.mIndices[v] = newIndex; - - // Ogres vertex index to ref into the source buffers. - const size_t ogreVertexIndex = ogreFace.mIndices[v]; - src->AddVertexMapping(ogreVertexIndex, newIndex); - - // Position - positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET); - positions->Read(&dest->mVertices[newIndex], sizePosition, 1); - - // Normal - if (normals) - { - normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET); - normals->Read(&dest->mNormals[newIndex], sizeNormal, 1); - } - // UV0 - if (uv1 && uv1Dest) - { - uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET); - uv1->Read(&uv1Dest[newIndex], sizeUv1, 1); - uv1Dest[newIndex].y = (uv1Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form - } - // UV1 - if (uv2 && uv2Dest) - { - uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET); - uv2->Read(&uv2Dest[newIndex], sizeUv2, 1); - uv2Dest[newIndex].y = (uv2Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form - } - } - } - - // Bones and bone weights - if (parent->skeleton && boneAssignments) - { - AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices); - std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights(); - - dest->mNumBones = referencedBones.size(); - dest->mBones = new aiBone*[dest->mNumBones]; - - size_t assimpBoneIndex = 0; - for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) - { - Bone *bone = parent->skeleton->BoneById((*rbIter)); - dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]); - } - } - - return dest; + if (operationType != OT_TRIANGLE_LIST) { + throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType); + } + + aiMesh *dest = new aiMesh(); + dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + if (!name.empty()) + dest->mName = name; + + // Material index + if (materialIndex != -1) + dest->mMaterialIndex = materialIndex; + + // Pick source vertex data from shader geometry or from internal geometry. + VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData); + + VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION); + VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL); + VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0); + VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1); + + // Sanity checks + if (!positionsElement) { + throw DeadlyImportError("Failed to import Ogre VertexElement::VES_POSITION. Mesh does not have vertex positions!"); + } else if (positionsElement->type != VertexElement::VET_FLOAT3) { + throw DeadlyImportError("Ogre Mesh position vertex element type != VertexElement::VET_FLOAT3. This is not supported."); + } else if (normalsElement && normalsElement->type != VertexElement::VET_FLOAT3) { + throw DeadlyImportError("Ogre Mesh normal vertex element type != VertexElement::VET_FLOAT3. This is not supported."); + } + + // Faces + dest->mNumFaces = indexData->faceCount; + dest->mFaces = new aiFace[dest->mNumFaces]; + + // Assimp required unique vertices, we need to convert from Ogres shared indexing. + size_t uniqueVertexCount = dest->mNumFaces * 3; + dest->mNumVertices = uniqueVertexCount; + dest->mVertices = new aiVector3D[dest->mNumVertices]; + + // Source streams + MemoryStream *positions = src->VertexBuffer(positionsElement->source); + MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0); + MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0); + MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0); + + // Element size + const size_t sizePosition = positionsElement->Size(); + const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0); + const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0); + const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0); + + // Vertex width + const size_t vWidthPosition = src->VertexSize(positionsElement->source); + const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0); + const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0); + const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0); + + bool boneAssignments = src->HasBoneAssignments(); + + // Prepare normals + if (normals) + dest->mNormals = new aiVector3D[dest->mNumVertices]; + + // Prepare UVs, ignoring incompatible UVs. + if (uv1) + { + if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3) + { + dest->mNumUVComponents[0] = uv1Element->ComponentCount(); + dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices]; + } + else + { + DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); + uv1 = 0; + } + } + if (uv2) + { + if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3) + { + dest->mNumUVComponents[1] = uv2Element->ComponentCount(); + dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices]; + } + else + { + DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); + uv2 = 0; + } + } + + aiVector3D *uv1Dest = (uv1 ? dest->mTextureCoords[0] : 0); + aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0); + + MemoryStream *faces = indexData->buffer.get(); + for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize(); + fi<dest->mNumFaces; ++fi) + { + // Source Ogre face + aiFace ogreFace; + ogreFace.mNumIndices = 3; + ogreFace.mIndices = new unsigned int[3]; + + faces->Seek(fi * fsize, aiOrigin_SET); + if (indexData->is32bit) + { + faces->Read(&ogreFace.mIndices[0], isize, 3); + } + else + { + uint16_t iout = 0; + for (size_t ii=0; ii<3; ++ii) + { + faces->Read(&iout, isize, 1); + ogreFace.mIndices[ii] = static_cast<unsigned int>(iout); + } + } + + // Destination Assimp face + aiFace &face = dest->mFaces[fi]; + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + + const size_t pos = fi * 3; + for (size_t v=0; v<3; ++v) + { + const size_t newIndex = pos + v; + + // Write face index + face.mIndices[v] = newIndex; + + // Ogres vertex index to ref into the source buffers. + const size_t ogreVertexIndex = ogreFace.mIndices[v]; + src->AddVertexMapping(ogreVertexIndex, newIndex); + + // Position + positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET); + positions->Read(&dest->mVertices[newIndex], sizePosition, 1); + + // Normal + if (normals) + { + normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET); + normals->Read(&dest->mNormals[newIndex], sizeNormal, 1); + } + // UV0 + if (uv1 && uv1Dest) + { + uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET); + uv1->Read(&uv1Dest[newIndex], sizeUv1, 1); + uv1Dest[newIndex].y = (uv1Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form + } + // UV1 + if (uv2 && uv2Dest) + { + uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET); + uv2->Read(&uv2Dest[newIndex], sizeUv2, 1); + uv2Dest[newIndex].y = (uv2Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form + } + } + } + + // Bones and bone weights + if (parent->skeleton && boneAssignments) + { + AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices); + std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights(); + + dest->mNumBones = referencedBones.size(); + dest->mBones = new aiBone*[dest->mNumBones]; + + size_t assimpBoneIndex = 0; + for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) + { + Bone *bone = parent->skeleton->BoneById((*rbIter)); + dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]); + } + } + + return dest; } // MeshXml MeshXml::MeshXml() : - sharedVertexData(0), - skeleton(0) + skeleton(0), + sharedVertexData(0) { } MeshXml::~MeshXml() { - Reset(); + Reset(); } void MeshXml::Reset() { - OGRE_SAFE_DELETE(skeleton) - OGRE_SAFE_DELETE(sharedVertexData) + OGRE_SAFE_DELETE(skeleton) + OGRE_SAFE_DELETE(sharedVertexData) - for(size_t i=0, len=subMeshes.size(); i<len; ++i) { - OGRE_SAFE_DELETE(subMeshes[i]) - } - subMeshes.clear(); + for(auto &mesh : subMeshes) { + OGRE_SAFE_DELETE(mesh) + } + subMeshes.clear(); } size_t MeshXml::NumSubMeshes() const { - return subMeshes.size(); + return subMeshes.size(); } SubMeshXml *MeshXml::GetSubMesh(uint16_t index) const { - for(size_t i=0; i<subMeshes.size(); ++i) - if (subMeshes[i]->index == index) - return subMeshes[i]; - return 0; + for(size_t i=0; i<subMeshes.size(); ++i) + if (subMeshes[i]->index == index) + return subMeshes[i]; + return 0; } void MeshXml::ConvertToAssimpScene(aiScene* dest) { - // Setup - dest->mNumMeshes = NumSubMeshes(); - dest->mMeshes = new aiMesh*[dest->mNumMeshes]; - - // Create root node - dest->mRootNode = new aiNode(); - dest->mRootNode->mNumMeshes = dest->mNumMeshes; - dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes]; - - // Export meshes - for(size_t i=0; i<dest->mNumMeshes; ++i) - { - dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this); - dest->mRootNode->mMeshes[i] = i; - } - - // Export skeleton - if (skeleton) - { - // Bones - if (!skeleton->bones.empty()) - { - BoneList rootBones = skeleton->RootBones(); - dest->mRootNode->mNumChildren = rootBones.size(); - dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren]; - - for(size_t i=0, len=rootBones.size(); i<len; ++i) - { - dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode); - } - } - - // Animations - if (!skeleton->animations.empty()) - { - dest->mNumAnimations = skeleton->animations.size(); - dest->mAnimations = new aiAnimation*[dest->mNumAnimations]; - - for(size_t i=0, len=skeleton->animations.size(); i<len; ++i) - { - dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation(); - } - } - } + // Setup + dest->mNumMeshes = NumSubMeshes(); + dest->mMeshes = new aiMesh*[dest->mNumMeshes]; + + // Create root node + dest->mRootNode = new aiNode(); + dest->mRootNode->mNumMeshes = dest->mNumMeshes; + dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes]; + + // Export meshes + for(size_t i=0; i<dest->mNumMeshes; ++i) + { + dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this); + dest->mRootNode->mMeshes[i] = i; + } + + // Export skeleton + if (skeleton) + { + // Bones + if (!skeleton->bones.empty()) + { + BoneList rootBones = skeleton->RootBones(); + dest->mRootNode->mNumChildren = rootBones.size(); + dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren]; + + for(size_t i=0, len=rootBones.size(); i<len; ++i) + { + dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode); + } + } + + // Animations + if (!skeleton->animations.empty()) + { + dest->mNumAnimations = skeleton->animations.size(); + dest->mAnimations = new aiAnimation*[dest->mNumAnimations]; + + for(size_t i=0, len=skeleton->animations.size(); i<len; ++i) + { + dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation(); + } + } + } } // SubMeshXml SubMeshXml::SubMeshXml() : - vertexData(0), - indexData(new IndexDataXml()) + indexData(new IndexDataXml()), + vertexData(0) { } SubMeshXml::~SubMeshXml() { - Reset(); + Reset(); } void SubMeshXml::Reset() { - OGRE_SAFE_DELETE(indexData) - OGRE_SAFE_DELETE(vertexData) + OGRE_SAFE_DELETE(indexData) + OGRE_SAFE_DELETE(vertexData) } aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent) { - aiMesh *dest = new aiMesh(); - dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - if (!name.empty()) - dest->mName = name; - - // Material index - if (materialIndex != -1) - dest->mMaterialIndex = materialIndex; - - // Faces - dest->mNumFaces = indexData->faceCount; - dest->mFaces = new aiFace[dest->mNumFaces]; - - // Assimp required unique vertices, we need to convert from Ogres shared indexing. - size_t uniqueVertexCount = dest->mNumFaces * 3; - dest->mNumVertices = uniqueVertexCount; - dest->mVertices = new aiVector3D[dest->mNumVertices]; - - VertexDataXml *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData); - bool boneAssignments = src->HasBoneAssignments(); - bool normals = src->HasNormals(); - size_t uvs = src->NumUvs(); - - // Prepare normals - if (normals) - dest->mNormals = new aiVector3D[dest->mNumVertices]; - - // Prepare UVs - for(size_t uvi=0; uvi<uvs; ++uvi) - { - dest->mNumUVComponents[uvi] = 2; - dest->mTextureCoords[uvi] = new aiVector3D[dest->mNumVertices]; - } - - for (size_t fi=0; fi<dest->mNumFaces; ++fi) - { - // Source Ogre face - aiFace &ogreFace = indexData->faces[fi]; - - // Destination Assimp face - aiFace &face = dest->mFaces[fi]; - face.mNumIndices = 3; - face.mIndices = new unsigned int[3]; - - const size_t pos = fi * 3; - for (size_t v=0; v<3; ++v) - { - const size_t newIndex = pos + v; - - // Write face index - face.mIndices[v] = newIndex; - - // Ogres vertex index to ref into the source buffers. - const size_t ogreVertexIndex = ogreFace.mIndices[v]; - src->AddVertexMapping(ogreVertexIndex, newIndex); - - // Position - dest->mVertices[newIndex] = src->positions[ogreVertexIndex]; - - // Normal - if (normals) - dest->mNormals[newIndex] = src->normals[ogreVertexIndex]; - - // UVs - for(size_t uvi=0; uvi<uvs; ++uvi) - { - aiVector3D *uvDest = dest->mTextureCoords[uvi]; - std::vector<aiVector3D> &uvSrc = src->uvs[uvi]; - uvDest[newIndex] = uvSrc[ogreVertexIndex]; - } - } - } - - // Bones and bone weights - if (parent->skeleton && boneAssignments) - { - AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices); - std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights(); - - dest->mNumBones = referencedBones.size(); - dest->mBones = new aiBone*[dest->mNumBones]; - - size_t assimpBoneIndex = 0; - for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) - { - Bone *bone = parent->skeleton->BoneById((*rbIter)); - dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]); - } - } - - return dest; + aiMesh *dest = new aiMesh(); + dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + if (!name.empty()) + dest->mName = name; + + // Material index + if (materialIndex != -1) + dest->mMaterialIndex = materialIndex; + + // Faces + dest->mNumFaces = indexData->faceCount; + dest->mFaces = new aiFace[dest->mNumFaces]; + + // Assimp required unique vertices, we need to convert from Ogres shared indexing. + size_t uniqueVertexCount = dest->mNumFaces * 3; + dest->mNumVertices = uniqueVertexCount; + dest->mVertices = new aiVector3D[dest->mNumVertices]; + + VertexDataXml *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData); + bool boneAssignments = src->HasBoneAssignments(); + bool normals = src->HasNormals(); + size_t uvs = src->NumUvs(); + + // Prepare normals + if (normals) + dest->mNormals = new aiVector3D[dest->mNumVertices]; + + // Prepare UVs + for(size_t uvi=0; uvi<uvs; ++uvi) + { + dest->mNumUVComponents[uvi] = 2; + dest->mTextureCoords[uvi] = new aiVector3D[dest->mNumVertices]; + } + + for (size_t fi=0; fi<dest->mNumFaces; ++fi) + { + // Source Ogre face + aiFace &ogreFace = indexData->faces[fi]; + + // Destination Assimp face + aiFace &face = dest->mFaces[fi]; + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + + const size_t pos = fi * 3; + for (size_t v=0; v<3; ++v) + { + const size_t newIndex = pos + v; + + // Write face index + face.mIndices[v] = newIndex; + + // Ogres vertex index to ref into the source buffers. + const size_t ogreVertexIndex = ogreFace.mIndices[v]; + src->AddVertexMapping(ogreVertexIndex, newIndex); + + // Position + dest->mVertices[newIndex] = src->positions[ogreVertexIndex]; + + // Normal + if (normals) + dest->mNormals[newIndex] = src->normals[ogreVertexIndex]; + + // UVs + for(size_t uvi=0; uvi<uvs; ++uvi) + { + aiVector3D *uvDest = dest->mTextureCoords[uvi]; + std::vector<aiVector3D> &uvSrc = src->uvs[uvi]; + uvDest[newIndex] = uvSrc[ogreVertexIndex]; + } + } + } + + // Bones and bone weights + if (parent->skeleton && boneAssignments) + { + AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices); + std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights(); + + dest->mNumBones = referencedBones.size(); + dest->mBones = new aiBone*[dest->mNumBones]; + + size_t assimpBoneIndex = 0; + for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex) + { + Bone *bone = parent->skeleton->BoneById((*rbIter)); + dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]); + } + } + + return dest; } // Animation Animation::Animation(Skeleton *parent) : - parentSkeleton(parent), - parentMesh(0), - length(0.0f), - baseTime(-1.0f) + parentMesh(NULL), + parentSkeleton(parent), + length(0.0f), + baseTime(-1.0f) { } -Animation::Animation(Mesh *parent) : - parentMesh(parent), - parentSkeleton(0), - length(0.0f), - baseTime(-1.0f) +Animation::Animation(Mesh *parent) : + parentMesh(parent), + parentSkeleton(0), + length(0.0f), + baseTime(-1.0f) { } VertexData *Animation::AssociatedVertexData(VertexAnimationTrack *track) const { - if (!parentMesh) - return 0; + if (!parentMesh) + return 0; - bool sharedGeom = (track->target == 0); - if (sharedGeom) - return parentMesh->sharedVertexData; - else - return parentMesh->GetSubMesh(track->target-1)->vertexData; + bool sharedGeom = (track->target == 0); + if (sharedGeom) + return parentMesh->sharedVertexData; + else + return parentMesh->GetSubMesh(track->target-1)->vertexData; } aiAnimation *Animation::ConvertToAssimpAnimation() { - aiAnimation *anim = new aiAnimation(); - anim->mName = name; - anim->mDuration = static_cast<double>(length); - anim->mTicksPerSecond = 1.0; - - // Tracks - if (!tracks.empty()) - { - anim->mNumChannels = tracks.size(); - anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; - - for(size_t i=0, len=tracks.size(); i<len; ++i) - { - anim->mChannels[i] = tracks[i].ConvertToAssimpAnimationNode(parentSkeleton); - } - } - return anim; + aiAnimation *anim = new aiAnimation(); + anim->mName = name; + anim->mDuration = static_cast<double>(length); + anim->mTicksPerSecond = 1.0; + + // Tracks + if (!tracks.empty()) + { + anim->mNumChannels = tracks.size(); + anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; + + for(size_t i=0, len=tracks.size(); i<len; ++i) + { + anim->mChannels[i] = tracks[i].ConvertToAssimpAnimationNode(parentSkeleton); + } + } + return anim; } // Skeleton Skeleton::Skeleton() : - blendMode(ANIMBLEND_AVERAGE) + bones(), + animations(), + blendMode(ANIMBLEND_AVERAGE) { } Skeleton::~Skeleton() { - Reset(); + Reset(); } void Skeleton::Reset() { - for(size_t i=0, len=bones.size(); i<len; ++i) { - OGRE_SAFE_DELETE(bones[i]) - } - bones.clear(); - for(size_t i=0, len=animations.size(); i<len; ++i) { - OGRE_SAFE_DELETE(animations[i]) - } - animations.clear(); + for(auto &bone : bones) { + OGRE_SAFE_DELETE(bone) + } + bones.clear(); + for(auto &anim : animations) { + OGRE_SAFE_DELETE(anim) + } + animations.clear(); } BoneList Skeleton::RootBones() const { - BoneList rootBones; - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { - if (!(*iter)->IsParented()) - rootBones.push_back((*iter)); - } - return rootBones; + BoneList rootBones; + for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) + { + if (!(*iter)->IsParented()) + rootBones.push_back((*iter)); + } + return rootBones; } size_t Skeleton::NumRootBones() const { - size_t num = 0; - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { - if (!(*iter)->IsParented()) - num++; - } - return num; + size_t num = 0; + for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) + { + if (!(*iter)->IsParented()) + num++; + } + return num; } Bone *Skeleton::BoneByName(const std::string &name) const { - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { - if ((*iter)->name == name) - return (*iter); - } - return 0; + for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) + { + if ((*iter)->name == name) + return (*iter); + } + return 0; } Bone *Skeleton::BoneById(uint16_t id) const { - for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) - { - if ((*iter)->id == id) - return (*iter); - } - return 0; + for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter) + { + if ((*iter)->id == id) + return (*iter); + } + return 0; } // Bone Bone::Bone() : - id(0), - parent(0), - parentId(-1), - scale(1.0f, 1.0f, 1.0f) + id(0), + parent(0), + parentId(-1), + scale(1.0f, 1.0f, 1.0f) { } bool Bone::IsParented() const { - return (parentId != -1 && parent != 0); + return (parentId != -1 && parent != 0); } uint16_t Bone::ParentId() const { - return static_cast<uint16_t>(parentId); + return static_cast<uint16_t>(parentId); } void Bone::AddChild(Bone *bone) { - if (!bone) - return; - if (bone->IsParented()) - throw DeadlyImportError("Attaching child Bone that is already parented: " + bone->name); - - bone->parent = this; - bone->parentId = id; - children.push_back(bone->id); + if (!bone) + return; + if (bone->IsParented()) + throw DeadlyImportError("Attaching child Bone that is already parented: " + bone->name); + + bone->parent = this; + bone->parentId = id; + children.push_back(bone->id); } void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton) { - if (!IsParented()) - worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse(); - else - worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse() * parent->worldMatrix; + if (!IsParented()) + worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse(); + else + worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse() * parent->worldMatrix; - defaultPose = aiMatrix4x4(scale, rotation, position); + defaultPose = aiMatrix4x4(scale, rotation, position); - // Recursively for all children now that the parent matrix has been calculated. - for (size_t i=0, len=children.size(); i<len; ++i) - { - Bone *child = skeleton->BoneById(children[i]); - if (!child) { - throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << children[i] << " for parent " << id << " " << name); - } - child->CalculateWorldMatrixAndDefaultPose(skeleton); - } + // Recursively for all children now that the parent matrix has been calculated. + for (auto boneId : children) + { + Bone *child = skeleton->BoneById(boneId); + if (!child) { + throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << boneId << " for parent " << id << " " << name); + } + child->CalculateWorldMatrixAndDefaultPose(skeleton); + } } aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode) { - // Bone node - aiNode* node = new aiNode(name); - node->mParent = parentNode; - node->mTransformation = defaultPose; - - // Children - if (!children.empty()) - { - node->mNumChildren = children.size(); - node->mChildren = new aiNode*[node->mNumChildren]; - - for(size_t i=0, len=children.size(); i<len; ++i) - { - Bone *child = skeleton->BoneById(children[i]); - if (!child) { - throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name); - } - node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node); - } - } - return node; -} - -aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights) -{ - aiBone *bone = new aiBone(); - bone->mName = name; - bone->mOffsetMatrix = worldMatrix; - - if (!boneWeights.empty()) - { - bone->mNumWeights = boneWeights.size(); - bone->mWeights = new aiVertexWeight[boneWeights.size()]; - memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight)); - } - - return bone; + // Bone node + aiNode* node = new aiNode(name); + node->mParent = parentNode; + node->mTransformation = defaultPose; + + // Children + if (!children.empty()) + { + node->mNumChildren = children.size(); + node->mChildren = new aiNode*[node->mNumChildren]; + + for(size_t i=0, len=children.size(); i<len; ++i) + { + Bone *child = skeleton->BoneById(children[i]); + if (!child) { + throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name); + } + node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node); + } + } + return node; +} + +aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVertexWeight> &boneWeights) +{ + aiBone *bone = new aiBone(); + bone->mName = name; + bone->mOffsetMatrix = worldMatrix; + + if (!boneWeights.empty()) + { + bone->mNumWeights = boneWeights.size(); + bone->mWeights = new aiVertexWeight[boneWeights.size()]; + memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight)); + } + + return bone; } // VertexAnimationTrack VertexAnimationTrack::VertexAnimationTrack() : - target(0), - type(VAT_NONE) + type(VAT_NONE), + target(0) { } aiNodeAnim *VertexAnimationTrack::ConvertToAssimpAnimationNode(Skeleton *skeleton) { - if (boneName.empty() || type != VAT_TRANSFORM) { - throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Cannot convert track that has no target bone name or is not type of VAT_TRANSFORM"); - } + if (boneName.empty() || type != VAT_TRANSFORM) { + throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Cannot convert track that has no target bone name or is not type of VAT_TRANSFORM"); + } + + aiNodeAnim *nodeAnim = new aiNodeAnim(); + nodeAnim->mNodeName = boneName; - aiNodeAnim *nodeAnim = new aiNodeAnim(); - nodeAnim->mNodeName = boneName; - - Bone *bone = skeleton->BoneByName(boneName); - if (!bone) { - throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton"); - } + Bone *bone = skeleton->BoneByName(boneName); + if (!bone) { + throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton"); + } - // Keyframes - size_t numKeyframes = transformKeyFrames.size(); + // Keyframes + size_t numKeyframes = transformKeyFrames.size(); - nodeAnim->mPositionKeys = new aiVectorKey[numKeyframes]; - nodeAnim->mRotationKeys = new aiQuatKey[numKeyframes]; - nodeAnim->mScalingKeys = new aiVectorKey[numKeyframes]; - nodeAnim->mNumPositionKeys = numKeyframes; - nodeAnim->mNumRotationKeys = numKeyframes; - nodeAnim->mNumScalingKeys = numKeyframes; + nodeAnim->mPositionKeys = new aiVectorKey[numKeyframes]; + nodeAnim->mRotationKeys = new aiQuatKey[numKeyframes]; + nodeAnim->mScalingKeys = new aiVectorKey[numKeyframes]; + nodeAnim->mNumPositionKeys = numKeyframes; + nodeAnim->mNumRotationKeys = numKeyframes; + nodeAnim->mNumScalingKeys = numKeyframes; - for(size_t kfi=0; kfi<numKeyframes; ++kfi) - { - TransformKeyFrame &kfSource = transformKeyFrames[kfi]; + for(size_t kfi=0; kfi<numKeyframes; ++kfi) + { + TransformKeyFrame &kfSource = transformKeyFrames[kfi]; - // Calculate the complete transformation from world space to bone space - aiVector3D pos; aiQuaternion rot; aiVector3D scale; + // Calculate the complete transformation from world space to bone space + aiVector3D pos; aiQuaternion rot; aiVector3D scale; - aiMatrix4x4 finalTransform = bone->defaultPose * kfSource.Transform(); - finalTransform.Decompose(scale, rot, pos); + aiMatrix4x4 finalTransform = bone->defaultPose * kfSource.Transform(); + finalTransform.Decompose(scale, rot, pos); - double t = static_cast<double>(kfSource.timePos); - nodeAnim->mPositionKeys[kfi].mTime = t; - nodeAnim->mRotationKeys[kfi].mTime = t; - nodeAnim->mScalingKeys[kfi].mTime = t; + double t = static_cast<double>(kfSource.timePos); + nodeAnim->mPositionKeys[kfi].mTime = t; + nodeAnim->mRotationKeys[kfi].mTime = t; + nodeAnim->mScalingKeys[kfi].mTime = t; - nodeAnim->mPositionKeys[kfi].mValue = pos; - nodeAnim->mRotationKeys[kfi].mValue = rot; - nodeAnim->mScalingKeys[kfi].mValue = scale; - } + nodeAnim->mPositionKeys[kfi].mValue = pos; + nodeAnim->mRotationKeys[kfi].mValue = rot; + nodeAnim->mScalingKeys[kfi].mValue = scale; + } - return nodeAnim; + return nodeAnim; } // TransformKeyFrame -TransformKeyFrame::TransformKeyFrame() : - timePos(0.0f), - scale(1.0f, 1.0f, 1.0f) +TransformKeyFrame::TransformKeyFrame() : + timePos(0.0f), + scale(1.0f, 1.0f, 1.0f) { } aiMatrix4x4 TransformKeyFrame::Transform() { - return aiMatrix4x4(scale, rotation, position); + return aiMatrix4x4(scale, rotation, position); } } // Ogre |