1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204 |
- /*
- Open Asset Import Library (assimp)
- ----------------------------------------------------------------------
- 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
- following conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of the assimp team, nor the names of its
- contributors may be used to endorse or promote products
- 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
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- 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
- 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
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ----------------------------------------------------------------------
- */
- #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
- #include "OgreStructs.h"
- #include "TinyFormatter.h"
- #include <assimp/scene.h>
- #include <assimp/DefaultLogger.hpp>
- #include "Exceptional.h"
- namespace Assimp
- {
- namespace Ogre
- {
- // VertexElement
- VertexElement::VertexElement() :
- index(0),
- source(0),
- offset(0),
- type(VET_FLOAT1),
- semantic(VES_POSITION)
- {
- }
- size_t VertexElement::Size() const
- {
- return TypeSize(type);
- }
- size_t VertexElement::ComponentCount() const
- {
- 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;
- }
- 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;
- }
- std::string VertexElement::TypeToString()
- {
- 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";
- }
- std::string VertexElement::SemanticToString()
- {
- 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";
- }
- // IVertexData
- IVertexData::IVertexData() :
- count(0)
- {
- }
- bool IVertexData::HasBoneAssignments() const
- {
- return !boneAssignments.empty();
- }
- void IVertexData::AddVertexMapping(uint32_t oldIndex, uint32_t newIndex)
- {
- BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]);
- vertexIndexMapping[oldIndex].push_back(newIndex);
- }
- void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const
- {
- 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;
- }
- std::set<uint16_t> IVertexData::ReferencedBonesByWeights() const
- {
- std::set<uint16_t> referenced;
- for (const auto &boneAssign : boneAssignments)
- {
- referenced.insert(boneAssign.boneIndex);
- }
- return referenced;
- }
- // VertexData
- VertexData::VertexData()
- {
- }
- VertexData::~VertexData()
- {
- Reset();
- }
- void VertexData::Reset()
- {
- // Releases shared ptr memory streams.
- vertexBindings.clear();
- vertexElements.clear();
- }
- uint32_t VertexData::VertexSize(uint16_t source) const
- {
- 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;
- }
- VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index)
- {
- for(auto & element : vertexElements)
- {
- if (element.semantic == semantic && element.index == index)
- return &element;
- }
- return 0;
- }
- // VertexDataXml
- VertexDataXml::VertexDataXml()
- {
- }
- bool VertexDataXml::HasPositions() const
- {
- return !positions.empty();
- }
- bool VertexDataXml::HasNormals() const
- {
- return !normals.empty();
- }
- bool VertexDataXml::HasTangents() const
- {
- return !tangents.empty();
- }
- bool VertexDataXml::HasUvs() const
- {
- return !uvs.empty();
- }
- size_t VertexDataXml::NumUvs() const
- {
- return uvs.size();
- }
- // IndexData
- IndexData::IndexData() :
- count(0),
- faceCount(0),
- is32bit(false)
- {
- }
- IndexData::~IndexData()
- {
- Reset();
- }
- void IndexData::Reset()
- {
- // Release shared ptr memory stream.
- buffer.reset();
- }
- size_t IndexData::IndexSize() const
- {
- return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
- }
- size_t IndexData::FaceSize() const
- {
- return IndexSize() * 3;
- }
- // Mesh
- Mesh::Mesh()
- : hasSkeletalAnimations(false)
- , skeleton(NULL)
- , sharedVertexData(NULL)
- , subMeshes()
- , animations()
- , poses()
- {
- }
- Mesh::~Mesh()
- {
- Reset();
- }
- void Mesh::Reset()
- {
- OGRE_SAFE_DELETE(skeleton)
- OGRE_SAFE_DELETE(sharedVertexData)
- 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();
- }
- 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;
- }
- void Mesh::ConvertToAssimpScene(aiScene* dest)
- {
- 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)
- {
- }
- // SubMesh
- SubMesh::SubMesh() :
- vertexData(0),
- indexData(new IndexData())
- {
- }
- SubMesh::~SubMesh()
- {
- Reset();
- }
- void SubMesh::Reset()
- {
- 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;
- }
- // MeshXml
- MeshXml::MeshXml() :
- skeleton(0),
- sharedVertexData(0)
- {
- }
- MeshXml::~MeshXml()
- {
- Reset();
- }
- void MeshXml::Reset()
- {
- OGRE_SAFE_DELETE(skeleton)
- OGRE_SAFE_DELETE(sharedVertexData)
- for(auto &mesh : subMeshes) {
- OGRE_SAFE_DELETE(mesh)
- }
- subMeshes.clear();
- }
- size_t MeshXml::NumSubMeshes() const
- {
- 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;
- }
- 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();
- }
- }
- }
- }
- // SubMeshXml
- SubMeshXml::SubMeshXml() :
- indexData(new IndexDataXml()),
- vertexData(0)
- {
- }
- SubMeshXml::~SubMeshXml()
- {
- Reset();
- }
- void SubMeshXml::Reset()
- {
- 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;
- }
- // Animation
- Animation::Animation(Skeleton *parent) :
- parentMesh(NULL),
- parentSkeleton(parent),
- 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;
- 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;
- }
- // Skeleton
- Skeleton::Skeleton() :
- bones(),
- animations(),
- blendMode(ANIMBLEND_AVERAGE)
- {
- }
- Skeleton::~Skeleton()
- {
- Reset();
- }
- void Skeleton::Reset()
- {
- 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;
- }
- 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;
- }
- 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;
- }
- 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;
- }
- // Bone
- Bone::Bone() :
- id(0),
- parent(0),
- parentId(-1),
- scale(1.0f, 1.0f, 1.0f)
- {
- }
- bool Bone::IsParented() const
- {
- return (parentId != -1 && parent != 0);
- }
- uint16_t Bone::ParentId() const
- {
- 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);
- }
- void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton)
- {
- if (!IsParented())
- worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse();
- else
- worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse() * parent->worldMatrix;
- defaultPose = aiMatrix4x4(scale, rotation, position);
- // 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;
- }
- // VertexAnimationTrack
- VertexAnimationTrack::VertexAnimationTrack() :
- 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");
- }
- 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");
- }
- // 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;
- 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;
- 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;
- nodeAnim->mPositionKeys[kfi].mValue = pos;
- nodeAnim->mRotationKeys[kfi].mValue = rot;
- nodeAnim->mScalingKeys[kfi].mValue = scale;
- }
- return nodeAnim;
- }
- // TransformKeyFrame
- TransformKeyFrame::TransformKeyFrame() :
- timePos(0.0f),
- scale(1.0f, 1.0f, 1.0f)
- {
- }
- aiMatrix4x4 TransformKeyFrame::Transform()
- {
- return aiMatrix4x4(scale, rotation, position);
- }
- } // Ogre
- } // Assimp
- #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
|