2012-04-22 22:26:26 +00:00
/*
Open Asset Import Library ( assimp )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Copyright ( c ) 2006 - 2012 , assimp team
All rights reserved .
2014-05-01 21:19:57 +00:00
Redistribution and use of this software in aSource and binary forms ,
2012-04-22 22:26:26 +00:00
with or without modification , are permitted provided that the
following conditions are met :
2014-05-01 21:19:57 +00:00
* Redistributions of aSource code must retain the above
2012-04-22 22:26:26 +00:00
copyright notice , this list of conditions and the
following disclaimer .
* Redistributions in binary form must reproduce the above
copyright notice , this list of conditions and the
following disclaimer in the documentation and / or other
materials provided with the distribution .
* Neither the name of the assimp team , nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
" AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# include "AssimpPCH.h"
# ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
2014-05-01 14:19:03 +00:00
# include "OgreImporter.h"
2012-04-22 22:26:26 +00:00
# include "TinyFormatter.h"
using namespace std ;
namespace Assimp
{
namespace Ogre
{
2014-05-01 13:33:15 +00:00
void OgreImporter : : ReadSkeleton ( const std : : string & pFile , Assimp : : IOSystem * pIOHandler , const aiScene * pScene ,
const std : : string & skeletonFile , vector < Bone > & Bones , vector < Animation > & Animations ) const
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
string filename = skeletonFile ;
if ( EndsWith ( filename , " .skeleton " ) )
{
DefaultLogger : : get ( ) - > warn ( " Mesh is referencing a Ogre binary skeleton. Parsing binary Ogre assets is not supported at the moment. Trying to find .skeleton.xml file instead. " ) ;
filename + = " .xml " ;
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
if ( ! pIOHandler - > Exists ( filename ) )
{
DefaultLogger : : get ( ) - > error ( " Failed to find skeleton file ' " + filename + " ', skeleton will be missing. " ) ;
return ;
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
boost : : scoped_ptr < IOStream > file ( pIOHandler - > Open ( filename ) ) ;
2014-05-02 21:20:17 +00:00
if ( ! file . get ( ) ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " Failed to open skeleton file " + filename ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
boost : : scoped_ptr < CIrrXML_IOStreamReader > stream ( new CIrrXML_IOStreamReader ( file . get ( ) ) ) ;
XmlReader * reader = irr : : io : : createIrrXMLReader ( stream . get ( ) ) ;
2014-05-02 21:20:17 +00:00
if ( ! reader ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " Failed to create XML reader for skeleton file " + filename ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
DefaultLogger : : get ( ) - > debug ( " Reading skeleton ' " + filename + " ' " ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Root
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " skeleton " ) ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " Root node is not <skeleton> but < " + string ( reader - > getNodeName ( ) ) + " > in " + filename ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Bones
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " bones " ) ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " No <bones> node in skeleton " + skeletonFile ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
NextNode ( reader ) ;
while ( CurrentNodeNameEquals ( reader , " bone " ) )
2012-04-22 22:26:26 +00:00
{
2014-05-02 21:20:17 +00:00
/** @todo Fix this mandatory ordering. Some exporters might just write rotation first etc.
There is no technical reason this has to be so strict . */
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
Bone bone ;
bone . Id = GetAttribute < int > ( reader , " id " ) ;
bone . Name = GetAttribute < string > ( reader , " name " ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " position " ) ) {
2012-04-22 22:26:26 +00:00
throw DeadlyImportError ( " Position is not first node in Bone! " ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
bone . Position . x = GetAttribute < float > ( reader , " x " ) ;
bone . Position . y = GetAttribute < float > ( reader , " y " ) ;
bone . Position . z = GetAttribute < float > ( reader , " z " ) ;
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " rotation " ) ) {
2012-04-22 22:26:26 +00:00
throw DeadlyImportError ( " Rotation is not the second node in Bone! " ) ;
2014-05-02 21:20:17 +00:00
}
2014-05-01 15:51:26 +00:00
bone . RotationAngle = GetAttribute < float > ( reader , " angle " ) ;
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " axis " ) ) {
2012-04-22 22:26:26 +00:00
throw DeadlyImportError ( " No axis specified for bone rotation! " ) ;
2014-05-02 21:20:17 +00:00
}
2014-05-01 15:51:26 +00:00
bone . RotationAxis . x = GetAttribute < float > ( reader , " x " ) ;
bone . RotationAxis . y = GetAttribute < float > ( reader , " y " ) ;
bone . RotationAxis . z = GetAttribute < float > ( reader , " z " ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
Bones . push_back ( bone ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
NextNode ( reader ) ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
// Order bones by Id
std : : sort ( Bones . begin ( ) , Bones . end ( ) ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Validate that bone indexes are not skipped.
/** @note Left this from original authors code, but not sure if this is strictly necessary
as per the Ogre skeleton spec . It might be more that other ( later ) code in this imported does not break . */
for ( size_t i = 0 , len = Bones . size ( ) ; i < len ; + + i )
2014-05-02 21:20:17 +00:00
{
if ( static_cast < int > ( Bones [ i ] . Id ) ! = static_cast < int > ( i ) ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " Bone Ids are not in sequence in " + skeletonFile ) ;
2014-05-02 21:20:17 +00:00
}
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
DefaultLogger : : get ( ) - > debug ( Formatter : : format ( ) < < " - Bones " < < Bones . size ( ) ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Bone hierarchy
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " bonehierarchy " ) ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " No <bonehierarchy> node found after <bones> in " + skeletonFile ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
NextNode ( reader ) ;
while ( CurrentNodeNameEquals ( reader , " boneparent " ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
string childName = GetAttribute < string > ( reader , " bone " ) ;
string parentName = GetAttribute < string > ( reader , " parent " ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
vector < Bone > : : iterator iterChild = find ( Bones . begin ( ) , Bones . end ( ) , childName ) ;
vector < Bone > : : iterator iterParent = find ( Bones . begin ( ) , Bones . end ( ) , parentName ) ;
if ( iterChild ! = Bones . end ( ) & & iterParent ! = Bones . end ( ) )
{
iterChild - > ParentId = iterParent - > Id ;
iterParent - > Children . push_back ( iterChild - > Id ) ;
}
else
2014-05-02 21:20:17 +00:00
{
2014-05-01 15:51:26 +00:00
DefaultLogger : : get ( ) - > warn ( " Failed to find bones for parenting: Child " + childName + " Parent " + parentName ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
NextNode ( reader ) ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
// Calculate bone matrices for root bones. Recursively does their children.
2012-04-22 22:26:26 +00:00
BOOST_FOREACH ( Bone & theBone , Bones )
{
2014-05-02 21:20:17 +00:00
if ( ! theBone . IsParented ( ) ) {
2012-04-22 22:26:26 +00:00
theBone . CalculateBoneToWorldSpaceMatrix ( Bones ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
aiVector3D zeroVec ( 0.f , 0.f , 0.f ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Animations
if ( CurrentNodeNameEquals ( reader , " animations " ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
DefaultLogger : : get ( ) - > debug ( " - Animations " ) ;
NextNode ( reader ) ;
while ( CurrentNodeNameEquals ( reader , " animation " ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
Animation animation ;
animation . Name = GetAttribute < string > ( reader , " name " ) ;
animation . Length = GetAttribute < float > ( reader , " length " ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Tracks
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " tracks " ) ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " No <tracks> node found in animation ' " + animation . Name + " ' in " + skeletonFile ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
NextNode ( reader ) ;
while ( CurrentNodeNameEquals ( reader , " track " ) )
{
Track track ;
track . BoneName = GetAttribute < string > ( reader , " bone " ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Keyframes
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " keyframes " ) ) {
2014-05-01 15:51:26 +00:00
throw DeadlyImportError ( " No <keyframes> node found in a track in animation ' " + animation . Name + " ' in " + skeletonFile ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
NextNode ( reader ) ;
while ( CurrentNodeNameEquals ( reader , " keyframe " ) )
{
KeyFrame keyFrame ;
keyFrame . Time = GetAttribute < float > ( reader , " time " ) ;
NextNode ( reader ) ;
while ( CurrentNodeNameEquals ( reader , " translate " ) | | CurrentNodeNameEquals ( reader , " rotate " ) | | CurrentNodeNameEquals ( reader , " scale " ) )
{
if ( CurrentNodeNameEquals ( reader , " translate " ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
keyFrame . Position . x = GetAttribute < float > ( reader , " x " ) ;
keyFrame . Position . y = GetAttribute < float > ( reader , " y " ) ;
keyFrame . Position . z = GetAttribute < float > ( reader , " z " ) ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
else if ( CurrentNodeNameEquals ( reader , " rotate " ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
float angle = GetAttribute < float > ( reader , " angle " ) ;
NextNode ( reader ) ;
2014-05-02 21:20:17 +00:00
if ( ! CurrentNodeNameEquals ( reader , " axis " ) ) {
throw DeadlyImportError ( " No axis for keyframe rotation in animation ' " + animation . Name + " ' " ) ;
}
2014-05-01 15:51:26 +00:00
aiVector3D axis ;
axis . x = GetAttribute < float > ( reader , " x " ) ;
axis . y = GetAttribute < float > ( reader , " y " ) ;
axis . z = GetAttribute < float > ( reader , " z " ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
if ( axis . Equal ( zeroVec ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
axis . x = 1.0f ;
2014-05-02 21:20:17 +00:00
if ( angle ! = 0 ) {
2014-05-01 15:51:26 +00:00
DefaultLogger : : get ( ) - > warn ( " Found invalid a key frame with a zero rotation axis in animation ' " + animation . Name + " ' " ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
keyFrame . Rotation = aiQuaternion ( axis , angle ) ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
else if ( CurrentNodeNameEquals ( reader , " scale " ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
keyFrame . Scaling . x = GetAttribute < float > ( reader , " x " ) ;
keyFrame . Scaling . y = GetAttribute < float > ( reader , " y " ) ;
keyFrame . Scaling . z = GetAttribute < float > ( reader , " z " ) ;
}
NextNode ( reader ) ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
track . Keyframes . push_back ( keyFrame ) ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
animation . Tracks . push_back ( track ) ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 15:51:26 +00:00
Animations . push_back ( animation ) ;
DefaultLogger : : get ( ) - > debug ( Formatter : : format ( ) < < " " < < animation . Name < < " ( " < < animation . Length < < " sec, " < < animation . Tracks . size ( ) < < " tracks) " ) ;
2012-04-22 22:26:26 +00:00
}
}
}
2014-05-01 21:19:57 +00:00
void OgreImporter : : CreateAssimpSkeleton ( aiScene * pScene , const std : : vector < Bone > & bones , const std : : vector < Animation > & animations )
2012-04-22 22:26:26 +00:00
{
2014-05-02 21:20:17 +00:00
if ( bones . empty ( ) ) {
2014-05-01 21:19:57 +00:00
return ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-02 21:20:17 +00:00
if ( ! pScene - > mRootNode ) {
2014-05-01 21:19:57 +00:00
throw DeadlyImportError ( " Creating Assimp skeleton: No root node created! " ) ;
2014-05-02 21:20:17 +00:00
}
if ( pScene - > mRootNode - > mNumChildren > 0 ) {
2014-05-01 21:19:57 +00:00
throw DeadlyImportError ( " Creating Assimp skeleton: Root node already has children! " ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
// Bones
vector < aiNode * > rootBones ;
BOOST_FOREACH ( const Bone & bone , bones )
2012-04-22 22:26:26 +00:00
{
2014-05-02 21:20:17 +00:00
if ( ! bone . IsParented ( ) ) {
2014-05-01 21:19:57 +00:00
rootBones . push_back ( CreateNodeFromBone ( bone . Id , bones , pScene - > mRootNode ) ) ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
}
2014-05-01 21:19:57 +00:00
if ( ! rootBones . empty ( ) )
2012-06-03 11:06:47 +00:00
{
2014-05-01 21:19:57 +00:00
pScene - > mRootNode - > mChildren = new aiNode * [ rootBones . size ( ) ] ;
pScene - > mRootNode - > mNumChildren = rootBones . size ( ) ;
2014-05-02 21:20:17 +00:00
for ( size_t i = 0 , len = rootBones . size ( ) ; i < len ; + + i ) {
2014-05-01 21:19:57 +00:00
pScene - > mRootNode - > mChildren [ i ] = rootBones [ i ] ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
}
2014-05-01 13:33:15 +00:00
// TODO: Auf nicht vorhandene Animationskeys achten!
// @todo Pay attention to non-existing animation Keys (google translated from above german comment)
2014-05-01 21:19:57 +00:00
// Animations
if ( ! animations . empty ( ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 21:19:57 +00:00
pScene - > mAnimations = new aiAnimation * [ animations . size ( ) ] ;
pScene - > mNumAnimations = animations . size ( ) ;
for ( size_t ai = 0 , alen = animations . size ( ) ; ai < alen ; + + ai )
2012-04-22 22:26:26 +00:00
{
2014-05-01 21:19:57 +00:00
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 )
2012-04-22 22:26:26 +00:00
{
2014-05-01 21:19:57 +00:00
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 ( ) )
{
2014-05-02 21:20:17 +00:00
for ( size_t createdAnimationIndex = 0 ; createdAnimationIndex < ai ; createdAnimationIndex + + ) {
delete pScene - > mAnimations [ createdAnimationIndex ] ;
}
2014-05-01 21:19:57 +00:00
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 ;
}
2012-04-22 22:26:26 +00:00
aiMatrix4x4 t0 , t1 ;
2014-05-01 21:19:57 +00:00
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 ;
2012-04-22 22:26:26 +00:00
//...and fill them
2014-05-01 21:19:57 +00:00
for ( size_t kfi = 0 ; kfi < numKeyframes ; + + kfi )
2012-04-22 22:26:26 +00:00
{
2014-05-01 21:19:57 +00:00
const KeyFrame & kfSource = tSource . Keyframes [ kfi ] ;
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
// 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 ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
// Calculate the complete transformation from world space to bone space
aiMatrix4x4 CompleteTransform = defaultBonePose * keyBonePose ;
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
aiVector3D kfPos ; aiQuaternion kfRot ; aiVector3D kfScale ;
CompleteTransform . Decompose ( kfScale , kfRot , kfPos ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
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 ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
animationNode - > mPositionKeys [ kfi ] . mValue = kfPos ;
animationNode - > mRotationKeys [ kfi ] . mValue = kfRot ;
animationNode - > mScalingKeys [ kfi ] . mValue = kfScale ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 21:19:57 +00:00
animation - > mChannels [ ti ] = animationNode ;
2012-04-22 22:26:26 +00:00
}
2014-05-01 21:19:57 +00:00
pScene - > mAnimations [ ai ] = animation ;
2012-04-22 22:26:26 +00:00
}
}
}
2014-05-01 21:19:57 +00:00
aiNode * OgreImporter : : CreateNodeFromBone ( int boneId , const std : : vector < Bone > & bones , aiNode * parent )
2012-04-22 22:26:26 +00:00
{
aiMatrix4x4 t0 , t1 ;
2014-05-01 21:19:57 +00:00
const Bone & source = bones [ boneId ] ;
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
aiNode * boneNode = new aiNode ( source . Name ) ;
boneNode - > mParent = parent ;
boneNode - > mTransformation = aiMatrix4x4 : : Translation ( source . Position , t0 ) * aiMatrix4x4 : : Rotation ( source . RotationAngle , source . RotationAxis , t1 ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
if ( ! source . Children . empty ( ) )
2012-04-22 22:26:26 +00:00
{
2014-05-01 21:19:57 +00:00
boneNode - > mChildren = new aiNode * [ source . Children . size ( ) ] ;
boneNode - > mNumChildren = source . Children . size ( ) ;
2012-04-22 22:26:26 +00:00
2014-05-02 21:20:17 +00:00
for ( size_t i = 0 , len = source . Children . size ( ) ; i < len ; + + i ) {
2014-05-01 21:19:57 +00:00
boneNode - > mChildren [ i ] = CreateNodeFromBone ( source . Children [ i ] , bones , boneNode ) ;
2014-05-02 21:20:17 +00:00
}
2014-05-01 21:19:57 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 21:19:57 +00:00
return boneNode ;
2012-04-22 22:26:26 +00:00
}
void Bone : : CalculateBoneToWorldSpaceMatrix ( vector < Bone > & Bones )
{
2014-05-01 15:51:26 +00:00
aiMatrix4x4 t0 , t1 ;
aiMatrix4x4 transform = aiMatrix4x4 : : Rotation ( - RotationAngle , RotationAxis , t1 ) * aiMatrix4x4 : : Translation ( - Position , t0 ) ;
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
if ( ! IsParented ( ) )
2014-05-02 21:20:17 +00:00
{
2014-05-01 15:51:26 +00:00
BoneToWorldSpace = transform ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
else
2014-05-02 21:20:17 +00:00
{
2014-05-01 15:51:26 +00:00
BoneToWorldSpace = transform * Bones [ ParentId ] . BoneToWorldSpace ;
2014-05-02 21:20:17 +00:00
}
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
// Recursively for all children now that the parent matrix has been calculated.
BOOST_FOREACH ( int childId , Children )
2012-04-22 22:26:26 +00:00
{
2014-05-01 15:51:26 +00:00
Bones [ childId ] . CalculateBoneToWorldSpaceMatrix ( Bones ) ;
2012-04-22 22:26:26 +00:00
}
}
2014-05-01 15:51:26 +00:00
} // Ogre
} // Assimp
2012-04-22 22:26:26 +00:00
2014-05-01 15:51:26 +00:00
# endif // ASSIMP_BUILD_NO_OGRE_IMPORTER