From 06f8a00549b56a357f55e2291ba3b123e8dc53a1 Mon Sep 17 00:00:00 2001 From: Stephen Gold <sgold@sonic.net> Date: Fri, 23 Mar 2018 01:42:08 -0700 Subject: [PATCH] fix JME issue #742 (attachment nodes for ignoreTransform geometries) --- .../main/java/com/jme3/animation/Bone.java | 10 +++- .../src/main/java/com/jme3/scene/Spatial.java | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/animation/Bone.java b/jme3-core/src/main/java/com/jme3/animation/Bone.java index 6cd751e3c..b60273ecc 100644 --- a/jme3-core/src/main/java/com/jme3/animation/Bone.java +++ b/jme3-core/src/main/java/com/jme3/animation/Bone.java @@ -535,11 +535,19 @@ public final class Bone implements Savable, JmeCloneable { attachNode.setLocalRotation(modelRot); attachNode.setLocalScale(modelScale); + } else if (targetGeometry.isIgnoreTransform()) { + /* + * The animated meshes ignore transforms: match the world transform + * of the attachments node to the bone's transform. + */ + Transform combined = new Transform(modelPos, modelRot, modelScale); + attachNode.setWorldTransform(combined); + } else { Spatial loopSpatial = targetGeometry; Transform combined = new Transform(modelPos, modelRot, modelScale); /* - * Climb the scene graph applying local transforms until the + * Climb the scene graph applying local transforms until the * attachments node's parent is reached. */ while (loopSpatial != attachParent && loopSpatial != null) { diff --git a/jme3-core/src/main/java/com/jme3/scene/Spatial.java b/jme3-core/src/main/java/com/jme3/scene/Spatial.java index c44db734b..ec2d992f7 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Spatial.java +++ b/jme3-core/src/main/java/com/jme3/scene/Spatial.java @@ -495,6 +495,53 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab return worldTransform; } + /** + * Alter the local transform so that the world transform approximates the + * specified value. + * + * @param world desired world transform (not null, unaffected) + * @throws IllegalArgumentException if the spatial ignores transform OR the + * parent's world transform isn't invertible + */ + public void setWorldTransform(Transform world) { + if (this instanceof Geometry && ((Geometry) this).ignoreTransform) { + throw new RuntimeException("spatial ignores transforms"); + } + + if (parent == null) { + /* + * special case: for a root spatial, the world transform is + * precisely the local transform + */ + setLocalTransform(world); + return; + } + + Transform parentTransform = parent.getWorldTransform(); + Vector3f parentScale = parentTransform.getScale(); + if (parentScale.x == 0f || parentScale.y == 0f || parentScale.z == 0f) { + throw new RuntimeException("parent scale isn't invertible"); + } + Quaternion parentInvRotation = parentTransform.getRotation().inverse(); + if (parentInvRotation == null) { + throw new RuntimeException("parent rotation isn't invertible"); + } + /* + * Undo the operations of Transform.combineWithParent() + */ + Transform tmpLocal = world.clone(); + Vector3f translation = tmpLocal.getTranslation(); + Quaternion rotation = tmpLocal.getRotation(); + tmpLocal.getScale().divideLocal(parentScale); + parentInvRotation.mult(rotation, rotation); + Vector3f parentTranslation = parentTransform.getTranslation(); + translation.subtractLocal(parentTranslation); + parentInvRotation.multLocal(translation); + translation.divideLocal(parentScale); + + setLocalTransform(tmpLocal); + } + /** * <code>rotateUpTo</code> is a utility function that alters the * local rotation to point the Y axis in the direction given by newUp.