summaryrefslogtreecommitdiffstats
path: root/3rdparty/assimp/code/OgreImporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/assimp/code/OgreImporter.cpp')
-rw-r--r--3rdparty/assimp/code/OgreImporter.cpp876
1 files changed, 0 insertions, 876 deletions
diff --git a/3rdparty/assimp/code/OgreImporter.cpp b/3rdparty/assimp/code/OgreImporter.cpp
deleted file mode 100644
index 9981b563..00000000
--- a/3rdparty/assimp/code/OgreImporter.cpp
+++ /dev/null
@@ -1,876 +0,0 @@
-/*
-Open Asset Import Library (ASSIMP)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2010, ASSIMP Development 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 Development 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.
-
-----------------------------------------------------------------------
-*/
-
-/** @file OgreImporter.cpp
- * @brief Implementation of the Ogre XML (.mesh.xml) loader.
- */
-#include "AssimpPCH.h"
-#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-
-#include <vector>
-#include <sstream>
-using namespace std;
-
-//#include "boost/format.hpp"
-//#include "boost/foreach.hpp"
-//using namespace boost;
-
-#include "TinyFormatter.h"
-
-#include "OgreImporter.h"
-#include "irrXMLWrapper.h"
-
-
-namespace Assimp
-{
-namespace Ogre
-{
-
-
-bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
-{
- if (!checkSig)//Check File Extension
- {
- std::string extension("mesh.xml");
- int l=extension.length();
- return pFile.substr(pFile.length()-l, l)==extension;
- }
- else//Check file Header
- {
- const char* tokens[] = {"<mesh>"};
- return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
- }
-}
-
-
-
-void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
-{
- m_CurrentFilename=pFile;
- m_CurrentIOHandler=pIOHandler;
- m_CurrentScene=pScene;
-
- //Open the File:
- boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
- if ( file.get() == NULL)
- throw DeadlyImportError("Failed to open file "+pFile+".");
-
- //Read the Mesh File:
- boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
- XmlReader* MeshFile = irr::io::createIrrXMLReader(mIOWrapper.get());
- if (!MeshFile)//parse the xml file
- throw DeadlyImportError("Failed to create XML Reader for "+pFile);
-
-
- DefaultLogger::get()->debug("Mesh File opened");
-
- //Read root Node:
- if (!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="mesh"))
- {
- throw DeadlyImportError("Root Node is not <mesh>! "+pFile+" "+MeshFile->getNodeName());
- }
-
- //Go to the submeshs:
- if (!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="submeshes"))
- {
- throw DeadlyImportError("No <submeshes> node in <mesh> node! "+pFile);
- }
-
-
- //-------------------Read the submeshs and materials:-----------------------
- std::list<boost::shared_ptr<SubMesh> > SubMeshes;
- vector<aiMaterial*> Materials;
- XmlRead(MeshFile);
- while (MeshFile->getNodeName()==string("submesh"))
- {
- SubMesh* theSubMesh=new SubMesh();
- theSubMesh->MaterialName=GetAttribute<string>(MeshFile, "material");
- DefaultLogger::get()->debug("Loading Submehs with Material: "+theSubMesh->MaterialName);
- ReadSubMesh(*theSubMesh, MeshFile);
-
- //just a index in a array, we add a mesh in each loop cycle, so we get indicies like 0, 1, 2 ... n;
- //so it is important to do this before pushing the mesh in the vector!
- theSubMesh->MaterialIndex=SubMeshes.size();
-
- SubMeshes.push_back(boost::shared_ptr<SubMesh>(theSubMesh));
-
- //Load the Material:
- aiMaterial* MeshMat=LoadMaterial(theSubMesh->MaterialName);
-
- //Set the Material:
- Materials.push_back(MeshMat);
- }
-
- if (SubMeshes.empty())
- throw DeadlyImportError("no submesh loaded!");
- if (SubMeshes.size()!=Materials.size())
- throw DeadlyImportError("materialcount doesn't match mesh count!");
-
- //____________________________________________________________
-
-
- //----------------Load the skeleton: -------------------------------
- vector<Bone> Bones;
- vector<Animation> Animations;
- if (MeshFile->getNodeName()==string("skeletonlink"))
- {
- string SkeletonFile=GetAttribute<string>(MeshFile, "name");
- LoadSkeleton(SkeletonFile, Bones, Animations);
- }
- else
- {
- DefaultLogger::get()->warn("No skeleton file will be loaded");
- DefaultLogger::get()->warn(MeshFile->getNodeName());
- }
- //__________________________________________________________________
-
-
- //----------------- Now fill the Assimp scene ---------------------------
-
- //put the aiMaterials in the scene:
- m_CurrentScene->mMaterials=new aiMaterial*[Materials.size()];
- m_CurrentScene->mNumMaterials=Materials.size();
- for (unsigned int i=0; i<Materials.size(); ++i)
- m_CurrentScene->mMaterials[i]=Materials[i];
-
- //create the aiMehs...
- vector<aiMesh*> aiMeshes;
- BOOST_FOREACH(boost::shared_ptr<SubMesh> theSubMesh, SubMeshes)
- {
- aiMeshes.push_back(CreateAssimpSubMesh(*theSubMesh, Bones));
- }
- //... and put them in the scene:
- m_CurrentScene->mNumMeshes=aiMeshes.size();
- m_CurrentScene->mMeshes=new aiMesh*[aiMeshes.size()];
- memcpy(m_CurrentScene->mMeshes, &(aiMeshes[0]), sizeof(aiMeshes[0])*aiMeshes.size());
-
- //Create the root node
- m_CurrentScene->mRootNode=new aiNode("root");
-
- //link the meshs with the root node:
- m_CurrentScene->mRootNode->mMeshes=new unsigned int[SubMeshes.size()];
- m_CurrentScene->mRootNode->mNumMeshes=SubMeshes.size();
- for (unsigned int i=0; i<SubMeshes.size(); ++i)
- m_CurrentScene->mRootNode->mMeshes[i]=i;
-
-
-
- CreateAssimpSkeleton(Bones, Animations);
- PutAnimationsInScene(Bones, Animations);
- //___________________________________________________________
-}
-
-
-
-void OgreImporter::GetExtensionList(std::set<std::string>& extensions)
-{
- extensions.insert("mesh.xml");
-}
-
-
-void OgreImporter::SetupProperties(const Importer* pImp)
-{
- m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
-}
-
-void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
-{
- XmlRead(Reader);
- //TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order
- //of faces and geometry changed, and not if we have more than one of one
- while (Reader->getNodeName()==string("faces") || string(Reader->getNodeName())=="geometry" || Reader->getNodeName()==string("boneassignments"))
- {
- if (string(Reader->getNodeName())=="faces")//Read the face list
- {
- //some info logging:
- unsigned int NumFaces=GetAttribute<int>(Reader, "count");
- stringstream ss; ss <<"Submesh has " << NumFaces << " Faces.";
- DefaultLogger::get()->debug(ss.str());
-
- while (XmlRead(Reader) && Reader->getNodeName()==string("face"))
- {
- Face NewFace;
- NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1");
- NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2");
- NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3");
- if (Reader->getAttributeValue("v4"))//this should be supported in the future
- {
- throw DeadlyImportError("Submesh has quads, only traingles are supported!");
- }
- theSubMesh.FaceList.push_back(NewFace);
- }
-
- }//end of faces
- else if (string(Reader->getNodeName())=="geometry")//Read the vertexdata
- {
- //some info logging:
- unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
- stringstream ss; ss<<"VertexCount: "<<NumVertices;
- DefaultLogger::get()->debug(ss.str());
-
- //General Informations about vertices
- XmlRead(Reader);
- if (!(Reader->getNodeName()==string("vertexbuffer")))
- {
- throw DeadlyImportError("vertexbuffer node is not first in geometry node!");
- }
- theSubMesh.HasPositions=GetAttribute<bool>(Reader, "positions");
- theSubMesh.HasNormals=GetAttribute<bool>(Reader, "normals");
- if (!Reader->getAttributeValue("texture_coords"))//we can have 1 or 0 uv channels, and if the mesh has no uvs, it also doesn't have the attribute
- theSubMesh.NumUvs=0;
- else
- theSubMesh.NumUvs=GetAttribute<int>(Reader, "texture_coords");
- if (theSubMesh.NumUvs>1)
- throw DeadlyImportError("too many texcoords (just 1 supported!)");
-
- //read all the vertices:
- XmlRead(Reader);
- while (Reader->getNodeName()==string("vertex"))
- {
- //read all vertex attributes:
-
- //Position
- if (theSubMesh.HasPositions)
- {
- XmlRead(Reader);
- aiVector3D NewPos;
- NewPos.x=GetAttribute<float>(Reader, "x");
- NewPos.y=GetAttribute<float>(Reader, "y");
- NewPos.z=GetAttribute<float>(Reader, "z");
- theSubMesh.Positions.push_back(NewPos);
- }
-
- //Normal
- if (theSubMesh.HasNormals)
- {
- XmlRead(Reader);
- aiVector3D NewNormal;
- NewNormal.x=GetAttribute<float>(Reader, "x");
- NewNormal.y=GetAttribute<float>(Reader, "y");
- NewNormal.z=GetAttribute<float>(Reader, "z");
- theSubMesh.Normals.push_back(NewNormal);
- }
-
- //Uv:
- if (1==theSubMesh.NumUvs)
- {
- XmlRead(Reader);
- aiVector3D NewUv;
- NewUv.x=GetAttribute<float>(Reader, "u");
- NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
- theSubMesh.Uvs.push_back(NewUv);
- }
- XmlRead(Reader);
- }
-
- }//end of "geometry
-
-
- else if (string(Reader->getNodeName())=="boneassignments")
- {
- theSubMesh.Weights.resize(theSubMesh.Positions.size());
- while (XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment"))
- {
- Weight NewWeight;
- unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex");
- NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex");
- NewWeight.Value=GetAttribute<float>(Reader, "weight");
- theSubMesh.BonesUsed=max(theSubMesh.BonesUsed, NewWeight.BoneId+1);//calculate the number of bones used (this is the highest id +1 becuase bone ids start at 0)
-
- theSubMesh.Weights[VertexId].push_back(NewWeight);
-
- //XmlRead(Reader);//Once i had this line, and than i got only every second boneassignment, but my first test models had even boneassignment counts, so i thougt, everything would work. And yes, i HATE irrXML!!!
- }
-
- }//end of boneassignments
- }
- DefaultLogger::get()->debug((Formatter::format(),
- "Positionen: ",theSubMesh.Positions.size(),
- " Normale: ",theSubMesh.Normals.size(),
- " TexCoords: ",theSubMesh.Uvs.size()
- ));
- DefaultLogger::get()->warn(Reader->getNodeName());
-
-
-
- //---------------Make all Vertexes unique: (this is required by assimp)-----------------------
- vector<Face> UniqueFaceList(theSubMesh.FaceList.size());
- unsigned int UniqueVertexCount=theSubMesh.FaceList.size()*3;//*3 because each face consists of 3 vertexes, because we only support triangles^^
- vector<aiVector3D> UniquePositions(UniqueVertexCount);
- vector<aiVector3D> UniqueNormals(UniqueVertexCount);
- vector<aiVector3D> UniqueUvs(UniqueVertexCount);
- vector< vector<Weight> > UniqueWeights((theSubMesh.Weights.size() ? UniqueVertexCount : 0));
-
- for (unsigned int i=0; i<theSubMesh.FaceList.size(); ++i)
- {
- //We precalculate the index vlaues her, because we need them in all vertex attributes
- unsigned int Vertex1=theSubMesh.FaceList[i].VertexIndices[0];
- unsigned int Vertex2=theSubMesh.FaceList[i].VertexIndices[1];
- unsigned int Vertex3=theSubMesh.FaceList[i].VertexIndices[2];
-
- UniquePositions[3*i+0]=theSubMesh.Positions[Vertex1];
- UniquePositions[3*i+1]=theSubMesh.Positions[Vertex2];
- UniquePositions[3*i+2]=theSubMesh.Positions[Vertex3];
-
- UniqueNormals[3*i+0]=theSubMesh.Normals[Vertex1];
- UniqueNormals[3*i+1]=theSubMesh.Normals[Vertex2];
- UniqueNormals[3*i+2]=theSubMesh.Normals[Vertex3];
-
- if (1==theSubMesh.NumUvs)
- {
- UniqueUvs[3*i+0]=theSubMesh.Uvs[Vertex1];
- UniqueUvs[3*i+1]=theSubMesh.Uvs[Vertex2];
- UniqueUvs[3*i+2]=theSubMesh.Uvs[Vertex3];
- }
-
- if (theSubMesh.Weights.size()) {
- UniqueWeights[3*i+0]=theSubMesh.Weights[Vertex1];
- UniqueWeights[3*i+1]=theSubMesh.Weights[Vertex2];
- UniqueWeights[3*i+2]=theSubMesh.Weights[Vertex3];
- }
-
- //The indexvalues a just continuous numbers (0, 1, 2, 3, 4, 5, 6...)
- UniqueFaceList[i].VertexIndices[0]=3*i+0;
- UniqueFaceList[i].VertexIndices[1]=3*i+1;
- UniqueFaceList[i].VertexIndices[2]=3*i+2;
- }
- //_________________________________________________________________________________________
-
- //now we have the unique datas, but want them in the SubMesh, so we swap all the containers:
- theSubMesh.FaceList.swap(UniqueFaceList);
- theSubMesh.Positions.swap(UniquePositions);
- theSubMesh.Normals.swap(UniqueNormals);
- theSubMesh.Uvs.swap(UniqueUvs);
- theSubMesh.Weights.swap(UniqueWeights);
-
- //------------- normalize weights -----------------------------
- //The Blender exporter doesn't care about whether the sum of all boneweights for a single vertex equals 1 or not,
- //so we have to make this sure:
- for (unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices
- {
- float WeightSum=0.0f;
- for (unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
- {
- WeightSum+=theSubMesh.Weights[VertexId][BoneId].Value;
- }
-
- //check if the sum is too far away from 1
- if (WeightSum<1.0f-0.05f || WeightSum>1.0f+0.05f)
- {
- //normalize all weights:
- for (unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
- {
- theSubMesh.Weights[VertexId][BoneId].Value/=WeightSum;
- }
- }
- }
- //_________________________________________________________
-}
-
-
-aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector<Bone>& Bones) const
-{
- const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
-
- aiMesh* NewAiMesh=new aiMesh();
-
- //Positions
- NewAiMesh->mVertices=new aiVector3D[theSubMesh.Positions.size()];
- memcpy(NewAiMesh->mVertices, &theSubMesh.Positions[0], theSubMesh.Positions.size()*sizeof(aiVector3D));
- NewAiMesh->mNumVertices=theSubMesh.Positions.size();
-
- //Normals
- NewAiMesh->mNormals=new aiVector3D[theSubMesh.Normals.size()];
- memcpy(NewAiMesh->mNormals, &theSubMesh.Normals[0], theSubMesh.Normals.size()*sizeof(aiVector3D));
-
- //Uvs
- if (0!=theSubMesh.NumUvs)
- {
- NewAiMesh->mNumUVComponents[0]=2;
- NewAiMesh->mTextureCoords[0]= new aiVector3D[theSubMesh.Uvs.size()];
- memcpy(NewAiMesh->mTextureCoords[0], &theSubMesh.Uvs[0], theSubMesh.Uvs.size()*sizeof(aiVector3D));
- }
-
-
- //---------------------------------------- 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(theSubMesh.BonesUsed);//now the outer list are the bones, and the inner vector the vertices
- for (unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices
- {
- for (unsigned int BoneId=0; BoneId<theSubMesh.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=theSubMesh.Weights[VertexId][BoneId].Value;
- aiWeights[theSubMesh.Weights[VertexId][BoneId].BoneId].push_back(NewWeight);
- }
- }
-
-
-
- vector<aiBone*> aiBones;
- aiBones.reserve(theSubMesh.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<theSubMesh.BonesUsed; ++i)
- {
- 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*));
- }
-
- //______________________________________________________________________________________________________
-
-
-
- //Faces
- NewAiMesh->mFaces=new aiFace[theSubMesh.FaceList.size()];
- for (unsigned int i=0; i<theSubMesh.FaceList.size(); ++i)
- {
- NewAiMesh->mFaces[i].mNumIndices=3;
- NewAiMesh->mFaces[i].mIndices=new unsigned int[3];
-
- NewAiMesh->mFaces[i].mIndices[0]=theSubMesh.FaceList[i].VertexIndices[0];
- NewAiMesh->mFaces[i].mIndices[1]=theSubMesh.FaceList[i].VertexIndices[1];
- NewAiMesh->mFaces[i].mIndices[2]=theSubMesh.FaceList[i].VertexIndices[2];
- }
- NewAiMesh->mNumFaces=theSubMesh.FaceList.size();
-
- //Link the material:
- NewAiMesh->mMaterialIndex=theSubMesh.MaterialIndex;//the index is set by the function who called ReadSubMesh
-
- return NewAiMesh;
-}
-
-
-void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vector<Animation> &Animations) const
-{
- const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
-
-
- //most likely the skeleton file will only end with .skeleton
- //But this is a xml reader, so we need: .skeleton.xml
- FileName+=".xml";
-
- DefaultLogger::get()->debug(string("Loading Skeleton: ")+FileName);
-
- //Open the File:
- boost::scoped_ptr<IOStream> File(m_CurrentIOHandler->Open(FileName));
- if (NULL==File.get())
- throw DeadlyImportError("Failed to open skeleton file "+FileName+".");
-
- //Read the Mesh File:
- boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(File.get()));
- XmlReader* SkeletonFile = irr::io::createIrrXMLReader(mIOWrapper.get());
- if (!SkeletonFile)
- throw DeadlyImportError(string("Failed to create XML Reader for ")+FileName);
-
- //Quick note: Whoever read this should know this one thing: irrXml fucking sucks!!!
-
- XmlRead(SkeletonFile);
- if (string("skeleton")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("No <skeleton> node in SkeletonFile: "+FileName);
-
-
-
- //------------------------------------load bones-----------------------------------------
- XmlRead(SkeletonFile);
- if (string("bones")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("No bones node in skeleton "+FileName);
-
- XmlRead(SkeletonFile);
-
- while (string("bone")==SkeletonFile->getNodeName())
- {
- //TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appear, so what....
-
- //read a new bone:
- Bone NewBone;
- NewBone.Id=GetAttribute<int>(SkeletonFile, "id");
- NewBone.Name=GetAttribute<string>(SkeletonFile, "name");
-
- //load the position:
- XmlRead(SkeletonFile);
- if (string("position")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("Position is not first node in Bone!");
- NewBone.Position.x=GetAttribute<float>(SkeletonFile, "x");
- NewBone.Position.y=GetAttribute<float>(SkeletonFile, "y");
- NewBone.Position.z=GetAttribute<float>(SkeletonFile, "z");
-
- //Rotation:
- XmlRead(SkeletonFile);
- if (string("rotation")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("Rotation is not the second node in Bone!");
- NewBone.RotationAngle=GetAttribute<float>(SkeletonFile, "angle");
- XmlRead(SkeletonFile);
- if (string("axis")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("No axis specified for bone rotation!");
- NewBone.RotationAxis.x=GetAttribute<float>(SkeletonFile, "x");
- NewBone.RotationAxis.y=GetAttribute<float>(SkeletonFile, "y");
- NewBone.RotationAxis.z=GetAttribute<float>(SkeletonFile, "z");
-
- //append the newly loaded bone to the bone list
- Bones.push_back(NewBone);
-
- //Proceed to the next bone:
- XmlRead(SkeletonFile);
- }
- //The bones in the file a not neccesarly ordered by there id's so we do it now:
- std::sort(Bones.begin(), Bones.end());
-
- //now the id of each bone should be equal to its position in the vector:
- //so we do a simple check:
- {
- bool IdsOk=true;
- for (int i=0; i<static_cast<signed int>(Bones.size()); ++i)//i is signed, because all Id's are also signed!
- {
- if (Bones[i].Id!=i)
- IdsOk=false;
- }
- if (!IdsOk)
- throw DeadlyImportError("Bone Ids are not valid!"+FileName);
- }
- DefaultLogger::get()->debug((Formatter::format(),"Number of bones: ",Bones.size()));
- //________________________________________________________________________________
-
-
-
-
-
-
- //----------------------------load bonehierarchy--------------------------------
- if (string("bonehierarchy")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("no bonehierarchy node in "+FileName);
-
- DefaultLogger::get()->debug("loading bonehierarchy...");
- XmlRead(SkeletonFile);
- while (string("boneparent")==SkeletonFile->getNodeName())
- {
- string Child, Parent;
- Child=GetAttribute<string>(SkeletonFile, "bone");
- Parent=GetAttribute<string>(SkeletonFile, "parent");
-
- unsigned int ChildId, ParentId;
- ChildId=find(Bones.begin(), Bones.end(), Child)->Id;
- ParentId=find(Bones.begin(), Bones.end(), Parent)->Id;
-
- Bones[ChildId].ParentId=ParentId;
- Bones[ParentId].Children.push_back(ChildId);
-
- XmlRead(SkeletonFile);//i once forget this line, which led to an endless loop, did i mentioned, that irrxml sucks??
- }
- //_____________________________________________________________________________
-
-
- //--------- Calculate the WorldToBoneSpace Matrix recursivly for all bones: ------------------
- BOOST_FOREACH(Bone theBone, Bones)
- {
- if (-1==theBone.ParentId) //the bone is a root bone
- {
- theBone.CalculateBoneToWorldSpaceMatrix(Bones);
- }
- }
- //_______________________________________________________________________
-
-
- //---------------------------load animations-----------------------------
- if (string("animations")==SkeletonFile->getNodeName())//animations are optional values
- {
- DefaultLogger::get()->debug("Loading Animations");
- XmlRead(SkeletonFile);
- while (string("animation")==SkeletonFile->getNodeName())
- {
- Animation NewAnimation;
- NewAnimation.Name=GetAttribute<string>(SkeletonFile, "name");
- NewAnimation.Length=GetAttribute<float>(SkeletonFile, "length");
-
- //Load all Tracks
- XmlRead(SkeletonFile);
- if (string("tracks")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("no tracks node in animation");
- XmlRead(SkeletonFile);
- while (string("track")==SkeletonFile->getNodeName())
- {
- Track NewTrack;
- NewTrack.BoneName=GetAttribute<string>(SkeletonFile, "bone");
-
- //Load all keyframes;
- XmlRead(SkeletonFile);
- if (string("keyframes")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("no keyframes node!");
- XmlRead(SkeletonFile);
- while (string("keyframe")==SkeletonFile->getNodeName())
- {
- Keyframe NewKeyframe;
- NewKeyframe.Time=GetAttribute<float>(SkeletonFile, "time");
-
- //Position:
- XmlRead(SkeletonFile);
- if (string("translate")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("translate node not first in keyframe");
- NewKeyframe.Position.x=GetAttribute<float>(SkeletonFile, "x");
- NewKeyframe.Position.y=GetAttribute<float>(SkeletonFile, "y");
- NewKeyframe.Position.z=GetAttribute<float>(SkeletonFile, "z");
-
- //Rotation:
- XmlRead(SkeletonFile);
- if (string("rotate")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("rotate is not second node in keyframe");
- float RotationAngle=GetAttribute<float>(SkeletonFile, "angle");
- aiVector3D RotationAxis;
- XmlRead(SkeletonFile);
- if (string("axis")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("No axis for keyframe rotation!");
- RotationAxis.x=GetAttribute<float>(SkeletonFile, "x");
- RotationAxis.y=GetAttribute<float>(SkeletonFile, "y");
- RotationAxis.z=GetAttribute<float>(SkeletonFile, "z");
- NewKeyframe.Rotation=aiQuaternion(RotationAxis, RotationAngle);
-
- //Scaling:
- XmlRead(SkeletonFile);
- if (string("scale")!=SkeletonFile->getNodeName())
- throw DeadlyImportError("no scalling key in keyframe!");
- NewKeyframe.Scaling.x=GetAttribute<float>(SkeletonFile, "x");
- NewKeyframe.Scaling.y=GetAttribute<float>(SkeletonFile, "y");
- NewKeyframe.Scaling.z=GetAttribute<float>(SkeletonFile, "z");
-
-
- NewTrack.Keyframes.push_back(NewKeyframe);
- XmlRead(SkeletonFile);
- }
-
-
- NewAnimation.Tracks.push_back(NewTrack);
- }
-
- Animations.push_back(NewAnimation);
- }
- }
- //_____________________________________________________________________________
-
-}
-
-
-void OgreImporter::CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations)
-{
- if (!m_CurrentScene->mRootNode)
- throw DeadlyImportError("No root node exists!!");
- if (0!=m_CurrentScene->mRootNode->mNumChildren)
- throw DeadlyImportError("Root Node already has childnodes!");
-
-
- //Createt the assimp bone hierarchy
- DefaultLogger::get()->debug("Root Bones");
- vector<aiNode*> RootBoneNodes;
- BOOST_FOREACH(Bone theBone, Bones)
- {
- if (-1==theBone.ParentId) //the bone is a root bone
- {
- DefaultLogger::get()->debug(theBone.Name);
- RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode));//which will recursily add all other nodes
- }
- }
-
- if (RootBoneNodes.size()) {
- m_CurrentScene->mRootNode->mNumChildren=RootBoneNodes.size();
- m_CurrentScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()];
- memcpy(m_CurrentScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size());
- }
-}
-
-
-void OgreImporter::PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations)
-{
- //-----------------Create the Assimp Animations --------------------
- 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
- {
- m_CurrentScene->mNumAnimations=Animations.size();
- m_CurrentScene->mAnimations=new aiAnimation*[Animations.size()];
- for (unsigned int i=0; i<Animations.size(); ++i)//create all animations
- {
- 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)
- {
- aiNodeAnim* NewNodeAnim=new aiNodeAnim();
- NewNodeAnim->mNodeName=Animations[i].Tracks[j].BoneName;
-
- //we need this, to acces the bones default pose, which we need to make keys absolute
- vector<Bone>::const_iterator CurBone=find(Bones.begin(), Bones.end(), NewNodeAnim->mNodeName);
- aiMatrix4x4 t0, t1;
- aiMatrix4x4 DefBonePose=//The default bone pose doesnt have a scaling value
- aiMatrix4x4::Rotation(CurBone->RotationAngle, CurBone->RotationAxis, t0)
- * aiMatrix4x4::Translation(CurBone->Position, t1);
-
- //Create the keyframe arrays...
- unsigned int KeyframeCount=Animations[i].Tracks[j].Keyframes.size();
- NewNodeAnim->mNumPositionKeys=KeyframeCount;
- NewNodeAnim->mPositionKeys=new aiVectorKey[KeyframeCount];
- NewNodeAnim->mNumRotationKeys=KeyframeCount;
- NewNodeAnim->mRotationKeys=new aiQuatKey[KeyframeCount];
- NewNodeAnim->mNumScalingKeys=KeyframeCount;
- NewNodeAnim->mScalingKeys=new aiVectorKey[KeyframeCount];
-
- //...and fill them
- for (unsigned int k=0; k<KeyframeCount; ++k)
- {
- 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::Scaling(Animations[i].Tracks[j].Keyframes[k].Scaling, t2) //scale
- * aiMatrix4x4(Animations[i].Tracks[j].Keyframes[k].Rotation.GetMatrix()) //rot
- * aiMatrix4x4::Translation(Animations[i].Tracks[j].Keyframes[k].Position, t3); //pos
-
-
- //calculate the complete transformation from world space to bone space
- aiMatrix4x4 CompleteTransform=DefBonePose * PoseToKey;
-
- aiVector3D Pos;
- aiQuaternion Rot;
- aiVector3D Scale;
-
- CompleteTransform.Decompose(Scale, Rot, Pos);
-
-
- NewNodeAnim->mPositionKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time;
- NewNodeAnim->mPositionKeys[k].mValue=Pos;
-
- NewNodeAnim->mRotationKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time;
- NewNodeAnim->mRotationKeys[k].mValue=Rot;
-
- NewNodeAnim->mScalingKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time;
- NewNodeAnim->mScalingKeys[k].mValue=Scale;
- }
-
- NewAnimation->mChannels[j]=NewNodeAnim;
- }
-
- m_CurrentScene->mAnimations[i]=NewAnimation;
- }
- }
-//TODO: Auf nicht vorhandene Animationskeys achten!
-//#pragma warning (s.o.)
- //__________________________________________________________________
-}
-
-
-
-aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode) const
-{
- const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
-
- //----Create the node for this bone and set its values-----
- aiNode* NewNode=new aiNode(Bones[BoneId].Name);
- NewNode->mParent=ParentNode;
-
- aiMatrix4x4 t0,t1;
- //create a matrix from the transformation values of the ogre bone
- NewNode->mTransformation=aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, t1)
- * aiMatrix4x4::Translation(Bones[BoneId].Position, t0)
-
- ;
- //__________________________________________________________
-
-
- //---------- 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)
- {
- NewNode->mChildren[i]=CreateAiNodeFromBone(Bones[BoneId].Children[i], Bones, NewNode);
- }
- //____________________________________________________
-
-
- return NewNode;
-}
-
-
-void Bone::CalculateBoneToWorldSpaceMatrix(vector<Bone> &Bones)
-{
- //Calculate the matrix for this bone:
-
- aiMatrix4x4 t0,t1;
- aiMatrix4x4 Transf=aiMatrix4x4::Translation(-Position, t0)
- * aiMatrix4x4::Rotation(-RotationAngle, RotationAxis, t1)
- ;
- if (-1==ParentId)
- {
- BoneToWorldSpace=Transf;
- }
- else
- {
- BoneToWorldSpace=Transf*Bones[ParentId].BoneToWorldSpace;
- }
-
- //and recursivly for all children:
- BOOST_FOREACH(int theChildren, Children)
- {
- Bones[theChildren].CalculateBoneToWorldSpaceMatrix(Bones);
- }
-}
-
-}//namespace Ogre
-}//namespace Assimp
-
-#endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER