Browse Source

OgreImporter: Cleanup skeleton related code and code that populates the assimp scene. Tested skeleton/animation imports and it seems to work correctly now.

Jonne Nauha 11 years ago
parent
commit
283394d695
5 changed files with 218 additions and 224 deletions
  1. 33 36
      code/OgreImporter.cpp
  2. 10 9
      code/OgreImporter.h
  3. 71 78
      code/OgreMesh.cpp
  4. 103 100
      code/OgreSkeleton.cpp
  5. 1 1
      include/assimp/config.h

+ 33 - 36
code/OgreImporter.cpp

@@ -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

+ 10 - 9
code/OgreImporter.h

@@ -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;
 };

+ 71 - 78
code/OgreMesh.cpp

@@ -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)
-	{
-		NewAiMesh->mNormals=new aiVector3D[submesh.Normals.size()];
-		memcpy(NewAiMesh->mNormals, &submesh.Normals[0], submesh.Normals.size()*sizeof(aiVector3D));
-	}
+	aiMesh *dest = new aiMesh();
 
+	// Material
+	dest->mMaterialIndex = submesh.MaterialIndex;
 
-	//until we have support for bitangents, no tangents will be written
-	/*
-	//Tangents
-	if(submesh.HasTangents)
+	// 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->mTangents=new aiVector3D[submesh.Tangents.size()];
-		memcpy(NewAiMesh->mTangents, &submesh.Tangents[0], submesh.Tangents.size()*sizeof(aiVector3D));
+		dest->mNormals = new aiVector3D[submesh.Normals.size()];
+		memcpy(dest->mNormals, &submesh.Normals[0], submesh.Normals.size() * sizeVector3D);
 	}
-	*/
-
-	//Uvs
-	if(submesh.Uvs.size()>0)
+	
+	// Tangents
+	// Until we have support for bitangents, no tangents will be written
+	/// @todo Investigate why the above?
+	if (submesh.HasTangents)
 	{
-		for(unsigned int i=0; i<submesh.Uvs.size(); ++i)
-		{
-			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));
-		}
+		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);
 	}
 
+	// UVs
+	for (size_t i=0, len=submesh.Uvs.size(); i<len; ++i)
+	{
+		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);
+	}
 
-	//---------------------------------------- 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
+	// 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 BoneId=0; BoneId<submesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
+		const vector<BoneWeight> &vertexWeights = submesh.Weights[vertexId];
+		for (size_t boneId=0, len=vertexWeights.size(); boneId<len; ++boneId)
 		{
-			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 BoneWeight &ogreWeight = vertexWeights[boneId];
+			assimpWeights[ogreWeight.Id].push_back(aiVertexWeight(vertexId, ogreWeight.Value));
 		}
 	}
 
-	
+	// Bones.
+	vector<aiBone*> assimpBones;
+	assimpBones.reserve(submesh.BonesUsed);
 
-	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)
+	for(size_t boneId=0, len=submesh.BonesUsed; boneId<len; ++boneId)
 	{
-		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*));
+		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);
 	}
 
-	//______________________________________________________________________________________________________
+	if (!assimpBones.empty())
+	{
+		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

+ 103 - 100
code/OgreSkeleton.cpp

@@ -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;
-
-			//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)
+			const Animation &aSource = animations[ai];
+
+			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];
+
+				aiNodeAnim *animationNode = new aiNodeAnim();
+				animationNode->mNodeName = tSource.BoneName;
+
+				// 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())
+				{
+					for(unsigned int a=0; a<ai; a++)
+						delete pScene->mAnimations[a];
+					delete [] pScene->mAnimations;
+					pScene->mAnimations = NULL;
+					pScene->mNumAnimations = 0;
+					
+					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;
+				}
 
-				//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);
-				
+				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;
 
-				//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)
+				for(size_t kfi=0; kfi<numKeyframes; ++kfi)
 				{
-					aiMatrix4x4 t2, t3;
+					const KeyFrame &kfSource = tSource.Keyframes[kfi];
 
-					//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;
-					
-					aiVector3D Pos;
-					aiQuaternion Rot;
-					aiVector3D Scale;
+					// 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);
 
-					CompleteTransform.Decompose(Scale, Rot, Pos);
+					// Calculate the complete transformation from world space to bone space
+					aiMatrix4x4 CompleteTransform = defaultBonePose * keyBonePose;
 
-					double Time=Animations[i].Tracks[j].Keyframes[k].Time;
+					aiVector3D kfPos; aiQuaternion kfRot; aiVector3D kfScale;
+					CompleteTransform.Decompose(kfScale, kfRot, kfPos);
 
-					NewNodeAnim->mPositionKeys[k].mTime=Time;
-					NewNodeAnim->mPositionKeys[k].mValue=Pos;
-					
-					NewNodeAnim->mRotationKeys[k].mTime=Time;
-					NewNodeAnim->mRotationKeys[k].mValue=Rot;
+					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);
 
-					NewNodeAnim->mScalingKeys[k].mTime=Time;
-					NewNodeAnim->mScalingKeys[k].mValue=Scale;
+					animationNode->mPositionKeys[kfi].mValue = kfPos;					
+					animationNode->mRotationKeys[kfi].mValue = kfRot;
+					animationNode->mScalingKeys[kfi].mValue = kfScale;
 				}
-				
-				NewAnimation->mChannels[j]=NewNodeAnim;
+				animation->mChannels[ti] = animationNode;
 			}
-
-			pScene->mAnimations[i]=NewAnimation;
+			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;

+ 1 - 1
include/assimp/config.h

@@ -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"