Lining up animations with motion

Started by
16 comments, last by RobM 9 years, 6 months ago

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?
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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

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.

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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

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.
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
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.


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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


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.

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.

This topic is closed to new replies.

Advertisement