Merge branch 'master' of https://github.com/jMonkeyEngine/jmonkeyengine.git
commit
3ee52c38ed
@ -0,0 +1,453 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package com.jme3.scene.plugins.blender.math; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import com.jme3.export.Savable; |
||||
import com.jme3.math.Quaternion; |
||||
|
||||
/** |
||||
* <code>DQuaternion</code> defines a single example of a more general class of |
||||
* hypercomplex numbers. DQuaternions extends a rotation in three dimensions to a |
||||
* rotation in four dimensions. This avoids "gimbal lock" and allows for smooth |
||||
* continuous rotation. |
||||
* |
||||
* <code>DQuaternion</code> is defined by four double point numbers: {x y z w}. |
||||
* |
||||
* This class's only purpose is to give better accuracy in floating point operations during computations. |
||||
* This is made by copying the original Quaternion class from jme3 core and leaving only required methods and basic computation methods, so that |
||||
* the class is smaller and easier to maintain. |
||||
* Should any other methods be needed, they will be added. |
||||
* |
||||
* @author Mark Powell |
||||
* @author Joshua Slack |
||||
* @author Marcin Roguski (Kaelthas) |
||||
*/ |
||||
public final class DQuaternion implements Savable, Cloneable, java.io.Serializable { |
||||
private static final long serialVersionUID = 5009180713885017539L; |
||||
|
||||
/** |
||||
* Represents the identity quaternion rotation (0, 0, 0, 1). |
||||
*/ |
||||
public static final DQuaternion IDENTITY = new DQuaternion(); |
||||
public static final DQuaternion DIRECTION_Z = new DQuaternion(); |
||||
public static final DQuaternion ZERO = new DQuaternion(0, 0, 0, 0); |
||||
protected double x, y, z, w = 1; |
||||
|
||||
/** |
||||
* Constructor instantiates a new <code>DQuaternion</code> object |
||||
* initializing all values to zero, except w which is initialized to 1. |
||||
* |
||||
*/ |
||||
public DQuaternion() { |
||||
} |
||||
|
||||
/** |
||||
* Constructor instantiates a new <code>DQuaternion</code> object from the |
||||
* given list of parameters. |
||||
* |
||||
* @param x |
||||
* the x value of the quaternion. |
||||
* @param y |
||||
* the y value of the quaternion. |
||||
* @param z |
||||
* the z value of the quaternion. |
||||
* @param w |
||||
* the w value of the quaternion. |
||||
*/ |
||||
public DQuaternion(double x, double y, double z, double w) { |
||||
this.set(x, y, z, w); |
||||
} |
||||
|
||||
public DQuaternion(Quaternion q) { |
||||
this(q.getX(), q.getY(), q.getZ(), q.getW()); |
||||
} |
||||
|
||||
public Quaternion toQuaternion() { |
||||
return new Quaternion((float) x, (float) y, (float) z, (float) w); |
||||
} |
||||
|
||||
public double getX() { |
||||
return x; |
||||
} |
||||
|
||||
public double getY() { |
||||
return y; |
||||
} |
||||
|
||||
public double getZ() { |
||||
return z; |
||||
} |
||||
|
||||
public double getW() { |
||||
return w; |
||||
} |
||||
|
||||
/** |
||||
* sets the data in a <code>DQuaternion</code> object from the given list |
||||
* of parameters. |
||||
* |
||||
* @param x |
||||
* the x value of the quaternion. |
||||
* @param y |
||||
* the y value of the quaternion. |
||||
* @param z |
||||
* the z value of the quaternion. |
||||
* @param w |
||||
* the w value of the quaternion. |
||||
* @return this |
||||
*/ |
||||
public DQuaternion set(double x, double y, double z, double w) { |
||||
this.x = x; |
||||
this.y = y; |
||||
this.z = z; |
||||
this.w = w; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets the data in this <code>DQuaternion</code> object to be equal to the |
||||
* passed <code>DQuaternion</code> object. The values are copied producing |
||||
* a new object. |
||||
* |
||||
* @param q |
||||
* The DQuaternion to copy values from. |
||||
* @return this |
||||
*/ |
||||
public DQuaternion set(DQuaternion q) { |
||||
x = q.x; |
||||
y = q.y; |
||||
z = q.z; |
||||
w = q.w; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets this DQuaternion to {0, 0, 0, 1}. Same as calling set(0,0,0,1). |
||||
*/ |
||||
public void loadIdentity() { |
||||
x = y = z = 0; |
||||
w = 1; |
||||
} |
||||
|
||||
/** |
||||
* <code>fromAngleAxis</code> sets this quaternion to the values specified |
||||
* by an angle and an axis of rotation. This method creates an object, so |
||||
* use fromAngleNormalAxis if your axis is already normalized. |
||||
* |
||||
* @param angle |
||||
* the angle to rotate (in radians). |
||||
* @param axis |
||||
* the axis of rotation. |
||||
* @return this quaternion |
||||
*/ |
||||
public DQuaternion fromAngleAxis(double angle, Vector3d axis) { |
||||
Vector3d normAxis = axis.normalize(); |
||||
this.fromAngleNormalAxis(angle, normAxis); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>fromAngleNormalAxis</code> sets this quaternion to the values |
||||
* specified by an angle and a normalized axis of rotation. |
||||
* |
||||
* @param angle |
||||
* the angle to rotate (in radians). |
||||
* @param axis |
||||
* the axis of rotation (already normalized). |
||||
*/ |
||||
public DQuaternion fromAngleNormalAxis(double angle, Vector3d axis) { |
||||
if (axis.x == 0 && axis.y == 0 && axis.z == 0) { |
||||
this.loadIdentity(); |
||||
} else { |
||||
double halfAngle = 0.5f * angle; |
||||
double sin = Math.sin(halfAngle); |
||||
w = Math.cos(halfAngle); |
||||
x = sin * axis.x; |
||||
y = sin * axis.y; |
||||
z = sin * axis.z; |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>add</code> adds the values of this quaternion to those of the |
||||
* parameter quaternion. The result is returned as a new quaternion. |
||||
* |
||||
* @param q |
||||
* the quaternion to add to this. |
||||
* @return the new quaternion. |
||||
*/ |
||||
public DQuaternion add(DQuaternion q) { |
||||
return new DQuaternion(x + q.x, y + q.y, z + q.z, w + q.w); |
||||
} |
||||
|
||||
/** |
||||
* <code>add</code> adds the values of this quaternion to those of the |
||||
* parameter quaternion. The result is stored in this DQuaternion. |
||||
* |
||||
* @param q |
||||
* the quaternion to add to this. |
||||
* @return This DQuaternion after addition. |
||||
*/ |
||||
public DQuaternion addLocal(DQuaternion q) { |
||||
x += q.x; |
||||
y += q.y; |
||||
z += q.z; |
||||
w += q.w; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>subtract</code> subtracts the values of the parameter quaternion |
||||
* from those of this quaternion. The result is returned as a new |
||||
* quaternion. |
||||
* |
||||
* @param q |
||||
* the quaternion to subtract from this. |
||||
* @return the new quaternion. |
||||
*/ |
||||
public DQuaternion subtract(DQuaternion q) { |
||||
return new DQuaternion(x - q.x, y - q.y, z - q.z, w - q.w); |
||||
} |
||||
|
||||
/** |
||||
* <code>subtract</code> subtracts the values of the parameter quaternion |
||||
* from those of this quaternion. The result is stored in this DQuaternion. |
||||
* |
||||
* @param q |
||||
* the quaternion to subtract from this. |
||||
* @return This DQuaternion after subtraction. |
||||
*/ |
||||
public DQuaternion subtractLocal(DQuaternion q) { |
||||
x -= q.x; |
||||
y -= q.y; |
||||
z -= q.z; |
||||
w -= q.w; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>mult</code> multiplies this quaternion by a parameter quaternion. |
||||
* The result is returned as a new quaternion. It should be noted that |
||||
* quaternion multiplication is not commutative so q * p != p * q. |
||||
* |
||||
* @param q |
||||
* the quaternion to multiply this quaternion by. |
||||
* @return the new quaternion. |
||||
*/ |
||||
public DQuaternion mult(DQuaternion q) { |
||||
return this.mult(q, null); |
||||
} |
||||
|
||||
/** |
||||
* <code>mult</code> multiplies this quaternion by a parameter quaternion. |
||||
* The result is returned as a new quaternion. It should be noted that |
||||
* quaternion multiplication is not commutative so q * p != p * q. |
||||
* |
||||
* It IS safe for q and res to be the same object. |
||||
* It IS NOT safe for this and res to be the same object. |
||||
* |
||||
* @param q |
||||
* the quaternion to multiply this quaternion by. |
||||
* @param res |
||||
* the quaternion to store the result in. |
||||
* @return the new quaternion. |
||||
*/ |
||||
public DQuaternion mult(DQuaternion q, DQuaternion res) { |
||||
if (res == null) { |
||||
res = new DQuaternion(); |
||||
} |
||||
double qw = q.w, qx = q.x, qy = q.y, qz = q.z; |
||||
res.x = x * qw + y * qz - z * qy + w * qx; |
||||
res.y = -x * qz + y * qw + z * qx + w * qy; |
||||
res.z = x * qy - y * qx + z * qw + w * qz; |
||||
res.w = -x * qx - y * qy - z * qz + w * qw; |
||||
return res; |
||||
} |
||||
|
||||
/** |
||||
* <code>mult</code> multiplies this quaternion by a parameter vector. The |
||||
* result is returned as a new vector. |
||||
* |
||||
* @param v |
||||
* the vector to multiply this quaternion by. |
||||
* @return the new vector. |
||||
*/ |
||||
public Vector3d mult(Vector3d v) { |
||||
return this.mult(v, null); |
||||
} |
||||
|
||||
/** |
||||
* Multiplies this DQuaternion by the supplied quaternion. The result is |
||||
* stored in this DQuaternion, which is also returned for chaining. Similar |
||||
* to this *= q. |
||||
* |
||||
* @param q |
||||
* The DQuaternion to multiply this one by. |
||||
* @return This DQuaternion, after multiplication. |
||||
*/ |
||||
public DQuaternion multLocal(DQuaternion q) { |
||||
double x1 = x * q.w + y * q.z - z * q.y + w * q.x; |
||||
double y1 = -x * q.z + y * q.w + z * q.x + w * q.y; |
||||
double z1 = x * q.y - y * q.x + z * q.w + w * q.z; |
||||
w = -x * q.x - y * q.y - z * q.z + w * q.w; |
||||
x = x1; |
||||
y = y1; |
||||
z = z1; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>mult</code> multiplies this quaternion by a parameter vector. The |
||||
* result is returned as a new vector. |
||||
* |
||||
* @param v |
||||
* the vector to multiply this quaternion by. |
||||
* @param store |
||||
* the vector to store the result in. It IS safe for v and store |
||||
* to be the same object. |
||||
* @return the result vector. |
||||
*/ |
||||
public Vector3d mult(Vector3d v, Vector3d store) { |
||||
if (store == null) { |
||||
store = new Vector3d(); |
||||
} |
||||
if (v.x == 0 && v.y == 0 && v.z == 0) { |
||||
store.set(0, 0, 0); |
||||
} else { |
||||
double vx = v.x, vy = v.y, vz = v.z; |
||||
store.x = w * w * vx + 2 * y * w * vz - 2 * z * w * vy + x * x * vx + 2 * y * x * vy + 2 * z * x * vz - z * z * vx - y * y * vx; |
||||
store.y = 2 * x * y * vx + y * y * vy + 2 * z * y * vz + 2 * w * z * vx - z * z * vy + w * w * vy - 2 * x * w * vz - x * x * vy; |
||||
store.z = 2 * x * z * vx + 2 * y * z * vy + z * z * vz - 2 * w * y * vx - y * y * vz + 2 * w * x * vy - x * x * vz + w * w * vz; |
||||
} |
||||
return store; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>toString</code> creates the string representation of this <code>DQuaternion</code>. The values of the quaternion are displaced (x, |
||||
* y, z, w), in the following manner: <br> |
||||
* (x, y, z, w) |
||||
* |
||||
* @return the string representation of this object. |
||||
* @see java.lang.Object#toString() |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return "(" + x + ", " + y + ", " + z + ", " + w + ")"; |
||||
} |
||||
|
||||
/** |
||||
* <code>equals</code> determines if two quaternions are logically equal, |
||||
* that is, if the values of (x, y, z, w) are the same for both quaternions. |
||||
* |
||||
* @param o |
||||
* the object to compare for equality |
||||
* @return true if they are equal, false otherwise. |
||||
*/ |
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (!(o instanceof DQuaternion)) { |
||||
return false; |
||||
} |
||||
|
||||
if (this == o) { |
||||
return true; |
||||
} |
||||
|
||||
DQuaternion comp = (DQuaternion) o; |
||||
if (Double.compare(x, comp.x) != 0) { |
||||
return false; |
||||
} |
||||
if (Double.compare(y, comp.y) != 0) { |
||||
return false; |
||||
} |
||||
if (Double.compare(z, comp.z) != 0) { |
||||
return false; |
||||
} |
||||
if (Double.compare(w, comp.w) != 0) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>hashCode</code> returns the hash code value as an integer and is |
||||
* supported for the benefit of hashing based collection classes such as |
||||
* Hashtable, HashMap, HashSet etc. |
||||
* |
||||
* @return the hashcode for this instance of DQuaternion. |
||||
* @see java.lang.Object#hashCode() |
||||
*/ |
||||
@Override |
||||
public int hashCode() { |
||||
long hash = 37; |
||||
hash = 37 * hash + Double.doubleToLongBits(x); |
||||
hash = 37 * hash + Double.doubleToLongBits(y); |
||||
hash = 37 * hash + Double.doubleToLongBits(z); |
||||
hash = 37 * hash + Double.doubleToLongBits(w); |
||||
return (int) hash; |
||||
|
||||
} |
||||
|
||||
public void write(JmeExporter e) throws IOException { |
||||
OutputCapsule cap = e.getCapsule(this); |
||||
cap.write(x, "x", 0); |
||||
cap.write(y, "y", 0); |
||||
cap.write(z, "z", 0); |
||||
cap.write(w, "w", 1); |
||||
} |
||||
|
||||
public void read(JmeImporter e) throws IOException { |
||||
InputCapsule cap = e.getCapsule(this); |
||||
x = cap.readFloat("x", 0); |
||||
y = cap.readFloat("y", 0); |
||||
z = cap.readFloat("z", 0); |
||||
w = cap.readFloat("w", 1); |
||||
} |
||||
|
||||
@Override |
||||
public DQuaternion clone() { |
||||
try { |
||||
return (DQuaternion) super.clone(); |
||||
} catch (CloneNotSupportedException e) { |
||||
throw new AssertionError(); // can not happen
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,170 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package com.jme3.scene.plugins.blender.math; |
||||
|
||||
import com.jme3.export.*; |
||||
import com.jme3.math.Transform; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Started Date: Jul 16, 2004<br> |
||||
* <br> |
||||
* Represents a translation, rotation and scale in one object. |
||||
* |
||||
* This class's only purpose is to give better accuracy in floating point operations during computations. |
||||
* This is made by copying the original Transfrom class from jme3 core and removing unnecessary methods so that |
||||
* the class is smaller and easier to maintain. |
||||
* Should any other methods be needed, they will be added. |
||||
* |
||||
* @author Jack Lindamood |
||||
* @author Joshua Slack |
||||
* @author Marcin Roguski (Kaelthas) |
||||
*/ |
||||
public final class DTransform implements Savable, Cloneable, java.io.Serializable { |
||||
private static final long serialVersionUID = 7812915425940606722L; |
||||
|
||||
private DQuaternion rotation; |
||||
private Vector3d translation; |
||||
private Vector3d scale; |
||||
|
||||
public DTransform(Transform transform) { |
||||
translation = new Vector3d(transform.getTranslation()); |
||||
rotation = new DQuaternion(transform.getRotation()); |
||||
scale = new Vector3d(transform.getScale()); |
||||
} |
||||
|
||||
public Transform toTransform() { |
||||
return new Transform(translation.toVector3f(), rotation.toQuaternion(), scale.toVector3f()); |
||||
} |
||||
|
||||
/** |
||||
* Sets this translation to the given value. |
||||
* @param trans |
||||
* The new translation for this matrix. |
||||
* @return this |
||||
*/ |
||||
public DTransform setTranslation(Vector3d trans) { |
||||
translation.set(trans); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets this rotation to the given DQuaternion value. |
||||
* @param rot |
||||
* The new rotation for this matrix. |
||||
* @return this |
||||
*/ |
||||
public DTransform setRotation(DQuaternion rot) { |
||||
rotation.set(rot); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets this scale to the given value. |
||||
* @param scale |
||||
* The new scale for this matrix. |
||||
* @return this |
||||
*/ |
||||
public DTransform setScale(Vector3d scale) { |
||||
this.scale.set(scale); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets this scale to the given value. |
||||
* @param scale |
||||
* The new scale for this matrix. |
||||
* @return this |
||||
*/ |
||||
public DTransform setScale(float scale) { |
||||
this.scale.set(scale, scale, scale); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Return the translation vector in this matrix. |
||||
* @return translation vector. |
||||
*/ |
||||
public Vector3d getTranslation() { |
||||
return translation; |
||||
} |
||||
|
||||
/** |
||||
* Return the rotation quaternion in this matrix. |
||||
* @return rotation quaternion. |
||||
*/ |
||||
public DQuaternion getRotation() { |
||||
return rotation; |
||||
} |
||||
|
||||
/** |
||||
* Return the scale vector in this matrix. |
||||
* @return scale vector. |
||||
*/ |
||||
public Vector3d getScale() { |
||||
return scale; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return this.getClass().getSimpleName() + "[ " + translation.x + ", " + translation.y + ", " + translation.z + "]\n" + "[ " + rotation.x + ", " + rotation.y + ", " + rotation.z + ", " + rotation.w + "]\n" + "[ " + scale.x + " , " + scale.y + ", " + scale.z + "]"; |
||||
} |
||||
|
||||
public void write(JmeExporter e) throws IOException { |
||||
OutputCapsule capsule = e.getCapsule(this); |
||||
capsule.write(rotation, "rot", new DQuaternion()); |
||||
capsule.write(translation, "translation", Vector3d.ZERO); |
||||
capsule.write(scale, "scale", Vector3d.UNIT_XYZ); |
||||
} |
||||
|
||||
public void read(JmeImporter e) throws IOException { |
||||
InputCapsule capsule = e.getCapsule(this); |
||||
|
||||
rotation = (DQuaternion) capsule.readSavable("rot", new DQuaternion()); |
||||
translation = (Vector3d) capsule.readSavable("translation", Vector3d.ZERO); |
||||
scale = (Vector3d) capsule.readSavable("scale", Vector3d.UNIT_XYZ); |
||||
} |
||||
|
||||
@Override |
||||
public DTransform clone() { |
||||
try { |
||||
DTransform tq = (DTransform) super.clone(); |
||||
tq.rotation = rotation.clone(); |
||||
tq.scale = scale.clone(); |
||||
tq.translation = translation.clone(); |
||||
return tq; |
||||
} catch (CloneNotSupportedException e) { |
||||
throw new AssertionError(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,867 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
|
||||
package com.jme3.scene.plugins.blender.math; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.Serializable; |
||||
import java.util.logging.Logger; |
||||
|
||||
import com.jme3.export.InputCapsule; |
||||
import com.jme3.export.JmeExporter; |
||||
import com.jme3.export.JmeImporter; |
||||
import com.jme3.export.OutputCapsule; |
||||
import com.jme3.export.Savable; |
||||
import com.jme3.math.FastMath; |
||||
import com.jme3.math.Vector3f; |
||||
|
||||
/* |
||||
* -- Added *Local methods to cut down on object creation - JS |
||||
*/ |
||||
|
||||
/** |
||||
* <code>Vector3d</code> defines a Vector for a three float value tuple. <code>Vector3d</code> can represent any three dimensional value, such as a |
||||
* vertex, a normal, etc. Utility methods are also included to aid in |
||||
* mathematical calculations. |
||||
* |
||||
* This class's only purpose is to give better accuracy in floating point operations during computations. |
||||
* This is made by copying the original Vector3f class from jme3 core and leaving only required methods and basic computation methods, so that |
||||
* the class is smaller and easier to maintain. |
||||
* Should any other methods be needed, they will be added. |
||||
* |
||||
* @author Mark Powell |
||||
* @author Joshua Slack |
||||
* @author Marcin Roguski (Kaelthas) |
||||
*/ |
||||
public final class Vector3d implements Savable, Cloneable, Serializable { |
||||
private static final long serialVersionUID = 3090477054277293078L; |
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Vector3d.class.getName()); |
||||
|
||||
public final static Vector3d ZERO = new Vector3d(); |
||||
public final static Vector3d UNIT_XYZ = new Vector3d(1, 1, 1); |
||||
public final static Vector3d UNIT_X = new Vector3d(1, 0, 0); |
||||
public final static Vector3d UNIT_Y = new Vector3d(0, 1, 0); |
||||
public final static Vector3d UNIT_Z = new Vector3d(0, 0, 1); |
||||
|
||||
/** |
||||
* the x value of the vector. |
||||
*/ |
||||
public double x; |
||||
|
||||
/** |
||||
* the y value of the vector. |
||||
*/ |
||||
public double y; |
||||
|
||||
/** |
||||
* the z value of the vector. |
||||
*/ |
||||
public double z; |
||||
|
||||
/** |
||||
* Constructor instantiates a new <code>Vector3d</code> with default |
||||
* values of (0,0,0). |
||||
* |
||||
*/ |
||||
public Vector3d() { |
||||
} |
||||
|
||||
/** |
||||
* Constructor instantiates a new <code>Vector3d</code> with provides |
||||
* values. |
||||
* |
||||
* @param x |
||||
* the x value of the vector. |
||||
* @param y |
||||
* the y value of the vector. |
||||
* @param z |
||||
* the z value of the vector. |
||||
*/ |
||||
public Vector3d(double x, double y, double z) { |
||||
this.x = x; |
||||
this.y = y; |
||||
this.z = z; |
||||
} |
||||
|
||||
/** |
||||
* Constructor instantiates a new <code>Vector3d</code> that is a copy |
||||
* of the provided vector |
||||
* @param copy |
||||
* The Vector3d to copy |
||||
*/ |
||||
public Vector3d(Vector3f vector3f) { |
||||
this(vector3f.x, vector3f.y, vector3f.z); |
||||
} |
||||
|
||||
public Vector3f toVector3f() { |
||||
return new Vector3f((float) x, (float) y, (float) z); |
||||
} |
||||
|
||||
/** |
||||
* <code>set</code> sets the x,y,z values of the vector based on passed |
||||
* parameters. |
||||
* |
||||
* @param x |
||||
* the x value of the vector. |
||||
* @param y |
||||
* the y value of the vector. |
||||
* @param z |
||||
* the z value of the vector. |
||||
* @return this vector |
||||
*/ |
||||
public Vector3d set(double x, double y, double z) { |
||||
this.x = x; |
||||
this.y = y; |
||||
this.z = z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>set</code> sets the x,y,z values of the vector by copying the |
||||
* supplied vector. |
||||
* |
||||
* @param vect |
||||
* the vector to copy. |
||||
* @return this vector |
||||
*/ |
||||
public Vector3d set(Vector3d vect) { |
||||
return this.set(vect.x, vect.y, vect.z); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>add</code> adds a provided vector to this vector creating a |
||||
* resultant vector which is returned. If the provided vector is null, null |
||||
* is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to add to this. |
||||
* @return the resultant vector. |
||||
*/ |
||||
public Vector3d add(Vector3d vec) { |
||||
if (null == vec) { |
||||
LOGGER.warning("Provided vector is null, null returned."); |
||||
return null; |
||||
} |
||||
return new Vector3d(x + vec.x, y + vec.y, z + vec.z); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>add</code> adds the values of a provided vector storing the |
||||
* values in the supplied vector. |
||||
* |
||||
* @param vec |
||||
* the vector to add to this |
||||
* @param result |
||||
* the vector to store the result in |
||||
* @return result returns the supplied result vector. |
||||
*/ |
||||
public Vector3d add(Vector3d vec, Vector3d result) { |
||||
result.x = x + vec.x; |
||||
result.y = y + vec.y; |
||||
result.z = z + vec.z; |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* <code>addLocal</code> adds a provided vector to this vector internally, |
||||
* and returns a handle to this vector for easy chaining of calls. If the |
||||
* provided vector is null, null is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to add to this vector. |
||||
* @return this |
||||
*/ |
||||
public Vector3d addLocal(Vector3d vec) { |
||||
if (null == vec) { |
||||
LOGGER.warning("Provided vector is null, null returned."); |
||||
return null; |
||||
} |
||||
x += vec.x; |
||||
y += vec.y; |
||||
z += vec.z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>add</code> adds the provided values to this vector, creating a |
||||
* new vector that is then returned. |
||||
* |
||||
* @param addX |
||||
* the x value to add. |
||||
* @param addY |
||||
* the y value to add. |
||||
* @param addZ |
||||
* the z value to add. |
||||
* @return the result vector. |
||||
*/ |
||||
public Vector3d add(double addX, double addY, double addZ) { |
||||
return new Vector3d(x + addX, y + addY, z + addZ); |
||||
} |
||||
|
||||
/** |
||||
* <code>addLocal</code> adds the provided values to this vector |
||||
* internally, and returns a handle to this vector for easy chaining of |
||||
* calls. |
||||
* |
||||
* @param addX |
||||
* value to add to x |
||||
* @param addY |
||||
* value to add to y |
||||
* @param addZ |
||||
* value to add to z |
||||
* @return this |
||||
*/ |
||||
public Vector3d addLocal(double addX, double addY, double addZ) { |
||||
x += addX; |
||||
y += addY; |
||||
z += addZ; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>scaleAdd</code> multiplies this vector by a scalar then adds the |
||||
* given Vector3d. |
||||
* |
||||
* @param scalar |
||||
* the value to multiply this vector by. |
||||
* @param add |
||||
* the value to add |
||||
*/ |
||||
public Vector3d scaleAdd(double scalar, Vector3d add) { |
||||
x = x * scalar + add.x; |
||||
y = y * scalar + add.y; |
||||
z = z * scalar + add.z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>scaleAdd</code> multiplies the given vector by a scalar then adds |
||||
* the given vector. |
||||
* |
||||
* @param scalar |
||||
* the value to multiply this vector by. |
||||
* @param mult |
||||
* the value to multiply the scalar by |
||||
* @param add |
||||
* the value to add |
||||
*/ |
||||
public Vector3d scaleAdd(double scalar, Vector3d mult, Vector3d add) { |
||||
x = mult.x * scalar + add.x; |
||||
y = mult.y * scalar + add.y; |
||||
z = mult.z * scalar + add.z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>dot</code> calculates the dot product of this vector with a |
||||
* provided vector. If the provided vector is null, 0 is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to dot with this vector. |
||||
* @return the resultant dot product of this vector and a given vector. |
||||
*/ |
||||
public double dot(Vector3d vec) { |
||||
if (null == vec) { |
||||
LOGGER.warning("Provided vector is null, 0 returned."); |
||||
return 0; |
||||
} |
||||
return x * vec.x + y * vec.y + z * vec.z; |
||||
} |
||||
|
||||
/** |
||||
* <code>cross</code> calculates the cross product of this vector with a |
||||
* parameter vector v. |
||||
* |
||||
* @param v |
||||
* the vector to take the cross product of with this. |
||||
* @return the cross product vector. |
||||
*/ |
||||
public Vector3d cross(Vector3d v) { |
||||
return this.cross(v, null); |
||||
} |
||||
|
||||
/** |
||||
* <code>cross</code> calculates the cross product of this vector with a |
||||
* parameter vector v. The result is stored in <code>result</code> |
||||
* |
||||
* @param v |
||||
* the vector to take the cross product of with this. |
||||
* @param result |
||||
* the vector to store the cross product result. |
||||
* @return result, after recieving the cross product vector. |
||||
*/ |
||||
public Vector3d cross(Vector3d v, Vector3d result) { |
||||
return this.cross(v.x, v.y, v.z, result); |
||||
} |
||||
|
||||
/** |
||||
* <code>cross</code> calculates the cross product of this vector with a |
||||
* parameter vector v. The result is stored in <code>result</code> |
||||
* |
||||
* @param otherX |
||||
* x component of the vector to take the cross product of with this. |
||||
* @param otherY |
||||
* y component of the vector to take the cross product of with this. |
||||
* @param otherZ |
||||
* z component of the vector to take the cross product of with this. |
||||
* @param result |
||||
* the vector to store the cross product result. |
||||
* @return result, after recieving the cross product vector. |
||||
*/ |
||||
public Vector3d cross(double otherX, double otherY, double otherZ, Vector3d result) { |
||||
if (result == null) { |
||||
result = new Vector3d(); |
||||
} |
||||
double resX = y * otherZ - z * otherY; |
||||
double resY = z * otherX - x * otherZ; |
||||
double resZ = x * otherY - y * otherX; |
||||
result.set(resX, resY, resZ); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* <code>crossLocal</code> calculates the cross product of this vector |
||||
* with a parameter vector v. |
||||
* |
||||
* @param v |
||||
* the vector to take the cross product of with this. |
||||
* @return this. |
||||
*/ |
||||
public Vector3d crossLocal(Vector3d v) { |
||||
return this.crossLocal(v.x, v.y, v.z); |
||||
} |
||||
|
||||
/** |
||||
* <code>crossLocal</code> calculates the cross product of this vector |
||||
* with a parameter vector v. |
||||
* |
||||
* @param otherX |
||||
* x component of the vector to take the cross product of with this. |
||||
* @param otherY |
||||
* y component of the vector to take the cross product of with this. |
||||
* @param otherZ |
||||
* z component of the vector to take the cross product of with this. |
||||
* @return this. |
||||
*/ |
||||
public Vector3d crossLocal(double otherX, double otherY, double otherZ) { |
||||
double tempx = y * otherZ - z * otherY; |
||||
double tempy = z * otherX - x * otherZ; |
||||
z = x * otherY - y * otherX; |
||||
x = tempx; |
||||
y = tempy; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>length</code> calculates the magnitude of this vector. |
||||
* |
||||
* @return the length or magnitude of the vector. |
||||
*/ |
||||
public double length() { |
||||
return Math.sqrt(this.lengthSquared()); |
||||
} |
||||
|
||||
/** |
||||
* <code>lengthSquared</code> calculates the squared value of the |
||||
* magnitude of the vector. |
||||
* |
||||
* @return the magnitude squared of the vector. |
||||
*/ |
||||
public double lengthSquared() { |
||||
return x * x + y * y + z * z; |
||||
} |
||||
|
||||
/** |
||||
* <code>distanceSquared</code> calculates the distance squared between |
||||
* this vector and vector v. |
||||
* |
||||
* @param v |
||||
* the second vector to determine the distance squared. |
||||
* @return the distance squared between the two vectors. |
||||
*/ |
||||
public double distanceSquared(Vector3d v) { |
||||
double dx = x - v.x; |
||||
double dy = y - v.y; |
||||
double dz = z - v.z; |
||||
return dx * dx + dy * dy + dz * dz; |
||||
} |
||||
|
||||
/** |
||||
* <code>distance</code> calculates the distance between this vector and |
||||
* vector v. |
||||
* |
||||
* @param v |
||||
* the second vector to determine the distance. |
||||
* @return the distance between the two vectors. |
||||
*/ |
||||
public double distance(Vector3d v) { |
||||
return Math.sqrt(this.distanceSquared(v)); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>mult</code> multiplies this vector by a scalar. The resultant |
||||
* vector is returned. |
||||
* |
||||
* @param scalar |
||||
* the value to multiply this vector by. |
||||
* @return the new vector. |
||||
*/ |
||||
public Vector3d mult(double scalar) { |
||||
return new Vector3d(x * scalar, y * scalar, z * scalar); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>mult</code> multiplies this vector by a scalar. The resultant |
||||
* vector is supplied as the second parameter and returned. |
||||
* |
||||
* @param scalar |
||||
* the scalar to multiply this vector by. |
||||
* @param product |
||||
* the product to store the result in. |
||||
* @return product |
||||
*/ |
||||
public Vector3d mult(double scalar, Vector3d product) { |
||||
if (null == product) { |
||||
product = new Vector3d(); |
||||
} |
||||
|
||||
product.x = x * scalar; |
||||
product.y = y * scalar; |
||||
product.z = z * scalar; |
||||
return product; |
||||
} |
||||
|
||||
/** |
||||
* <code>multLocal</code> multiplies this vector by a scalar internally, |
||||
* and returns a handle to this vector for easy chaining of calls. |
||||
* |
||||
* @param scalar |
||||
* the value to multiply this vector by. |
||||
* @return this |
||||
*/ |
||||
public Vector3d multLocal(double scalar) { |
||||
x *= scalar; |
||||
y *= scalar; |
||||
z *= scalar; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>multLocal</code> multiplies a provided vector to this vector |
||||
* internally, and returns a handle to this vector for easy chaining of |
||||
* calls. If the provided vector is null, null is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to mult to this vector. |
||||
* @return this |
||||
*/ |
||||
public Vector3d multLocal(Vector3d vec) { |
||||
if (null == vec) { |
||||
LOGGER.warning("Provided vector is null, null returned."); |
||||
return null; |
||||
} |
||||
x *= vec.x; |
||||
y *= vec.y; |
||||
z *= vec.z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>multLocal</code> multiplies this vector by 3 scalars |
||||
* internally, and returns a handle to this vector for easy chaining of |
||||
* calls. |
||||
* |
||||
* @param x |
||||
* @param y |
||||
* @param z |
||||
* @return this |
||||
*/ |
||||
public Vector3d multLocal(double x, double y, double z) { |
||||
this.x *= x; |
||||
this.y *= y; |
||||
this.z *= z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>multLocal</code> multiplies a provided vector to this vector |
||||
* internally, and returns a handle to this vector for easy chaining of |
||||
* calls. If the provided vector is null, null is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to mult to this vector. |
||||
* @return this |
||||
*/ |
||||
public Vector3d mult(Vector3d vec) { |
||||
if (null == vec) { |
||||
LOGGER.warning("Provided vector is null, null returned."); |
||||
return null; |
||||
} |
||||
return this.mult(vec, null); |
||||
} |
||||
|
||||
/** |
||||
* <code>multLocal</code> multiplies a provided vector to this vector |
||||
* internally, and returns a handle to this vector for easy chaining of |
||||
* calls. If the provided vector is null, null is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to mult to this vector. |
||||
* @param store |
||||
* result vector (null to create a new vector) |
||||
* @return this |
||||
*/ |
||||
public Vector3d mult(Vector3d vec, Vector3d store) { |
||||
if (null == vec) { |
||||
LOGGER.warning("Provided vector is null, null returned."); |
||||
return null; |
||||
} |
||||
if (store == null) { |
||||
store = new Vector3d(); |
||||
} |
||||
return store.set(x * vec.x, y * vec.y, z * vec.z); |
||||
} |
||||
|
||||
/** |
||||
* <code>divide</code> divides the values of this vector by a scalar and |
||||
* returns the result. The values of this vector remain untouched. |
||||
* |
||||
* @param scalar |
||||
* the value to divide this vectors attributes by. |
||||
* @return the result <code>Vector</code>. |
||||
*/ |
||||
public Vector3d divide(double scalar) { |
||||
scalar = 1f / scalar; |
||||
return new Vector3d(x * scalar, y * scalar, z * scalar); |
||||
} |
||||
|
||||
/** |
||||
* <code>divideLocal</code> divides this vector by a scalar internally, |
||||
* and returns a handle to this vector for easy chaining of calls. Dividing |
||||
* by zero will result in an exception. |
||||
* |
||||
* @param scalar |
||||
* the value to divides this vector by. |
||||
* @return this |
||||
*/ |
||||
public Vector3d divideLocal(double scalar) { |
||||
scalar = 1f / scalar; |
||||
x *= scalar; |
||||
y *= scalar; |
||||
z *= scalar; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>divide</code> divides the values of this vector by a scalar and |
||||
* returns the result. The values of this vector remain untouched. |
||||
* |
||||
* @param scalar |
||||
* the value to divide this vectors attributes by. |
||||
* @return the result <code>Vector</code>. |
||||
*/ |
||||
public Vector3d divide(Vector3d scalar) { |
||||
return new Vector3d(x / scalar.x, y / scalar.y, z / scalar.z); |
||||
} |
||||
|
||||
/** |
||||
* <code>divideLocal</code> divides this vector by a scalar internally, |
||||
* and returns a handle to this vector for easy chaining of calls. Dividing |
||||
* by zero will result in an exception. |
||||
* |
||||
* @param scalar |
||||
* the value to divides this vector by. |
||||
* @return this |
||||
*/ |
||||
public Vector3d divideLocal(Vector3d scalar) { |
||||
x /= scalar.x; |
||||
y /= scalar.y; |
||||
z /= scalar.z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>negate</code> returns the negative of this vector. All values are |
||||
* negated and set to a new vector. |
||||
* |
||||
* @return the negated vector. |
||||
*/ |
||||
public Vector3d negate() { |
||||
return new Vector3d(-x, -y, -z); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>negateLocal</code> negates the internal values of this vector. |
||||
* |
||||
* @return this. |
||||
*/ |
||||
public Vector3d negateLocal() { |
||||
x = -x; |
||||
y = -y; |
||||
z = -z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>subtract</code> subtracts the values of a given vector from those |
||||
* of this vector creating a new vector object. If the provided vector is |
||||
* null, null is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to subtract from this vector. |
||||
* @return the result vector. |
||||
*/ |
||||
public Vector3d subtract(Vector3d vec) { |
||||
return new Vector3d(x - vec.x, y - vec.y, z - vec.z); |
||||
} |
||||
|
||||
/** |
||||
* <code>subtractLocal</code> subtracts a provided vector to this vector |
||||
* internally, and returns a handle to this vector for easy chaining of |
||||
* calls. If the provided vector is null, null is returned. |
||||
* |
||||
* @param vec |
||||
* the vector to subtract |
||||
* @return this |
||||
*/ |
||||
public Vector3d subtractLocal(Vector3d vec) { |
||||
if (null == vec) { |
||||
LOGGER.warning("Provided vector is null, null returned."); |
||||
return null; |
||||
} |
||||
x -= vec.x; |
||||
y -= vec.y; |
||||
z -= vec.z; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>subtract</code> |
||||
* |
||||
* @param vec |
||||
* the vector to subtract from this |
||||
* @param result |
||||
* the vector to store the result in |
||||
* @return result |
||||
*/ |
||||
public Vector3d subtract(Vector3d vec, Vector3d result) { |
||||
if (result == null) { |
||||
result = new Vector3d(); |
||||
} |
||||
result.x = x - vec.x; |
||||
result.y = y - vec.y; |
||||
result.z = z - vec.z; |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* <code>subtract</code> subtracts the provided values from this vector, |
||||
* creating a new vector that is then returned. |
||||
* |
||||
* @param subtractX |
||||
* the x value to subtract. |
||||
* @param subtractY |
||||
* the y value to subtract. |
||||
* @param subtractZ |
||||
* the z value to subtract. |
||||
* @return the result vector. |
||||
*/ |
||||
public Vector3d subtract(double subtractX, double subtractY, double subtractZ) { |
||||
return new Vector3d(x - subtractX, y - subtractY, z - subtractZ); |
||||
} |
||||
|
||||
/** |
||||
* <code>subtractLocal</code> subtracts the provided values from this vector |
||||
* internally, and returns a handle to this vector for easy chaining of |
||||
* calls. |
||||
* |
||||
* @param subtractX |
||||
* the x value to subtract. |
||||
* @param subtractY |
||||
* the y value to subtract. |
||||
* @param subtractZ |
||||
* the z value to subtract. |
||||
* @return this |
||||
*/ |
||||
public Vector3d subtractLocal(double subtractX, double subtractY, double subtractZ) { |
||||
x -= subtractX; |
||||
y -= subtractY; |
||||
z -= subtractZ; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>normalize</code> returns the unit vector of this vector. |
||||
* |
||||
* @return unit vector of this vector. |
||||
*/ |
||||
public Vector3d normalize() { |
||||
double length = x * x + y * y + z * z; |
||||
if (length != 1f && length != 0f) { |
||||
length = 1.0f / Math.sqrt(length); |
||||
return new Vector3d(x * length, y * length, z * length); |
||||
} |
||||
return this.clone(); |
||||
} |
||||
|
||||
/** |
||||
* <code>normalizeLocal</code> makes this vector into a unit vector of |
||||
* itself. |
||||
* |
||||
* @return this. |
||||
*/ |
||||
public Vector3d normalizeLocal() { |
||||
// NOTE: this implementation is more optimized
|
||||
// than the old jme normalize as this method
|
||||
// is commonly used.
|
||||
double length = x * x + y * y + z * z; |
||||
if (length != 1f && length != 0f) { |
||||
length = 1.0f / Math.sqrt(length); |
||||
x *= length; |
||||
y *= length; |
||||
z *= length; |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <code>angleBetween</code> returns (in radians) the angle between two vectors. |
||||
* It is assumed that both this vector and the given vector are unit vectors (iow, normalized). |
||||
* |
||||
* @param otherVector |
||||
* a unit vector to find the angle against |
||||
* @return the angle in radians. |
||||
*/ |
||||
public double angleBetween(Vector3d otherVector) { |
||||
double dot = this.dot(otherVector); |
||||
// the vectors are normalized, but if they are parallel then the dot product migh get a value like: 1.000000000000000002
|
||||
// which is caused by floating point operations; in such case, the acos function will return NaN so we need to clamp this value
|
||||
dot = FastMath.clamp((float) dot, -1, 1); |
||||
return Math.acos(dot); |
||||
} |
||||
|
||||
@Override |
||||
public Vector3d clone() { |
||||
try { |
||||
return (Vector3d) super.clone(); |
||||
} catch (CloneNotSupportedException e) { |
||||
throw new AssertionError(); // can not happen
|
||||
} |
||||
} |
||||
|
||||
/** |
||||
* are these two vectors the same? they are is they both have the same x,y, |
||||
* and z values. |
||||
* |
||||
* @param o |
||||
* the object to compare for equality |
||||
* @return true if they are equal |
||||
*/ |
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (!(o instanceof Vector3d)) { |
||||
return false; |
||||
} |
||||
|
||||
if (this == o) { |
||||
return true; |
||||
} |
||||
|
||||
Vector3d comp = (Vector3d) o; |
||||
if (Double.compare(x, comp.x) != 0) { |
||||
return false; |
||||
} |
||||
if (Double.compare(y, comp.y) != 0) { |
||||
return false; |
||||
} |
||||
if (Double.compare(z, comp.z) != 0) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* <code>hashCode</code> returns a unique code for this vector object based |
||||
* on it's values. If two vectors are logically equivalent, they will return |
||||
* the same hash code value. |
||||
* @return the hash code value of this vector. |
||||
*/ |
||||
@Override |
||||
public int hashCode() { |
||||
long hash = 37; |
||||
hash += 37 * hash + Double.doubleToLongBits(x); |
||||
hash += 37 * hash + Double.doubleToLongBits(y); |
||||
hash += 37 * hash + Double.doubleToLongBits(z); |
||||
return (int) hash; |
||||
} |
||||
|
||||
/** |
||||
* <code>toString</code> returns the string representation of this vector. |
||||
* The format is: |
||||
* |
||||
* org.jme.math.Vector3d [X=XX.XXXX, Y=YY.YYYY, Z=ZZ.ZZZZ] |
||||
* |
||||
* @return the string representation of this vector. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return "(" + x + ", " + y + ", " + z + ")"; |
||||
} |
||||
|
||||
public void write(JmeExporter e) throws IOException { |
||||
OutputCapsule capsule = e.getCapsule(this); |
||||
capsule.write(x, "x", 0); |
||||
capsule.write(y, "y", 0); |
||||
capsule.write(z, "z", 0); |
||||
} |
||||
|
||||
public void read(JmeImporter e) throws IOException { |
||||
InputCapsule capsule = e.getCapsule(this); |
||||
x = capsule.readDouble("x", 0); |
||||
y = capsule.readDouble("y", 0); |
||||
z = capsule.readDouble("z", 0); |
||||
} |
||||
} |
Loading…
Reference in new issue