Distortions while blending animations

I have skinned and animated a character in Maya with several independent animations, and I’d like to be able to switch between these animations via fading one in and another one out with setControlEffect.

This works, but during the blending some parts of the character become distorted very much. I thought when interpolating the different animations Panda would consider that the skeleton has to stay the same, e.g. the arm doesn’t become longer etc. but this is not the case. It seems like the joints are just linearly interpolated between there respective positions.

Is there any way to prevent Panda from doing this and to execute blended animations in a way that the skeleton structure stays intact? I would be very pleased if it is possible because otherwise I had to produce a transition from every animation to every other animation.

If you specify a blendType of PartBundle.BTNormalizedLinear, then Panda will indeed try to ensure that joints do not change scale during the blend. This is the default blend type if you are using the interface Actor.enableBlend() to turn on blend mode. On the other hand, if you are explicitly passing blendType = PartBundle.BTLinear, or even worse, something like blendType = 1, then you will get strictly linear blending, as you describe, which can rescale the joints.

Is it possible you are specifying an incorrect value for blendType?


I didn’t specify any value for blendType, but if I specify PartBundle.BTNormalizedLinear explicitly, it doesn’t change anything. I also tried blendType = PartBundle.BTLinear; then the distortion looks different, but in a similar way, if you get my point.

I think I figured out that maybe it’s not the relative position of the joints that’s changing. What I’m doing is blending from a swinging arm motion while walking to a raised arm while waving with the hand. So when the arm rotates around its shoulder joint the whole arm becomes flat, like it was not uniformally scaled.

I use IK and FK in different animations, so at first I thought it might have to do with this, but if I export both animations with FK the distortion still occurs. Or would I have to get rid of the IK handles in the model too? Any other idea?

Oh, and thanks for the quick answer!

Hmm, it sounds like it might be a bug in the blending algorithm. Can you post your egg files somewhere where I can download them to take a closer look?


I’ve zipped the stuff that is important for this problem, you can download all the egg-files here.

When you press ‘r’, the animation blends from walking to waving, with ‘t’ it goes the other way round.

OK, there was a bug in there. My apologies. The code was failing to correct for a shear transform that was introduced by the particular combination of joint angles in your animation.

I’ve checked in a fix. If you need to get the fix right away, you’ll have to use CVS to get the very latest version of Panda3D from the sourceforge.net repository, and build it from source yourself. On the other hand, you may be able to wait for the next official release, since it is really just a minor visual bug until then. :slight_smile:

Incidentally, did you know about LerpAnimInterval? This is a special interval class that is designed to cross-fade animations on an Actor, just as your crossBlend() function does, but it can do it a bit more efficiently (since more of the work is happening down in C++). I was able to replace your crossBlend() function with code like this:

def crossBlend(actorPart,fadeInAnim,fadeOutAnim,duration):
    fadeInt = LerpAnimInterval(actor[actorPart], duration = duration,
                               startAnim = fadeOutAnim, endAnim = fadeInAnim)


Yay, I found a bug! Good to know that it wasn’t my fault.
Thanks again, hope it will work now when the compilation is finished.

I didn’t know about that function either, and created my own implementation as well. It would be great to see it mentioned in the manual.

Hi, is there anyway you can re-post this example again. I’m trying to get animation blending working in panda 1.3.2 and it simply isn’t working as far as I can tell. I’m using the documented methods, but it would be nice if there was a concrete working example to mull over.