OgreImporter: Cleanup skeleton related code and code that populates the assimp scene. Tested skeleton/animation imports and it seems to work correctly now.
parent
f5c7b283bc
commit
283394d695
|
@ -69,6 +69,18 @@ namespace Assimp
|
|||
namespace Ogre
|
||||
{
|
||||
|
||||
const aiImporterDesc* OgreImporter::GetInfo() const
|
||||
{
|
||||
return &desc;
|
||||
}
|
||||
|
||||
|
||||
void OgreImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
||||
m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
|
||||
}
|
||||
|
||||
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
|
||||
{
|
||||
if (!checkSig)
|
||||
|
@ -127,7 +139,7 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
|||
if (!CurrentNodeNameEquals(reader, nnSubMeshes))
|
||||
throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
|
||||
|
||||
list<boost::shared_ptr<SubMesh> > subMeshes;
|
||||
vector<boost::shared_ptr<SubMesh> > subMeshes;
|
||||
vector<aiMaterial*> materials;
|
||||
|
||||
NextNode(reader.get());
|
||||
|
@ -195,48 +207,33 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
|||
|
||||
// -------------------- Apply to aiScene --------------------
|
||||
|
||||
//put the aiMaterials in the scene:
|
||||
pScene->mMaterials=new aiMaterial*[materials.size()];
|
||||
pScene->mNumMaterials=materials.size();
|
||||
for(unsigned int i=0; i<materials.size(); ++i)
|
||||
pScene->mMaterials[i]=materials[i];
|
||||
// Materials
|
||||
pScene->mMaterials = new aiMaterial*[materials.size()];
|
||||
pScene->mNumMaterials = materials.size();
|
||||
|
||||
//create the aiMehs...
|
||||
vector<aiMesh*> aiMeshes;
|
||||
BOOST_FOREACH(boost::shared_ptr<SubMesh> theSubMesh, subMeshes)
|
||||
for(size_t i=0, len=materials.size(); i<len; ++i)
|
||||
pScene->mMaterials[i] = materials[i];
|
||||
|
||||
// Meshes
|
||||
pScene->mMeshes = new aiMesh*[subMeshes.size()];
|
||||
pScene->mNumMeshes = subMeshes.size();
|
||||
|
||||
for(size_t i=0, len=subMeshes.size(); i<len; ++i)
|
||||
{
|
||||
aiMeshes.push_back(CreateAssimpSubMesh(pScene, *theSubMesh, Bones));
|
||||
boost::shared_ptr<SubMesh> submesh = subMeshes[i];
|
||||
pScene->mMeshes[i] = CreateAssimpSubMesh(pScene, *(submesh.get()), Bones);
|
||||
}
|
||||
//... and put them in the scene:
|
||||
pScene->mNumMeshes=aiMeshes.size();
|
||||
pScene->mMeshes=new aiMesh*[aiMeshes.size()];
|
||||
memcpy(pScene->mMeshes, &(aiMeshes[0]), sizeof(aiMeshes[0])*aiMeshes.size());
|
||||
|
||||
//Create the root node
|
||||
pScene->mRootNode=new aiNode("root");
|
||||
|
||||
//link the meshs with the root node:
|
||||
pScene->mRootNode->mMeshes=new unsigned int[subMeshes.size()];
|
||||
pScene->mRootNode->mNumMeshes=subMeshes.size();
|
||||
// Create the root node
|
||||
pScene->mRootNode = new aiNode();
|
||||
pScene->mRootNode->mMeshes = new unsigned int[subMeshes.size()];
|
||||
pScene->mRootNode->mNumMeshes = subMeshes.size();
|
||||
|
||||
for(unsigned int i=0; i<subMeshes.size(); ++i)
|
||||
pScene->mRootNode->mMeshes[i]=i;
|
||||
for(size_t i=0, len=subMeshes.size(); i<len; ++i)
|
||||
pScene->mRootNode->mMeshes[i] = static_cast<unsigned int>(i);
|
||||
|
||||
// Skeleton and animations
|
||||
CreateAssimpSkeleton(pScene, Bones, Animations);
|
||||
PutAnimationsInScene(pScene, Bones, Animations);
|
||||
}
|
||||
|
||||
|
||||
const aiImporterDesc* OgreImporter::GetInfo () const
|
||||
{
|
||||
return &desc;
|
||||
}
|
||||
|
||||
|
||||
void OgreImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
||||
m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
|
||||
}
|
||||
|
||||
} // Ogre
|
||||
|
|
|
@ -71,16 +71,16 @@ class OgreImporter : public BaseImporter
|
|||
{
|
||||
public:
|
||||
/// BaseImporter override.
|
||||
virtual bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
|
||||
virtual bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
|
||||
|
||||
/// BaseImporter override.
|
||||
virtual void InternReadFile(const std::string &pFile, aiScene* pScene, IOSystem* pIOHandler);
|
||||
virtual void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
|
||||
|
||||
/// BaseImporter override.
|
||||
virtual const aiImporterDesc* GetInfo () const;
|
||||
virtual const aiImporterDesc *GetInfo() const;
|
||||
|
||||
/// BaseImporter override.
|
||||
virtual void SetupProperties(const Importer* pImp);
|
||||
virtual void SetupProperties(const Importer *pImp);
|
||||
|
||||
private:
|
||||
//-------------------------------- OgreMesh.cpp -------------------------------
|
||||
|
@ -98,7 +98,7 @@ private:
|
|||
static void ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry);
|
||||
|
||||
/// Uses the bone data to convert a SubMesh into a aiMesh which will be created and returned.
|
||||
aiMesh* CreateAssimpSubMesh(aiScene *pScene, const SubMesh &submesh, const std::vector<Bone>& bones) const;
|
||||
aiMesh *CreateAssimpSubMesh(aiScene *pScene, const SubMesh &submesh, const std::vector<Bone> &bones) const;
|
||||
|
||||
//-------------------------------- OgreSkeleton.cpp -------------------------------
|
||||
|
||||
|
@ -110,10 +110,10 @@ private:
|
|||
void PutAnimationsInScene(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
||||
|
||||
/// Creates the aiSkeleton in current scene.
|
||||
void CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
||||
void CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &bones, const std::vector<Animation> &animations);
|
||||
|
||||
/// Recursivly creates a filled aiNode from a given root bone.
|
||||
static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
|
||||
/// Recursively creates a filled aiNode from a given root bone.
|
||||
static aiNode* CreateNodeFromBone(int boneId, const std::vector<Bone> &bones, aiNode *parent);
|
||||
|
||||
//-------------------------------- OgreMaterial.cpp -------------------------------
|
||||
|
||||
|
@ -131,7 +131,8 @@ private:
|
|||
std::string m_userDefinedMaterialLibFile;
|
||||
bool m_detectTextureTypeFromFilename;
|
||||
|
||||
SubMesh m_SharedGeometry;///< we will just use the vertexbuffers of the submesh
|
||||
/// VertexBuffer for the sub meshes that use shader geometry.
|
||||
SubMesh m_SharedGeometry;
|
||||
|
||||
std::map<aiTextureType, unsigned int> m_textures;
|
||||
};
|
||||
|
|
|
@ -442,110 +442,103 @@ void OgreImporter::ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry)
|
|||
//_________________________________________________________
|
||||
}
|
||||
|
||||
aiMesh* OgreImporter::CreateAssimpSubMesh(aiScene *pScene, const SubMesh& submesh, const vector<Bone>& bones) const
|
||||
aiMesh *OgreImporter::CreateAssimpSubMesh(aiScene *pScene, const SubMesh& submesh, const vector<Bone>& bones) const
|
||||
{
|
||||
aiMesh* NewAiMesh = new aiMesh();
|
||||
|
||||
//Positions
|
||||
NewAiMesh->mVertices=new aiVector3D[submesh.Positions.size()];
|
||||
memcpy(NewAiMesh->mVertices, &submesh.Positions[0], submesh.Positions.size()*sizeof(aiVector3D));
|
||||
NewAiMesh->mNumVertices=submesh.Positions.size();
|
||||
const size_t sizeVector3D = sizeof(aiVector3D);
|
||||
|
||||
//Normals
|
||||
if(submesh.HasNormals)
|
||||
aiMesh *dest = new aiMesh();
|
||||
|
||||
// Material
|
||||
dest->mMaterialIndex = submesh.MaterialIndex;
|
||||
|
||||
// Positions
|
||||
dest->mVertices = new aiVector3D[submesh.Positions.size()];
|
||||
dest->mNumVertices = submesh.Positions.size();
|
||||
memcpy(dest->mVertices, &submesh.Positions[0], submesh.Positions.size() * sizeVector3D);
|
||||
|
||||
// Normals
|
||||
if (submesh.HasNormals)
|
||||
{
|
||||
NewAiMesh->mNormals=new aiVector3D[submesh.Normals.size()];
|
||||
memcpy(NewAiMesh->mNormals, &submesh.Normals[0], submesh.Normals.size()*sizeof(aiVector3D));
|
||||
dest->mNormals = new aiVector3D[submesh.Normals.size()];
|
||||
memcpy(dest->mNormals, &submesh.Normals[0], submesh.Normals.size() * sizeVector3D);
|
||||
}
|
||||
|
||||
// Tangents
|
||||
// Until we have support for bitangents, no tangents will be written
|
||||
/// @todo Investigate why the above?
|
||||
if (submesh.HasTangents)
|
||||
{
|
||||
DefaultLogger::get()->warn("Tangents found from Ogre mesh but writing to Assimp mesh not yet supported!");
|
||||
//dest->mTangents = new aiVector3D[submesh.Tangents.size()];
|
||||
//memcpy(dest->mTangents, &submesh.Tangents[0], submesh.Tangents.size() * sizeVector3D);
|
||||
}
|
||||
|
||||
|
||||
//until we have support for bitangents, no tangents will be written
|
||||
/*
|
||||
//Tangents
|
||||
if(submesh.HasTangents)
|
||||
// UVs
|
||||
for (size_t i=0, len=submesh.Uvs.size(); i<len; ++i)
|
||||
{
|
||||
NewAiMesh->mTangents=new aiVector3D[submesh.Tangents.size()];
|
||||
memcpy(NewAiMesh->mTangents, &submesh.Tangents[0], submesh.Tangents.size()*sizeof(aiVector3D));
|
||||
dest->mNumUVComponents[i] = 2;
|
||||
dest->mTextureCoords[i] = new aiVector3D[submesh.Uvs[i].size()];
|
||||
memcpy(dest->mTextureCoords[i], &(submesh.Uvs[i][0]), submesh.Uvs[i].size() * sizeVector3D);
|
||||
}
|
||||
*/
|
||||
|
||||
//Uvs
|
||||
if(submesh.Uvs.size()>0)
|
||||
// Bone weights. Convert internal vertex-to-bone mapping to bone-to-vertex.
|
||||
vector<vector<aiVertexWeight> > assimpWeights(submesh.BonesUsed);
|
||||
for(size_t vertexId=0, len=submesh.Weights.size(); vertexId<len; ++vertexId)
|
||||
{
|
||||
for(unsigned int i=0; i<submesh.Uvs.size(); ++i)
|
||||
const vector<BoneWeight> &vertexWeights = submesh.Weights[vertexId];
|
||||
for (size_t boneId=0, len=vertexWeights.size(); boneId<len; ++boneId)
|
||||
{
|
||||
NewAiMesh->mNumUVComponents[i]=2;
|
||||
NewAiMesh->mTextureCoords[i]=new aiVector3D[submesh.Uvs[i].size()];
|
||||
memcpy(NewAiMesh->mTextureCoords[i], &(submesh.Uvs[i][0]), submesh.Uvs[i].size()*sizeof(aiVector3D));
|
||||
const BoneWeight &ogreWeight = vertexWeights[boneId];
|
||||
assimpWeights[ogreWeight.Id].push_back(aiVertexWeight(vertexId, ogreWeight.Value));
|
||||
}
|
||||
}
|
||||
|
||||
// Bones.
|
||||
vector<aiBone*> assimpBones;
|
||||
assimpBones.reserve(submesh.BonesUsed);
|
||||
|
||||
//---------------------------------------- bones --------------------------------------------
|
||||
|
||||
//Copy the weights in in Bone-Vertices Struktur
|
||||
//(we have them in a Vertex-bones Structur, this is much easier for making them unique, which is required by assimp
|
||||
vector< vector<aiVertexWeight> > aiWeights(submesh.BonesUsed);//now the outer list are the bones, and the inner vector the vertices
|
||||
for(unsigned int VertexId=0; VertexId<submesh.Weights.size(); ++VertexId)//iterate over all vertices
|
||||
for(size_t boneId=0, len=submesh.BonesUsed; boneId<len; ++boneId)
|
||||
{
|
||||
for(unsigned int BoneId=0; BoneId<submesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
|
||||
{
|
||||
aiVertexWeight NewWeight;
|
||||
NewWeight.mVertexId=VertexId;//the current Vertex, we can't use the Id form the submehs weights, because they are bone id's
|
||||
NewWeight.mWeight=submesh.Weights[VertexId][BoneId].Value;
|
||||
aiWeights[submesh.Weights[VertexId][BoneId].Id].push_back(NewWeight);
|
||||
}
|
||||
const vector<aiVertexWeight> &boneWeights = assimpWeights[boneId];
|
||||
if (boneWeights.size() == 0)
|
||||
continue;
|
||||
|
||||
// @note The bones list is sorted by id's, this was done in LoadSkeleton.
|
||||
aiBone *assimpBone = new aiBone();
|
||||
assimpBone->mName = bones[boneId].Name;
|
||||
assimpBone->mOffsetMatrix = bones[boneId].BoneToWorldSpace;
|
||||
assimpBone->mNumWeights = boneWeights.size();
|
||||
assimpBone->mWeights = new aiVertexWeight[boneWeights.size()];
|
||||
memcpy(assimpBone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight));
|
||||
|
||||
assimpBones.push_back(assimpBone);
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<aiBone*> aiBones;
|
||||
aiBones.reserve(submesh.BonesUsed);//the vector might be smaller, because there might be empty bones (bones that are not attached to any vertex)
|
||||
|
||||
//create all the bones and fill them with informations
|
||||
for(unsigned int i=0; i<submesh.BonesUsed; ++i)
|
||||
if (!assimpBones.empty())
|
||||
{
|
||||
if(aiWeights[i].size()>0)
|
||||
{
|
||||
aiBone* NewBone=new aiBone();
|
||||
NewBone->mNumWeights=aiWeights[i].size();
|
||||
NewBone->mWeights=new aiVertexWeight[aiWeights[i].size()];
|
||||
memcpy(NewBone->mWeights, &(aiWeights[i][0]), sizeof(aiVertexWeight)*aiWeights[i].size());
|
||||
NewBone->mName=bones[i].Name;//The bone list should be sorted after its id's, this was done in LoadSkeleton
|
||||
NewBone->mOffsetMatrix=bones[i].BoneToWorldSpace;
|
||||
|
||||
aiBones.push_back(NewBone);
|
||||
}
|
||||
}
|
||||
NewAiMesh->mNumBones=aiBones.size();
|
||||
|
||||
// mBones must be NULL if mNumBones is non 0 or the validation fails.
|
||||
if (aiBones.size()) {
|
||||
NewAiMesh->mBones=new aiBone* [aiBones.size()];
|
||||
memcpy(NewAiMesh->mBones, &(aiBones[0]), aiBones.size()*sizeof(aiBone*));
|
||||
dest->mBones = new aiBone*[assimpBones.size()];
|
||||
dest->mNumBones = assimpBones.size();
|
||||
|
||||
for(size_t i=0, len=assimpBones.size(); i<len; ++i)
|
||||
dest->mBones[i] = assimpBones[i];
|
||||
}
|
||||
|
||||
//______________________________________________________________________________________________________
|
||||
// Faces
|
||||
dest->mFaces = new aiFace[submesh.Faces.size()];
|
||||
dest->mNumFaces = submesh.Faces.size();
|
||||
|
||||
|
||||
|
||||
//Faces
|
||||
NewAiMesh->mFaces=new aiFace[submesh.Faces.size()];
|
||||
for(unsigned int i=0; i<submesh.Faces.size(); ++i)
|
||||
for(size_t i=0, len=submesh.Faces.size(); i<len; ++i)
|
||||
{
|
||||
NewAiMesh->mFaces[i].mNumIndices=3;
|
||||
NewAiMesh->mFaces[i].mIndices=new unsigned int[3];
|
||||
dest->mFaces[i].mNumIndices = 3;
|
||||
dest->mFaces[i].mIndices = new unsigned int[3];
|
||||
|
||||
NewAiMesh->mFaces[i].mIndices[0]=submesh.Faces[i].VertexIndices[0];
|
||||
NewAiMesh->mFaces[i].mIndices[1]=submesh.Faces[i].VertexIndices[1];
|
||||
NewAiMesh->mFaces[i].mIndices[2]=submesh.Faces[i].VertexIndices[2];
|
||||
const Face &f = submesh.Faces[i];
|
||||
dest->mFaces[i].mIndices[0] = f.VertexIndices[0];
|
||||
dest->mFaces[i].mIndices[1] = f.VertexIndices[1];
|
||||
dest->mFaces[i].mIndices[2] = f.VertexIndices[2];
|
||||
}
|
||||
NewAiMesh->mNumFaces=submesh.Faces.size();
|
||||
|
||||
//Link the material:
|
||||
NewAiMesh->mMaterialIndex=submesh.MaterialIndex;//the index is set by the function who called ReadSubMesh
|
||||
|
||||
return NewAiMesh;
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // Ogre
|
||||
|
|
|
@ -5,11 +5,11 @@ Open Asset Import Library (assimp)
|
|||
Copyright (c) 2006-2012, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
Redistribution and use of this software in aSource and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
* Redistributions of aSource code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
|
@ -254,143 +254,146 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
|||
}
|
||||
}
|
||||
|
||||
void OgreImporter::CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &/*Animations*/)
|
||||
void OgreImporter::CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &bones, const std::vector<Animation> &animations)
|
||||
{
|
||||
if(!pScene->mRootNode)
|
||||
throw DeadlyImportError("No root node exists!!");
|
||||
if(0!=pScene->mRootNode->mNumChildren)
|
||||
throw DeadlyImportError("Root Node already has childnodes!");
|
||||
if (bones.empty())
|
||||
return;
|
||||
|
||||
if (!pScene->mRootNode)
|
||||
throw DeadlyImportError("Creating Assimp skeleton: No root node created!");
|
||||
if (pScene->mRootNode->mNumChildren > 0)
|
||||
throw DeadlyImportError("Creating Assimp skeleton: Root node already has children!");
|
||||
|
||||
//Createt the assimp bone hierarchy
|
||||
vector<aiNode*> RootBoneNodes;
|
||||
BOOST_FOREACH(const Bone &theBone, Bones)
|
||||
// Bones
|
||||
vector<aiNode*> rootBones;
|
||||
BOOST_FOREACH(const Bone &bone, bones)
|
||||
{
|
||||
if(-1==theBone.ParentId) //the bone is a root bone
|
||||
{
|
||||
//which will recursily add all other nodes
|
||||
RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, pScene->mRootNode));
|
||||
}
|
||||
if (!bone.IsParented())
|
||||
rootBones.push_back(CreateNodeFromBone(bone.Id, bones, pScene->mRootNode));
|
||||
}
|
||||
|
||||
if(RootBoneNodes.size() > 0)
|
||||
if (!rootBones.empty())
|
||||
{
|
||||
pScene->mRootNode->mNumChildren=RootBoneNodes.size();
|
||||
pScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()];
|
||||
memcpy(pScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size());
|
||||
}
|
||||
}
|
||||
pScene->mRootNode->mChildren = new aiNode*[rootBones.size()];
|
||||
pScene->mRootNode->mNumChildren = rootBones.size();
|
||||
|
||||
for(size_t i=0, len=rootBones.size(); i<len; ++i)
|
||||
pScene->mRootNode->mChildren[i] = rootBones[i];
|
||||
}
|
||||
|
||||
void OgreImporter::PutAnimationsInScene(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &Animations)
|
||||
{
|
||||
// TODO: Auf nicht vorhandene Animationskeys achten!
|
||||
// @todo Pay attention to non-existing animation Keys (google translated from above german comment)
|
||||
|
||||
if(Animations.size()>0)//Maybe the model had only a skeleton and no animations. (If it also has no skeleton, this function would'nt have been called
|
||||
|
||||
// Animations
|
||||
if (!animations.empty())
|
||||
{
|
||||
pScene->mNumAnimations=Animations.size();
|
||||
pScene->mAnimations=new aiAnimation*[Animations.size()];
|
||||
for(unsigned int i=0; i<Animations.size(); ++i)//create all animations
|
||||
pScene->mAnimations = new aiAnimation*[animations.size()];
|
||||
pScene->mNumAnimations = animations.size();
|
||||
|
||||
for(size_t ai=0, alen=animations.size(); ai<alen; ++ai)
|
||||
{
|
||||
aiAnimation* NewAnimation=new aiAnimation();
|
||||
NewAnimation->mName=Animations[i].Name;
|
||||
NewAnimation->mDuration=Animations[i].Length;
|
||||
NewAnimation->mTicksPerSecond=1.0f;
|
||||
const Animation &aSource = animations[ai];
|
||||
|
||||
//Create all tracks in this animation
|
||||
NewAnimation->mNumChannels=Animations[i].Tracks.size();
|
||||
NewAnimation->mChannels=new aiNodeAnim*[Animations[i].Tracks.size()];
|
||||
for(unsigned int j=0; j<Animations[i].Tracks.size(); ++j)
|
||||
aiAnimation *animation = new aiAnimation();
|
||||
animation->mName = aSource.Name;
|
||||
animation->mDuration = aSource.Length;
|
||||
animation->mTicksPerSecond = 1.0f;
|
||||
|
||||
// Tracks
|
||||
animation->mChannels = new aiNodeAnim*[aSource.Tracks.size()];
|
||||
animation->mNumChannels = aSource.Tracks.size();
|
||||
|
||||
for(size_t ti=0, tlen=aSource.Tracks.size(); ti<tlen; ++ti)
|
||||
{
|
||||
aiNodeAnim* NewNodeAnim=new aiNodeAnim();
|
||||
NewNodeAnim->mNodeName=Animations[i].Tracks[j].BoneName;
|
||||
const Track &tSource = aSource.Tracks[ti];
|
||||
|
||||
//we need this, to acces the bones default pose, which we need to make keys absolute to the default bone pose
|
||||
vector<Bone>::const_iterator CurBone=find(Bones.begin(), Bones.end(), NewNodeAnim->mNodeName);
|
||||
aiMatrix4x4 t0, t1;
|
||||
aiMatrix4x4 DefBonePose=aiMatrix4x4::Translation(CurBone->Position, t1)
|
||||
* aiMatrix4x4::Rotation(CurBone->RotationAngle, CurBone->RotationAxis, t0);
|
||||
|
||||
aiNodeAnim *animationNode = new aiNodeAnim();
|
||||
animationNode->mNodeName = tSource.BoneName;
|
||||
|
||||
//Create the keyframe arrays...
|
||||
unsigned int KeyframeCount=Animations[i].Tracks[j].Keyframes.size();
|
||||
NewNodeAnim->mNumPositionKeys=KeyframeCount;
|
||||
NewNodeAnim->mNumRotationKeys=KeyframeCount;
|
||||
NewNodeAnim->mNumScalingKeys =KeyframeCount;
|
||||
NewNodeAnim->mPositionKeys=new aiVectorKey[KeyframeCount];
|
||||
NewNodeAnim->mRotationKeys=new aiQuatKey[KeyframeCount];
|
||||
NewNodeAnim->mScalingKeys =new aiVectorKey[KeyframeCount];
|
||||
|
||||
//...and fill them
|
||||
for(unsigned int k=0; k<KeyframeCount; ++k)
|
||||
// We need this, to access the bones default pose.
|
||||
// Which we need to make keys absolute to the default bone pose.
|
||||
vector<Bone>::const_iterator boneIter = find(bones.begin(), bones.end(), tSource.BoneName);
|
||||
if (boneIter == bones.end())
|
||||
{
|
||||
aiMatrix4x4 t2, t3;
|
||||
|
||||
//Create a matrix to transfrom a vector from the bones default pose to the bone bones in this animation key
|
||||
aiMatrix4x4 PoseToKey=
|
||||
aiMatrix4x4::Translation(Animations[i].Tracks[j].Keyframes[k].Position, t3) //pos
|
||||
* aiMatrix4x4(Animations[i].Tracks[j].Keyframes[k].Rotation.GetMatrix()) //rot
|
||||
* aiMatrix4x4::Scaling(Animations[i].Tracks[j].Keyframes[k].Scaling, t2); //scale
|
||||
|
||||
|
||||
//calculate the complete transformation from world space to bone space
|
||||
aiMatrix4x4 CompleteTransform=DefBonePose * PoseToKey;
|
||||
for(unsigned int a=0; a<ai; a++)
|
||||
delete pScene->mAnimations[a];
|
||||
delete [] pScene->mAnimations;
|
||||
pScene->mAnimations = NULL;
|
||||
pScene->mNumAnimations = 0;
|
||||
|
||||
aiVector3D Pos;
|
||||
aiQuaternion Rot;
|
||||
aiVector3D Scale;
|
||||
|
||||
CompleteTransform.Decompose(Scale, Rot, Pos);
|
||||
|
||||
double Time=Animations[i].Tracks[j].Keyframes[k].Time;
|
||||
|
||||
NewNodeAnim->mPositionKeys[k].mTime=Time;
|
||||
NewNodeAnim->mPositionKeys[k].mValue=Pos;
|
||||
|
||||
NewNodeAnim->mRotationKeys[k].mTime=Time;
|
||||
NewNodeAnim->mRotationKeys[k].mValue=Rot;
|
||||
|
||||
NewNodeAnim->mScalingKeys[k].mTime=Time;
|
||||
NewNodeAnim->mScalingKeys[k].mValue=Scale;
|
||||
DefaultLogger::get()->error("Failed to find bone for name " + tSource.BoneName + " when creating animation " + aSource.Name +
|
||||
". This is a serious error, animations wont be imported.");
|
||||
return;
|
||||
}
|
||||
|
||||
NewAnimation->mChannels[j]=NewNodeAnim;
|
||||
}
|
||||
|
||||
pScene->mAnimations[i]=NewAnimation;
|
||||
aiMatrix4x4 t0, t1;
|
||||
aiMatrix4x4 defaultBonePose = aiMatrix4x4::Translation(boneIter->Position, t1) * aiMatrix4x4::Rotation(boneIter->RotationAngle, boneIter->RotationAxis, t0);
|
||||
|
||||
// Keyframes
|
||||
unsigned int numKeyframes = tSource.Keyframes.size();
|
||||
|
||||
animationNode->mPositionKeys = new aiVectorKey[numKeyframes];
|
||||
animationNode->mRotationKeys = new aiQuatKey[numKeyframes];
|
||||
animationNode->mScalingKeys = new aiVectorKey[numKeyframes];
|
||||
animationNode->mNumPositionKeys = numKeyframes;
|
||||
animationNode->mNumRotationKeys = numKeyframes;
|
||||
animationNode->mNumScalingKeys = numKeyframes;
|
||||
|
||||
//...and fill them
|
||||
for(size_t kfi=0; kfi<numKeyframes; ++kfi)
|
||||
{
|
||||
const KeyFrame &kfSource = tSource.Keyframes[kfi];
|
||||
|
||||
// Create a matrix to transform a vector from the bones
|
||||
// default pose to the bone bones in this animation key
|
||||
aiMatrix4x4 t2, t3;
|
||||
aiMatrix4x4 keyBonePose =
|
||||
aiMatrix4x4::Translation(kfSource.Position, t3) *
|
||||
aiMatrix4x4(kfSource.Rotation.GetMatrix()) *
|
||||
aiMatrix4x4::Scaling(kfSource.Scaling, t2);
|
||||
|
||||
// Calculate the complete transformation from world space to bone space
|
||||
aiMatrix4x4 CompleteTransform = defaultBonePose * keyBonePose;
|
||||
|
||||
aiVector3D kfPos; aiQuaternion kfRot; aiVector3D kfScale;
|
||||
CompleteTransform.Decompose(kfScale, kfRot, kfPos);
|
||||
|
||||
animationNode->mPositionKeys[kfi].mTime = static_cast<double>(kfSource.Time);
|
||||
animationNode->mRotationKeys[kfi].mTime = static_cast<double>(kfSource.Time);
|
||||
animationNode->mScalingKeys[kfi].mTime = static_cast<double>(kfSource.Time);
|
||||
|
||||
animationNode->mPositionKeys[kfi].mValue = kfPos;
|
||||
animationNode->mRotationKeys[kfi].mValue = kfRot;
|
||||
animationNode->mScalingKeys[kfi].mValue = kfScale;
|
||||
}
|
||||
animation->mChannels[ti] = animationNode;
|
||||
}
|
||||
pScene->mAnimations[ai] = animation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode)
|
||||
aiNode* OgreImporter::CreateNodeFromBone(int boneId, const std::vector<Bone> &bones, aiNode* parent)
|
||||
{
|
||||
//----Create the node for this bone and set its values-----
|
||||
aiNode* NewNode=new aiNode(Bones[BoneId].Name);
|
||||
NewNode->mParent=ParentNode;
|
||||
|
||||
aiMatrix4x4 t0,t1;
|
||||
NewNode->mTransformation=
|
||||
aiMatrix4x4::Translation(Bones[BoneId].Position, t0)
|
||||
*aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, t1)
|
||||
;
|
||||
//__________________________________________________________
|
||||
const Bone &source = bones[boneId];
|
||||
|
||||
aiNode* boneNode = new aiNode(source.Name);
|
||||
boneNode->mParent = parent;
|
||||
boneNode->mTransformation = aiMatrix4x4::Translation(source.Position, t0) * aiMatrix4x4::Rotation(source.RotationAngle, source.RotationAxis, t1);
|
||||
|
||||
//---------- recursivly create all children Nodes: ----------
|
||||
NewNode->mNumChildren=Bones[BoneId].Children.size();
|
||||
NewNode->mChildren=new aiNode*[Bones[BoneId].Children.size()];
|
||||
for(unsigned int i=0; i<Bones[BoneId].Children.size(); ++i)
|
||||
if (!source.Children.empty())
|
||||
{
|
||||
NewNode->mChildren[i]=CreateAiNodeFromBone(Bones[BoneId].Children[i], Bones, NewNode);
|
||||
boneNode->mChildren = new aiNode*[source.Children.size()];
|
||||
boneNode->mNumChildren = source.Children.size();
|
||||
|
||||
for(size_t i=0, len=source.Children.size(); i<len; ++i)
|
||||
boneNode->mChildren[i] = CreateNodeFromBone(source.Children[i], bones, boneNode);
|
||||
}
|
||||
//____________________________________________________
|
||||
|
||||
|
||||
return NewNode;
|
||||
return boneNode;
|
||||
}
|
||||
|
||||
|
||||
void Bone::CalculateBoneToWorldSpaceMatrix(vector<Bone> &Bones)
|
||||
{
|
||||
aiMatrix4x4 t0, t1;
|
||||
|
|
|
@ -809,7 +809,7 @@ enum aiComponent
|
|||
* order: <material-name>.material, <mesh-filename-base>.material and
|
||||
* lastly the material name defined by this config property.
|
||||
* <br>
|
||||
* Property type: String. Default value: n/a.
|
||||
* Property type: String. Default value: Scene.material.
|
||||
*/
|
||||
#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE \
|
||||
"IMPORT_OGRE_MATERIAL_FILE"
|
||||
|
|
Loading…
Reference in New Issue