Skip to content
18 changes: 18 additions & 0 deletions jme3-core/src/main/java/com/jme3/scene/Spatial.java
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,24 @@ 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);
}
store.multLocal(worldTransform.getRotation().inverse());
return store;
}

/**
* <code>getParent</code> retrieves this node's parent. If the parent is
* null this is the root node.
Expand Down
31 changes: 31 additions & 0 deletions jme3-core/src/test/java/com/jme3/scene/SpatialTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -119,4 +122,32 @@ 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.assertEquals(worldTranslation,testNode.getWorldTranslation());
Assert.assertEquals(worldRotation,testNode.getWorldRotation());

nodeB.attachChild(testNode);

Assert.assertNotEquals(worldTranslation,testNode.getWorldTranslation());
Assert.assertNotEquals(worldRotation,testNode.getWorldRotation());

testNode.setLocalTranslation(nodeB.worldToLocal(worldTranslation,null));
Assert.assertEquals(worldTranslation,testNode.getWorldTranslation());

testNode.setLocalRotation(nodeB.worldToLocal(worldRotation,null));
Assert.assertEquals(worldRotation,testNode.getWorldRotation());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest using isSimilar for equality checks so it doesn't fail on round-off error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point

}
}
Loading