Sign in to follow this  
XVincentX

Animation by keyframe - D3D9

Recommended Posts

Hello! Mabye this is not the right place for this question.... Suppose we have a keyframe struct

typedef struct _kf
{
DWORD Time;
D3DMATRIX matTransformation;
} sKeyFrame;

Now suppose i've an array of this struct, defined in this mode (i remember that the D3DXMATRIX constructor takes also a float array...)
sKeyFrame Keyframes[4] = 
{
	// Keyframe 1, 0ms
	{   0, 1.000000f, 0.000000f, 0.000000f, 0.000000f,
	0.000000f, 1.000000f, 0.000000f, 0.000000f,
	0.000000f, 0.000000f, 1.000000f, 0.000000f,
	0.000000f, 0.000000f, 0.000000f, 1.000000f },
	// Keyframe 2, 40ms
	{  400, 0.000796f, 1.000000f, 0.000000f, 0.000000f,
	-1.000000f, 0.000796f, 0.000000f, 0.000000f,
	0.000000f, 0.000000f, 1.000000f, 0.000000f,
	50.000000f, 0.000000f, 0.000000f, 1.000000f },
	// Keyframe 3, 80ms
	{  800, -0.999999f,  0.001593f, 0.000000f, 0.000000f,
	-0.001593f, -0.999999f, 0.000000f, 0.000000f,
	0.000000f,  0.000000f, 1.000000f, 0.000000f,
	25.000000f, 25.000000f, 0.000000f, 1.000000f },
	// Keyframe 4, 120ms
	{ 1200, 1.000000f, 0.000000f, 0.000000f, 0.000000f,
	0.000000f, 1.000000f, 0.000000f, 0.000000f,
	0.000000f, 0.000000f, 1.000000f, 0.000000f,
	0.000000f, 0.000000f, 0.000000f, 1.000000f }
};
I've read by the jim adam's book about animation in DirectX that for animate the mesh with these keyframes in cyclical mode, we must do...
 static DWORD StartTime = timeGetTime();
DWORD Time = timeGetTime() - StartTime;
DWORD KeyFrame = 0;
for (int i = 0; i < 4; i++)
{
if ( Time >= Keyframes[i].Time )
KeyFrame = i;
}
DWORD Keyframe2 = (KeyFrame==3) ? KeyFrame : KeyFrame + 1;
DWORD TimeDiff = Keyframes[Keyframe2].Time -
Keyframes[KeyFrame].Time;
if(!TimeDiff)
TimeDiff=1;
float Scalar = (float)(Time - Keyframes[KeyFrame].Time) / (float)TimeDiff;
D3DXMATRIX matInt = D3DXMATRIX(Keyframes[Keyframe2].matTransformation) -
D3DXMATRIX(Keyframes[KeyFrame].matTransformation);
matInt *= Scalar;

matInt += D3DXMATRIX(Keyframes[KeyFrame].matTransformation);
Now there are some things that i've not understood (also i've it's needed the past??? :D) Why DWORD Keyframe2 = (KeyFrame==3) ? KeyFrame : KeyFrame + 1? I think that i should set KeyFrame2 to 0, to restart animation.... What is the scalar value? Why i have to substract the two matrices to have the matInt? Why i've to mul matrix for the scalar value? why i've also to add matrix with the matTransformation of first keyframe? And in all, when the animation it's complete, it does not continue, it stops.. Thank you!

Share this post


Link to post
Share on other sites
Quote:

Why DWORD Keyframe2 = (KeyFrame==3) ? KeyFrame : KeyFrame + 1? I think that i should set KeyFrame2 to 0, to restart animation....


That line doesn't restart the animation. It simply set KeyFrame2 to a value greater or equals than KeyFrame and less than 4. If you want to restart the animation you have to "restart" the timer when it reaches the last keyframe.

In code:
DWORD Time = (timeGetTime() - StartTime) % Keyframes[3].Time;

Quote:

float Scalar = (float)(Time - Keyframes[KeyFrame].Time) / (float)TimeDiff;

D3DXMATRIX matInt = D3DXMATRIX(Keyframes[Keyframe2].matTransformation) -

D3DXMATRIX(Keyframes[KeyFrame].matTransformation);

matInt *= Scalar;

That code linearly interpolate the matrix of the two keyframes.

I think is useless to copy some code from a book if you doesn't understand it. I suggest to learn the basics before trying to do harder things like skeletal animation.

Share this post


Link to post
Share on other sites
DWORD Time = (timeGetTime() - StartTime) % Keyframes[3].Time;


thanks for the answer but i've not understand how it can restart by add the mod with time of third keyframe...

Share this post


Link to post
Share on other sites
Quote:
Original post by XVincentX
DWORD Time = (timeGetTime() - StartTime) % Keyframes[3].Time;


thanks for the answer but i've not understand how it can restart by add the mod with time of third keyframe...


Assuming that Keyframes[3].Time is the length of the whole animation, the mod will cause the time to wrap to the animation length. Any values greater than Keyframes[3].Time will wrap back around to 0 and re-start. Modding x by y gives you the remainder when you divide x by y, and this will always be a number between 0 and y-1 (for positive integers).

If I were you, I would take this book with a grain of salt, for two reasons:
1. The code that you originally posted will not cycle the animation, it will clamp it at the last frame. If the book claims that it will cycle it, it is wrong.
2. The reason why the number 3 is used is because Keyframes[3] is the fourth keyframe, and in this author's example, its the last keyframe. Using a hardcoded value like this, even in a simple example, is terrible programming practice.

Share this post


Link to post
Share on other sites
Just a quick note. You really don't want to store full matrices inside your keyframes. This is very inefficient, and interpolating between matrices isn't good either.

But especially memory usage wise it is pretty bad. It is better to make different keyframe tracks for position, rotation and possibly scale.

Just wanted to mention it :) If this book teaches it this way it for sure doesn't teach you how to do it on the best way :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this