From 4f104e4200a3808bcc4348027f0ff43616648c05 Mon Sep 17 00:00:00 2001 From: "Kae..pl" Date: Wed, 10 Apr 2013 11:52:31 +0000 Subject: [PATCH] Bugfix: (hopefully) final fixes to armature applying to models without applied transformations (+ removing unused pieces of code) git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10529 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../blender/animations/ArmatureHelper.java | 8 +-- .../blender/animations/BoneContext.java | 66 ++++++++----------- .../blender/modifiers/ArmatureModifier.java | 30 ++------- .../plugins/blender/objects/ObjectHelper.java | 25 ------- 4 files changed, 35 insertions(+), 94 deletions(-) diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java index 2775fb21a..ad019d768 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java @@ -85,17 +85,15 @@ public class ArmatureHelper extends AbstractBlenderHelper { * the parent bone * @param result * the list where the newly created bone will be added - * @param bonesPoseChannels - * a map of bones poses channels * @param blenderContext * the blender context * @throws BlenderFileException * an exception is thrown when there is problem with the blender * file */ - public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List result, Matrix4f arbt, final Map bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException { - BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, arbt, bonesPoseChannels, blenderContext); - bc.buildBone(result, bonesOMAs, blenderContext); + public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List result, Matrix4f objectToArmatureTransformation, BlenderContext blenderContext) throws BlenderFileException { + BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, blenderContext); + bc.buildBone(result, bonesOMAs, objectToArmatureTransformation, blenderContext); } /** diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java b/engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java index 196d6a634..0f45f001c 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java @@ -37,8 +37,6 @@ public class BoneContext { private Matrix4f restMatrix; /** Bone's total inverse transformation. */ private Matrix4f inverseTotalTransformation; - /** Bone's parent inverse matrix. */ - private Matrix4f inverseParentMatrix; /** The length of the bone. */ private float length; @@ -49,18 +47,14 @@ public class BoneContext { * the OMA of the bone's armature object * @param boneStructure * the bone's structure - * @param objectToArmatureMatrix - * object-to-armature transformation matrix - * @param bonesPoseChannels - * a map of pose channels for each bone OMA * @param blenderContext * the blender context * @throws BlenderFileException * an exception is thrown when problem with blender data reading * occurs */ - public BoneContext(Long armatureObjectOMA, Structure boneStructure, Matrix4f objectToArmatureMatrix, final Map bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException { - this(boneStructure, armatureObjectOMA, null, objectToArmatureMatrix, bonesPoseChannels, blenderContext); + public BoneContext(Long armatureObjectOMA, Structure boneStructure, BlenderContext blenderContext) throws BlenderFileException { + this(boneStructure, armatureObjectOMA, null, blenderContext); } /** @@ -72,17 +66,13 @@ public class BoneContext { * the OMA of the bone's armature object * @param parent * bone's parent (null if the bone is the root bone) - * @param objectToArmatureMatrix - * object-to-armature transformation matrix - * @param bonesPoseChannels - * a map of pose channels for each bone OMA * @param blenderContext * the blender context * @throws BlenderFileException * an exception is thrown when problem with blender data reading * occurs */ - private BoneContext(Structure boneStructure, Long armatureObjectOMA, BoneContext parent, Matrix4f objectToArmatureMatrix, final Map bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException { + private BoneContext(Structure boneStructure, Long armatureObjectOMA, BoneContext parent, BlenderContext blenderContext) throws BlenderFileException { this.parent = parent; this.boneStructure = boneStructure; this.armatureObjectOMA = armatureObjectOMA; @@ -90,34 +80,23 @@ public class BoneContext { length = ((Number) boneStructure.getFieldValue("length")).floatValue(); ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); armatureMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", blenderContext.getBlenderKey().isFixUpAxis()); - - this.computeRestMatrix(objectToArmatureMatrix); + + //compute the bone's rest matrix + restMatrix = armatureMatrix.clone(); + inverseTotalTransformation = restMatrix.invert(); + if(parent != null) { + restMatrix = parent.inverseTotalTransformation.mult(restMatrix); + } + + //create the children List childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase(blenderContext); for (Structure child : childbase) { - this.children.add(new BoneContext(child, armatureObjectOMA, this, objectToArmatureMatrix, bonesPoseChannels, blenderContext)); + this.children.add(new BoneContext(child, armatureObjectOMA, this, blenderContext)); } blenderContext.setBoneContext(boneStructure.getOldMemoryAddress(), this); } - /** - * This method computes the rest matrix for the bone. - * - * @param objectToArmatureMatrix - * object-to-armature transformation matrix - */ - private void computeRestMatrix(Matrix4f objectToArmatureMatrix) { - if (parent != null) { - inverseParentMatrix = parent.inverseTotalTransformation.clone(); - } else { - inverseParentMatrix = objectToArmatureMatrix.clone(); - } - - restMatrix = armatureMatrix.clone(); - inverseTotalTransformation = restMatrix.invert(); - - restMatrix = inverseParentMatrix.mult(restMatrix); - } /** * This method builds the bone. It recursively builds the bone's children. @@ -126,27 +105,34 @@ public class BoneContext { * a list of bones where the newly created bone will be added * @param boneOMAs * the map between bone and its old memory address + * @param objectToArmatureMatrix + * object to armature transformation matrix * @param blenderContext * the blender context * @return newly created bone */ - public Bone buildBone(List bones, Map boneOMAs, BlenderContext blenderContext) { + public Bone buildBone(List bones, Map boneOMAs, Matrix4f objectToArmatureMatrix, BlenderContext blenderContext) { Long boneOMA = boneStructure.getOldMemoryAddress(); bone = new Bone(boneName); bones.add(bone); boneOMAs.put(bone, boneOMA); blenderContext.addLoadedFeatures(boneOMA, boneName, boneStructure, bone); - Matrix4f pose = this.restMatrix.clone(); ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); - Vector3f poseLocation = pose.toTranslationVector(); - Quaternion rotation = pose.toRotationQuat(); - Vector3f scale = objectHelper.getScale(pose); + Vector3f poseLocation = restMatrix.toTranslationVector(); + Quaternion rotation = restMatrix.toRotationQuat().normalizeLocal(); + Vector3f scale = objectHelper.getScale(restMatrix); + if(parent == null) { + Quaternion rotationQuaternion = objectToArmatureMatrix.toRotationQuat().normalizeLocal(); + scale.multLocal(objectHelper.getScale(objectToArmatureMatrix)); + rotationQuaternion.multLocal(poseLocation.addLocal(objectToArmatureMatrix.toTranslationVector())); + rotation.multLocal(rotationQuaternion); + } bone.setBindTransforms(poseLocation, rotation, scale); for (BoneContext child : children) { - bone.addChild(child.buildBone(bones, boneOMAs, blenderContext)); + bone.addChild(child.buildBone(bones, boneOMAs, objectToArmatureMatrix, blenderContext)); } return bone; diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java index 761f1da8b..30b87d46d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java @@ -17,9 +17,7 @@ import com.jme3.animation.Bone; import com.jme3.animation.BoneTrack; import com.jme3.animation.Skeleton; import com.jme3.animation.SkeletonControl; -import com.jme3.math.Matrix3f; import com.jme3.math.Matrix4f; -import com.jme3.math.Quaternion; import com.jme3.scene.Geometry; import com.jme3.scene.Mesh; import com.jme3.scene.Node; @@ -87,32 +85,16 @@ import com.jme3.util.BufferUtils; // load skeleton Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); - Structure pose = ((Pointer) armatureObject.getFieldValue("pose")).fetchData(blenderContext.getInputStream()).get(0); - List chanbase = ((Structure) pose.getFieldValue("chanbase")).evaluateListBase(blenderContext); - - Map bonesPoseChannels = new HashMap(chanbase.size()); - for (Structure poseChannel : chanbase) { - Pointer pBone = (Pointer) poseChannel.getFieldValue("bone"); - bonesPoseChannels.put(pBone.getOldMemoryAddress(), poseChannel); - } - - Matrix4f objectToArmatureTransformation = Matrix4f.IDENTITY; ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); - - if(objectHelper.isLineage(armatureObject, objectStructure, blenderContext)) { - boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis(); - Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis); - Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis); - objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix); - Matrix3f rot = objectToArmatureTransformation.toRotationMatrix(); - objectToArmatureTransformation = new Matrix4f(); - objectToArmatureTransformation.setRotationQuaternion(new Quaternion().fromRotationMatrix(rot)); - } + boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis(); + Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis); + Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis); + Matrix4f objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix); List bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext); List bonesList = new ArrayList(); for (int i = 0; i < bonebase.size(); ++i) { - armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectToArmatureTransformation, bonesPoseChannels, blenderContext); + armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectToArmatureTransformation, blenderContext); } bonesList.add(0, new Bone("")); Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]); @@ -244,7 +226,7 @@ import com.jme3.util.BufferUtils; } node.addControl(control); node.addControl(new SkeletonControl(animData.skeleton)); - + return node; } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java index bf243aa08..076b09212 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java @@ -250,31 +250,6 @@ public class ObjectHelper extends AbstractBlenderHelper { } return result; } - - /** - * Method tells if the structure1 is a lineage of structure2. - * - * @param structure1 - * the first structure - * @param structure2 - * the second structure - * @return true if the first structure is a lineage of the second - * structure and false otherwise - * @throws BlenderFileException - * thrown when problems with reading the blend file occur - */ - public boolean isLineage(Structure structure1, Structure structure2, BlenderContext blenderContext) throws BlenderFileException { - Pointer pParent = (Pointer) structure2.getFieldValue("parent"); - while (pParent.isNotNull()) { - long oma = pParent.getOldMemoryAddress(); - if (structure1.getOldMemoryAddress().longValue() == oma) { - return true; - } - structure2 = blenderContext.getFileBlock(oma).getStructure(blenderContext); - pParent = (Pointer) structure2.getFieldValue("parent"); - } - return false; - } /** * This method calculates local transformation for the object. Parentage is taken under consideration.