Let Rotation Quaternion as ‘Q’,
Vector as ‘V’
Then the rotated vector is Q x V, not V x Q.
Below is the test class for bug reproduce.
when v = (0, 0, 1)
rotate v by q1 is (0, 1, 0)
rotate v by q1 and q2 is (1, 0, 0)
so after successive call of n.rotate(q1), n.rotate(q2)
n.getWorldRotation().multLocal(v) should be equal to (1, 0, 0).
[patch]
Index: src/core/com/jme3/scene/Spatial.java
===================================================================
— src/core/com/jme3/scene/Spatial.java (revision 6599)
+++ src/core/com/jme3/scene/Spatial.java (working copy)
@@ -950,7 +950,7 @@
-
@return The spatial on which this method is called, e.g <code>this</code>.
*/
public Spatial rotate(Quaternion rot){
-
this.localTransform.getRotation().multLocal(rot);<br />
-
rot.mult(localTransform.getRotation(), localTransform.getRotation());<br />
this.worldTransform.setRotation(this.localTransform.getRotation());
setTransformRefresh();
[/patch]
[java]
public class TestSpatialRotate {
public static void main(String[] args) {
Vector3f v = Vector3f.UNIT_Z.clone();
Quaternion q1 = new Quaternion();
Quaternion q2 = new Quaternion();
q1.fromAngleNormalAxis(-FastMath.HALF_PI, Vector3f.UNIT_X);
q1.multLocal(v);
if (!equals(v, Vector3f.UNIT_Y)) {
System.out.println(v);
throw new RuntimeException();
}
q2.fromAngleNormalAxis(-FastMath.HALF_PI, Vector3f.UNIT_Z);
q2.multLocal(v);
if (!equals(v, Vector3f.UNIT_X)) {
System.out.println(v);
throw new RuntimeException();
}
v.set(Vector3f.UNIT_Z);
Node n = new Node();
n.rotate(q1);
n.rotate(q2);
n.updateGeometricState();
n.getWorldRotation().multLocal(v);
if (!equals(v, Vector3f.UNIT_X)) {
System.out.println(v);
throw new RuntimeException();
}
}
private static boolean equals(Vector3f v1, Vector3f v2) {
return equals(v1.x, v2.x) && equals(v1.y, v2.y) && equals(v1.z, v2.z);
}
private static boolean equals(float z1, float z2) {
return FastMath.abs(z1-z2) < 0.001f;
}
}
[/java]