Bugfix: improved computation of 'Local with parent' bone constraint space (not yet perfect but much better than the previous one).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@11017 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
experimental
Kae..pl 11 years ago
parent fc8be06297
commit 84aa234446
  1. 7
      engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java
  2. 66
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java

@ -210,6 +210,13 @@ public class BoneContext {
return blenderContext.getSkeleton(armatureObjectOMA); return blenderContext.getSkeleton(armatureObjectOMA);
} }
/**
* @return the initial bone's matrix in model space
*/
public Matrix4f getBoneMatrixInModelSpace() {
return boneMatrixInModelSpace;
}
/** /**
* Tells if the bone is of specified property defined by its flag. * Tells if the bone is of specified property defined by its flag.
* @param flagMask * @param flagMask

@ -8,7 +8,6 @@ import java.util.logging.Logger;
import com.jme3.animation.Bone; import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton; import com.jme3.animation.Skeleton;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Transform; import com.jme3.math.Transform;
@ -34,9 +33,6 @@ import com.jme3.util.TempVars;
public class ConstraintHelper extends AbstractBlenderHelper { public class ConstraintHelper extends AbstractBlenderHelper {
private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName()); private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName());
private static final Quaternion POS_PARLOC_SPACE_QUATERNION = new Quaternion(new float[] { FastMath.HALF_PI, 0, 0 });
private static final Quaternion NEG_PARLOC_SPACE_QUATERNION = new Quaternion(new float[] { -FastMath.HALF_PI, 0, 0 });
/** /**
* Helper constructor. * Helper constructor.
* *
@ -242,28 +238,28 @@ public class ConstraintHelper extends AbstractBlenderHelper {
assert bone.getParent() != null : "CONSTRAINT_SPACE_LOCAL should be evaluated as CONSTRAINT_SPACE_POSE if the bone has no parent!"; assert bone.getParent() != null : "CONSTRAINT_SPACE_LOCAL should be evaluated as CONSTRAINT_SPACE_POSE if the bone has no parent!";
result = new Transform(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale()); result = new Transform(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale());
break; break;
case CONSTRAINT_SPACE_POSE: case CONSTRAINT_SPACE_POSE: {
Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4); Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal(); Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix); Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector()); result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
break; break;
case CONSTRAINT_SPACE_PARLOCAL: }
Matrix4f parentLocalMatrix = tempVars.tempMat4; case CONSTRAINT_SPACE_PARLOCAL: {
if (bone.getParent() != null) { Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
Bone parent = bone.getParent(); Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
this.toMatrix(parent.getLocalPosition(), parent.getLocalRotation(), parent.getLocalScale(), parentLocalMatrix); Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
} else { result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
parentLocalMatrix.loadIdentity(); Bone parent = bone.getParent();
} if(parent != null) {
Matrix4f boneLocalMatrix = this.toMatrix(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale(), tempVars.tempMat42); BoneContext parentContext = blenderContext.getBoneContext(parent);
Matrix4f resultMatrix = parentLocalMatrix.multLocal(boneLocalMatrix); Vector3f head = parent.getModelSpacePosition();
Vector3f tail = head.add(bone.getModelSpaceRotation().mult(Vector3f.UNIT_Y.mult(parentContext.getLength())));
result.getTranslation().subtractLocal(tail);
Vector3f loc = resultMatrix.toTranslationVector(); }
Quaternion rot = resultMatrix.toRotationQuat().normalizeLocal().multLocal(NEG_PARLOC_SPACE_QUATERNION);
Vector3f scl = resultMatrix.toScaleVector();
result = new Transform(loc, rot, scl);
break; break;
}
default: default:
throw new IllegalStateException("Unknown space type: " + space); throw new IllegalStateException("Unknown space type: " + space);
} }
@ -342,19 +338,27 @@ public class ConstraintHelper extends AbstractBlenderHelper {
break; break;
} }
case CONSTRAINT_SPACE_PARLOCAL: case CONSTRAINT_SPACE_PARLOCAL:
Matrix4f parentLocalInverseMatrix = tempVars.tempMat4; Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
if (bone.getParent() != null) { Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
this.toMatrix(bone.getParent().getLocalPosition(), bone.getParent().getLocalRotation(), bone.getParent().getLocalScale(), parentLocalInverseMatrix); Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
parentLocalInverseMatrix.invertLocal(); Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
} else { Bone parent = bone.getParent();
parentLocalInverseMatrix.loadIdentity(); if (parent != null) {
//first add the initial parent matrix to the bone's model matrix
BoneContext parentContext = blenderContext.getBoneContext(parent);
Matrix4f initialParentMatrixInModelSpace = parentContext.getBoneMatrixInModelSpace();
Matrix4f currentParentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
//the bone will now move with its parent in model space
//now we need to subtract the difference between current parent's model matrix and its initial model matrix
boneMatrixInModelSpace = initialParentMatrixInModelSpace.mult(boneMatrixInModelSpace);
Matrix4f diffMatrix = initialParentMatrixInModelSpace.mult(currentParentMatrixInModelSpace.invert());
boneMatrixInModelSpace.multLocal(diffMatrix);
//now the bone will have its position in model space with initial parent's model matrix added
} }
Matrix4f m = this.toMatrix(transform.getTranslation(), transform.getRotation(), transform.getScale(), tempVars.tempMat42); bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
Matrix4f result = parentLocalInverseMatrix.multLocal(m);
Vector3f loc = result.toTranslationVector();
Quaternion rot = result.toRotationQuat().normalizeLocal().multLocal(POS_PARLOC_SPACE_QUATERNION);
Vector3f scl = result.toScaleVector();
bone.setBindTransforms(loc, rot, scl);
break; break;
default: default:
tempVars.release(); tempVars.release();

Loading…
Cancel
Save