• Advertisement
Sign in to follow this  

Lining up animations with motion

This topic is 1244 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts


So my animation system is really getting somewhere. Using data, I can specify my full animation state machine with blended transitions and blend trees, really happy so far.

So I was playing about with my mocap suit adding some test animations and I thought it might be good to have my character turn on the spot left and right using animations rather than just spinning him. So I did an animation of me standing idle and turning on the spot to around 90 degrees.

So I added it into my state machine, a transition from idle to the turning left state (blending in 0.2 secs), then, after the turn left animation completes, an auto follow-on transition for turning left into idle (again blending in 0.2 secs). The transitions all looked fine but of course when he went back to idle, he flipped from 90 degrees left back to facing forward again.

I knew at some point I'd have to combine the animations and positioning/orientation in some way so set about having a go. One issue was that my animations blend between each frame including the last and first frame and if I suddenly jump the character by 90 degrees when the first frame is used, I get a little frame arctifact where it shows the tween between last and first. To circumvent this I decided to allow animations to blend between all frames apart from last to first. This stopped the little arctifact showing after his orientation was changed but it meant I had a 'pop' where, although he was facing in the right direction, the last animation frame didn't match the first - something that blending solves.. Hmm...

So as far as I see it, I have two options.

1) do the turn mocap animations in situ, meaning I do the action of turning but I somehow keep the same heading, kind of like a rotational moonwalk! Can't see this being viable (let alone possible).

2) I play around with my animations before exporting them to my engine to ensure that the last frame matches the first exactly. Seems feasible but might be fiddly and a lot of work.

Walking will probably not be such an issue as he's facing the same direction so I can blend them.

Has anyone had experience of this before that may be able to offer some guidance?

Share this post


Link to post
Share on other sites
Advertisement

One issue was that my animations blend between each frame including the last and first frame

 

I'm having to guess a bit without details of your implementation. I'm assuming, for each animation, you have a timed keyframes ("pose" data for a fixed tick count in the animation sequence.) The mentioned issue seems to be the focus of your problem. Blending frames for animation times (tick counts) between data frames is the common approach. From your description it sounds like, for instance, for an animation of period n, at time 0 in the sequence, you blend keyframe n with keyframe 0. If so, can you explain why? If not, can you provide more information on your frame blending algorithm?

 

It may also be that you're not applying the character orientation correctly. By orientation, I mean rotation such as a matrix or quaternion. If you apply the rotation (direction/heading) before the character is rendered, it's not clear why there is a connection between the keyframe data and how the character is rendered at a rotated position.

 

EDIT: It occurs to me that you may be applying the orientation matrix/quaternion directly to the animation data. If so, that may be the problem. A more common approach is to do your animation calculations (blending, etc.), and apply a separate positioning/rotation in the rendering process.

Edited by Buckeye

Share this post


Link to post
Share on other sites
Thanks for the reply. Yes, I blend (or lerp) between keyframes to ensure I have constant animation timings regardless of frame rate or physics rate. This works nicely. For looping animations, if my local time goes beyond the last frame, I blend between the last frame and the first frame but otherwise I find where the local animation time is in the time intervals and blend between the two closest frames - this all works perfectly regardless of frame rate/ ms per frame time, etc. it's fairly standard I believe.

In terms of applying the rotation, I simply add a rotation value (90 degrees in this case) to the entity (the player)'s overall orientation, I don't make any changes to the animation data.

What I currently have as a prototype is a signalling system where the animation system signals to the player component that animation 'x' has completed or is about to reuse frame 0. If the animation has 120 frames (0-119) and the local animation time says we're just past frame index 119 which means we need to blend between 119 and 0, the player is signalled at which point the rotation is applied.

I think it's worth noting that it's not really a timing issue, the rotation is applied correctly at the right time but because the end of the animation is very different to the start, you get untidy results in that last blend. If you remove the blend on the last frame and switch immediately back to the first frame, you still get an arctifact or pop because the physical stance of the player at the start of the animation is slightly different to the stance at the end. The rotation part works ok.

If you just play the turning animation over and over, you get a 'pop' when he flicks from the end of the animation at 90 degrees back to 0 degrees. For him to rotate seamlessly, his stance at the end of the animation (at which point you apply the yaw rotation to the mesh) must be exactly the same as at the start, unfortunately in my animation that isn't the case.

Does that make more sense? It's tricky to explain.

Edit: I think it's also worth noting that if you blend an idle animation with the player facing forward with the final frames of the turn left animation, you would be tweening between two frames that have very different orientations (from an animation data perspective) so u less it was a quick blend, you'd still get popping.

I'm guessing the ideal situation would be to remove the yaw orientation from the turning animation data. Then you could just apply a rotation to the mesh in the game and it would all line up nicely.

Share this post


Link to post
Share on other sites

If you just play the turning animation over and over, you get a 'pop' when he flicks from the end of the animation at 90 degrees back to 0 degrees. For him to rotate seamlessly, his stance at the end of the animation (at which point you apply the yaw rotation to the mesh) must be exactly the same as at the start, unfortunately in my animation that isn't the case.

Does that make more sense? It's tricky to explain.

 

That makes sense. And, indeed, a character rotation being part of the animation is the problem, particularly when blending a rotating animation ("turn") with a non-rotating one ("idle" or "walk"), as the turn is relative to world-space (sort of), but idle/walk/run are taking place in character-space. I have implemented a "turn" animation by divorcing the yaw from the turn (as you mention), and applying the orientation separately. I didn't get very satisfactory results as it's difficult (as you likely know) to determine how much yaw is part of the full character rotation, and how much is part of each body part's motion to achieve rotation.

 

However, divorcing yaw rotation from the turn would seem to be the best promise. I was not using mocap data and, for a "rotationless" turning animation, was able to sync a constant rotation rate to the full animation, i.e., a constant radians-per-second rotation applied to the character's world orientation (after the animation calcs). As a result, it wasn't very natural looking, as "we" don't turn at a constant rate, which (I assume) would be the case with mocap. Further, the appearance varied a bit depending on the magnitude of the rotation - 45 degs vs 90 degs, etc. Separating yaw from a mocap turn doesn't sound like much fun.

 

However, just a suggestion (and this is just blue sky thinking) - it may be a bit complicated, but applying a yaw rate (either constant or variable [sine function?]) to such an animation may not be too bad. That is, revise the mocap frame data by subtracting a per-frame yaw rate, and add that same yaw rate during rendering. That would, at a minimum, put the turn and idle animations into "character" space and take the turn out of "world" space for blending purposes.

Edited by Buckeye

Share this post


Link to post
Share on other sites
The root bone's delta translation and rotation (not absolute) will affect your character's pose. You wouldn't usually loop a turning animation, rather you will blend the same animation with itself if you detect you need to turn again. The new turn is always launch based on your current pose. This way you don't blend two extreme poses and you can still have your skeleton in world space if you need.

Share this post


Link to post
Share on other sites
I think you're right, that does seem like it would work well, I just thought it may be fiddly. In your last paragraph you mentioned about extracting the yaw from the animation. This might not actually be as tricky as it sounds.

The yaw would just come from the root bone so if I can somehow extract that for every frame, I would, as you say, be able to apply it to the (mesh) during the animation. Doing it by hand would be very tedious and it probably wouldn't look right. So if I take an average of the yaw for the first 3 or 4 frames of the animation before he starts turning, I could take each subsequent frame's yaw and subtract the average to get the delta. I'll give this a go and see what happens.

You could apply the same logic to running animations too (probably more easily) which would give you more control over the exact position of the model for things like collision detection.

Thanks very much for your input, I'll let you know how I get on

Share this post


Link to post
Share on other sites
What do you mean by blending the same animation with itself? Isn't that the same as looping but blending between the last and first frame?

The root bone's delta translation and rotation (not absolute) will affect your character's pose. You wouldn't usually loop a turning animation, rather you will blend the same animation with itself if you detect you need to turn again. The new turn is always launch based on your current pose. This way you don't blend two extreme poses and you can still have your skeleton in world space if you need.

Share this post


Link to post
Share on other sites


I could take each subsequent frame's yaw and subtract the average to get the delta.

 

Sounds like that would result in a per-frame "custom" rotation. You might check if yaw is roughly sinusoidal and, if close enough, that would be easier to implement.

 


You could apply the same logic to running animations too

 

If by "same logic," you mean using translation vs. rotation, and your animations include world-space translation, that may work nicely. If I remember correctly, as with turning, character-space movement maps (roughly) sinusoidally to world-space translation.

Share this post


Link to post
Share on other sites


What do you mean by blending the same animation with itself? Isn't that the same as looping but blending between the last and first frame?

 

Frequently you will blend between animations to make them appear continuous. Other times you don't want to blend between animations, especially if you want them to come to a full stop.

 

If your character avatar is running you probably want to blend the animations over a few frames to keep it smooth. If your character should come to a complete stop between animations, like going from a 'stop walking' clip over to the idle loop, then you won't be blending animations. In my experience the number of animation frames to blend is typically a number set by the animators, from zero to whatever. 

 

On my last two projects, our animators had a default blend of 5 frames, not the first and last.

 

As for why blend with itself, it isn't specifically to blend with itself. It is blending from an animation to the next. It is only coincidental that the next animation clip is another instance of itself. A running right turn could just as easily be blending with a 'running left turn', a 'start sprint', a 'slow to walk', or 'running smash into brick wall' animation.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites


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?

Share this post


Link to post
Share on other sites


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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement