2010-04-30 07:15:08 +00:00
/*
2012-02-03 03:38:30 +00:00
Open Asset Import Library ( assimp )
2010-04-30 07:15:08 +00:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2012-02-03 03:38:30 +00:00
Copyright ( c ) 2006 - 2012 , assimp team
2010-04-30 07:15:08 +00:00
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 .
2009-09-05 12:04:32 +00:00
2012-02-03 03:38:30 +00:00
* Neither the name of the assimp team , nor the names of its
2010-04-30 07:15:08 +00:00
contributors may be used to endorse or promote products
derived from this software without specific prior
2012-02-03 03:38:30 +00:00
written permission of the assimp team .
2010-04-30 07:15:08 +00:00
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"
2009-09-05 12:04:32 +00:00
# ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
# include <vector>
# include <sstream>
using namespace std ;
2009-09-21 17:41:57 +00:00
//#include "boost/format.hpp"
//#include "boost/foreach.hpp"
2010-05-10 21:06:44 +00:00
//using namespace boost;
# include "TinyFormatter.h"
2009-09-05 12:04:32 +00:00
# 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 )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Failed to open file " + pFile + " . " ) ;
2009-09-05 12:04:32 +00:00
//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
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Failed to create XML Reader for " + pFile ) ;
2009-09-05 12:04:32 +00:00
2009-09-05 15:49:23 +00:00
DefaultLogger : : get ( ) - > debug ( " Mesh File opened " ) ;
2009-09-05 12:04:32 +00:00
//Read root Node:
if ( ! ( XmlRead ( MeshFile ) & & string ( MeshFile - > getNodeName ( ) ) = = " mesh " ) )
{
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Root Node is not <mesh>! " + pFile + " " + MeshFile - > getNodeName ( ) ) ;
2009-09-05 12:04:32 +00:00
}
//Go to the submeshs:
if ( ! ( XmlRead ( MeshFile ) & & string ( MeshFile - > getNodeName ( ) ) = = " submeshes " ) )
{
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " No <submeshes> node in <mesh> node! " + pFile ) ;
2009-09-05 12:04:32 +00:00
}
2010-04-19 17:50:52 +00:00
//-------------------Read the submeshs and materials:-----------------------
2010-05-10 21:06:44 +00:00
std : : list < boost : : shared_ptr < SubMesh > > SubMeshes ;
2010-04-19 17:50:52 +00:00
vector < aiMaterial * > Materials ;
2009-09-05 12:04:32 +00:00
XmlRead ( MeshFile ) ;
2010-04-19 17:50:52 +00:00
while ( MeshFile - > getNodeName ( ) = = string ( " submesh " ) )
2009-09-05 12:04:32 +00:00
{
2010-04-19 17:50:52 +00:00
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 ( ) ;
2010-05-10 21:06:44 +00:00
SubMeshes . push_back ( boost : : shared_ptr < SubMesh > ( theSubMesh ) ) ;
2010-04-19 17:50:52 +00:00
2009-09-28 16:53:33 +00:00
//Load the Material:
2010-04-19 17:50:52 +00:00
aiMaterial * MeshMat = LoadMaterial ( theSubMesh - > MaterialName ) ;
2009-09-28 16:53:33 +00:00
//Set the Material:
2010-04-19 17:50:52 +00:00
Materials . push_back ( MeshMat ) ;
2009-09-05 12:04:32 +00:00
}
2010-04-19 17:50:52 +00:00
if ( SubMeshes . empty ( ) )
throw DeadlyImportError ( " no submesh loaded! " ) ;
if ( SubMeshes . size ( ) ! = Materials . size ( ) )
throw DeadlyImportError ( " materialcount doesn't match mesh count! " ) ;
2009-09-05 12:04:32 +00:00
2009-09-13 18:26:54 +00:00
//____________________________________________________________
//----------------Load the skeleton: -------------------------------
2009-09-28 16:53:33 +00:00
vector < Bone > Bones ;
vector < Animation > Animations ;
2009-09-13 18:26:54 +00:00
if ( MeshFile - > getNodeName ( ) = = string ( " skeletonlink " ) )
{
string SkeletonFile = GetAttribute < string > ( MeshFile , " name " ) ;
2009-09-28 16:53:33 +00:00
LoadSkeleton ( SkeletonFile , Bones , Animations ) ;
2009-09-13 18:26:54 +00:00
}
2009-09-17 19:05:46 +00:00
else
2009-09-28 16:53:33 +00:00
{
DefaultLogger : : get ( ) - > warn ( " No skeleton file will be loaded " ) ;
2009-09-17 19:05:46 +00:00
DefaultLogger : : get ( ) - > warn ( MeshFile - > getNodeName ( ) ) ;
2009-09-28 16:53:33 +00:00
}
2009-09-13 18:26:54 +00:00
//__________________________________________________________________
2010-04-19 17:50:52 +00:00
//----------------- 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 ;
2010-05-10 21:06:44 +00:00
BOOST_FOREACH ( boost : : shared_ptr < SubMesh > theSubMesh , SubMeshes )
2010-04-19 17:50:52 +00:00
{
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 ;
2009-09-28 16:53:33 +00:00
CreateAssimpSkeleton ( Bones , Animations ) ;
2010-11-09 18:13:08 +00:00
PutAnimationsInScene ( Bones , Animations ) ;
2010-04-19 17:50:52 +00:00
//___________________________________________________________
2009-09-05 12:04:32 +00:00
}
2010-03-02 17:38:01 +00:00
void OgreImporter : : GetExtensionList ( std : : set < std : : string > & extensions )
2009-09-05 12:04:32 +00:00
{
2010-03-02 17:38:01 +00:00
extensions . insert ( " mesh.xml " ) ;
2009-09-05 12:04:32 +00:00
}
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 ) ;
2010-11-09 18:13:08 +00:00
//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
2009-09-13 18:26:54 +00:00
while ( Reader - > getNodeName ( ) = = string ( " faces " ) | | string ( Reader - > getNodeName ( ) ) = = " geometry " | | Reader - > getNodeName ( ) = = string ( " boneassignments " ) )
2009-09-05 12:04:32 +00:00
{
if ( string ( Reader - > getNodeName ( ) ) = = " faces " ) //Read the face list
{
//some info logging:
unsigned int NumFaces = GetAttribute < int > ( Reader , " count " ) ;
2011-04-03 15:12:05 +00:00
ostringstream ss ; ss < < " Submesh has " < < NumFaces < < " Faces. " ;
2009-09-05 15:49:23 +00:00
DefaultLogger : : get ( ) - > debug ( ss . str ( ) ) ;
2009-09-05 12:04:32 +00:00
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
{
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Submesh has quads, only traingles are supported! " ) ;
2009-09-05 12:04:32 +00:00
}
2009-09-28 16:53:33 +00:00
theSubMesh . FaceList . push_back ( NewFace ) ;
2009-09-05 12:04:32 +00:00
}
2009-09-13 18:26:54 +00:00
} //end of faces
2009-09-05 12:04:32 +00:00
else if ( string ( Reader - > getNodeName ( ) ) = = " geometry " ) //Read the vertexdata
{
//some info logging:
unsigned int NumVertices = GetAttribute < int > ( Reader , " vertexcount " ) ;
2011-04-03 15:12:05 +00:00
ostringstream ss ; ss < < " VertexCount: " < < NumVertices ;
2009-09-05 15:49:23 +00:00
DefaultLogger : : get ( ) - > debug ( ss . str ( ) ) ;
2009-09-05 12:04:32 +00:00
//General Informations about vertices
XmlRead ( Reader ) ;
if ( ! ( Reader - > getNodeName ( ) = = string ( " vertexbuffer " ) ) )
{
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " vertexbuffer node is not first in geometry node! " ) ;
2009-09-05 12:04:32 +00:00
}
2009-09-28 16:53:33 +00:00
theSubMesh . HasPositions = GetAttribute < bool > ( Reader , " positions " ) ;
theSubMesh . HasNormals = GetAttribute < bool > ( Reader , " normals " ) ;
2009-09-17 19:05:46 +00:00
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
2009-09-28 16:53:33 +00:00
theSubMesh . NumUvs = 0 ;
2009-09-17 19:05:46 +00:00
else
2009-09-28 16:53:33 +00:00
theSubMesh . NumUvs = GetAttribute < int > ( Reader , " texture_coords " ) ;
if ( theSubMesh . NumUvs > 1 )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " too many texcoords (just 1 supported!) " ) ;
2009-09-05 12:04:32 +00:00
//read all the vertices:
XmlRead ( Reader ) ;
while ( Reader - > getNodeName ( ) = = string ( " vertex " ) )
{
//read all vertex attributes:
//Position
2009-09-28 16:53:33 +00:00
if ( theSubMesh . HasPositions )
2009-09-05 12:04:32 +00:00
{
XmlRead ( Reader ) ;
aiVector3D NewPos ;
NewPos . x = GetAttribute < float > ( Reader , " x " ) ;
NewPos . y = GetAttribute < float > ( Reader , " y " ) ;
NewPos . z = GetAttribute < float > ( Reader , " z " ) ;
2009-09-28 16:53:33 +00:00
theSubMesh . Positions . push_back ( NewPos ) ;
2009-09-05 12:04:32 +00:00
}
//Normal
2009-09-28 16:53:33 +00:00
if ( theSubMesh . HasNormals )
2009-09-05 12:04:32 +00:00
{
XmlRead ( Reader ) ;
aiVector3D NewNormal ;
NewNormal . x = GetAttribute < float > ( Reader , " x " ) ;
NewNormal . y = GetAttribute < float > ( Reader , " y " ) ;
NewNormal . z = GetAttribute < float > ( Reader , " z " ) ;
2009-09-28 16:53:33 +00:00
theSubMesh . Normals . push_back ( NewNormal ) ;
2009-09-05 12:04:32 +00:00
}
//Uv:
2009-09-28 16:53:33 +00:00
if ( 1 = = theSubMesh . NumUvs )
2009-09-05 12:04:32 +00:00
{
XmlRead ( Reader ) ;
aiVector3D NewUv ;
NewUv . x = GetAttribute < float > ( Reader , " u " ) ;
2009-09-05 15:49:23 +00:00
NewUv . y = GetAttribute < float > ( Reader , " v " ) * ( - 1 ) + 1 ; //flip the uv vertikal, blender exports them so!
2009-09-28 16:53:33 +00:00
theSubMesh . Uvs . push_back ( NewUv ) ;
2009-09-05 12:04:32 +00:00
}
XmlRead ( Reader ) ;
}
2009-09-13 18:26:54 +00:00
} //end of "geometry
2010-04-16 19:10:09 +00:00
2009-09-13 18:26:54 +00:00
else if ( string ( Reader - > getNodeName ( ) ) = = " boneassignments " )
{
2009-09-28 16:53:33 +00:00
theSubMesh . Weights . resize ( theSubMesh . Positions . size ( ) ) ;
2009-09-13 18:26:54 +00:00
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 " ) ;
2009-09-28 16:53:33 +00:00
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)
2009-09-13 18:26:54 +00:00
2009-09-28 16:53:33 +00:00
theSubMesh . Weights [ VertexId ] . push_back ( NewWeight ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//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!!!
2009-09-13 18:26:54 +00:00
}
} //end of boneassignments
2009-09-05 12:04:32 +00:00
}
2010-05-10 21:06:44 +00:00
DefaultLogger : : get ( ) - > debug ( ( Formatter : : format ( ) ,
" Positionen: " , theSubMesh . Positions . size ( ) ,
" Normale: " , theSubMesh . Normals . size ( ) ,
" TexCoords: " , theSubMesh . Uvs . size ( )
) ) ;
2009-09-17 19:05:46 +00:00
DefaultLogger : : get ( ) - > warn ( Reader - > getNodeName ( ) ) ;
2009-09-13 18:26:54 +00:00
2009-09-05 12:04:32 +00:00
2009-09-13 18:26:54 +00:00
//---------------Make all Vertexes unique: (this is required by assimp)-----------------------
2009-09-28 16:53:33 +00:00
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 ) ;
2010-04-13 15:51:18 +00:00
vector < vector < Weight > > UniqueWeights ( ( theSubMesh . Weights . size ( ) ? UniqueVertexCount : 0 ) ) ;
2009-09-28 16:53:33 +00:00
for ( unsigned int i = 0 ; i < theSubMesh . FaceList . size ( ) ; + + i )
2009-09-05 12:04:32 +00:00
{
2009-09-28 16:53:33 +00:00
//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 ] ;
2009-09-05 12:04:32 +00:00
2009-09-28 16:53:33 +00:00
UniqueNormals [ 3 * i + 0 ] = theSubMesh . Normals [ Vertex1 ] ;
UniqueNormals [ 3 * i + 1 ] = theSubMesh . Normals [ Vertex2 ] ;
UniqueNormals [ 3 * i + 2 ] = theSubMesh . Normals [ Vertex3 ] ;
2009-09-05 12:04:32 +00:00
2009-09-28 16:53:33 +00:00
if ( 1 = = theSubMesh . NumUvs )
2009-09-17 19:05:46 +00:00
{
2009-09-28 16:53:33 +00:00
UniqueUvs [ 3 * i + 0 ] = theSubMesh . Uvs [ Vertex1 ] ;
UniqueUvs [ 3 * i + 1 ] = theSubMesh . Uvs [ Vertex2 ] ;
UniqueUvs [ 3 * i + 2 ] = theSubMesh . Uvs [ Vertex3 ] ;
2009-09-17 19:05:46 +00:00
}
2009-09-05 12:04:32 +00:00
2010-04-13 15:51:18 +00:00
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 ] ;
}
2009-09-13 18:26:54 +00:00
2009-09-28 16:53:33 +00:00
//The indexvalues a just continuous numbers (0, 1, 2, 3, 4, 5, 6...)
2009-09-05 12:04:32 +00:00
UniqueFaceList [ i ] . VertexIndices [ 0 ] = 3 * i + 0 ;
UniqueFaceList [ i ] . VertexIndices [ 1 ] = 3 * i + 1 ;
UniqueFaceList [ i ] . VertexIndices [ 2 ] = 3 * i + 2 ;
}
2009-09-13 18:26:54 +00:00
//_________________________________________________________________________________________
2009-09-05 12:04:32 +00:00
2009-09-28 16:53:33 +00:00
//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 ) ;
2010-04-16 19:10:09 +00:00
//------------- 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 ;
}
}
}
//_________________________________________________________
2009-09-28 16:53:33 +00:00
}
2009-09-05 12:04:32 +00:00
2009-09-13 18:26:54 +00:00
2010-04-19 17:50:52 +00:00
aiMesh * OgreImporter : : CreateAssimpSubMesh ( const SubMesh & theSubMesh , const vector < Bone > & Bones ) const
2009-09-28 16:53:33 +00:00
{
2010-04-19 17:50:52 +00:00
const aiScene * const m_CurrentScene = this - > m_CurrentScene ; //make sure, that we can access but not change the scene
2011-06-09 14:29:32 +00:00
( void ) m_CurrentScene ;
2009-09-05 12:04:32 +00:00
aiMesh * NewAiMesh = new aiMesh ( ) ;
2010-04-19 17:50:52 +00:00
2009-09-05 12:04:32 +00:00
//Positions
2009-09-28 16:53:33 +00:00
NewAiMesh - > mVertices = new aiVector3D [ theSubMesh . Positions . size ( ) ] ;
memcpy ( NewAiMesh - > mVertices , & theSubMesh . Positions [ 0 ] , theSubMesh . Positions . size ( ) * sizeof ( aiVector3D ) ) ;
NewAiMesh - > mNumVertices = theSubMesh . Positions . size ( ) ;
2009-09-05 12:04:32 +00:00
//Normals
2009-09-28 16:53:33 +00:00
NewAiMesh - > mNormals = new aiVector3D [ theSubMesh . Normals . size ( ) ] ;
memcpy ( NewAiMesh - > mNormals , & theSubMesh . Normals [ 0 ] , theSubMesh . Normals . size ( ) * sizeof ( aiVector3D ) ) ;
2009-09-05 12:04:32 +00:00
//Uvs
2009-09-28 16:53:33 +00:00
if ( 0 ! = theSubMesh . NumUvs )
2009-09-17 19:05:46 +00:00
{
NewAiMesh - > mNumUVComponents [ 0 ] = 2 ;
2009-09-28 16:53:33 +00:00
NewAiMesh - > mTextureCoords [ 0 ] = new aiVector3D [ theSubMesh . Uvs . size ( ) ] ;
memcpy ( NewAiMesh - > mTextureCoords [ 0 ] , & theSubMesh . Uvs [ 0 ] , theSubMesh . Uvs . size ( ) * sizeof ( aiVector3D ) ) ;
2009-09-17 19:05:46 +00:00
}
2009-09-05 12:04:32 +00:00
2009-09-28 16:53:33 +00:00
//---------------------------------------- Bones --------------------------------------------
2010-04-16 19:10:09 +00:00
2009-09-28 16:53:33 +00:00
//Copy the weights in in Bone-Vertices Struktur
2010-04-16 19:10:09 +00:00
//(we have them in a Vertex-Bones Structur, this is much easier for making them unique, which is required by assimp
2009-09-28 16:53:33 +00:00
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 ) ;
}
}
2010-04-16 19:10:09 +00:00
2009-09-28 16:53:33 +00:00
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 ( ) ) ;
2010-03-19 20:45:40 +00:00
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 ;
2009-09-28 16:53:33 +00:00
aiBones . push_back ( NewBone ) ;
}
}
NewAiMesh - > mNumBones = aiBones . size ( ) ;
2010-04-13 15:51:18 +00:00
// 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 * ) ) ;
}
2009-09-28 16:53:33 +00:00
//______________________________________________________________________________________________________
2009-09-13 18:26:54 +00:00
2009-09-05 12:04:32 +00:00
//Faces
2009-09-28 16:53:33 +00:00
NewAiMesh - > mFaces = new aiFace [ theSubMesh . FaceList . size ( ) ] ;
for ( unsigned int i = 0 ; i < theSubMesh . FaceList . size ( ) ; + + i )
2009-09-05 12:04:32 +00:00
{
NewAiMesh - > mFaces [ i ] . mNumIndices = 3 ;
NewAiMesh - > mFaces [ i ] . mIndices = new unsigned int [ 3 ] ;
2009-09-28 16:53:33 +00:00
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 ] ;
2009-09-05 12:04:32 +00:00
}
2009-09-28 16:53:33 +00:00
NewAiMesh - > mNumFaces = theSubMesh . FaceList . size ( ) ;
2009-09-05 12:04:32 +00:00
2009-09-28 16:53:33 +00:00
//Link the material:
NewAiMesh - > mMaterialIndex = theSubMesh . MaterialIndex ; //the index is set by the function who called ReadSubMesh
2010-04-19 17:50:52 +00:00
return NewAiMesh ;
2009-09-05 12:04:32 +00:00
}
2009-09-28 16:53:33 +00:00
2010-04-19 17:50:52 +00:00
void OgreImporter : : LoadSkeleton ( std : : string FileName , vector < Bone > & Bones , vector < Animation > & Animations ) const
2009-09-13 18:26:54 +00:00
{
2010-04-19 17:50:52 +00:00
const aiScene * const m_CurrentScene = this - > m_CurrentScene ; //make sure, that we can access but not change the scene
2011-06-09 14:29:32 +00:00
( void ) m_CurrentScene ;
2010-04-19 17:50:52 +00:00
2009-09-13 18:26:54 +00:00
//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 ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Failed to open skeleton file " + FileName + " . " ) ;
2009-09-13 18:26:54 +00:00
//Read the Mesh File:
boost : : scoped_ptr < CIrrXML_IOStreamReader > mIOWrapper ( new CIrrXML_IOStreamReader ( File . get ( ) ) ) ;
XmlReader * SkeletonFile = irr : : io : : createIrrXMLReader ( mIOWrapper . get ( ) ) ;
if ( ! SkeletonFile )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( string ( " Failed to create XML Reader for " ) + FileName ) ;
2009-09-13 18:26:54 +00:00
//Quick note: Whoever read this should know this one thing: irrXml fucking sucks!!!
XmlRead ( SkeletonFile ) ;
if ( string ( " skeleton " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " No <skeleton> node in SkeletonFile: " + FileName ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//------------------------------------load bones-----------------------------------------
XmlRead ( SkeletonFile ) ;
if ( string ( " bones " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " No bones node in skeleton " + FileName ) ;
2009-09-17 19:05:46 +00:00
2009-09-13 18:26:54 +00:00
XmlRead ( SkeletonFile ) ;
2009-09-17 19:05:46 +00:00
while ( string ( " bone " ) = = SkeletonFile - > getNodeName ( ) )
2009-09-13 18:26:54 +00:00
{
2010-03-19 20:45:40 +00:00
//TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appear, so what....
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//read a new bone:
Bone NewBone ;
NewBone . Id = GetAttribute < int > ( SkeletonFile , " id " ) ;
NewBone . Name = GetAttribute < string > ( SkeletonFile , " name " ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//load the position:
XmlRead ( SkeletonFile ) ;
if ( string ( " position " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Position is not first node in Bone! " ) ;
2009-09-17 19:05:46 +00:00
NewBone . Position . x = GetAttribute < float > ( SkeletonFile , " x " ) ;
NewBone . Position . y = GetAttribute < float > ( SkeletonFile , " y " ) ;
NewBone . Position . z = GetAttribute < float > ( SkeletonFile , " z " ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//Rotation:
XmlRead ( SkeletonFile ) ;
if ( string ( " rotation " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Rotation is not the second node in Bone! " ) ;
2009-09-17 19:05:46 +00:00
NewBone . RotationAngle = GetAttribute < float > ( SkeletonFile , " angle " ) ;
XmlRead ( SkeletonFile ) ;
if ( string ( " axis " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " No axis specified for bone rotation! " ) ;
2009-09-17 19:05:46 +00:00
NewBone . RotationAxis . x = GetAttribute < float > ( SkeletonFile , " x " ) ;
NewBone . RotationAxis . y = GetAttribute < float > ( SkeletonFile , " y " ) ;
NewBone . RotationAxis . z = GetAttribute < float > ( SkeletonFile , " z " ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//append the newly loaded bone to the bone list
Bones . push_back ( NewBone ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//Proceed to the next bone:
XmlRead ( SkeletonFile ) ;
2009-09-13 18:26:54 +00:00
}
//The bones in the file a not neccesarly ordered by there id's so we do it now:
2009-09-21 17:41:57 +00:00
std : : sort ( Bones . begin ( ) , Bones . end ( ) ) ;
2010-04-19 17:50:52 +00:00
2009-09-13 18:26:54 +00:00
//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 )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Bone Ids are not valid! " + FileName ) ;
2009-09-13 18:26:54 +00:00
}
2010-05-10 21:06:44 +00:00
DefaultLogger : : get ( ) - > debug ( ( Formatter : : format ( ) , " Number of bones: " , Bones . size ( ) ) ) ;
2009-09-17 19:05:46 +00:00
//________________________________________________________________________________
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//----------------------------load bonehierarchy--------------------------------
if ( string ( " bonehierarchy " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " no bonehierarchy node in " + FileName ) ;
2009-09-17 19:05:46 +00:00
DefaultLogger : : get ( ) - > debug ( " loading bonehierarchy... " ) ;
XmlRead ( SkeletonFile ) ;
while ( string ( " boneparent " ) = = SkeletonFile - > getNodeName ( ) )
2009-09-13 18:26:54 +00:00
{
2009-09-17 19:05:46 +00:00
string Child , Parent ;
Child = GetAttribute < string > ( SkeletonFile , " bone " ) ;
Parent = GetAttribute < string > ( SkeletonFile , " parent " ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
unsigned int ChildId , ParentId ;
ChildId = find ( Bones . begin ( ) , Bones . end ( ) , Child ) - > Id ;
ParentId = find ( Bones . begin ( ) , Bones . end ( ) , Parent ) - > Id ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
Bones [ ChildId ] . ParentId = ParentId ;
Bones [ ParentId ] . Children . push_back ( ChildId ) ;
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
XmlRead ( SkeletonFile ) ; //i once forget this line, which led to an endless loop, did i mentioned, that irrxml sucks??
2009-09-13 18:26:54 +00:00
}
2009-09-17 19:05:46 +00:00
//_____________________________________________________________________________
2009-09-13 18:26:54 +00:00
2009-09-28 16:53:33 +00:00
//--------- Calculate the WorldToBoneSpace Matrix recursivly for all bones: ------------------
BOOST_FOREACH ( Bone theBone , Bones )
{
if ( - 1 = = theBone . ParentId ) //the bone is a root bone
{
2010-03-19 20:45:40 +00:00
theBone . CalculateBoneToWorldSpaceMatrix ( Bones ) ;
2009-09-28 16:53:33 +00:00
}
}
//_______________________________________________________________________
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
//---------------------------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 ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " no tracks node in animation " ) ;
2009-09-17 19:05:46 +00:00
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 ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " no keyframes node! " ) ;
2009-09-17 19:05:46 +00:00
XmlRead ( SkeletonFile ) ;
while ( string ( " keyframe " ) = = SkeletonFile - > getNodeName ( ) )
{
Keyframe NewKeyframe ;
NewKeyframe . Time = GetAttribute < float > ( SkeletonFile , " time " ) ;
//Position:
XmlRead ( SkeletonFile ) ;
if ( string ( " translate " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " translate node not first in keyframe " ) ;
2010-03-19 20:45:40 +00:00
NewKeyframe . Position . x = GetAttribute < float > ( SkeletonFile , " x " ) ;
NewKeyframe . Position . y = GetAttribute < float > ( SkeletonFile , " y " ) ;
NewKeyframe . Position . z = GetAttribute < float > ( SkeletonFile , " z " ) ;
2009-09-17 19:05:46 +00:00
//Rotation:
XmlRead ( SkeletonFile ) ;
if ( string ( " rotate " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " rotate is not second node in keyframe " ) ;
2009-09-17 19:05:46 +00:00
float RotationAngle = GetAttribute < float > ( SkeletonFile , " angle " ) ;
aiVector3D RotationAxis ;
XmlRead ( SkeletonFile ) ;
if ( string ( " axis " ) ! = SkeletonFile - > getNodeName ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " No axis for keyframe rotation! " ) ;
2009-09-17 19:05:46 +00:00
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 ( ) )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " no scalling key in keyframe! " ) ;
2009-09-17 19:05:46 +00:00
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 ) ;
}
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
NewAnimation . Tracks . push_back ( NewTrack ) ;
}
2009-09-13 18:26:54 +00:00
2009-09-17 19:05:46 +00:00
Animations . push_back ( NewAnimation ) ;
}
}
//_____________________________________________________________________________
2009-09-13 18:26:54 +00:00
2009-09-28 16:53:33 +00:00
}
2009-09-13 18:26:54 +00:00
2011-06-09 14:29:32 +00:00
void OgreImporter : : CreateAssimpSkeleton ( const std : : vector < Bone > & Bones , const std : : vector < Animation > & /*Animations*/ )
2009-09-28 16:53:33 +00:00
{
2009-09-13 18:26:54 +00:00
if ( ! m_CurrentScene - > mRootNode )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " No root node exists!! " ) ;
2009-09-13 18:26:54 +00:00
if ( 0 ! = m_CurrentScene - > mRootNode - > mNumChildren )
2010-03-18 17:00:12 +00:00
throw DeadlyImportError ( " Root Node already has childnodes! " ) ;
2009-09-13 18:26:54 +00:00
2010-11-09 18:13:08 +00:00
//Createt the assimp bone hierarchy
2009-09-13 18:26:54 +00:00
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 ) ;
2010-03-19 20:45:40 +00:00
RootBoneNodes . push_back ( CreateAiNodeFromBone ( theBone . Id , Bones , m_CurrentScene - > mRootNode ) ) ; //which will recursily add all other nodes
2009-09-13 18:26:54 +00:00
}
}
2010-11-21 18:27:28 +00:00
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 ( ) ) ;
}
2010-04-19 17:50:52 +00:00
}
2009-09-17 19:05:46 +00:00
2010-04-19 17:50:52 +00:00
void OgreImporter : : PutAnimationsInScene ( const std : : vector < Bone > & Bones , const std : : vector < Animation > & Animations )
{
2009-09-17 19:05:46 +00:00
//-----------------Create the Assimp Animations --------------------
2010-11-09 18:13:08 +00:00
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
2009-09-17 19:05:46 +00:00
{
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 ;
2009-09-28 16:53:33 +00:00
NewAnimation - > mTicksPerSecond = 1.0f ;
2009-09-17 19:05:46 +00:00
//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 ;
2010-03-19 20:45:40 +00:00
//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 ) ;
2010-04-16 19:10:09 +00:00
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 ) ;
2010-03-19 20:45:40 +00:00
2009-09-17 19:05:46 +00:00
//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 )
{
2010-04-16 19:10:09 +00:00
aiMatrix4x4 t2 , t3 ;
2010-03-19 20:45:40 +00:00
2010-04-16 19:10:09 +00:00
//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
2010-03-19 20:45:40 +00:00
//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 ) ;
2009-09-17 19:05:46 +00:00
NewNodeAnim - > mPositionKeys [ k ] . mTime = Animations [ i ] . Tracks [ j ] . Keyframes [ k ] . Time ;
2010-03-19 20:45:40 +00:00
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 ;
2009-09-17 19:05:46 +00:00
}
NewAnimation - > mChannels [ j ] = NewNodeAnim ;
}
m_CurrentScene - > mAnimations [ i ] = NewAnimation ;
}
}
2010-04-16 19:10:09 +00:00
//TODO: Auf nicht vorhandene Animationskeys achten!
2010-04-17 21:36:13 +00:00
//#pragma warning (s.o.)
2009-09-17 19:05:46 +00:00
//__________________________________________________________________
2009-09-13 18:26:54 +00:00
}
2009-09-17 19:05:46 +00:00
2010-04-19 17:50:52 +00:00
aiNode * OgreImporter : : CreateAiNodeFromBone ( int BoneId , const std : : vector < Bone > & Bones , aiNode * ParentNode ) const
2009-09-13 18:26:54 +00:00
{
2010-04-19 17:50:52 +00:00
const aiScene * const m_CurrentScene = this - > m_CurrentScene ; //make sure, that we can access but not change the scene
2011-06-09 14:29:32 +00:00
( void ) m_CurrentScene ;
2010-04-19 17:50:52 +00:00
2009-09-13 18:26:54 +00:00
//----Create the node for this bone and set its values-----
aiNode * NewNode = new aiNode ( Bones [ BoneId ] . Name ) ;
NewNode - > mParent = ParentNode ;
2009-09-21 17:41:57 +00:00
aiMatrix4x4 t0 , t1 ;
2009-09-13 18:26:54 +00:00
//create a matrix from the transformation values of the ogre bone
2010-03-19 20:45:40 +00:00
NewNode - > mTransformation = aiMatrix4x4 : : Rotation ( Bones [ BoneId ] . RotationAngle , Bones [ BoneId ] . RotationAxis , t1 )
* aiMatrix4x4 : : Translation ( Bones [ BoneId ] . Position , t0 )
2009-09-13 18:26:54 +00:00
;
//__________________________________________________________
2009-09-28 16:53:33 +00:00
//---------- recursivly create all children Nodes: ----------
2009-09-13 18:26:54 +00:00
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 ;
}
2010-03-19 20:45:40 +00:00
void Bone : : CalculateBoneToWorldSpaceMatrix ( vector < Bone > & Bones )
2009-09-28 16:53:33 +00:00
{
//Calculate the matrix for this bone:
2010-03-19 20:45:40 +00:00
2009-09-29 10:39:17 +00:00
aiMatrix4x4 t0 , t1 ;
2010-03-19 20:45:40 +00:00
aiMatrix4x4 Transf = aiMatrix4x4 : : Translation ( - Position , t0 )
* aiMatrix4x4 : : Rotation ( - RotationAngle , RotationAxis , t1 )
;
2009-09-28 16:53:33 +00:00
if ( - 1 = = ParentId )
{
2010-03-19 20:45:40 +00:00
BoneToWorldSpace = Transf ;
2009-09-28 16:53:33 +00:00
}
else
{
2010-03-24 21:26:31 +00:00
BoneToWorldSpace = Transf * Bones [ ParentId ] . BoneToWorldSpace ;
2009-09-28 16:53:33 +00:00
}
//and recursivly for all children:
BOOST_FOREACH ( int theChildren , Children )
{
2010-03-19 20:45:40 +00:00
Bones [ theChildren ] . CalculateBoneToWorldSpaceMatrix ( Bones ) ;
2009-09-28 16:53:33 +00:00
}
}
2009-09-05 12:04:32 +00:00
} //namespace Ogre
} //namespace Assimp
2010-02-06 23:52:41 +00:00
# endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER