Animation Blending

Started by
170 comments, last by haegarr 15 years, 6 months ago
Quote:Original post by RobTheBloke
It's not done for efficiency, it's done to make the anim system re-usable and improve build times. Doing it the other way requires the anim system to know about bones, meshes, lights, materials, blend shapes, and anything else it might want to animate. Ultimately that breaks modularity and makes the system a PITA to work with. (btw, I have been writing commercial anim systems for the last 10 years or so, so i've seen the positives and negatives from most ways of doing it.

Uhh, well, I'm reworking my first animation system. So your experience in this topic is by far greater. Nevertheless, there is something in-between black and white: Your abstraction is absolute in that you use a single data type only: float over all. Our abstraction is less strict, but we still have an abstraction. ATM we are speaking of float scalars, float vectors, and (unit) quaternions. You have these types, too, of course, but look at them as sequence of 1 to 4 floats. This allows you to concentrate all the state variables, and to perform a unified blending operation on them. Hence you can presumbly perform a more efficient blending w.r.t. caching and/or SSE. On the other hand, you have the requirement of continuous float buffers for every and all operations, or else the cache advantage will be lowered. Moreover, you are restricted to operations that can be performed on all (vector) components separately. E.g. you could do a nlerp (although only with an "external" normalization step) but no slerp. Don't misunderstand me: That is okay so far. I believe that this makes a performance difference to your benefits (although I'm not able to quantize it).

Quote:Original post by RobTheBloke
Quote:Original post by godmodder
My last argument is about the logic of the code. Think about what happens in real life: a bone doesn't query it's next position but is forced into it. Having the tracks explicitely impose a transformation on the bones seems more realistic. I like to imagine it like controlling a puppet with strings.

But that argument fails the second you have something like an aim constraint that is applied before the final stage of the animation. With your method, the character would have to be updated, and then you'd have get the aim to pull data from those transforms, and then you'd fill the temp buffer with more data. You're adding another read where you don't need it, that or you'd always be a frame behind.

That depends on how the aiming is done. IK solutions need not necessarily be implemented the traditional way. Aiming, and any other animation given an advantage by IK, can itself be implemented by blending (perhaps static) animations. Putting this animation to a higher priority and there is no need to "post-process".

Quote:Original post by godmodder
Quote:Original post by RobTheBloke
It's not done for efficiency, it's done to make the anim system re-usable and improve build times. Doing it the other way requires the anim system to know about bones, meshes, lights, materials, blend shapes, and anything else it might want to animate. Ultimately that breaks modularity and makes the system a PITA to work with.

Our system doesn't need to know anything about those specifics either. We just need to pass a generic scenegraph node to the animation system, which could represent almost anything.

In fact, the scenegraph node here is nothing more than a scope for the name resolution. As such, its purpose is to restrict the name resolution to work on a defined set of possible outcomes. This is done for both efficieny and re-usability. One can pass a specific NameResolver if wanted. It is also possible to give it up if one absolutely wishes to do so.


In the meanwhile I've read some stuff on animation trees. You remember that little discussion belonging to morpheme at the beginning of this thread? With the concept of animation trees in mind I no longer wonder that morpheme provides 30 or so blend modes (that isn't meant in a negative sense). It also explains RobTheBloke's insisting on masking. I see 2 big differences: Concentration of animated values vs. distribution of generally modifyable values, and the splitting of data and operations vs. "class" building. Its not surprising that exactly both these issues are currently subject of discussion in this thread.
Advertisement
Hello,
Sorry For Late Reply. You know i go to school. Im just 15 years old who wants to be a programmer :)

I started reading some answers in here, I really forgot to tell you about that.

My Question is FourCC Semantic includes four things:
Position, Local Position, Orientation, Local Orientation?

Or something else. I didn't use in my Code of Skeleton System any const FourCC &semantic. Do i need to use that?

I just did thing like that:

bool Resolve(_uint boneID, CAnimQuatVariable &var);bool Resolve(_uint boneID, CAnimVector3Variable &var);


Do i need that semantic thing here?

And what to do now: Pre-Post Blending or Runtime blending? Which works faster? If Runtime blending works faster, how to implement it? (I have Pre-Post Blending)

Thanks,
Kasya

P.S on Saturday i think i'll finish that Instance and Prototype for Animation. I'm getting used to Game Programming really. I neved understood that Animation like that. Thank you very much! :D
Quote:Original post by Kasya
My Question is FourCC Semantic includes four things:
Position, Local Position, Orientation, Local Orientation?

Or something else. I didn't use in my Code of Skeleton System any const FourCC &semantic. Do i need to use that?

Not necessarily.

The semantic is used in the resolution step of the binding process. Hence it is used if and only if a general binding is done at all. E.g. if all your animations are complete w.r.t. the targeted skeleton, and the tracks are in the same order as the skeleton's bones, then you don't need a resolution. I personally allow incomplete animations, and I don't rely on the correct order, so I need some resolution. I pay with some additional runtime costs, of course.

There is a post anywhere in this thread where I describe some variations, with and without semantics. In the minimalistic approach you don't need semantics, since each bone (as identified by the boneId) provides a single (local) position and (local) orientation only. Hence the both routines you've presented in the above post are sufficient.

On the other hand, if you want to animate the skeleton global positions and orientations also, then there are 2 positions and 2 orientations. Or, if you want to animate the x, y, and z channels of the position separately, you'll have 3 floats. In such cases you need an additional criteria for resolution, e.g. a semantic. You have to decide whether such cases are senseful for you.

I have introduced the semantic simply because I allow animations to be bound to other entities than skeletons, too. So I need a more general resolving method.

Quote:Original post by Kasya
And what to do now: Pre-Post Blending or Runtime blending? Which works faster? If Runtime blending works faster, how to implement it? (I have Pre-Post Blending)

What do you mean with "Pre-Post Blending"? Do you mean the routines preBlending(...) and postBlending(...) I've introduced earlier? These routines are for preparing and reworking blending. If you mean something else, so please explain what you mean.

Quote:Original post by Kasya
I neved understood that Animation like that.

Notice please that this approach to animations is just one. Other possibilities exist as well, e.g. the "animation tree" as is favored by RobTheBloke.
@haegarr

Yes i mean PreBlending and PostBlending. In one post i think RobTheBloke said he's using Runtime Blending, not PreBlending and PostBlending. How to do that? Is that neccesary? And what you think if i'll create Animation System like in Unreal 3:

Quote:
Animation is driven by a tree of animation objects including: Blend controllers, data-driven controllers, physics controllers, and procedural animation controllers.

?

Thanks
Kasya
Quote:Original post by Kasya
Yes i mean PreBlending and PostBlending. In one post i think RobTheBloke said he's using Runtime Blending, not PreBlending and PostBlending. How to do that? Is that neccesary?

IMHO "runtime blending" (as opposed to "precomputed blending") means that blending is done at, well, runtime. Both approaches do blending at runtime. Perhaps RobTheBloke means something special when he spoke about "Runtime Blending", but then I don't know.

About the roles of preBlending and postBlending: Think of computing a mean value. A code snippet would look like
// preparationsum = 0;// main partfor( int i=0; i<length; ++i ) {    sum += value;}// reworkingsum /= length;

This snippet can be broken down in 3 sections: The preparation sets the sum to 0, the loop sums up, and the reworking by normalizes the sum. preBlending, accuBlend (or others), and postBlending are to be understood in the same way. It is just a mechanism that allows (and is used by) distributed invocations of the blending calculations.

Quote:Original post by Kasya
And what you think if i'll create Animation System like in Unreal 3:
Quote:
Animation is driven by a tree of animation objects including: Blend controllers, data-driven controllers, physics controllers, and procedural animation controllers.

This sounds like Unreal 3 uses animation trees. Such an animations system uses a bit a different approach, and is IMHO in fact what RobTheBloke is favouring. It has some advantages and some disadvantages. Notice please that the "controlling" is a part we have not yet (deeply) discussed in this thread at all.

Several commercial packages use animation trees, so that method is approved to work. Hence, you can rely on it and choose it as your implementation, of course. There are 2 or 3 principle differences to the other animation system, so you may be required to rewrite some stuff.
Hello,
@haegarr what does an Animation tree structure need? And can i use Skeleton Instance and Skeleton Prototype with Animation Trees? Or i need to create something like Skeleton Trees?

Thanks,
Kasya
@haegarr

void Skeleton::reworkPose() {    forEach( bone in bones ) {        if( !bone->m_positionVariable.m_totalWeight ) {            bone->m_positionVariable.m_value = bone->m_positionInBindPose;        }        if( !bone-> m_orientationVariable.m_totalWeight ) {            bone-> m_orientationVariable.m_value = bone->m_orientationInBindPose;        }    }}


In your code what is bone->m_orientationInBindPose. Is that _backing->m_orientation; (SkeletonPrototype::Bone _backing)? or its that bone's current orientation?

Thanks
Kasya
Animation tree is a kind of animation system that handles animation like a mathematical expression. The expression uses poses as type of operands and results. A pose, as ever in the sense of skeletal animation, is the state of a part or of the entire skeleton. The operators itself are nodes in the tree, and the literals are leaves of the tree. Operators can be (and most will be) parametrized.

An example:
p := dissolve( walk, run, 0.3 ) + turnLeft*0.2
is an expression composed as
p := p1 + p2
of
p1 := dissolve( walk, run, 0.3 )
p2 := turnLeft*0.2 = scale( turnLeft, 0.2 )
so that 3 nodes exist, one cross-dissolve node, one scaling node, and one addition node. Moreover, 3 leaves exist (okay, leaves are often implemented as nodes, too, but I made this distinction here for clarity), namely "walk", "run", and "turnLeft". The leaves are in fact animation players. They are like AnimationInstance if the blending is stripped away from them.

If you can read power point files, then perhaps these slides may give you an overview. If you interpret the animation tree system, you will hit some differences to the other animation system, as I've already mentioned earlier.

However, the differences are not as big as they seem at a first glance. As soon as I find some time, I will evaluate how the both systems can be melted together. You have noticed that controlling wasn't an issue under discussion so far. The controlling at the lower level is an inherent part of the animation tree (that's the reason for the many node types RobTheBloke has mentioned earlier).

Quote:Original post by Kasya
In your code what is bone->m_orientationInBindPose. Is that _backing->m_orientation; (SkeletonPrototype::Bone _backing)?

Exactly. The purpose is to guarantee that the skeleton's bone state is set to something senseful. Since the system doesn't enforce an animation to be complete w.r.t. the entirety of bone variables, it may happen that some variables are not touched after all current animations are blended. E.g. bone positions will often not be animated and are hence typical candidates. Hence the reworking iterates over the bones and looks whether it can find untouched variables, and set them to a nominal value (the said bind pose).
Hello again. It's been a while and I got blending of animations to work. I can now blend an arbitrary amount of animations together. I'll add support for layering when I find the time. This leads me to the problem of animation controlling. This is what I came up with:

1) gather input from the system controls
2) set the character animation state machine in a certain state (e.g. RUNNING)
3) the state machine knows how to transition from one state to another and it sets the right blending modes etc...
4) the animations are applied in the right way to the character

Now, I don't know if this is a good way of doing things, but it seems like a reasonable approach. The state machine for a character could be constructed by the game code itself, or read from a file created by the artists. There's one thing I don't know how to solve: where do additive and layered animations fit in such an animation state machine? Here's a picture of the most important state transitions in my game. Every transition is done by transitional blending of animations:

animation state machine

In almost every state, it's possible to take out your guns and to start shooting. (but you can't shoot while crouching for instance) Should shooting be a seperate state? If this is the case, I would have to connect almost every state with it and even then it wouldn't be entirely correct because the previous animation should still be running and mixed with it. The same problem exists for additive animations such as leaning left while running. What would you suggest?

Part 3 is a bit problematic too. Should a blend tree be constructed in this step? How would this tree be traversed then? I think the approach taken in this step is highly correlated with the solution for the previous question.

As you can see, I have a rough picture of how this should be done, but there are few details which I hope you can fill in for me.

Jeroen
The following are thoughts, not purely pulled out of air (i.e. existing games use such a technique), but still not implemented by myself. People with more experience may constradict me...

I'm not a friend of a strict state maschine approach. By definition, a state is current in a state maschine. So we would need a state for forward going, but another one for forward going while shooting, and another one for forward going while waving, and another one for forward going while ... that would IMHO contradict the flexible blending approach a bit. Not only the states but also the amount of edges in the belonging graph will be numerous.

Instead, I think of different animation axes. E.g. one such animation axis may be the forward motion. The controlling variable on that axis would be the (forward) velocity. The velocity is part of the object's state, and is controlled by user input (e.g. velocity is increased up to a limit by each pressing of the UP key, and decreased by pressing the DOWN key; things like that), physical constraints (e.g. the weight of armour), terrain (e.g. the slope in motion direction, grip), or whatever you can think of.

Now, the axis' job is to translate the velocity into an animation. For that purpose particular concrete animations are associated with a value on the axis. E.g. the "walk" animation is made for a velocity of 1 m/s, the "jog" animation is made for a velocity of 4 m/s, and the "run" animation is made for 7 m/s. Obviously, if the current velocity is in the range [4,7] m/s, a blending between the surrounding animations "jog" and "run" has to be performed, and the blending factor is f = (v-4)/(7-4) what is well known from keyframing, of course. (As usual, one has to do a phase correction by adapting the animation playback speeds. But that has nothing to do with the controlling technique.)

I have excluded v==0 in the above example for simplicity. This is because it is likely that blending of "stand" with any forward motion will not look pretty. From what I have read in the inet, starting to walk is often done by an explicit animation. E.g. the animation starts by lifting the right foot and performs the first step until it is in sync with the slowest forward motion animation.

So, the axis above is a 1 dimensional, continuous (and limited) axis. It is no problem to define multi-dimensional axes as well. Let's assume that we define the forward motion not only by the (strict) forward velocity but couple it with a left/right moving. So a particular animation may be made for 3 m/s forward motion with a 5°/s curve motion. Then the state will be represented by a tuple (v,d), for example.

It is also possible to have discrete axes. E.g. a boolean that controls "shooting" or not shooting.

With variables as those above some kind of rule set and cross influences can be build. E.g. the forward velocity can be used to influence the propability of hits when shooting. Or one can jump only if the forward velocity is above a minimum, or the jump distance is determined from the velocity, or ...

Nevertheless, the above mechanism is not sufficient for all purposes. E.g. whether or not the character is upright or crouching may be used to switch entire axes (oh well, if one really wants one can understand this as a discrete macro axis :)). The walk/jog/run axis above is active only if the character is in its upright state. Such a "macroscopic" behaviour can be modelled by a discrete state maschine, of course. This may have the advantage to not get lost in control scripting, since the state maschine may be used to devide up the rule set into several smaller sets.

The total set of variables like the forward velocity, shooting-or-not, upright-or-crouching-or-falling, ... together defines the state of the character.

This topic is closed to new replies.

Advertisement