Sign in to follow this  
Medo Mex

Blending Two Animations

Recommended Posts

Lets say I have 4 different animation presets inside "character.x":

- Idle

- Walking

- Running

- Reloading weapon

 

I can play any of them, switch between idle to walking smoothly, but

 

How do I play both animations "running and reloading weapon" at the same time?

 

I have been looking for any code sample to accomplish that using D3D9 but I didn't find any.

 

I'm using D3D9 Animation Controller ID3DXAnimationController.

Share this post


Link to post
Share on other sites

I'm able to do animation blending by assigning the two animations into two animation tracks.

 

But now I have another problem, how do I make the transition smooth? I have done it with single animation track, but when I have two animation tracks playing at the same time (animation blending) I don't know how to make the transition smooth between the old animation and the new one.

Share this post


Link to post
Share on other sites

From a technical point of view, the 4 animations enumerated in the OP may require up to 3 different mechanisms:

 

1. Idle <-> Walking often requires one or perhaps 2 modeled animation (i.e. no blending at all) for transitions to look realistic / aesthetic.

 

2. Walking <-> Running can be done with blending. However, both animations are cyclic, and hence blending requires the permanent alignment of the animation phases (i.e. relative acceleration of walking and deceleration of running) during the weighting being truly between 0 and 1.

 

3. Reloading Weapon is usually implemented as override to a part of the other animations (i.e. it does influence the arms but it doesn't influence the legs); this is often called "animation layering" instead of animation blending.

 

Unfortunately, I'm not familiar with D3D's animation controlling, but perhaps the above hints help in finding suitable solutions.

Share this post


Link to post
Share on other sites

@Tispe: That works well ONLY if I'm playing one animation in the animation track, usually I set the old animation on one track and the new one in the other track and I get smooth transition, but now I'm trying to play 2 animations on the track at the same time.

 

The following make the transition smooth if I'm switching between one animation to another:

animController->KeyTrackEnable(m_currentTrack, false, m_currentTime + transitionTime);
animController->KeyTrackWeight(m_currentTrack, 0.0f, m_currentTime, transitionTime, D3DXTRANSITION_LINEAR);
animController->SetTrackEnable(newTrack, true);
animController->KeyTrackWeight(newTrack, 1.0f, m_currentTime, transitionTime, D3DXTRANSITION_LINEAR);
 
In my case I have to apply 2 newTrack instead of one, but I couldn't make it smooth like in the above code.
 
I tried something similar to the above code, but it reset both animations (while I only want to change one animation on track at once, not both)
Edited by Medo3337

Share this post


Link to post
Share on other sites

perhaps becuse when you add the new track, animController->SetTrackEnable(newTrack, true);  the current weight is default to 1.0f. Then you try to transition from 1.0f to 1.0f. Try setting the weight of the new track to 0.0f first.

Edited by Tispe

Share this post


Link to post
Share on other sites

@Tispe: Let me explain to you better:

 

Available Animation presets:

- Walk

- Run

- Reload

 

Here is example:

character->walk();
delay(5000); // Delay for 5 seconds
character->reload();

What do I expect from the above code?

The character starting walking and after 5 seconds he will reload his weapon WHILE still walking.

 

What happens instead?

The character start walking, but when he reload, the "walking" animation RESET

 

What should happen?

When the character reload his weapon, the animation transition should only affect his arms and not his legs, the walking sequence should not get affected

 

I can only resolve this problem when I don't have animation smooth transition by only changing the intended animation track while leaving the other as it is, but how do I fix it while I have smooth transition?

Edited by Medo3337

Share this post


Link to post
Share on other sites

I'm not quite sure what the problem is. If your reload animation has animation keys for your legs then that track will affect them.

reload(){
animController->SetTrackWeight(m_ReloadTrack, 0.0f);		//init weight to 0
animController->SetTrackEnable(m_ReloadTrack, true);
animController->KeyTrackWeight(m_ReloadTrack, 1.0f, m_currentTime, transitionTime, D3DXTRANSITION_LINEAR);	//Start the animation with linear transition blending


//I don't know if you can stack these events. Give it a try anyway. If not this part must be run when you want to turn off the reload animation
animController->KeyTrackWeight(m_ReloadTrack, 0.0f, m_currentTime+transitionTime+AnimationLength, transitionTime, D3DXTRANSITION_LINEAR);
animController->KeyTrackEnable(m_ReloadTrack, false, m_currentTime+2*transitionTime+AnimationLength);
}

Share this post


Link to post
Share on other sites

@Tispe: No, the reload animation is only for reloading, run animation is only running.

 

I want to play both animations run and reload (at the same time)

 

He is my current code to play 2 animations at the same time (and it's working):

animController->UnkeyAllTrackEvents(m_currentTrack);
animController->UnkeyAllTrackEvents(newTrack);

// Get animations
animController->SetTrackAnimationSet(0, walkAnimSet);
animController->SetTrackAnimationSet(1, reloadAnimSet);

// Assign "walk" animation to track 0
animController->SetTrackEnable(0, true);
animController->KeyTrackWeight(0, 1.0f, m_currentTime, transitionTime, D3DXTRANSITION_LINEAR);
animController->SetTrackSpeed(0, 1.0f);

// Assign "reload" animation to track 1
animController->SetTrackEnable(1, true);
animController->KeyTrackWeight(1, 1.0f, m_currentTime, transitionTime, D3DXTRANSITION_LINEAR);
animController->SetTrackSpeed(1, 1.0f);

The only problem is that the animation transition is not smooth, how do I make the transition smooth?

Edited by Medo3337

Share this post


Link to post
Share on other sites

If you want to walk while reloading then you don't transition between any tracks at all, you simply enable the reload animation ontop of the walk animation.

 

If you want to smoothly enable the reload animation then you gradually increase its weight from 0.0f to 1.0f, all while the walk track is weighted 1.0f.

 

If your walking animation makes your arms swing back and forth then the reload animation will "fight" with the walking animation for control of the arms. Therefore it is normal that the reload animation do not have animation keys for lower body bones, and walk animation do not have animation keys for upper body bones. A walk animation will then have to be composed of lower body + upper body, two tracks just to walk!

 

Then you gradually swap out the "walk-upper" animation with the reload animation, which only affects the upper body.

Share this post


Link to post
Share on other sites

@Tispe: I'm getting jerky transition between animations no matter what I do on the track, simply executing the following code make the animation change suddenly:

animController->SetTrackAnimationSet(0, walkAnim);
animController->SetTrackAnimationSet(1, reloadAnim);

Share this post


Link to post
Share on other sites

@Tispe: Well, that's not how I manage animations, I could have bunches of animations, maybe 10-12 different animation per character.

 

The way I'm working on it is that I ONLY assign currently playing animations to the track.

Share this post


Link to post
Share on other sites

Ok, I have a suggestion then.

 

Before you reload your animation tracks, get the current track position using ::GetTrackDesc().

 

When you reapply the animation track, use ::SetTrackPosition() with the position you got from ::GetTrackDesc().

 

Do the same for the track weight, then the track should be where it left off.

 

You can do all of these steps by using SetTrackDesc() instead of :SetTrackPosition() :SetTrackWeight().

::GetTrackDesc();

//reload track

::SetTrackDesc();
Edited by Tispe

Share this post


Link to post
Share on other sites

@Tispe: Take a look at my code, it's manipulating the walking animation making the character walking animation restart from the beginning.

 

I don't know why, I'm just trying to add reload animation to the track (without doing anything to walk animation)

D3DXTRACK_DESC trackDesc;
m_animController->GetTrackDesc(currentTrack, &trackDesc);

m_animController->UnkeyAllTrackEvents(0);
m_animController->UnkeyAllTrackEvents(1);

m_animController->SetTrackAnimationSet(0, walkAnim); // Walking
m_animController->SetTrackAnimationSet(1, reloadAnim); // Reloading

// Keep walking (I don't want to do changes on walking animation here)
m_animController->SetTrackDesc(0, &trackDesc);

// Add reloading animation to the track
m_animController->SetTrackEnable(1, true);
m_animController->SetTrackWeight(1, 1.0f);
m_animController->KeyTrackWeight(1, 1.0f, m_currentTime, transitionTime, D3DXTRANSITION_LINEAR);
m_animController->SetTrackSpeed(1, 1.0f);

Share this post


Link to post
Share on other sites
m_animController->GetTrackDesc(currentTrack, &trackDesc);

Make sure currentTrack is 0, since that is where you place the walking animation

m_animController->SetTrackWeight(1, 1.0f);

Change this to:

m_animController->SetTrackWeight(1, 0.0f);

Did it work?

Share this post


Link to post
Share on other sites

@Tispe: No, same problem, it's restarting the walk animation (smoothly)

 

My intention is to ONLY play reload animation without restarting the walk animation or doing any manipulation to it.

 

Here is the code: 

// Get walk animation track desc
D3DXTRACK_DESC trackDesc;
animController->GetTrackDesc(0, &trackDesc);

animController->UnkeyAllTrackEvents(0);
animController->UnkeyAllTrackEvents(1);

animController->SetTrackAnimationSet(0, walkAnim);
animController->SetTrackAnimationSet(1, reloadAnim);

// Walk animation
animController->SetTrackDesc(0, &trackDesc);

// Reload animation
animController->SetTrackEnable(1, true);
animController->SetTrackWeight(1, 0.0f);
animController->KeyTrackWeight(1, 1.0f, currentTime, transitionTime, D3DXTRANSITION_LINEAR);
animController->SetTrackSpeed(1, 1.0f);
Edited by Medo3337

Share this post


Link to post
Share on other sites

I have a strong feeling your reload animation is trying to animate the lower body. Try to only play the reload animation and watch what happens to the legs, if they move then that would be the problem.

Share this post


Link to post
Share on other sites

Thanks for the great book.

 

I checked it but I couldn't find any example or tutorial for smooth transition when playing multiple animations at the same time.

 

This sample works very well:

http://gearengine.googlecode.com/svn-history/r51/trunk/GearEngine/AnimatedOject.cpp

 

But it can only play one single animation at once, how do I make it play multiple animation at the same time and switch between them smoothly?

 

I want to be able to switch arms animation smoothly while I still have another animation playing for the legs.

 

Assigning both animations to two tracks works but it doesn't switch animations smoothly.

Share this post


Link to post
Share on other sites

@Anddos: I have already done all of that.

 

I'm trying to play any number of animations at the same time (altogether), example: Head animation + Arms animation + Legs animation = Final animation

 

Multiple animation playing on one single character at once, I have done that by setting each one on different track.

 

Now, I have three animations playing on the character, how do I change one of them smoothly? for example:

Change arms animation smoothly while I still have head animation and legs animation playing?

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