Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.5.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
AssimpAnimationDataLoader.cpp
1 #include <IO/AssimpLoader/AssimpAnimationDataLoader.hpp>
2 
3 #include <assimp/scene.h>
4 #include <set>
5 
6 #include <Core/Animation/KeyFramedValue.hpp>
7 #include <Core/Animation/KeyFramedValueInterpolators.hpp>
8 #include <Core/Asset/AnimationData.hpp>
9 #include <Core/Math/Math.hpp>
10 #include <Core/Utils/Log.hpp>
11 
12 #include <IO/AssimpLoader/AssimpWrapper.hpp>
13 
14 namespace Ra {
15 namespace IO {
16 
17 using namespace Core::Utils; // log
18 using namespace Core::Animation;
19 using namespace Core::Asset;
20 
23  DataLoader<AnimationData>( VERBOSE_MODE ) {}
24 
27 
29 void AssimpAnimationDataLoader::loadData( const aiScene* scene,
30  std::vector<std::unique_ptr<AnimationData>>& data ) {
31  data.clear();
32 
33  if ( scene == nullptr ) {
34  LOG( logDEBUG ) << "AssimpAnimationDataLoader : scene is nullptr.";
35  return;
36  }
37 
38  if ( !sceneHasAnimation( scene ) ) {
39  LOG( logDEBUG ) << "AssimpAnimationDataLoader : scene has no animation.";
40  return;
41  }
42 
43  if ( m_verbose ) {
44  LOG( logDEBUG ) << "File contains animation.";
45  LOG( logDEBUG ) << "Animation Loading begin...";
46  }
47 
48  loadAnimationData( scene, data );
49 
50  if ( m_verbose ) { LOG( logDEBUG ) << "Animation Loading end.\n"; }
51 }
52 
54 bool AssimpAnimationDataLoader::sceneHasAnimation( const aiScene* scene ) const {
55  return ( sceneAnimationSize( scene ) != 0 );
56 }
57 
58 uint AssimpAnimationDataLoader::sceneAnimationSize( const aiScene* scene ) const {
59  if ( scene->HasAnimations() ) { return scene->mNumAnimations; }
60  return 0;
61 }
62 
64 void AssimpAnimationDataLoader::fetchName( const aiAnimation* anim, AnimationData* data ) const {
65  data->setName( assimpToCore( anim->mName ) );
66 }
67 
69 void AssimpAnimationDataLoader::fetchTime( const aiAnimation* anim, AnimationData* data ) const {
70  const auto tick = Scalar( anim->mTicksPerSecond );
71  const auto duration = Scalar( anim->mDuration );
72 
73  AnimationTime time;
75  time.setStart( 0.0 );
76  if ( Ra::Core::Math::areApproxEqual( tick, 0_ra ) ) {
77  dt = 0.0;
78  time.setEnd( duration );
79  }
80  else {
81  dt = Scalar( 1.0 ) / tick;
82  time.setEnd( dt * duration );
83  }
84  data->setTime( time );
85  data->setTimeStep( dt );
86 }
87 
90  const aiScene* scene,
91  std::vector<std::unique_ptr<AnimationData>>& data ) const {
92  const uint size = sceneAnimationSize( scene );
93  data.resize( size );
94  for ( uint i = 0; i < size; ++i ) {
95  aiAnimation* anim = scene->mAnimations[i];
96  AnimationData* animData = new AnimationData();
97  fetchName( anim, animData );
98  fetchTime( anim, animData );
99  fetchAnimation( anim, animData );
100  if ( m_verbose ) { animData->displayInfo(); }
101  data[i].reset( animData );
102  }
103 }
104 
105 void AssimpAnimationDataLoader::fetchAnimation( const aiAnimation* anim,
106  AnimationData* data ) const {
107  const uint size = anim->mNumChannels;
108  AnimationTime time = data->getTime();
109  std::vector<HandleAnimation> keyFrame( size );
110  for ( uint i = 0; i < size; ++i ) {
111  fetchHandleAnimation( anim->mChannels[i], keyFrame[i], data->getTimeStep() );
112  time.extends( keyFrame[i].m_animationTime );
113  }
114  data->setHandleData( keyFrame );
115  data->setTime( time );
116 }
117 
119  HandleAnimation& data,
120  const AnimationTime::Time dt ) const {
121  const uint T_size = node->mNumPositionKeys;
122  const uint R_size = node->mNumRotationKeys;
123  const uint S_size = node->mNumScalingKeys;
124  data.m_name = assimpToCore( node->mNodeName );
125 
126  // check if there are keyframes
127  if ( T_size == 0 && R_size == 0 && S_size == 0 ) { return; }
128 
129  // fetch the first keyframes
130  std::set<AnimationTime::Time> keyFrame;
131  AnimationTime::Time time( node->mPositionKeys[0].mTime );
132  // According to Assimp's doc, time can be negative so deal with it
133  AnimationTime::Time timeOffset = time < 0_ra ? -time : 0_ra;
134  keyFrame.insert( time + timeOffset );
135  KeyFramedValue<Core::Vector3> tr( time + timeOffset,
136  assimpToCore( node->mPositionKeys[0].mValue ) );
137  time = Scalar( node->mRotationKeys[0].mTime );
138  keyFrame.insert( time );
139  KeyFramedValue<Core::Quaternion> rot( time + timeOffset,
140  assimpToCore( node->mRotationKeys[0].mValue ) );
141  time = Scalar( node->mScalingKeys[0].mTime );
142  keyFrame.insert( time );
143  KeyFramedValue<Core::Vector3> s( time + timeOffset,
144  assimpToCore( node->mScalingKeys[0].mValue ) );
145 
146  // fetch the other keyframes
147  for ( uint i = 1; i < T_size; ++i ) {
148  time = Scalar( node->mPositionKeys[i].mTime ) + timeOffset;
149  tr.insertKeyFrame( time, assimpToCore( node->mPositionKeys[i].mValue ) );
150  keyFrame.insert( time );
151  }
152 
153  for ( uint i = 1; i < R_size; ++i ) {
154  time = Scalar( node->mRotationKeys[i].mTime ) + timeOffset;
155  rot.insertKeyFrame( time, assimpToCore( node->mRotationKeys[i].mValue ) );
156  keyFrame.insert( time );
157  }
158 
159  for ( uint i = 1; i < S_size; ++i ) {
160  time = Scalar( node->mScalingKeys[i].mTime ) + timeOffset;
161  s.insertKeyFrame( time, assimpToCore( node->mScalingKeys[i].mValue ) );
162  keyFrame.insert( time );
163  }
164 
165  // fill data
166  data.m_animationTime = AnimationTime( *keyFrame.begin(), *keyFrame.rbegin() );
167  for ( const auto& t : keyFrame ) {
168  Core::Transform T;
169  T.fromPositionOrientationScale( tr.at( t, linearInterpolate<Core::Vector3> ),
170  rot.at( t, linearInterpolate<Core::Quaternion> ),
171  s.at( t, linearInterpolate<Core::Vector3> ) );
172  data.m_anim.insertKeyFrame( ( Ra::Core::Math::areApproxEqual( dt, 0_ra ) ? t : ( dt * t ) ),
173  T );
174  }
175  data.m_anim.removeKeyFrame( 0 );
176 }
177 
178 } // namespace IO
179 } // namespace Ra
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)
void setStart(const Time &start)
void setEnd(const Time &end)
~AssimpAnimationDataLoader() override
DESTRUCTOR.
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
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 loadData(const aiScene *scene, std::vector< std::unique_ptr< Core::Asset::AnimationData >> &data) override
LOADING.
void fetchName(const aiAnimation *anim, Core::Asset::AnimationData *data) const
NAME.
void loadAnimationData(const aiScene *scene, std::vector< std::unique_ptr< Core::Asset::AnimationData >> &data) const
KEY FRAME.
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
Definition: Cage.cpp:3
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.