Radium Engine  1.6.3
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AssimpAnimationDataLoader.cpp
1#include <Core/Animation/KeyFramedValue.hpp>
2#include <Core/Animation/KeyFramedValueInterpolators.hpp>
3#include <Core/Asset/AnimationData.hpp>
4#include <Core/Math/Math.hpp>
5#include <Core/Types.hpp>
6#include <Core/Utils/Log.hpp>
7#include <Eigen/Core>
8#include <IO/AssimpLoader/AssimpAnimationDataLoader.hpp>
9#include <IO/AssimpLoader/AssimpWrapper.hpp>
10#include <algorithm>
11#include <assimp/anim.h>
12#include <assimp/scene.h>
13#include <iterator>
14#include <ostream>
15#include <set>
16#include <string>
17
18namespace Ra {
19namespace IO {
20
21using namespace Core::Utils; // log
22using namespace Core::Animation;
23using namespace Core::Asset;
24
27 DataLoader<AnimationData>( VERBOSE_MODE ) {}
28
31
33void AssimpAnimationDataLoader::loadData( const aiScene* scene,
35 data.clear();
36
37 if ( scene == nullptr ) {
38 LOG( logDEBUG ) << "AssimpAnimationDataLoader : scene is nullptr.";
39 return;
40 }
41
42 if ( !sceneHasAnimation( scene ) ) {
43 LOG( logDEBUG ) << "AssimpAnimationDataLoader : scene has no animation.";
44 return;
45 }
46
47 if ( m_verbose ) {
48 LOG( logDEBUG ) << "File contains animation.";
49 LOG( logDEBUG ) << "Animation Loading begin...";
50 }
51
52 loadAnimationData( scene, data );
53
54 if ( m_verbose ) { LOG( logDEBUG ) << "Animation Loading end.\n"; }
55}
56
58bool AssimpAnimationDataLoader::sceneHasAnimation( const aiScene* scene ) const {
59 return ( sceneAnimationSize( scene ) != 0 );
60}
61
62uint AssimpAnimationDataLoader::sceneAnimationSize( const aiScene* scene ) const {
63 if ( scene->HasAnimations() ) { return scene->mNumAnimations; }
64 return 0;
65}
66
68void AssimpAnimationDataLoader::fetchName( const aiAnimation* anim, AnimationData* data ) const {
69 data->setName( assimpToCore( anim->mName ) );
70}
71
73void AssimpAnimationDataLoader::fetchTime( const aiAnimation* anim, AnimationData* data ) const {
74 const auto tick = Scalar( anim->mTicksPerSecond );
75 const auto duration = Scalar( anim->mDuration );
76
77 AnimationTime time;
79 time.setStart( 0.0 );
80 if ( Ra::Core::Math::areApproxEqual( tick, 0_ra ) ) {
81 dt = 0.0;
82 time.setEnd( duration );
83 }
84 else {
85 dt = Scalar( 1.0 ) / tick;
86 time.setEnd( dt * duration );
87 }
88 data->setTime( time );
89 data->setTimeStep( dt );
90}
91
94 const aiScene* scene,
96 const uint size = sceneAnimationSize( scene );
97 data.resize( size );
98 for ( uint i = 0; i < size; ++i ) {
99 aiAnimation* anim = scene->mAnimations[i];
100 AnimationData* animData = new AnimationData();
101 fetchName( anim, animData );
102 fetchTime( anim, animData );
103 fetchAnimation( anim, animData );
104 if ( m_verbose ) { animData->displayInfo(); }
105 data[i].reset( animData );
106 }
107}
108
109void AssimpAnimationDataLoader::fetchAnimation( const aiAnimation* anim,
110 AnimationData* data ) const {
111 const uint size = anim->mNumChannels;
112 AnimationTime time = data->getTime();
113 std::vector<HandleAnimation> keyFrame( size );
114 for ( uint i = 0; i < size; ++i ) {
115 fetchHandleAnimation( anim->mChannels[i], keyFrame[i], data->getTimeStep() );
116 time.extends( keyFrame[i].m_animationTime );
117 }
118 data->setHandleData( keyFrame );
119 data->setTime( time );
120}
121
123 HandleAnimation& data,
124 const AnimationTime::Time dt ) const {
125 const uint T_size = node->mNumPositionKeys;
126 const uint R_size = node->mNumRotationKeys;
127 const uint S_size = node->mNumScalingKeys;
128 data.m_name = assimpToCore( node->mNodeName );
129
130 // check if there are keyframes
131 if ( T_size == 0 && R_size == 0 && S_size == 0 ) { return; }
132
133 // fetch the first keyframes
135 AnimationTime::Time time( node->mPositionKeys[0].mTime );
136 // According to Assimp's doc, time can be negative so deal with it
137 AnimationTime::Time timeOffset = time < 0_ra ? -time : 0_ra;
138 keyFrame.insert( time + timeOffset );
139 KeyFramedValue<Core::Vector3> tr( time + timeOffset,
140 assimpToCore( node->mPositionKeys[0].mValue ) );
141 time = Scalar( node->mRotationKeys[0].mTime );
142 keyFrame.insert( time );
143 KeyFramedValue<Core::Quaternion> rot( time + timeOffset,
144 assimpToCore( node->mRotationKeys[0].mValue ) );
145 time = Scalar( node->mScalingKeys[0].mTime );
146 keyFrame.insert( time );
147 KeyFramedValue<Core::Vector3> s( time + timeOffset,
148 assimpToCore( node->mScalingKeys[0].mValue ) );
149
150 // fetch the other keyframes
151 for ( uint i = 1; i < T_size; ++i ) {
152 time = Scalar( node->mPositionKeys[i].mTime ) + timeOffset;
153 tr.insertKeyFrame( time, assimpToCore( node->mPositionKeys[i].mValue ) );
154 keyFrame.insert( time );
155 }
156
157 for ( uint i = 1; i < R_size; ++i ) {
158 time = Scalar( node->mRotationKeys[i].mTime ) + timeOffset;
159 rot.insertKeyFrame( time, assimpToCore( node->mRotationKeys[i].mValue ) );
160 keyFrame.insert( time );
161 }
162
163 for ( uint i = 1; i < S_size; ++i ) {
164 time = Scalar( node->mScalingKeys[i].mTime ) + timeOffset;
165 s.insertKeyFrame( time, assimpToCore( node->mScalingKeys[i].mValue ) );
166 keyFrame.insert( time );
167 }
168
169 // fill data
170 data.m_animationTime = AnimationTime( *keyFrame.begin(), *keyFrame.rbegin() );
171 for ( const auto& t : keyFrame ) {
172 Core::Transform T;
173 T.fromPositionOrientationScale( tr.at( t, linearInterpolate<Core::Vector3> ),
174 rot.at( t, linearInterpolate<Core::Quaternion> ),
175 s.at( t, linearInterpolate<Core::Vector3> ) );
176 data.m_anim.insertKeyFrame( ( Ra::Core::Math::areApproxEqual( dt, 0_ra ) ? t : ( dt * t ) ),
177 T );
178 }
179 data.m_anim.removeKeyFrame( 0 );
180}
181
182} // namespace IO
183} // namespace Ra
T begin(T... args)
void insertKeyFrame(const Scalar &t, const VALUE_TYPE &frame)
VALUE_TYPE at(const Scalar &t, const Interpolator &interpolator) const
bool removeKeyFrame(size_t i) override
void setHandleData(const std::vector< HandleAnimation > &frameList)
AnimationTime::Time getTimeStep() const
const AnimationTime & getTime() const
void setName(const std::string &name)
void setTimeStep(const AnimationTime::Time &delta)
void setTime(const AnimationTime &time)
~AssimpAnimationDataLoader() override
DESTRUCTOR.
void loadData(const aiScene *scene, std::vector< std::unique_ptr< Core::Asset::AnimationData > > &data) override
LOADING.
void fetchTime(const aiAnimation *anim, Core::Asset::AnimationData *data) const
TIME.
void fetchHandleAnimation(aiNodeAnim *node, Core::Asset::HandleAnimation &data, const Core::Asset::AnimationTime::Time dt) const
void loadAnimationData(const aiScene *scene, std::vector< std::unique_ptr< Core::Asset::AnimationData > > &data) const
KEY FRAME.
bool sceneHasAnimation(const aiScene *scene) const
QUERY.
uint sceneAnimationSize(const aiScene *scene) const
AssimpAnimationDataLoader(const bool VERBOSE_MODE=false)
CONSTRUCTOR.
void fetchAnimation(const aiAnimation *anim, Core::Asset::AnimationData *data) const
void fetchName(const aiAnimation *anim, Core::Asset::AnimationData *data) const
NAME.
T insert(T... args)
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type areApproxEqual(T x, T y, T espilonBoostFactor=T(10))
Compare two numbers such that |x-y| < espilon*epsilonBoostFactor.
Definition Math.hpp:42
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:4
T rbegin(T... args)
std::string m_name
The Handle's name.
AnimationTime m_animationTime
The AnimationTime for the Handle.
Core::Animation::KeyFramedValue< Transform > m_anim
The list of KeyFramed transforms applied to the Handle.