#include "assimp_view.h"
#include <tuple>
using namespace AssimpView;
AnimEvaluator::AnimEvaluator( const aiAnimation* pAnim)
{
mAnim = pAnim;
mLastTime = 0.0;
mLastPositions.resize( pAnim->mNumChannels, std::make_tuple( 0, 0, 0));
}
void AnimEvaluator::Evaluate( double pTime)
{
double ticksPerSecond = mAnim->mTicksPerSecond != 0.0 ? mAnim->mTicksPerSecond : 25.0;
pTime *= ticksPerSecond;
double time = 0.0f;
if( mAnim->mDuration > 0.0)
time = fmod( pTime, mAnim->mDuration);
if( mTransforms.size() != mAnim->mNumChannels)
mTransforms.resize( mAnim->mNumChannels);
for( unsigned int a = 0; a < mAnim->mNumChannels; a++)
{
const aiNodeAnim* channel = mAnim->mChannels[a];
aiVector3D presentPosition( 0, 0, 0);
if( channel->mNumPositionKeys > 0)
{
unsigned int frame = (time >= mLastTime) ? std::get<0>(mLastPositions[a]) : 0;
while( frame < channel->mNumPositionKeys - 1)
{
if( time < channel->mPositionKeys[frame+1].mTime)
break;
frame++;
}
unsigned int nextFrame = (frame + 1) % channel->mNumPositionKeys;
const aiVectorKey& key = channel->mPositionKeys[frame];
const aiVectorKey& nextKey = channel->mPositionKeys[nextFrame];
double diffTime = nextKey.mTime - key.mTime;
if( diffTime < 0.0)
diffTime += mAnim->mDuration;
if( diffTime > 0)
{
float factor = float( (time - key.mTime) / diffTime);
presentPosition = key.mValue + (nextKey.mValue - key.mValue) * factor;
} else
{
presentPosition = key.mValue;
}
std::get<0>(mLastPositions[a]) = frame;
}
aiQuaternion presentRotation( 1, 0, 0, 0);
if( channel->mNumRotationKeys > 0)
{
unsigned int frame = (time >= mLastTime) ? std::get<1>(mLastPositions[a]) : 0;
while( frame < channel->mNumRotationKeys - 1)
{
if( time < channel->mRotationKeys[frame+1].mTime)
break;
frame++;
}
unsigned int nextFrame = (frame + 1) % channel->mNumRotationKeys;
const aiQuatKey& key = channel->mRotationKeys[frame];
const aiQuatKey& nextKey = channel->mRotationKeys[nextFrame];
double diffTime = nextKey.mTime - key.mTime;
if( diffTime < 0.0)
diffTime += mAnim->mDuration;
if( diffTime > 0)
{
float factor = float( (time - key.mTime) / diffTime);
aiQuaternion::Interpolate( presentRotation, key.mValue, nextKey.mValue, factor);
} else
{
presentRotation = key.mValue;
}
std::get<1>(mLastPositions[a]) = frame;
}
aiVector3D presentScaling( 1, 1, 1);
if( channel->mNumScalingKeys > 0)
{
unsigned int frame = (time >= mLastTime) ? std::get<2>(mLastPositions[a]) : 0;
while( frame < channel->mNumScalingKeys - 1)
{
if( time < channel->mScalingKeys[frame+1].mTime)
break;
frame++;
}
presentScaling = channel->mScalingKeys[frame].mValue;
std::get<2>(mLastPositions[a]) = frame;
}
aiMatrix4x4& mat = mTransforms[a];
mat = aiMatrix4x4( presentRotation.GetMatrix());
mat.a1 *= presentScaling.x; mat.b1 *= presentScaling.x; mat.c1 *= presentScaling.x;
mat.a2 *= presentScaling.y; mat.b2 *= presentScaling.y; mat.c2 *= presentScaling.y;
mat.a3 *= presentScaling.z; mat.b3 *= presentScaling.z; mat.c3 *= presentScaling.z;
mat.a4 = presentPosition.x; mat.b4 = presentPosition.y; mat.c4 = presentPosition.z;
}
mLastTime = time;
}