Swapping doesnt work:)
Egon, if I give you the source code(commented),
and some model files, and how they are supposed to look,
could you check it out?
Actually, if you ran through a few of the methods, I am sure you would pick up on something, if it is an obvious mistake.
Its only really SimpleSkeleton's buildJoints(), and advanceAnimation()
that appear to be in error.
What is strange, is that the rest pose of the skeleton is perfect.
So is the movement of vertices in relation to their joint(s).
The problem is that the rotational keyframes are not being applied correctly.
They all move relative to the parent joint, but not in the correct direction!:)
As I mentioned above, IF I use a model that has NO rotation in its rest pose,
the keyframe rotations seem to work. NOT in the right direction - but they moved like they do in the modeler.
It is almost as if the Keyframes are rotated -90 degrees along y(?) axis, compared to the MESH, and the skeletons REST POSE.
This first bit DOES put the bones in the right REST pose.
/**
* 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;
SimpleVector curTranslation = curFrame.translation;
SimpleVector prevTranslation = prevFrame.translation;
transVec.x = prevTranslation.x + (curTranslation.x - prevTranslation.x) * interpValue;
transVec.y = prevTranslation.y + (curTranslation.y - prevTranslation.y) * interpValue;
transVec.z = prevTranslation.z + (curTranslation.z - prevTranslation.z) * interpValue;
}
//-------------------------------------------------------------
// Ensure we are at the correct rotational keyframe for this
// time in the animation sequence.
//-------------------------------------------------------------
frame = bone.currentRotationKeyframe;
while(frame < bone.rotationKeyframes[currentAnimation].length &&
bone.rotationKeyframes[currentAnimation][frame].time < time)
{
frame++;
}
bone.currentRotationKeyframe = frame;
//-------------------------------------------------------------
// Same as above, but for the rotational keyframes instead.
//-------------------------------------------------------------
if (frame == 0)
{
bone.rotationFinal = bone.rotationKeyframes[currentAnimation][0].rotationMatrix;
}
else if (frame == bone.rotationKeyframes[currentAnimation].length)
{
bone.rotationFinal = bone.rotationKeyframes[currentAnimation][frame-1].rotationMatrix;
}
else
{
RotationKeyframe curFrame = bone.rotationKeyframes[currentAnimation][frame];
RotationKeyframe prevFrame = bone.rotationKeyframes[currentAnimation][frame-1];
Matrix curMatrix = curFrame.rotationMatrix;
Matrix prevMatrix = prevFrame.rotationMatrix;
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);
}
}
}