Animating a joint relative to position of any underlying pose/additive animation

Hello. I’m working on animation again and I’ve encountered a challenge I’m not quite sure how to solve.

The main example of the problem I’m trying to solve is with my animation of a third-person-shooter character. I want to have one-frame poses for aiming “flat”, aiming up, and aiming down. Then, I want to have animations for running in the four cardinal directions and the four directions between them. In some of the running animations, the character’s torso rotates back and forth as they run. This necessitates that the shoulders are animated to keep them pointing their weapon in front of them.

But then that means that I can’t simply blend in/out the different aiming animations for looking down/up while running! Because the shoulder is animated during the run animation, the weight of that animation means that the running animation is going to drag the the shoulder back to aiming “flat”, assuming the running animation was made based on the aiming flat idle pose. And if I only have the walk animation affect the legs, it looks like the character isn’t aiming where they’re shooting anymore as their body sways around but they keep pointing their weapon in the same relative direction.

Is there some way I can configure an animation to affect a part of the model relative to any underlying pose? Like Vertex(Final) = (Blended Pose) + (transform relative to base pose) It seems possible to do this in blender, at least…

Of course I might also be able to make a hack like using several actions in blender to create a properly blended animation for each permutation, but that feels like much more work. Is there an efficient solution to this?

I’m not sure that I follow here: surely, if your running animation affects only the legs, then the torso shouldn’t be affected by it at all, and thus your gun should point in the direction in which it’s animated?

Or are your character’s torso-bones children of its leg-bones…?

Or alternatively, have you perhaps not gone far enough in having the torso be part of the “aiming” animation? That is, have the “running” animation affect only the legs–no part of the torso at all–and the “aiming” animation be responsible for the torso entire?

That said, I want to check: since you’ve considered having separate animations for torso and legs, does that mean that you’ve looked into half-body animation?

(If you haven’t been using half-body animation, then I would expect the blending of animations for the torso and legs to result in neither looking quite right.)

Sorry, there’s a misunderstanding here. The model im talking about is only my best example of an issue that exists throughout my animation workflow. In the part you quoted, i was trying to explain why pure half-body animation wouldn’t solve my problem…
The character’s running animation needs to affect the upper body, because it doesnt look right if they arent throwing their weight around and maintaining ballance while they run.

Im afk so i cant make more visual examples right now, but ill try and make a simplified explanation of the “perfect world” solution i desire.
AFAIK, panda3d only has options for variations of linear blending of multiple animations. If we were linearly blending just one kind of value, it’d look like this:
(2+8)/2 = 5

What would be more useful in my situation is additive blending, so like
8(main animation) + 2(animation layer) = 10
Or 8 + -2 = 6

Which lets us add a motion relative to an existing animation.

I dont think panda3d has this now though, so my question is if theres an efficient way to reach a similar effect.

Ah, fair enough–I thought that you might have been talking about half-body animation, but I wasn’t sure, and it seemed better to check!

Sure, but can you not perhaps incorporate that into your “aiming” animations–making them no longer single-frame, of course, but allowing them to incorporate reactions to movement?

(This would of course incur one animation per movement state, but should work well, I imagine.)

I may be mistaken, but I’m not sure that this would work–at least, not without having your animation layer incorporate some adjustment for the motion of the main animation.

For example, consider the following stick-figure:

      O
      |-----
      |
      |

Now, let’s say that the main animation has this figure bend backwards:

   O  /
    \/
     \
      |

Because of the parent-child relationship between “back” and “arm”, the arm is lifted by the motion of the back–without the arm having any animation of its own, mind!

To counter this, we’d presumably want to animate the “arm” downwards. But if that backwards bend isn’t present throughout the main animation, then when it’s not bending backwards the downwards animation of the “arm” would result in the arm pointing downwards…

What you really want, if not half-body animation, is arguably some form of inverse kinematics, in which you specify the object-relative direction for the arms and then do the reverse calculations to determine the required bone-positions for those arms…

[edit]
If you do decide to look into inverse kinematics, then perhaps take a look at this thread:

RDB found a solution on discord.
There were two main blocking points to making animation layers: First, all of panda3d’s blend types end up dividing the combined result of all applied animations by the sum of the weights of each animation. Secondly, panda3d stores the transformation of each bone in an animation relative to it’s parent bone and without being relative to the armature’s rest position in any way.

Fortunately, RDB figured out a way to bypass both of those:
If you make the armature’s rest pose an animation, by setting that animation with a negative effect you bypass both those issues at once. First, (and there’s not an easy way to explain this) “the negative rest position should stop an animaiton based on the rest position meant to be layered on other animations from biasing the model towards the rest position.” Secondly, because the rest position is contributing a negative value to the net weight and the net weight is a simple sum of all animations weights, It should cancel the weight added by the animation layer, meaning it will not reduce the impact of other animations.

So a function to play something as an animation layer would look something like this: (This is based on my own animation class and not Actor)

def play_anim_layer(self, name:str, part:str = "modelRoot", blend:float = 1, start:int = None):
   self.play(name, part, blend, start)
   if self.is_playing("rest_pose", part):
      self.change_blend("rest_pose", part, -blend + self.get_blend("rest_pose", part))
   else:
      self.change_blend("rest_pose", part, -blend)
   #Then set a doMethodLater to reduce the blend when the animation layer ends
1 Like