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 2fe1775d3e..b10a700e7a 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Spatial.java +++ b/jme3-core/src/main/java/com/jme3/scene/Spatial.java @@ -986,6 +986,28 @@ public Vector3f worldToLocal(final Vector3f in, final Vector3f store) { return worldTransform.transformInverseVector(in, store); } + /** + * Transforms the given quaternion from world space to local space relative to this object's transform. + * + * @param in the input quaternion in world space that needs to be transformed + * @param store an optional Quaternion to store the result; if null, a new Quaternion will be created + * @return the transformed quaternion in local space, either stored in the provided Quaternion or a new one + */ + public Quaternion worldToLocal(final Quaternion in, Quaternion store){ + checkDoTransformUpdate(); + if(store == null){ + store=new Quaternion(in); + }else{ + store.set(in); + } + TempVars tempVars = TempVars.get(); + Quaternion worldRotation = tempVars.quat1.set(getWorldRotation()); + worldRotation.inverseLocal(); + store.multLocal(worldRotation); + tempVars.release(); + return store; + } + /** * getParent retrieves this node's parent. If the parent is * null this is the root node. diff --git a/jme3-core/src/test/java/com/jme3/scene/SpatialTest.java b/jme3-core/src/test/java/com/jme3/scene/SpatialTest.java index 038bdc3fc8..48c9147920 100644 --- a/jme3-core/src/test/java/com/jme3/scene/SpatialTest.java +++ b/jme3-core/src/test/java/com/jme3/scene/SpatialTest.java @@ -31,6 +31,9 @@ */ package com.jme3.scene; +import com.jme3.math.FastMath; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; import com.jme3.scene.control.UpdateControl; import org.junit.Assert; import org.junit.Test; @@ -119,4 +122,33 @@ public void testAddControlAt() { Assert.assertEquals(testSpatial, control1.getSpatial()); Assert.assertEquals(testSpatial, control2.getSpatial()); } + + @Test + public void testTransferToOtherNode(){ + Node nodeA = new Node("nodeA"); + Node nodeB = new Node("nodeB"); + Node testNode=new Node("testNode"); + nodeA.setLocalTranslation(-1,0,0); + nodeB.setLocalTranslation(1,0,0); + nodeB.rotate(0,90* FastMath.DEG_TO_RAD,0); + testNode.setLocalTranslation(1,0,0); + nodeA.attachChild(testNode); + Vector3f worldTranslation = testNode.getWorldTranslation().clone(); + Quaternion worldRotation = testNode.getWorldRotation().clone(); + + Assert.assertTrue(worldTranslation.isSimilar(testNode.getWorldTranslation(),1e-6f)); + Assert.assertTrue(worldRotation.isSimilar(testNode.getWorldRotation(),1e-6f)); + + nodeB.attachChild(testNode); + + Assert.assertFalse(worldTranslation.isSimilar(testNode.getWorldTranslation(),1e-6f)); + Assert.assertFalse(worldRotation.isSimilar(testNode.getWorldRotation(),1e-6f)); + + testNode.setLocalTranslation(nodeB.worldToLocal(worldTranslation,null)); + Assert.assertTrue(worldTranslation.isSimilar(testNode.getWorldTranslation(),1e-6f)); + + testNode.setLocalRotation(nodeB.worldToLocal(worldRotation,null)); + System.out.println(testNode.getWorldRotation()); + Assert.assertTrue(worldRotation.isSimilar(testNode.getWorldRotation(),1e-6f)); + } }