Rotate bones without parent-child rotations applied

I have a skeleton where I need to position the bones by applying world frame rotations to each one. Coming from Ogre, there was an option to bone->setInheritOrientation(false) which would not have a child’s bone inherit the parent’s orientation, but still allow the child bone to be positioned to the parent bone’s end. Going over the documentation, it seems like the material is either outdated or missing things. For instance, I have been trying to find documentation on setUserTransformsWorld because I think it might be the thing that I need, but can’t find this method in the documentation.

Also, setUserTransformsWorld makes you put in the global position of the joint as well as the orientation. What is the best way to tackle this? Do I need to calculate the forward kinematics of the skeleton with all the bone orientations first? If possible, I would like to keep computation time to a minimum because I eventually want this to be deployed on an Android device.

Thanks for all your help.

–P-Worm

Sorry for the bump, but does anyone have a place I can look for help? Or can anyone explain how setUserTransformsWorld is supposed to work?

–P-Worm

What tool chain are you using? I know blender has the inherit orientation option for bones although I’ve no idea how if/how it works on import.

By work orientation do you really mean that? Doesn’t that mean that if you rotate/move your model some of the limbs will remain in place?

I don’t want the limbs to remain in place, I want to orient each bone globally. Right now if I rotate a thigh up 90 degrees, the calf and foot will rotate with it, Instead, I want the thigh to move up and the calf to move with it (at the knee), but the calf to still be oriented vertically.

–P-Worm

[java]@Override
public void simpleInitApp() {
// Setup the camera
flyCam.setMoveSpeed(400f);
cam.setLocation(new Vector3f(6.4013605f, 7.488437f, 12.843031f));
cam.setRotation(new Quaternion(-0.060740203f, 0.93925786f, -0.2398315f, -0.2378785f));

    // Setup the light
    DirectionalLight mainLight = new DirectionalLight();
    mainLight.setDirection(new Vector3f(-0.1f, -0.7f, -1f).normalizeLocal());
    mainLight.setColor(new ColorRGBA(1f, 1f, 1f, 1f));
    rootNode.addLight(mainLight);
    
Node avatar = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");

control = avatar.getControl(AnimControl.class);

// Get the names of the bones
Bone rootBone[] = control.getSkeleton().getRoots();
List bones = new ArrayList(rootBone[0].getChildren());
for(Bone bone : bones) {
    System.out.println(bone.getChildren());
}

// Translate bone names so they are more sensible
boneNames.put("armRUpper", "Joint10");
boneNames.put("armRLower", "Joint11");
boneNames.put("armRHand", "Joint12");
boneNames.put("armLUpper", "Joint15");
boneNames.put("armLLower", "Joint16");
boneNames.put("armLHand", "Joint17");

// Show skeleton
SkeletonDebugger skelDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.getAdditionalRenderState().setWireframe(true);
mat.setColor("Color", ColorRGBA.Green);
mat.getAdditionalRenderState().setDepthTest(false);
skelDebug.setMaterial(mat);
avatar.attachChild(skelDebug);

rootNode.attachChild(avatar);
avatar.rotate(0, FastMath.PI, 0);
}

@Override
public void simpleUpdate(float tpf) {
//control.setEnabled(false);
Bone armR = control.getSkeleton().getBone(boneNames.get("armRUpper"));

mRoll += tpf;

Quaternion q = new Quaternion();

armR.setUserControl(true);
Vector3f armRPos = new Vector3f(armR.getLocalPosition());
q.fromAngles(mRoll, 0, 0);
    
System.out.println(q.toString());
armR.setUserTransformsWorld(armRPos, q);
armR.updateWorldVectors();


}[/java]

This is where I am at right now. I am trying to rotate one of the bones globally while having all of the children of the bone stay in the same rotation. What I get from this is the bone is collapsed and seems to be non existent. Any ideas?

P-Worm

…I’m curious what getModelSpaceScale() returns at this point.
http://hub.jmonkeyengine.org/javadoc/com/jme3/animation/Bone.html#getModelSpaceScale()

If it returns all 0’s then that’s why your geometry disappears. Looking at the code, it’s supposed to be inherited by the root bone but I thought I’d check anyway.

Just gave it a shot and it returns all 1’s for the bone armR. I did this check after setUserTransformsWorld and updateWorldVectors. I really think that I am using setUserTransformsWorld and updateWorldVectors incorrectly, but documentation on both seems like it is in development.

P-Worm

[java]private void rotateBone(Bone boneIn, float roll, float pitch, float yaw) {
// Rotate the quaternion properly
Quaternion rotX = new Quaternion();
Quaternion rotY = new Quaternion();
Quaternion rotZ = new Quaternion();
rotX.loadIdentity();
rotY.loadIdentity();
rotZ.loadIdentity();

Quaternion fullRotation = new Quaternion();
    fullRotation.loadIdentity();

rotX.fromAngleAxis(roll, Vector3f.UNIT_X);
rotY.fromAngleAxis(-yaw, Vector3f.UNIT_Y);
rotZ.fromAngleAxis(pitch, Vector3f.UNIT_Z);
fullRotation = rotY.mult(rotZ);
fullRotation = fullRotation.mult(rotX);


Bone childBone = boneIn.getChildren().get(0);

boneIn.setUserControl(true);
childBone.setUserControl(true);

boneIn.setUserTransforms(Vector3f.ZERO, fullRotation, Vector3f.UNIT_XYZ);
childBone.setUserTransforms(Vector3f.ZERO, fullRotation.inverse(), Vector3f.UNIT_XYZ);
}[/java]

I’ve tried making a function to rotate a bone and then “unrotate” the next child bone. My idea was that I wanted to globally rotate the first bone in the chain and then reset the rotation of the next bone in the chain. After that I would take that next bone and globally rotate it while unrotating that bone’s child. However, while doing the rotation, jMonkey seems to skip some rotations. If a bone down the chain gets rotated with the parents rotation, then rotated back, then rotated again to the new location it skips the rotate back step. I can’t for the life of me figure out what is going on here.

Any help?

P-Worm