Lining up animations with motion

Started by
16 comments, last by RobM 9 years, 6 months ago
Yes, Frob's answer was more clear. I use the term blending to mean smoothly transitioning from one animation to the next. Looping I use to refer to repeatedly cycling the same animation.

Technically either can do what you're looking for, but conceptually it's tricky (at least for my small brain) to figure out how to reconcile the extreme trajectory differences when interpolating two poses that are oriented so differently in the base data.

I find it much easier to understand creating a new animation controller using the animation asset launched at the character's current orientation, and blending that animation controller with the one that is finishing. While the orientation of the key frames in data on their respective frames is extremely different, in world space they are similar (each animation controller has a different orientation offset determined by the character's orientation when the animation is launched).

I generally use looping (interpolating somehow from the last frame back to the first) for things like idling animations or looping run cycles.
Advertisement
Frob/Cardinal, I think you may have missed my, probably, badly explained issue.

My animation system can already blend between animation states using a user-configurable period of time and starting point. This is driven by the transitions in my state engine. So you might have:

Idle state (play animation on loop)
Transition to walk (blends at the point on the current animation (idling) with the first frame of the state we're transitioning to (walking) and does so over a specified period (e.g. 0.5 secs) until it has fully blended at which point we're in the walking state and playing that animation. This is all working really well and looks, even with my bad mocap animations, not bad at all.

My issue is that I have a turn animation with rotational data in it and I'm trying to blend it with an animation that doesn't have rotational (direction/heading) data in it.

Buckeye has suggested removing the heading changes in that animation data meaning I can blend between that and an idle animation and just rotate the whole mesh and everything should line up. This seems feasible to me.

I can't really see any other way around it
Imagine we have two animations, one of a man idling facing north throughout the entire animation. The other he starts off facing north but then turns and faces east.

If I just want him to idle, turn to the east and then idle, my state machine would look like this:

Idle state
Transition to Face east following on with return to idle state

(In my engine I can specify that a transition can automatically move/blend to another state after it has completed its animation)

So we're in the idle state and we push the face east button and we start the transition blend between the idling state and the face east state. I specify a blend time of 0.5 seconds. So we've nicely blended and we're now 0.5 seconds into the face east state and we're midway through that animation facing, say north-east. Even though the mesh has rotated 45 degrees inside the animation, its actual game orientation is still facing north. So with 0.5 seconds to go before the end of the face east animation, we start the transition back to the idling state.

Here is the problem, the idling state pose is facing north but the character on screen is now facing north-east and fast approaching east. If we blend between them, it blend between orientation/directions which is not what we want.

If we were to snap the animations together with no blending, not a problem, we can finish the face east state animation, and just before we switch over to the idling state, we rotate the mesh by 90 degrees. That works but there's no nice blend and we get a pop.

If we try the blend between face east and idling, there is a point at which you have to rotate the mesh 90 degrees and unfortunately because the animations (or at least the frames at that point) are facing in different directions, you get incorrect results wherever you decide to change the mesh's yaw.


Oh, and as for motion, many art tools support something I've always heard of as 'motion accumulation'.

If the motion accumulation flag is clear then characters remain at their root location, occupy the original footprint, and play their animation in place. If the motion accumulation flag is set the motion will be applied to the character's location at the end of the animation clip.

If the character is moving the game does not continuously update the root location, it only updates it at the end of the clip. The character may have been at (32,7), and at the end of the clip on the final frame they are instantly transported to (33,7). it is the code's responsibility to ensure the footprint area is clear so the animation clip can run between locations.

i always wondered how they did that...

isn't that harder?

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


i always wondered how they did that...

isn't that harder?

Not really, and it also solves the newly-updated description of the error.

The steps are simple enough on the object scripts:

if( World.PlaceJig( ... ) ) {

Actor.PlayAnimation( ... ); // Do the clip that causes motion. Animation system will automatically accumulate the motion if animators set the flag.

World.RemoveJig(...);

} else {

Actor.PlayAnimation(...); // Do the appropriate failure clip instead.

}

In our system PlayAnimation() returns early for blended animations, so it might still have 5 or 10 or 0 animation frames remaining on the engine side, but from the game script side the actor is ready to do whatever action comes next.


Here is the problem, the idling state pose is facing north but the character on screen is now facing north-east and fast approaching east. If we blend between them, it blend between orientation/directions which is not what we want.

If the root location has not changed, you are blending (i.e. simultaneously playing) two animations and the combined direction works without effort.

The first one has the model's center location translated from the root bone, with the root still facing the original north and the animation turning the model to mostly east. The second simultaneous, blended animation has the model moving to idle with their arms and legs and whatever other additional motion.

When the first animation ends the accumulated motion is applied to the model's root; the model teleports to the new location. During the next frame everything is smooth because the earlier animation-caused motion now matches the updated root location.

This means the model's forward direction always remains correct. During blending it is correct because the first animation updates the model's position relative to the root followed by updating the position for the second animation; if both clips move the model then both motions are added together and both start from the constant original root, adding the two transformations gives the proper rotation and motion. After the first animation completes it is still correct because the model has been repositioned to exactly the same spot as the end of the completed first animation; any motion in the second clip is still correct, no popping happens.

In most engines I've worked on, actually moving the root of a character is a moderately expensive operation. Moving something means moving the space it occupies, which means tests and possible changes to several spatial trees such as the navmesh and visibility culling trees. It isn't a bad cost by itself, but multiplied by every animation would result in an enormous work load. By letting everything animate within a small area a 'footprint' or 'jig' can be reserved at the beginning of the clip. Failure when placing the footprint means the action should fail in place. For example, if the player pauses the game, plops some walls around the player in a world editor, then resumes the game, the player should be unable to place walls inside the current reserved jig/footprint path because it has been reserved in the spatial tree, but when that running segment is complete the next animation clip should be unable to place the subsequent footprint because the wall is in the way so the code should take a different action, like stopping short.

The performance benefit over one spatial tree update every frame for every animated object, you instead have one spatial tree update at the beginning when an animation jig or footprint is placed, and another spatial tree update when the jig or footprint is removed and the model moved to the new location. That's just two hits at most, zero if the animation doesn't move, instead of one spatial tree hit per animation per update.

I spent some time on this last night and I've managed to get it working, thanks to you guys.

I've taken the position data and yaw/heading angle from the root bone on each animation and inserted it into each clip as a separate stream of data. When I'm blending between a clip that has motion data and one that doesn't (e.g. In-place idling), I simply transform the non-motion data pose to match that of the other one, then blend. At the end of the transition, I transform and rotate the character to match that of the motion data - works great. My character now turns on the spot and when he stops turning, he nicely blends back into idling facing exactly the right direction - it actually looks pretty natural for a first attempt. I now just need to have a look at foot placement but I'm really happy with it so far.

Thanks again for all your help
I was going to start a new topic but this new issue is closely related to this one...

One thing I noticed when I rotated my character, after blending, to match that of the animation frame which contained the separate motion/rotation data is that there was a one frame glitch that happened intermittently. I didn't mention it as I assumed it was something like a frame mismatch.

Now I've investigated it more, it's a very odd thing that happening. When I execute the Idle->turning->idle sequence, I sometimes get a glitch in a frame where it looks like my character is, well, caught in a vertical blank. Sometimes it doesn't happen and it transitions smoothly and other times there is one frame where something is not right, either part of his legs disappear or his head but it happens so quickly in one frame that I can't make it out.

I've tried several things here to debug the issue:

1) added full logging to the whole animation process so I can see exactly what frames (or animation sample) is being used where, what the blend factors are (sometimes if this goes over 1 it can cause animations to go funny), what the matrix values are for my eventual skinning palette. I've been through this log with a fine tooth comb when the glitch happens and everything is exactly as it should be.

2) I've run the app under pixwin (still using dx9) and captured the whole frame set when the glitch happens and get this, when I play back the frames in pixwin, it still happens intermittently!

In pixwin I captured approximately 3000 frames (around 3 seconds worth) and I've been through every frame surrounding roughly where the glitch is and I can't find it. In pix when you capture the whole frame set, when you click on a frame with 'render' selected in the render window, it plays through all the frames and stops on the one you've got selected. I've been through 500 frames worth and sometimes the glitch happens and sometimes it doesn't - very strange.

So if I don't add the yaw value to my player's orientation matrix at the end of the animation transition/blend, I do not get the glitch (the player flicks back to facing north, but even with that I can see there's no glitch). If I add a tiny constant yaw to my player during its update method every frame, he slowly spins with no glitch, even when I'm carrying out the animations (although obviously he flicks back to 'north' each time, but still no glitch).

The thing I can't get my head around is that it's even intermittent in pix and pix is replaying the exact same animation sequence (ruling out any animation synchronisation issues).

Any ideas? I'm at a loss on this one
Apologies for bringing this back to the top, I just wanted to close the topic off. I managed to clear the 'glitch' - unfortunately I don't know why it was happening but I refactored out all my 'prototype' code and laid everything out much neater and it solved the issue. I've got my little character wandering about the screen now with some nicely blended animations.

This topic is closed to new replies.

Advertisement