Time-based animation

Started by
16 comments, last by ta0soft 13 years, 1 month ago
Is there a way to convert a rotation vector into a quaternion? [/quote]
Not sure what you mean by "rotation vector," but look at the D3DXQuaternion... functions to create a quaternion in one of several ways.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Advertisement
What I meant was, is there a function that takes yaw/pitch/roll values and returns a quaternion, but you pointed me in the right direction.

It works now! But something is still wrong. Translation and rotation seem to be working fine but the interpolated scale is off. My keyframes are all set to 1.0, 1.0, 1.0 scale, but when I render the animation the mesh shrinks... No idea why :( Am I supposed to normalize something?


Transform* Animation::Update(void)
{
if (Get_KeyFrameCount() == 1) return p_KeyFrames[0]->Get_Transform();

D3DXVECTOR3 transInterp, scaleInterp;
D3DXQUATERNION rotInterp;

if (p_StartTime == 0) p_StartTime = timeGetTime();
p_ElapsedTime = timeGetTime() - p_StartTime;
p_Duration = p_ElapsedTime % p_KeyFrames[Get_KeyFrameCount() - 1]->Get_Time();

for (DWORD i = 0; i < Get_KeyFrameCount(); i++)
{
if (p_Duration >= p_KeyFrames->Get_Time()) p_KeyFrame = i;
}

p_KeyFrame2 = p_KeyFrame == (Get_KeyFrameCount() - 1) ? p_KeyFrame : p_KeyFrame + 1;

DWORD timeDiff = p_KeyFrames[p_KeyFrame2]->Get_Time() - p_KeyFrames[p_KeyFrame]->Get_Time();
if (timeDiff == 0) timeDiff = 1;

float scalar = (float)(p_Duration - p_KeyFrames[p_KeyFrame]->Get_Time()) / (float)timeDiff;

transInterp = p_KeyFrames[p_KeyFrame]->Get_Position() + (1 - scalar) * p_KeyFrames[p_KeyFrame2]->Get_Position();
scaleInterp = p_KeyFrames[p_KeyFrame]->Get_Scale() + (1 - scalar) * p_KeyFrames[p_KeyFrame2]->Get_Scale();
D3DXQuaternionSlerp(&rotInterp, &p_KeyFrames[p_KeyFrame]->Get_Rotation(), &p_KeyFrames[p_KeyFrame2]->Get_Rotation(), scalar);

return new Transform(transInterp, rotInterp, scaleInterp);
};



D3DXMATRIX Transform::Get_Matrix(void)
{
D3DXMATRIXA16 matScale, matRot, matTrans;

D3DXMatrixScaling(&matScale, p_Scale.x, p_Scale.y, p_Scale.z);
D3DXMatrixRotationQuaternion(&matRot, &p_Rotation);
D3DXMatrixTranslation(&matTrans, p_Position.x, p_Position.y, p_Position.z);

return matScale * matRot * matTrans;
};



What have you checked with regard to the values you calculate in your Update function? You can't always debug code just by observing what it does.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Well I've tried using different animation files with a different amount of keyframes and they all seem to perform the same. I've also tried animating different subsets of the mesh. Translation and rotation work exacly as expected, but the mesh (or subset) shrinks from the first keyframe to the last.


// Move mesh 5 points along z axis and back again
[Animation]
Subset=-1
Loop=-1
Key=0 0 0 0 0 0 0 1 1 1
Key=1000 0 0 5 0 0 0 1 1 1
Key=2000 0 0 0 0 0 0 1 1 1

// Rotate subset[1] 1.5 radians along x axis
[Animation]
Subset=1
Loop=-1
Key=0 0 0 0 0 0 0 1 1 1
Key=1000 0 0 0 1.5 0 0 1 1 1

// Move and rotate subset[2]
[Animation]
Subset=2
Loop=-1
Key=0 0 0 0 0 0 0 1 1 1
Key=2000 -5 0 0 1.5 0 0 1 1 1
Key=4000 0 0 0 0 0 0 1 1 1
Key=6000 5 0 0 -1.5 0 0 1 1 1
[/quote]
Okay, it appears the keys all have scales of ( 1,1,1 ) - if the last 3 digits are scale - as you said. As mentioned above, what have you done to determine that your Update function works as expected? Have you stepped through the code, looking at values (such as scaleInterp) when they're calculated?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

After looking at the values more closely, scale isn't the only thing acting strange. Consider the following animation:


// Move 3 points along x axis
[Animation]
Subset=1
Loop=-1
Key=0 0 0 0 0 0 0 1 1 1
Key=100 3 0 0 0 0 0 1 1 1
[/quote]

I used OutputDebugString to look at the interpolated values, transInterp should start at 0, 0, 0 and end at 3, 0, 0 but it looks like it's doing the opposite. scaleInterp starts at 2, 2, 2 and ends at 1, 1, 1 (no idea why). rotInterp works as expected, so I'm guessing it has something to do with the equasion (keyframe1Scale + (1 - scalar) * keyframe2Scale)


Time: 0 ms
transInterp: 3.0000 0.0000 0.0000
rotInterp: 0.0000 0.0000 0.0000 1.0000
scaleInterp: 2.0000 2.0000 2.0000

Time: 40 ms
transInterp: 1.8000 0.0000 0.0000
rotInterp: 0.0000 0.0000 0.0000 1.0000
scaleInterp: 1.6000 1.6000 1.6000

Time: 50 ms
transInterp: 1.5000 0.0000 0.0000
rotInterp: 0.0000 0.0000 0.0000 1.0000
scaleInterp: 1.5000 1.5000 1.5000

Time: 70 ms
transInterp: 0.9000 0.0000 0.0000
rotInterp: 0.0000 0.0000 0.0000 1.0000
scaleInterp: 1.3000 1.3000 1.3000

Time: 90 ms
transInterp: 0.3000 0.0000 0.0000
rotInterp: 0.0000 0.0000 0.0000 1.0000
scaleInterp: 1.1000 1.1000 1.1000

Time: 100 ms
transInterp: 3.0000 0.0000 0.0000
rotInterp: 0.0000 0.0000 0.0000 1.0000
scaleInterp: 2.0000 2.0000 2.0000
[/quote]
Linear [size=2]interpolation is done as
[size=2]g( w ) := f[sub]1[/sub] [size=2]* ( 1 - w ) + f[sub]2[/sub][size=2] * w == f[sub]1[/sub][size=2] + ( f[sub]2[/sub][size=2] - f[sub]1[/sub][size=2] ) * w
[size=2]with w being the weight, f[sub]1[/sub][size=2] being the "start" value and f[sub]2[/sub][size=2] the "end" value, so that
[size=2]g( w=0 ) == f[sub][size=2]1[/sub][size=2]
g( w=1 ) == f[sub][size=2]2[/sub][size=2]
[sub][/sub]
[sub]Use that for translation as well as for scaling.[/sub]
[sub] [/sub]
[sub]For comparison: Your (wrong) equation seems to be [/sub]
[sub]

[size=2]f[sub]1[/sub] [size=2]+ ( 1 - w ) * f[sub]2[/sub][/sub]

I figured it out by using D3DXVec3Lerp as Buckeye mentioned above. Works perfect now thanks to both of you for the help and patience!

This topic is closed to new replies.

Advertisement