|
|
@ -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(); |
|
|
|