I have a problem I have been struggling with while I have been working on my project off and on for a few months now. Basically, I have a GLOBAL orientation for each bone in a skeleton and I want to set all of these rotations. Looking through the source code, it does not look like jMonkey has support for this because if I rotate a bone, it rotates all of the bones down the chain.
I looked at using bone.setUserTransformsWorld, but this gave me two problems. First, you need to set the global location of the bone and doing the forward kinematics of each bone does not sound like my idea of a good time. Second, when I used this method and then used updateWorldVectors (as was suggested in another post) my skeleton would crumple down into a little ball.
So my next idea was to rotate each bone and then rotate that bone’s child inversely before moving on to the next. As an example, if I rotate my upper arm forward and then my lower arm with an inverse rotation, I would end up with the lower arm in it’s original rotation (pointing down) before doing that arm’s real rotation. My problem comes that I need to “reset” the skeleton to its bind pose at the start of my update loop before I do this. My orientations are global and rotations are done incrementally; incidentally if I need to set the rotation of a bone to 30 degrees about the x-axis, a rotation of 30 degrees every update cycle actually gets the bone to spin instead of sticking to the correct orientation.
Looking through the source, Skeleton.java has two methods it looks like I can use to accomplish this. First is reset() and the second is resetAndUpdate(). My problem is I can’t get either of these to work. I have tried rotating one bone in both my initialize method or the top of the update method and then calling both of these reset methods at the end of my update loop. Both trials don’t reset the model to the bind pose. I’ve also tried using updateWorldVectors() after and this seems to change nothing. Any ideas of what I’m doing wrong?
P-Worm
In initialize:
[java]
// Setup the avatar
avatarNode = (Node) assetManager.loadModel(“Models/BaseBody/BaseBody.mesh.j3o”);
Material matAvatar = new Material(assetManager, “MatDefs/Lighting.j3md”);
matAvatar.setTexture(“DiffuseMap”, assetManager.loadTexture(“Textures/flatGrey.png”));
avatarNode.setMaterial(matAvatar);
control = avatarNode.getControl(AnimControl.class);
avatarNode.scale(2.2f);
rootNode.attachChild(avatarNode);
String boneName = boneNames.get("armLUpper");
Bone bone = control.getSkeleton().getBone(boneName);
bone.setUserControl(true);
Quaternion eulerQuatInit = eulerRotate(-(float)FastMath.HALF_PI/(float)2.5,0,0);
Quaternion fullRotation = new Quaternion();
fullRotation = fullRotation.mult(eulerQuatInit);
bone.setUserTransforms(Vector3f.ZERO, fullRotation, Vector3f.UNIT_XYZ);
[/java]
In update loop:
[java]
mRoll += 50 * tpf;
super.update(tpf);
rootNode.updateLogicalState(tpf);
rootNode.updateGeometricState();
control.getSkeleton().resetAndUpdate();
control.getSkeleton().updateWorldVectors();
[/java]