Active ragdoll system

Hi, I’ve just began working on an active ragdoll system for the characters in my game, similar to Wolfire’s implementation for rabbits falling down hill e.t.c. in Overgrowth.

It seems fairly straight forward conceptually, as he mentions that this was developed by trying to “match poses through joint constraints”.

I’ve used the KinematicRagdollControl as a starting point for testing purposes, as all the physics joints are already set up in relation to their Bone counterparts here. On transition into ragdoll mode, I’ve introduced an extra method called “lockJointToPreservePose” (with an optional level of flexibility) which is executed on each joint in the skeleton.

Firstly, I wanted to share this idea and see if anyone else has already thought of implementing something like this in jme3 as it seems like it would be a cool feature.

Secondly, it appears I’m not so hot on 3D angles and rotations, so none of my MANY attempts at calculating the angle between the two bones have been quite right. One of my first attempts (which was the simplest implementation I could think of) is pasted below. Can any fresh pair of eyes see what might be wrong with doing it this way?

Thanks

private void lockJointToPreservePose(PhysicsBoneLink link) {
    Quaternion startRotation = link.bone.getWorldBindRotation();
    Quaternion endRotation = link.bone.getLocalRotation();
    Quaternion differenceInRotation = startRotation.add(endRotation.inverse());
    
    float flexibility = 0; //FastMath.PI / 16;

    float[] angles = new float[3];
    differenceInRotation.toAngles(angles);

    RagdollUtils.setJointLimit(link.joint,
            angles[0] + flexibility, angles[0] - flexibility,
            angles[1] + flexibility, angles[1] - flexibility,
            angles[2] + flexibility, angles[2] - flexibility);
}
2 Likes

Cool! Looking forward to this.

So about the angle calculation, David Rosen would say " well…that easy that’s just some trigonometry with an angle and a cosine…".

But since we’re not half as clever as this guy, I guess it’s a bit more challenging.
If you’re using 3.0, the name of the methods are VERY misleading, and you may have this issue because you are actually not using what you think you’re using.

See this commit where I changed the methods names so that they fit reality. Updated documentation of the Bone class and changed names of the tran… · jMonkeyEngine/jmonkeyengine@3f43d78 · GitHub

getWorldBindRotation has nothing to do with world space : it’s the bone bind rotation regarding its parent bone (rotation of the bone in T pose).
getLocalRotation is the curent rotation of the bone regarding its parent bone.
So I’m not sure what you want to achieve with that method.

Indeed! :smile:

getWorldBindRotation has nothing to do with world space :

Yeah, that did confuse me at first as I thought as the name suggests it was the rotation in world space, but keeping in mind what you said, that it is the T pose rotation in relation to it’s parent bone, when I calculate “differenceInRotation” I should get the resulting rotation (away from it’s T bone position) due to the effect of the animation.

This is good and working in this video below… (I’ve added a bit of flexibility to the joints too, which is why he’s not perfectly rigid, but you can see the pose still holds)

Correct pose match

My trouble is, when I activate pose matching near the beginning of an animation loop, he twists out 90 degrees for some reason, and although he ends up in a “sensible” pose (i.e he doesn’t screw up into a ball like some of my other attempts) it’s just clearly not the right pose…

Bad pose match

Mhh ok that can be due to something else. When you compute the difference rotation between 2 quaternions, the resulting rotation is the shortest one. so let’s say you have a 10° rotation on one axis and a 350° rotation on the same axis, the difference will not be 340° but -20°. This can screw things up big time.
@pspeed can confirm (or not) as he’s the math guru around here. :smiley:
So usually when you have a rotation of more than 180° you want to split it in several rotations.
Not sure that’s your issue but it looks like it.