The result appears to swap the actual axis.It is hard to explain. Basically...

The first matrix is the bone's rotation axis, and the second is the rotation of the current keyframe.It is my assumption that the keyframe is relative to the rest pose/rotation of the bone.

If I have a rest rotation that has an axis pointing 45 degrees up on the Y axis,applying a keyframe rotation with an axis of 45 degrees up on y also, it is almost as if it stays 45 degrees up Y, but moves ~45 degrees along another axis.

Strange, huh?

EDIT:Worth mentioning...The skeletal system works BRILLIANT, if the rest post has no rotations.

If I make a snake, with all the bones in a line, i can animate it any way I want,and it works fine.It seems to be due to the adding of rest rotation with keyframe rotations.

/** * Initializes the skeleton's bones, by setting up their * transformation matrices. */private void setupBones(){sortBones();for (SimpleBone bone : bones){bone.transRelative = new SimpleVector(bone.localTranslation);Matrix localRotation = new Matrix();localRotation.rotateAxis(bone.localRotationAxis,-bone.localRotationAngle);bone.rotationAbsolute = localRotation;//.invert3x3();if (bone.parent != null) {//=========================================================// If bone has a parent, apply its rotation matrix to// the child bone.//=========================================================bone.rotationAbsolute.matMul(bone.parent.rotationAbsolute);bone.transRelative.matMul(bone.parent.rotationAbsolute);//---------------------------------------------------------// Inherit the absolute transformation from the parent // bone, adding it to this child bone's relative // transformation, to get this bone's absolute // transformation.//---------------------------------------------------------bone.transAbsolute = new SimpleVector(bone.parent.transAbsolute);bone.transAbsolute.add(bone.transRelative); } else {//========================================================// This is a parent bone.// We do not inherit any transformations,// and do not have any parent rotation matrices to apply.//======================================================== bone.transAbsolute = new SimpleVector(bone.transRelative); }}}

/** * Advances the animation sequence. * The faster this method is called, the higher the * fidelity of the animation. * * The keyframes are self timed, and will not be * made faster by more calls to this method. */public void advanceAnimation(){SkeletalAnimation animation = animations[currentAnimation];//=================================================================// Ensure that the animation time has not been exceeded.// If so, restart animation sequence, or clip to end time,// if the animation is non-looping.//================================================================double time = timer.getTime();

if (time > animation.length){if (animation.looping){restartAnimation();time = 0;}else{ time = animation.length;}}//================================================================// Calculate the final transform of all bones at this time// in the animation.//// Inbetween keyframes are interpolated for smoother transition.//================================================================for( int i = 0; i < bones.length; i++){SimpleVector transVec = new SimpleVector(); SimpleBone bone = bones[i]; int frame; //------------------------------------------------------------ // If the bone has no keyframes, then skip it. //------------------------------------------------------------ if (bone.rotationKeyframes[currentAnimation] == null && bone.translationKeyframes[currentAnimation] == null) {bone.transFinal.set(bone.transAbsolute); continue; } //------------------------------------------------------------ // Ensure we are at the correct keyframe for this time // in the animation. //------------------------------------------------------------ frame = bone.currentTranslationKeyframe; while(frame < bone.translationKeyframes[currentAnimation].length && bone.translationKeyframes[currentAnimation][frame].time < time) {frame++; } bone.currentTranslationKeyframe = frame; //------------------------------------------------------------ // Find the correct translation vector for this time in the // animation, for this bone. // // If the frame is at the start, or the end, then the // vector is taken directly from the keyframes. // However, if it is neither, the vector is interpolated // from the current keyframe, and the previous keyframe. //------------------------------------------------------------ if (frame == 0) {transVec.set(bone.translationKeyframes[currentAnimation][0].translation); } else if (frame == bone.translationKeyframes[currentAnimation].length) {transVec.set(bone.translationKeyframes[currentAnimation][frame-1].translation); } else {TranslationKeyframe curFrame = bone.translationKeyframes[currentAnimation][frame];TranslationKeyframe prevFrame = bone.translationKeyframes[currentAnimation][frame-1];float timeDelta = (curFrame.time)-(prevFrame.time); float interpValue = (float)(time-(prevFrame.time))/timeDelta;

Matrix matrix = new Matrix(); matrix.interpolate(prevMatrix,curMatrix, interpValue); //--------------------------------------------------------- // Set the bones rotationFinal matrix, for use by // vertices, and child bones. //--------------------------------------------------------- bone.rotationFinal = matrix;//prevMatrix.cloneMatrix(); } //------------------------------------------------------------- // Apply the transformation vector to the relativeFinal // transformation of this bone. //------------------------------------------------------------- SimpleVector relativeFinal = new SimpleVector(bone.transRelative); relativeFinal.add(transVec); if(bone.parent == null) {//---------------------------------------------------------// We are a parent bone, so just use the relative final// as the final transform.// There are no rotations, or transformations to inherit.//---------------------------------------------------------bone.transFinal = relativeFinal; } else {//---------------------------------------------------------// We are a child bone, so inherit any rotations,// and inherit the parent bone's final transformation// to get our own.//---------------------------------------------------------bone.rotationFinal.matMul(bone.parent.rotationFinal);relativeFinal.matMul(bone.parent.rotationFinal); bone.transFinal.set(bone.parent.transFinal); bone.transFinal.add(relativeFinal); }}}

You may give me the code, but i'm not sure if i manage to have a closer look before wednesday. I think you'll be faster by checking this out yourself. Anyway, jkust to make sure that i understand this correctly: You mean that something like this:

Could it be that the axis of the keyframe's rotation has to be transformed into "rest space" first? I.e. if the rest space's rotation is 90° around X and the keyframe's axis is (0,0,1), that the actual rotation of the keyframe has to be around (0,0,1)"*x90°"=(0,-1,0) and not around (0,0,1)?I've no clue...i'm just guessing here, and that's the first thing that came to my mind.

Could this be so, even if the rotation keyframes "appear" relative?Ill try this.I know i had to apply the invert of the bones rest position to the vertices to "undo" the rest position. I am not sure it that would for for the bones themselves, but, worth a try.

I don't mean to undo the "rest rotation" on the keyframe's axis but to apply it. But both things could be possible and both are worth a try. When you don't know how these rotations are actucally related, there's not much left than trying.

Does "applied to the keyframe" mean that it's applied to the rotation axis of it? I guess so...Matrix math IS terrible. It always twists my head after some time of thinking.

So we have a rest rotation around an axis in object space(?) and a keyframe rotation on top of this in...object space(?), rest space(?)...? And while the rest rotation is fine, the keyframe rotation is wrong, i.e. it goes in the wrong direction? Did i get it?

I did not think it would matter though, because all keyframes, are supposed to be in object space?

It will still matter, because object space uses the same system. Just to make this crystal clear to everyone: In jPCT, y is down, z goes INTO the screen and x to the left. Others, where y goes up, have z pointing out of the screen.