Radium Engine  1.5.20
Loading...
Searching...
No Matches
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
14namespace Ra {
15namespace IO {
16
17using namespace Core::Utils; // log
18using namespace Core::Animation;
19using namespace Core::Asset;
20
23 DataLoader<AnimationData>( VERBOSE_MODE ) {}
24
27
29void AssimpAnimationDataLoader::loadData( const aiScene* scene,
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
54bool AssimpAnimationDataLoader::sceneHasAnimation( const aiScene* scene ) const {
55 return ( sceneAnimationSize( scene ) != 0 );
56}
57
58uint AssimpAnimationDataLoader::sceneAnimationSize( const aiScene* scene ) const {
59 if ( scene->HasAnimations() ) { return scene->mNumAnimations; }
60 return 0;
61}
62
64void AssimpAnimationDataLoader::fetchName( const aiAnimation* anim, AnimationData* data ) const {
65 data->setName( assimpToCore( anim->mName ) );
66}
67
69void 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,
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
105void 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
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
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:3
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.