# c++ Directx9 X File Animation (finding when an animation has finished)

## Recommended Posts

r_bewick    146
Hi, how can I find out when a model has finished its current animation, and when it starts a new one, the current time of the animation, and the time the animation takes to complete? thanks, r_bewick

##### Share on other sites
Steve_Segreto    2080
There are two concepts of time with the Animation Mixer for DX9, a global time and a periodic track time. The global time goes from 0 to infinity and isn't very useful for your purposes. A track's periodic position can be queried either by asking the animation set what its periodic position is or getting the track description information from the mixer (see below).

ID3DXAnimationSet::GetPeriodicPosition() - Returns time position in the local timeframe of an animation set.
ID3DXAnimationSet::GetPeriod() - Gets the period (length) of the animation set.

Now the tricky part is deciding when the current animation has ended and when the next one begins. Its tricky because the animation mixer wasn't designed to tell you that information because it pretty much doesn't know for sure either.

There are two situations to consider:

1. You could be looping the current animation and it doesn't actually hit the end exactly it just cycles back to the beginning because the time delta you updated the mixer with is fairly large (slower framerate).

2. You could be doing a cross-fade, blending out of one animation and into another, so the current animation isn't 100% running anymore, but it isn't 100% ended either.

The easiest way to detect when you are "close" to the end of a period on a particular track is like this:

LPD3DXANIMATIONSET pASTrack = NULL;pAC->GetTrackAnimationSet( m_dwCurrentTrack, &pASTrack );if( pASTrack ){    D3DXTRACK_DESC td;    pAC->GetTrackDesc( m_dwCurrentTrack, &td );    if( td.Position > pASTrack->GetPeriod() - EPSILON)    {        // Animation is within EPSILON of its end.    }}

A more correct way would be to query the track position after each update and see if its wrapped from your last recorded position.

[Edited by - Steve_Segreto on May 1, 2010 11:23:50 AM]

##### Share on other sites
r_bewick    146
Thanks so much Steve_Segreto! your information is very clear and easy to read. I know what to do now. Thanks :)

##### Share on other sites
_Camus_    138
Another good way is using D3DXKEY_CALLBACK, you compress the track you want
to know with D3DXCreateCompressedAnimationSet, fill D3DXKEY_CALLBACK as parameter in order to set in witch keytime you need the callback to be called. On the function

pAnimController->AdvanceTime( time, POINTER TO CALLBACK );

Every time your track get to that position, the callback will be called,
you can set it to the end of the animation, or any particular time you need, like sounds or hits, anything.

For further and good written information xD, take a look to the multi-animation sample of directx sdk.

By the way, and sorry my ignorance, what the hell is the operator -&wtf; ??

pAC->GetTrackAnimationSet( m_dwCurrentTrack, &pASTrack );

->

What is gt? i don't understand, and i didn't find any information about that operator =S.

##### Share on other sites
Steve_Segreto    2080
Thanks I used the wrong tag to display the code snippet ;) I think I fixed it now...

##### Share on other sites
r_bewick    146
I've been testing out the code you gave me, Steve_Segreto, and also queried the track position after each update and see if its wrapped from my last recorded position.

For some unknown reason, The track position is set to 0 when the mesh is animating, and when I set a new track then it shows the time that has passed.

eg. My mesh is walking and it shows 0/period (0 being current animation time)
and when i switch the track eg to the attack animation, then back again, it will show the time the mesh walked for then. Like it only updates when you have switched to a different track and back again. Why could this be?

also GetPeriodicPosition() <--- for some reason this is not resetting after the animation restarts. It just keeps going up, like global time of that animation... (weird aye)
also when the track is set to a different one, then back again, the PeriodicPosition should be reset as the animation is restarted. But it is not.

GetPeriod works fine though.

thankyou for the reply, _Camus_. I will now test out what you wrote it looks promising.

##### Share on other sites
Steve_Segreto    2080
What values do you use for the tick rate, loop length and playback enum for the first animation and the second animation?

These values are inferred if you are using the built-in animation controller that gets created via D3DXLoadMeshHierarchyFromX()

Alternatively if you use this API...

HRESULT D3DXCreateKeyframedAnimationSet(
__in LPCSTR pName,
__in DOUBLE TicksPerSecond,
__in D3DXPLAYBACK_TYPE Playback,
__in UINT NumAnimations,
__in UINT NumCallbackKeys,
__in const LPD3DXKEY_CALLBACK *pCallKeys,
__out LPD3DXKEYFRAMEDANIMATIONSET *ppAnimationSet
);

you can specify them yourself.

Even if you use the first way, you can query the playback type via
ID3DXKeyframedAnimationSet->GetPlaybackType(), the length via ID3DXKeyframedAnimationSet->GetPeriod() and the tick rate via ID3DXKeyframedAnimationSet->GetSourceTicksPerSecond()