Bugfix: taking scale into account when loading constraint's world matrix.

Refactoring: reducing the amount of allocated matrices during applying and loading constraint's matrices.

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

@ -104,7 +104,7 @@ public class BoneContext {
Spatial armature = (Spatial) objectHelper.toObject(blenderContext.getFileBlock(armatureObjectOMA).getStructure(blenderContext), blenderContext); Spatial armature = (Spatial) objectHelper.toObject(blenderContext.getFileBlock(armatureObjectOMA).getStructure(blenderContext), blenderContext);
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class); ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
Matrix4f armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform()); Matrix4f armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform(), new Matrix4f());
// and now compute the final bone matrix in world space // and now compute the final bone matrix in world space
globalBoneMatrix = armatureWorldMatrix.mult(globalBoneMatrix); globalBoneMatrix = armatureWorldMatrix.mult(globalBoneMatrix);

@ -25,6 +25,7 @@ import com.jme3.scene.plugins.blender.file.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Pointer; import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.objects.ObjectHelper; import com.jme3.scene.plugins.blender.objects.ObjectHelper;
import com.jme3.util.TempVars;
/** /**
* This class should be used for constraint calculations. * This class should be used for constraint calculations.
@ -224,46 +225,51 @@ public class ConstraintHelper extends AbstractBlenderHelper {
BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName); BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName);
Bone bone = targetBoneContext.getBone(); Bone bone = targetBoneContext.getBone();
if(bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) { if (bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) {
space = Space.CONSTRAINT_SPACE_POSE; space = Space.CONSTRAINT_SPACE_POSE;
} }
TempVars tempVars = TempVars.get();// use readable names of the matrices so that the code is more clear
Transform result;
switch (space) { switch (space) {
case CONSTRAINT_SPACE_WORLD: case CONSTRAINT_SPACE_WORLD:
Spatial model = (Spatial) blenderContext.getLoadedFeature(targetBoneContext.getSkeletonOwnerOma(), LoadedFeatureDataType.LOADED_FEATURE); Spatial model = (Spatial) blenderContext.getLoadedFeature(targetBoneContext.getSkeletonOwnerOma(), LoadedFeatureDataType.LOADED_FEATURE);
Transform worldTransform = new Transform(bone.getModelSpacePosition(), bone.getModelSpaceRotation(), bone.getModelSpaceScale()); Matrix4f boneModelMatrix = this.toMatrix(bone.getModelSpacePosition(), bone.getModelSpaceRotation(), bone.getModelSpaceScale(), tempVars.tempMat4);
worldTransform.getTranslation().addLocal(model.getWorldTranslation()); Matrix4f modelWorldMatrix = this.toMatrix(model.getWorldTransform(), tempVars.tempMat42);
worldTransform.getRotation().multLocal(model.getWorldRotation()); Matrix4f boneMatrixInWorldSpace = modelWorldMatrix.multLocal(boneModelMatrix);
worldTransform.getScale().multLocal(model.getWorldScale()); result = new Transform(boneMatrixInWorldSpace.toTranslationVector(), boneMatrixInWorldSpace.toRotationQuat(), boneMatrixInWorldSpace.toScaleVector());
return worldTransform; break;
case CONSTRAINT_SPACE_LOCAL: case CONSTRAINT_SPACE_LOCAL:
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!";
return new Transform(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale()); result = new Transform(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale());
break;
case CONSTRAINT_SPACE_POSE: case CONSTRAINT_SPACE_POSE:
Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD)); Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform()).invertLocal(); Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix); Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
return new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector()); result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
break;
case CONSTRAINT_SPACE_PARLOCAL: case CONSTRAINT_SPACE_PARLOCAL:
Matrix4f parentLocalMatrix = Matrix4f.IDENTITY; Matrix4f parentLocalMatrix = tempVars.tempMat4;
if (bone.getParent() != null) { if (bone.getParent() != null) {
Bone parent = bone.getParent(); Bone parent = bone.getParent();
parentLocalMatrix = this.toMatrix(parent.getLocalPosition(), parent.getLocalRotation(), parent.getLocalScale()); this.toMatrix(parent.getLocalPosition(), parent.getLocalRotation(), parent.getLocalScale(), parentLocalMatrix);
} else { } else {
// we need to clone it because otherwise we could spoil parentLocalMatrix.loadIdentity();
// the IDENTITY matrix
parentLocalMatrix = parentLocalMatrix.clone();
} }
Matrix4f boneLocalMatrix = this.toMatrix(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale()); Matrix4f boneLocalMatrix = this.toMatrix(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale(), tempVars.tempMat42);
Matrix4f result = parentLocalMatrix.multLocal(boneLocalMatrix); Matrix4f resultMatrix = parentLocalMatrix.multLocal(boneLocalMatrix);
Vector3f loc = result.toTranslationVector(); Vector3f loc = resultMatrix.toTranslationVector();
Quaternion rot = result.toRotationQuat().normalizeLocal().multLocal(NEG_PARLOC_SPACE_QUATERNION); Quaternion rot = resultMatrix.toRotationQuat().normalizeLocal().multLocal(NEG_PARLOC_SPACE_QUATERNION);
Vector3f scl = result.toScaleVector(); Vector3f scl = resultMatrix.toScaleVector();
return new Transform(loc, rot, scl); result = new Transform(loc, rot, scl);
break;
default: default:
throw new IllegalStateException("Unknown space type: " + space); throw new IllegalStateException("Unknown space type: " + space);
} }
tempVars.release();
return result;
} else { } else {
switch (space) { switch (space) {
case CONSTRAINT_SPACE_LOCAL: case CONSTRAINT_SPACE_LOCAL:
@ -301,60 +307,61 @@ public class ConstraintHelper extends AbstractBlenderHelper {
BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName); BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName);
Bone bone = targetBoneContext.getBone(); Bone bone = targetBoneContext.getBone();
if(bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) { if (bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) {
space = Space.CONSTRAINT_SPACE_POSE; space = Space.CONSTRAINT_SPACE_POSE;
} }
TempVars tempVars = TempVars.get();
switch (space) { switch (space) {
case CONSTRAINT_SPACE_LOCAL: case CONSTRAINT_SPACE_LOCAL:
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!";
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale()); bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
break; break;
case CONSTRAINT_SPACE_WORLD: { case CONSTRAINT_SPACE_WORLD: {
Matrix4f boneMatrixInWorldSpace = this.toMatrix(transform); Matrix4f boneMatrixInWorldSpace = this.toMatrix(transform, tempVars.tempMat4);
Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD)).invertLocal(); Matrix4f modelWorldMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42);
Matrix4f boneMatrixInModelSpace = invertedModelMatrix.mult(boneMatrixInWorldSpace); Matrix4f boneMatrixInModelSpace = modelWorldMatrix.invertLocal().multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent(); Bone parent = bone.getParent();
if (parent != null) { if (parent != null) {
Matrix4f invertedParentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale()).invertLocal(); Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
boneMatrixInModelSpace = invertedParentMatrixInModelSpace.mult(boneMatrixInModelSpace); boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
} }
bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector()); bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
break; break;
} }
case CONSTRAINT_SPACE_POSE: { case CONSTRAINT_SPACE_POSE: {
Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform()); Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform)); Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD)).invertLocal(); Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
Matrix4f boneMatrixInModelSpace = invertedModelMatrix.mult(boneMatrixInWorldSpace); Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent(); Bone parent = bone.getParent();
if(parent != null) { if (parent != null) {
Matrix4f invertedParentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale()).invertLocal(); Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
boneMatrixInModelSpace = invertedParentMatrixInModelSpace.mult(boneMatrixInModelSpace); boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
} }
bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector()); bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
break; break;
} }
case CONSTRAINT_SPACE_PARLOCAL: case CONSTRAINT_SPACE_PARLOCAL:
Matrix4f parentLocalMatrix = Matrix4f.IDENTITY; Matrix4f parentLocalInverseMatrix = tempVars.tempMat4;
if (bone.getParent() != null) { if (bone.getParent() != null) {
parentLocalMatrix = this.toMatrix(bone.getParent().getLocalPosition(), bone.getParent().getLocalRotation(), bone.getParent().getLocalScale()); this.toMatrix(bone.getParent().getLocalPosition(), bone.getParent().getLocalRotation(), bone.getParent().getLocalScale(), parentLocalInverseMatrix);
parentLocalMatrix.invertLocal(); parentLocalInverseMatrix.invertLocal();
} else { } else {
// we need to clone it because otherwise we could parentLocalInverseMatrix.loadIdentity();
// spoil the IDENTITY matrix
parentLocalMatrix = parentLocalMatrix.clone();
} }
Matrix4f m = this.toMatrix(transform.getTranslation(), transform.getRotation(), transform.getScale()); Matrix4f m = this.toMatrix(transform.getTranslation(), transform.getRotation(), transform.getScale(), tempVars.tempMat42);
Matrix4f result = parentLocalMatrix.multLocal(m); Matrix4f result = parentLocalInverseMatrix.multLocal(m);
Vector3f loc = result.toTranslationVector(); Vector3f loc = result.toTranslationVector();
Quaternion rot = result.toRotationQuat().normalizeLocal().multLocal(POS_PARLOC_SPACE_QUATERNION); Quaternion rot = result.toRotationQuat().normalizeLocal().multLocal(POS_PARLOC_SPACE_QUATERNION);
Vector3f scl = result.toScaleVector(); Vector3f scl = result.toScaleVector();
bone.setBindTransforms(loc, rot, scl); bone.setBindTransforms(loc, rot, scl);
break; break;
default: default:
tempVars.release();
throw new IllegalStateException("Invalid space type for target object: " + space.toString()); throw new IllegalStateException("Invalid space type for target object: " + space.toString());
} }
tempVars.release();
skeleton.updateWorldVectors(); skeleton.updateWorldVectors();
} else { } else {
switch (space) { switch (space) {
@ -367,9 +374,11 @@ public class ConstraintHelper extends AbstractBlenderHelper {
} else { } else {
Transform parentWorldTransform = feature.getParent().getWorldTransform(); Transform parentWorldTransform = feature.getParent().getWorldTransform();
Matrix4f parentMatrix = this.toMatrix(parentWorldTransform).invertLocal(); TempVars tempVars = TempVars.get();
Matrix4f m = this.toMatrix(transform); Matrix4f parentInverseMatrix = this.toMatrix(parentWorldTransform, tempVars.tempMat4).invertLocal();
m = m.multLocal(parentMatrix); Matrix4f m = this.toMatrix(transform, tempVars.tempMat42);
m = m.multLocal(parentInverseMatrix);
tempVars.release();
transform.setTranslation(m.toTranslationVector()); transform.setTranslation(m.toTranslationVector());
transform.setRotation(m.toRotationQuat()); transform.setRotation(m.toRotationQuat());
@ -389,28 +398,37 @@ public class ConstraintHelper extends AbstractBlenderHelper {
* *
* @param transform * @param transform
* the transform to be converted * the transform to be converted
* @return 4x4 matrix that represents the given transform * @param store
* the matrix where the result will be stored
* @return the store matrix
*/ */
public Matrix4f toMatrix(Transform transform) { public Matrix4f toMatrix(Transform transform, Matrix4f store) {
if (transform != null) { if (transform != null) {
return this.toMatrix(transform.getTranslation(), transform.getRotation(), transform.getScale()); return this.toMatrix(transform.getTranslation(), transform.getRotation(), transform.getScale(), store);
} }
return Matrix4f.IDENTITY.clone(); store.loadIdentity();
return store;
} }
/** /**
* Converts given transformation parameters into the matrix. * Converts given transformation parameters into the matrix.
* *
* @param transform * @param position
* the transform to be converted * the position of the feature
* @return 4x4 matrix that represents the given transformation parameters * @param rotation
* the rotation of the feature
* @param scale
* the scale of the feature
* @param store
* the matrix where the result will be stored
* @return the store matrix
*/ */
private Matrix4f toMatrix(Vector3f position, Quaternion rotation, Vector3f scale) { private Matrix4f toMatrix(Vector3f position, Quaternion rotation, Vector3f scale, Matrix4f store) {
Matrix4f result = new Matrix4f(); store.loadIdentity();
result.setTranslation(position); store.setTranslation(position);
result.setRotationQuaternion(rotation); store.setRotationQuaternion(rotation);
result.setScale(scale); store.setScale(scale);
return result; return store;
} }
/** /**

Loading…
Cancel
Save