•      Sign In
• Create Account

## Looping animation problem

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

2 replies to this topic

### #1belfegor  Members

2833
Like
0Likes
Like

Posted 07 March 2013 - 07:14 AM

I was reading "Skinned Mesh Character Animation with Direct3D 9.0c" pdf book by Frank Luna, wich is mostly about animating with D3DX animation classes.
But in it there was also an example of general function for bone interpolation between key frames, witch i took to experiment with (i have ommited scaling factor since i dont need that):

void AnimationController::interpolateKeys(std::size_t k0Inx, std::size_t k1Inx, std::size_t boneInx, D3DXMATRIX& L)

{

const auto& vKeyFrames  = vAnimations[currAnimInx]->getKeyFrames();

const float currAnimLen = vAnimations[currAnimInx]->getLength();

const auto& k0          = vKeyFrames[boneInx][k0Inx];

const auto& k1          = vKeyFrames[boneInx][k1Inx];

// Transform to [0, 1]

float t        = currTime;

float t0       = k0.time;

float t1       = k1.time;

if(k1Inx == 0)

{

t1 = currAnimLen;

}

float lerpTime = (t - t0) / (t1 - t0);

// Compute interpolated RST-values.

D3DXVECTOR3 lerpedT;

D3DXQUATERNION lerpedR;

D3DXVec3Lerp(&lerpedT, &k0.T, &k1.T, lerpTime);

D3DXQuaternionSlerp(&lerpedR, &k0.R, &k1.R, lerpTime);

// Build and return the interpolated local

// transformation matrix for this bone.

D3DXMATRIX T, R;

D3DXMatrixTranslation(&T, lerpedT.x, lerpedT.y, lerpedT.z);

D3DXMatrixRotationQuaternion(&R, &lerpedR);

L = R * T;

assert(!(t > t1));

assert(!(t < t0));

}

void AnimationController::interpolateBone(std::size_t boneInx, D3DXMATRIX& L)

{

std::size_t numKeys      = vAnimations[currAnimInx]->getNumKeys();

std::size_t secondKeyInx = currKeyFrameInx + 1;

if(secondKeyInx >= numKeys)

{

secondKeyInx = 0u;

}

interpolateKeys(currKeyFrameInx, secondKeyInx, boneInx, L);

}

So i write 3ds max exporter plugin using igame interface classes to export skinned data needed for my own animation structure.
This is my update function witch i call every frame:

void AnimationController::update(float dt)

{

const float currAnimLen = vAnimations[currAnimInx]->getLength();

currTime += dt;

// force time into corect range

while(currTime > currAnimLen)

{

currTime -= currAnimLen;

}

// Find first key index

const auto& vKeys   = vAnimations[currAnimInx]->getKeyFrames();

std::size_t numKeys = vAnimations[currAnimInx]->getNumKeys();

currKeyFrameInx = numKeys;

for(std::size_t i = 0; i < numKeys; ++i)

{

float ct = vKeys[0][i+1].time;

if(ct > currTime)

{

currKeyFrameInx = i;

break;

}

}

}

// and call it in my skinned mesh

void SkinnedMesh::update(float dt)

{

animCtrl->update(dt);

for(std::size_t i = 0; i < vBones.size(); ++i)

{

animCtrl->interpolateBone(i, vBones[i].localMat);

}

combineTransforms();

for(std::size_t i = 0; i < vBones.size(); ++i)

{

const auto& vPoseMat = animCtrl->getPoseMat();

vFinalTransforms[i] = vPoseMat[i] * vBones[i].combMat;

}

}

The problem is when it is about at the end frames my character have strange glitch/"sudden jerky movement". I made a video so you can better se what is the problem:

When i play animation in modeling editor, then it loops corectly.

Please comment my code if you see something wrong.
Thank you for your time.

### #2Paradigm Shifter  Members

5832
Like
1Likes
Like

Posted 07 March 2013 - 07:20 AM

for(std::size_t i = 0; i < numKeys; ++i)

{

float ct = vKeys[0][i+1].time;



That looks dodgy... what if i == numKeys - 1, you access vKeys array beyond the end....

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

### #3belfegor  Members

2833
Like
0Likes
Like

Posted 07 March 2013 - 07:41 AM

I have tried this also:

currKeyFrameInx     = 0u;
for(std::size_t i = (numKeys - 1); --i;)
{
float ct = vKeys[0][i].time;
if(ct < currTime)
{
currKeyFrameInx = i;
break;
}
}


But for some reason it isn't in range and it asserts:

assert(!(t > t1));


since t must be t0 < t < t1.

Any tip how should i find correct index for key.

EDIT:

I have 23 keyframes (in one second), this is the keys time (they are in seconds):

EDIT2:

Actually i made a mistake, it should be:

for(std::size_t i = numKeys; --i;)

{

float ct = vKeys[0][i].time;

if(ct < currTime)

{

currKeyFrameInx = i;

break;

}

}


Now it looks correct. Need to refresh my memory how for loop works.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.