|
|
@ -29,7 +29,6 @@ |
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
package com.jme3.math; |
|
|
|
package com.jme3.math; |
|
|
|
|
|
|
|
|
|
|
|
import com.jme3.export.InputCapsule; |
|
|
|
import com.jme3.export.InputCapsule; |
|
|
@ -60,7 +59,6 @@ import java.util.logging.Logger; |
|
|
|
public final class Quaternion implements Savable, Cloneable { |
|
|
|
public final class Quaternion implements Savable, Cloneable { |
|
|
|
|
|
|
|
|
|
|
|
private static final Logger logger = Logger.getLogger(Quaternion.class.getName()); |
|
|
|
private static final Logger logger = Logger.getLogger(Quaternion.class.getName()); |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Represents the identity quaternion rotation (0, 0, 0, 1). |
|
|
|
* Represents the identity quaternion rotation (0, 0, 0, 1). |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -71,7 +69,6 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
static { |
|
|
|
static { |
|
|
|
DIRECTION_Z.fromAxes(Vector3f.UNIT_X, Vector3f.UNIT_Y, Vector3f.UNIT_Z); |
|
|
|
DIRECTION_Z.fromAxes(Vector3f.UNIT_X, Vector3f.UNIT_Y, Vector3f.UNIT_Z); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected float x, y, z, w; |
|
|
|
protected float x, y, z, w; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -214,11 +211,12 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* @return true if this Quaternion is {0,0,0,1} |
|
|
|
* @return true if this Quaternion is {0,0,0,1} |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public boolean isIdentity() { |
|
|
|
public boolean isIdentity() { |
|
|
|
if (x == 0 && y == 0 && z == 0 && w == 1) |
|
|
|
if (x == 0 && y == 0 && z == 0 && w == 1) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
else |
|
|
|
} else { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* <code>fromAngles</code> builds a quaternion from the Euler rotation |
|
|
|
* <code>fromAngles</code> builds a quaternion from the Euler rotation |
|
|
@ -228,9 +226,10 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* the Euler angles of rotation (in radians). |
|
|
|
* the Euler angles of rotation (in radians). |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Quaternion fromAngles(float[] angles) { |
|
|
|
public Quaternion fromAngles(float[] angles) { |
|
|
|
if (angles.length != 3) |
|
|
|
if (angles.length != 3) { |
|
|
|
throw new IllegalArgumentException( |
|
|
|
throw new IllegalArgumentException( |
|
|
|
"Angles array must have three elements"); |
|
|
|
"Angles array must have three elements"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return fromAngles(angles[0], angles[1], angles[2]); |
|
|
|
return fromAngles(angles[0], angles[1], angles[2]); |
|
|
|
} |
|
|
|
} |
|
|
@ -290,10 +289,11 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* @return the float[] in which the angles are stored. |
|
|
|
* @return the float[] in which the angles are stored. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public float[] toAngles(float[] angles) { |
|
|
|
public float[] toAngles(float[] angles) { |
|
|
|
if (angles == null) |
|
|
|
if (angles == null) { |
|
|
|
angles = new float[3]; |
|
|
|
angles = new float[3]; |
|
|
|
else if (angles.length != 3) |
|
|
|
} else if (angles.length != 3) { |
|
|
|
throw new IllegalArgumentException("Angles array must have three elements"); |
|
|
|
throw new IllegalArgumentException("Angles array must have three elements"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
float sqw = w * w; |
|
|
|
float sqw = w * w; |
|
|
|
float sqx = x * x; |
|
|
|
float sqx = x * x; |
|
|
@ -351,24 +351,21 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
y = (m02 - m20) * s; |
|
|
|
y = (m02 - m20) * s; |
|
|
|
z = (m10 - m01) * s; |
|
|
|
z = (m10 - m01) * s; |
|
|
|
} else if ((m00 > m11) && (m00 > m22)) { |
|
|
|
} else if ((m00 > m11) && (m00 > m22)) { |
|
|
|
float s = FastMath |
|
|
|
float s = FastMath.sqrt(1.0f + m00 - m11 - m22); // |s|>=1
|
|
|
|
.sqrt(1.0f + m00 - m11 - m22); // |s|>=1
|
|
|
|
|
|
|
|
x = s * 0.5f; // |x| >= .5
|
|
|
|
x = s * 0.5f; // |x| >= .5
|
|
|
|
s = 0.5f / s; |
|
|
|
s = 0.5f / s; |
|
|
|
y = (m10 + m01) * s; |
|
|
|
y = (m10 + m01) * s; |
|
|
|
z = (m02 + m20) * s; |
|
|
|
z = (m02 + m20) * s; |
|
|
|
w = (m21 - m12) * s; |
|
|
|
w = (m21 - m12) * s; |
|
|
|
} else if (m11 > m22) { |
|
|
|
} else if (m11 > m22) { |
|
|
|
float s = FastMath |
|
|
|
float s = FastMath.sqrt(1.0f + m11 - m00 - m22); // |s|>=1
|
|
|
|
.sqrt(1.0f + m11 - m00 - m22); // |s|>=1
|
|
|
|
|
|
|
|
y = s * 0.5f; // |y| >= .5
|
|
|
|
y = s * 0.5f; // |y| >= .5
|
|
|
|
s = 0.5f / s; |
|
|
|
s = 0.5f / s; |
|
|
|
x = (m10 + m01) * s; |
|
|
|
x = (m10 + m01) * s; |
|
|
|
z = (m21 + m12) * s; |
|
|
|
z = (m21 + m12) * s; |
|
|
|
w = (m02 - m20) * s; |
|
|
|
w = (m02 - m20) * s; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
float s = FastMath |
|
|
|
float s = FastMath.sqrt(1.0f + m22 - m00 - m11); // |s|>=1
|
|
|
|
.sqrt(1.0f + m22 - m00 - m11); // |s|>=1
|
|
|
|
|
|
|
|
z = s * 0.5f; // |z| >= .5
|
|
|
|
z = s * 0.5f; // |z| >= .5
|
|
|
|
s = 0.5f / s; |
|
|
|
s = 0.5f / s; |
|
|
|
x = (m02 + m20) * s; |
|
|
|
x = (m02 + m20) * s; |
|
|
@ -505,8 +502,9 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* @return the column specified by the index. |
|
|
|
* @return the column specified by the index. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Vector3f getRotationColumn(int i, Vector3f store) { |
|
|
|
public Vector3f getRotationColumn(int i, Vector3f store) { |
|
|
|
if (store == null) |
|
|
|
if (store == null) { |
|
|
|
store = new Vector3f(); |
|
|
|
store = new Vector3f(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
float norm = norm(); |
|
|
|
float norm = norm(); |
|
|
|
if (norm != 1.0f) { |
|
|
|
if (norm != 1.0f) { |
|
|
@ -733,6 +731,28 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
this.w = (scale0 * this.w) + (scale1 * q2.w); |
|
|
|
this.w = (scale0 * this.w) + (scale1 * q2.w); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Sets the values of this quaternion to the nlerp from itself to q2 by blend. |
|
|
|
|
|
|
|
* @param q2 |
|
|
|
|
|
|
|
* @param blend |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void nlerp(Quaternion q2, float blend) { |
|
|
|
|
|
|
|
float dot = dot(q2); |
|
|
|
|
|
|
|
float blendI = 1.0f - blend; |
|
|
|
|
|
|
|
if (dot < 0.0f) { |
|
|
|
|
|
|
|
x = blendI * x - blend * q2.x; |
|
|
|
|
|
|
|
y = blendI * y - blend * q2.y; |
|
|
|
|
|
|
|
z = blendI * z - blend * q2.z; |
|
|
|
|
|
|
|
w = blendI * w - blend * q2.w; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
x = blendI * x + blend * q2.x; |
|
|
|
|
|
|
|
y = blendI * y + blend * q2.y; |
|
|
|
|
|
|
|
z = blendI * z + blend * q2.z; |
|
|
|
|
|
|
|
w = blendI * w + blend * q2.w; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
normalizeLocal(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* <code>add</code> adds the values of this quaternion to those of the |
|
|
|
* <code>add</code> adds the values of this quaternion to those of the |
|
|
|
* parameter quaternion. The result is returned as a new quaternion. |
|
|
|
* parameter quaternion. The result is returned as a new quaternion. |
|
|
@ -818,8 +838,9 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* @return the new quaternion. |
|
|
|
* @return the new quaternion. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Quaternion mult(Quaternion q, Quaternion res) { |
|
|
|
public Quaternion mult(Quaternion q, Quaternion res) { |
|
|
|
if (res == null) |
|
|
|
if (res == null) { |
|
|
|
res = new Quaternion(); |
|
|
|
res = new Quaternion(); |
|
|
|
|
|
|
|
} |
|
|
|
float qw = q.w, qx = q.x, qy = q.y, qz = q.z; |
|
|
|
float qw = q.w, qx = q.x, qy = q.y, qz = q.z; |
|
|
|
res.x = x * qw + y * qz - z * qy + w * qx; |
|
|
|
res.x = x * qw + y * qz - z * qy + w * qx; |
|
|
|
res.y = -x * qz + y * qw + z * qx + w * qy; |
|
|
|
res.y = -x * qz + y * qw + z * qx + w * qy; |
|
|
@ -859,9 +880,10 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* coordinate system. |
|
|
|
* coordinate system. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Quaternion fromAxes(Vector3f[] axis) { |
|
|
|
public Quaternion fromAxes(Vector3f[] axis) { |
|
|
|
if (axis.length != 3) |
|
|
|
if (axis.length != 3) { |
|
|
|
throw new IllegalArgumentException( |
|
|
|
throw new IllegalArgumentException( |
|
|
|
"Axis array must have three elements"); |
|
|
|
"Axis array must have three elements"); |
|
|
|
|
|
|
|
} |
|
|
|
return fromAxes(axis[0], axis[1], axis[2]); |
|
|
|
return fromAxes(axis[0], axis[1], axis[2]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -991,8 +1013,9 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* @return the result vector. |
|
|
|
* @return the result vector. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Vector3f mult(Vector3f v, Vector3f store) { |
|
|
|
public Vector3f mult(Vector3f v, Vector3f store) { |
|
|
|
if (store == null) |
|
|
|
if (store == null) { |
|
|
|
store = new Vector3f(); |
|
|
|
store = new Vector3f(); |
|
|
|
|
|
|
|
} |
|
|
|
if (v.x == 0 && v.y == 0 && v.z == 0) { |
|
|
|
if (v.x == 0 && v.y == 0 && v.z == 0) { |
|
|
|
store.set(0, 0, 0); |
|
|
|
store.set(0, 0, 0); |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -1168,10 +1191,18 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Quaternion comp = (Quaternion) o; |
|
|
|
Quaternion comp = (Quaternion) o; |
|
|
|
if (Float.compare(x,comp.x) != 0) return false; |
|
|
|
if (Float.compare(x, comp.x) != 0) { |
|
|
|
if (Float.compare(y,comp.y) != 0) return false; |
|
|
|
return false; |
|
|
|
if (Float.compare(z,comp.z) != 0) return false; |
|
|
|
} |
|
|
|
if (Float.compare(w,comp.w) != 0) return false; |
|
|
|
if (Float.compare(y, comp.y) != 0) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (Float.compare(z, comp.z) != 0) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (Float.compare(w, comp.w) != 0) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1287,8 +1318,9 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
* direction of this Quaternion. |
|
|
|
* direction of this Quaternion. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Quaternion opposite(Quaternion store) { |
|
|
|
public Quaternion opposite(Quaternion store) { |
|
|
|
if (store == null) |
|
|
|
if (store == null) { |
|
|
|
store = new Quaternion(); |
|
|
|
store = new Quaternion(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Vector3f axis = new Vector3f(); |
|
|
|
Vector3f axis = new Vector3f(); |
|
|
|
float angle = toAngleAxis(axis); |
|
|
|
float angle = toAngleAxis(axis); |
|
|
@ -1315,4 +1347,3 @@ public final class Quaternion implements Savable, Cloneable { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|