diff options
author | Curtis Rueden <[email protected]> | 2015-11-18 09:10:28 -0600 |
---|---|---|
committer | Curtis Rueden <[email protected]> | 2015-11-27 22:55:12 -0600 |
commit | 0bc630ab20ae013225c0c93ff13733457724f143 (patch) | |
tree | 92cb5c4bc2ef7440ea2daccecc490092a7bf12f8 /src/org | |
parent | 89caa5181fae34eaaec6d4e0a40c08ea5d38844e (diff) |
Relocate package prefix to org.jogamp.vecmath
Updating the package prefix avoids clashes with old versions of Java 3D.
This is especially important on OS X, where Java 3D 1.3 is sometimes
present on the java.ext.path, taking precedence over the classpath.
Diffstat (limited to 'src/org')
49 files changed, 30379 insertions, 0 deletions
diff --git a/src/org/jogamp/vecmath/AxisAngle4d.java b/src/org/jogamp/vecmath/AxisAngle4d.java new file mode 100644 index 0000000..f1e0e3b --- /dev/null +++ b/src/org/jogamp/vecmath/AxisAngle4d.java @@ -0,0 +1,651 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +/** + * A four-element axis angle represented by double-precision floating point + * x,y,z,angle components. An axis angle is a rotation of angle (radians) + * about the vector (x,y,z). + * + */ +public class AxisAngle4d implements java.io.Serializable, Cloneable { + + + // Compatible with 1.1 + static final long serialVersionUID = 3644296204459140589L; + + /** + * The x coordinate. + */ + public double x; + + /** + * The y coordinate. + */ + public double y; + + /** + * The z coordinate. + */ + public double z; + + /** + * The angle of rotation in radians. + */ + public double angle; + + // Fixed to issue 538 + final static double EPS = 1.0e-12; + + /** + * Constructs and initializes an AxisAngle4d from the specified + * x, y, z, and angle. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param angle the angle of rotation in radians + */ + public AxisAngle4d(double x, double y, double z, double angle) + { + this.x = x; + this.y = y; + this.z = z; + this.angle = angle; + } + + + /** + * Constructs and initializes an AxisAngle4d from the components + * contained in the array. + * @param a the array of length 4 containing x,y,z,angle in order + */ + public AxisAngle4d(double[] a) + { + this.x = a[0]; + this.y = a[1]; + this.z = a[2]; + this.angle = a[3]; + } + /** + * Constructs and initializes an AxisAngle4d from the specified AxisAngle4d. + * @param a1 the AxisAngle4d containing the initialization x y z angle data + */ + public AxisAngle4d(AxisAngle4d a1) + { + this.x = a1.x; + this.y = a1.y; + this.z = a1.z; + this.angle = a1.angle; + } + + + /** + * Constructs and initializes an AxisAngle4d from the specified + * AxisAngle4f. + * @param a1 the AxisAngle4f containing the initialization x y z angle data + */ + public AxisAngle4d(AxisAngle4f a1) + { + this.x = a1.x; + this.y = a1.y; + this.z = a1.z; + this.angle = a1.angle; + } + + + /** + * Constructs and initializes an AxisAngle4d from the specified + * axis and angle. + * @param axis the axis + * @param angle the angle of rotation in radian + * + * @since vecmath 1.2 + */ + public AxisAngle4d(Vector3d axis, double angle) { + this.x = axis.x; + this.y = axis.y; + this.z = axis.z; + this.angle = angle; + } + + + /** + * Constructs and initializes an AxisAngle4d to (0,0,1,0). + */ + public AxisAngle4d() + { + this.x = 0.0; + this.y = 0.0; + this.z = 1.0; + this.angle = 0.0; + } + + + /** + * Sets the value of this axis angle to the specified x,y,z,angle. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param angle the angle of rotation in radians + */ + public final void set(double x, double y, double z, double angle) + { + this.x = x; + this.y = y; + this.z = z; + this.angle = angle; + } + + + /** + * Sets the value of this axis angle to the specified x,y,z,angle. + * @param a the array of length 4 containing x,y,z,angle in order + */ + public final void set(double[] a) + { + this.x = a[0]; + this.y = a[1]; + this.z = a[2]; + this.angle = a[3]; + } + + + /** + * Sets the value of this axis angle to the value of axis angle a1. + * @param a1 the axis angle to be copied + */ + public final void set(AxisAngle4d a1) + { + this.x = a1.x; + this.y = a1.y; + this.z = a1.z; + this.angle = a1.angle; + } + + + /** + * Sets the value of this axis angle to the value of axis angle a1. + * @param a1 the axis angle to be copied + */ + public final void set(AxisAngle4f a1) + { + this.x = a1.x; + this.y = a1.y; + this.z = a1.z; + this.angle = a1.angle; + } + + + /** + * Sets the value of this AxisAngle4d to the specified + * axis and angle. + * @param axis the axis + * @param angle the angle of rotation in radians + * + * @since vecmath 1.2 + */ + public final void set(Vector3d axis, double angle) { + this.x = axis.x; + this.y = axis.y; + this.z = axis.z; + this.angle = angle; + } + + + /** + * Gets the value of this axis angle and places it into the array a of + * length four in x,y,z,angle order. + * @param a the array of length four + */ + public final void get(double[] a) + { + a[0] = this.x; + a[1] = this.y; + a[2] = this.z; + a[3] = this.angle; + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0). + * + * @param m1 the matrix4f + */ + public final void set(Matrix4f m1) + { + Matrix3d m3d = new Matrix3d(); + + m1.get(m3d); + + x = (float)(m3d.m21 - m3d.m12); + y = (float)(m3d.m02 - m3d.m20); + z = (float)(m3d.m10 - m3d.m01); + double mag = x*x + y*y + z*z; + + if (mag > EPS ) { + mag = Math.sqrt(mag); + double sin = 0.5*mag; + double cos = 0.5*(m3d.m00 + m3d.m11 + m3d.m22 - 1.0); + + angle = (float)Math.atan2(sin, cos); + + double invMag = 1.0/mag; + x = x*invMag; + y = y*invMag; + z = z*invMag; + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0). + * + * @param m1 the matrix4d + */ + public final void set(Matrix4d m1) + { + Matrix3d m3d = new Matrix3d(); + + m1.get(m3d); + + x = (float)(m3d.m21 - m3d.m12); + y = (float)(m3d.m02 - m3d.m20); + z = (float)(m3d.m10 - m3d.m01); + + double mag = x*x + y*y + z*z; + + if (mag > EPS ) { + mag = Math.sqrt(mag); + + double sin = 0.5*mag; + double cos = 0.5*(m3d.m00 + m3d.m11 + m3d.m22 - 1.0); + angle = (float)Math.atan2(sin, cos); + + double invMag = 1.0/mag; + x = x*invMag; + y = y*invMag; + z = z*invMag; + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0). + * @param m1 the matrix3f + */ + public final void set(Matrix3f m1) + { + x = (float)(m1.m21 - m1.m12); + y = (float)(m1.m02 - m1.m20); + z = (float)(m1.m10 - m1.m01); + double mag = x*x + y*y + z*z; + + if (mag > EPS ) { + mag = Math.sqrt(mag); + + double sin = 0.5*mag; + double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0); + angle = (float)Math.atan2(sin, cos); + + double invMag = 1.0/mag; + x = x*invMag; + y = y*invMag; + z = z*invMag; + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0). + * @param m1 the matrix3d + */ + public final void set(Matrix3d m1) + { + x = (float)(m1.m21 - m1.m12); + y = (float)(m1.m02 - m1.m20); + z = (float)(m1.m10 - m1.m01); + + double mag = x*x + y*y + z*z; + + if (mag > EPS ) { + mag = Math.sqrt(mag); + + double sin = 0.5*mag; + double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0); + + angle = (float)Math.atan2(sin, cos); + + double invMag = 1.0/mag; + x = x*invMag; + y = y*invMag; + z = z*invMag; + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + + } + + + + /** + * Sets the value of this axis-angle to the rotational equivalent + * of the passed quaternion. + * If the specified quaternion has no rotational component, the value + * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0). + * @param q1 the Quat4f + */ + public final void set(Quat4f q1) + { + double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z; + + if( mag > EPS ) { + mag = Math.sqrt(mag); + double invMag = 1.0/mag; + + x = q1.x*invMag; + y = q1.y*invMag; + z = q1.z*invMag; + angle = 2.0*Math.atan2(mag, q1.w); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + } + + + /** + * Sets the value of this axis-angle to the rotational equivalent + * of the passed quaternion. + * If the specified quaternion has no rotational component, the value + * of this AxisAngle4d is set to an angle of 0 about an axis of (0,1,0). + * @param q1 the Quat4d + */ + public final void set(Quat4d q1) + { + double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z; + + if ( mag > EPS ) { + mag = Math.sqrt(mag); + double invMag = 1.0/mag; + + x = q1.x*invMag; + y = q1.y*invMag; + z = q1.z*invMag; + angle = 2.0*Math.atan2(mag, q1.w); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0f; + } + } + + + /** + * Returns a string that contains the values of this AxisAngle4d. + * The form is (x,y,z,angle). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.angle + ")"; + } + + + /** + * Returns true if all of the data members of AxisAngle4d a1 are + * equal to the corresponding data members in this AxisAngle4d. + * @param a1 the axis-angle with which the comparison is made + * @return true or false + */ + public boolean equals(AxisAngle4d a1) + { + try { + return(this.x == a1.x && this.y == a1.y && this.z == a1.z + && this.angle == a1.angle); + } + catch (NullPointerException e2) {return false;} + + } + /** + * Returns true if the Object o1 is of type AxisAngle4d and all of the + * data members of o1 are equal to the corresponding data members in + * this AxisAngle4d. + * @param o1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object o1) + { + try { + AxisAngle4d a2 = (AxisAngle4d) o1; + return(this.x == a2.x && this.y == a2.y && this.z == a2.z + && this.angle == a2.angle); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + + } + + + /** + * Returns true if the L-infinite distance between this axis-angle + * and axis-angle a1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(angle1-angle2)]. + * @param a1 the axis-angle to be compared to this axis-angle + * @param epsilon the threshold value + */ + public boolean epsilonEquals(AxisAngle4d a1, double epsilon) + { + double diff; + + diff = x - a1.x; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - a1.y; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = z - a1.z; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = angle - a1.angle; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different AxisAngle4d objects with identical data values + * (i.e., AxisAngle4d.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashDoubleBits(bits, x); + bits = VecMathUtil.hashDoubleBits(bits, y); + bits = VecMathUtil.hashDoubleBits(bits, z); + bits = VecMathUtil.hashDoubleBits(bits, angle); + return VecMathUtil.hashFinish(bits); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get the axis angle, in radians.<br> + * An axis angle is a rotation angle about the vector (x,y,z). + * + * @return the angle, in radians. + * + * @since vecmath 1.5 + */ + public final double getAngle() { + return angle; + } + + + /** + * Set the axis angle, in radians.<br> + * An axis angle is a rotation angle about the vector (x,y,z). + * + * @param angle The angle to set, in radians. + * + * @since vecmath 1.5 + */ + public final void setAngle(double angle) { + this.angle = angle; + } + + + /** + * Get value of <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public double getX() { + return x; + } + + + /** + * Set a new value for <i>x</i> coordinate. + * + * @param x the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(double x) { + this.x = x; + } + + + /** + * Get value of <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getY() { + return y; + } + + + /** + * Set a new value for <i>y</i> coordinate. + * + * @param y the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(double y) { + this.y = y; + } + + + /** + * Get value of <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public double getZ() { + return z; + } + + + /** + * Set a new value for <i>z</i> coordinate. + * + * @param z the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(double z) { + this.z = z; + } + +} diff --git a/src/org/jogamp/vecmath/AxisAngle4f.java b/src/org/jogamp/vecmath/AxisAngle4f.java new file mode 100644 index 0000000..e78f769 --- /dev/null +++ b/src/org/jogamp/vecmath/AxisAngle4f.java @@ -0,0 +1,647 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A four-element axis angle represented by single-precision floating point + * x,y,z,angle components. An axis angle is a rotation of angle (radians) + * about the vector (x,y,z). + * + */ +public class AxisAngle4f implements java.io.Serializable, Cloneable { + + // Compatible with 1.1 + static final long serialVersionUID = -163246355858070601L; + + /** + * The x coordinate. + */ + public float x; + + /** + * The y coordinate. + */ + public float y; + + /** + * The z coordinate. + */ + public float z; + + /** + * The angle of rotation in radians. + */ + public float angle; + + final static double EPS = 0.000001; + + /** + * Constructs and initializes a AxisAngle4f from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param angle the angle of rotation in radians + */ + public AxisAngle4f(float x, float y, float z, float angle) + { + this.x = x; + this.y = y; + this.z = z; + this.angle = angle; + } + + + /** + * Constructs and initializes an AxisAngle4f from the array of length 4. + * @param a the array of length 4 containing x,y,z,angle in order + */ + public AxisAngle4f(float[] a) + { + this.x = a[0]; + this.y = a[1]; + this.z = a[2]; + this.angle = a[3]; + } + + + /** + * Constructs and initializes an AxisAngle4f from the specified + * AxisAngle4f. + * @param a1 the AxisAngle4f containing the initialization x y z angle data + */ + public AxisAngle4f(AxisAngle4f a1) + { + this.x = a1.x; + this.y = a1.y; + this.z = a1.z; + this.angle = a1.angle; + } + + + /** + * Constructs and initializes an AxisAngle4f from the specified AxisAngle4d. + * @param a1 the AxisAngle4d containing the initialization x y z angle data + */ + public AxisAngle4f(AxisAngle4d a1) + { + this.x = (float) a1.x; + this.y = (float) a1.y; + this.z = (float) a1.z; + this.angle = (float) a1.angle; + } + + + /** + * Constructs and initializes an AxisAngle4f from the specified + * axis and angle. + * @param axis the axis + * @param angle the angle of rotation in radians + * + * @since vecmath 1.2 + */ + public AxisAngle4f(Vector3f axis, float angle) { + this.x = axis.x; + this.y = axis.y; + this.z = axis.z; + this.angle = angle; + } + + + /** + * Constructs and initializes an AxisAngle4f to (0,0,1,0). + */ + public AxisAngle4f() + { + this.x = 0.0f; + this.y = 0.0f; + this.z = 1.0f; + this.angle = 0.0f; + } + + + /** + * Sets the value of this axis-angle to the specified x,y,z,angle. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param angle the angle of rotation in radians + */ + public final void set(float x, float y, float z, float angle) + { + this.x = x; + this.y = y; + this.z = z; + this.angle = angle; + } + + + /** + * Sets the value of this axis-angle to the specified values in the + * array of length 4. + * @param a the array of length 4 containing x,y,z,angle in order + */ + public final void set(float[] a) + { + this.x = a[0]; + this.y = a[1]; + this.z = a[2]; + this.angle = a[3]; + } + + + /** + * Sets the value of this axis-angle to the value of axis-angle a1. + * @param a1 the axis-angle to be copied + */ + public final void set(AxisAngle4f a1) + { + this.x = a1.x; + this.y = a1.y; + this.z = a1.z; + this.angle = a1.angle; + } + + + /** + * Sets the value of this axis-angle to the value of axis-angle a1. + * @param a1 the axis-angle to be copied + */ + public final void set(AxisAngle4d a1) + { + this.x = (float) a1.x; + this.y = (float) a1.y; + this.z = (float) a1.z; + this.angle = (float) a1.angle; + } + + + /** + * Sets the value of this AxisAngle4f to the specified + * axis and angle. + * @param axis the axis + * @param angle the angle of rotation in radians + * + * @since vecmath 1.2 + */ + public final void set(Vector3f axis, float angle) { + this.x = axis.x; + this.y = axis.y; + this.z = axis.z; + this.angle = angle; + } + + + /** + * Copies the value of this axis-angle into the array a. + * @param a the array + */ + public final void get(float[] a) + { + a[0] = this.x; + a[1] = this.y; + a[2] = this.z; + a[3] = this.angle; + } + + + /** + * Sets the value of this axis-angle to the rotational equivalent + * of the passed quaternion. + * If the specified quaternion has no rotational component, the value + * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0). + * @param q1 the Quat4f + */ + public final void set(Quat4f q1) + { + double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z; + + if ( mag > EPS ) { + mag = Math.sqrt(mag); + double invMag = 1.0/mag; + + x = (float)(q1.x*invMag); + y = (float)(q1.y*invMag); + z = (float)(q1.z*invMag); + angle = (float)(2.0*Math.atan2(mag, q1.w)); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + } + + + /** + * Sets the value of this axis-angle to the rotational equivalent + * of the passed quaternion. + * If the specified quaternion has no rotational component, the value + * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0). + * @param q1 the Quat4d + */ + public final void set(Quat4d q1) + { + double mag = q1.x*q1.x + q1.y*q1.y + q1.z*q1.z; + + if (mag > EPS) { + mag = Math.sqrt(mag); + double invMag = 1.0/mag; + + x = (float)(q1.x*invMag); + y = (float)(q1.y*invMag); + z = (float)(q1.z*invMag); + angle = (float)(2.0*Math.atan2(mag, q1.w)); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0). + * @param m1 the matrix4f + */ + public final void set(Matrix4f m1) + { + Matrix3f m3f = new Matrix3f(); + + m1.get(m3f); + + x = m3f.m21 - m3f.m12; + y = m3f.m02 - m3f.m20; + z = m3f.m10 - m3f.m01; + double mag = x*x + y*y + z*z; + + if (mag > EPS) { + mag = Math.sqrt(mag); + double sin = 0.5*mag; + double cos = 0.5*(m3f.m00 + m3f.m11 + m3f.m22 - 1.0); + + angle = (float)Math.atan2(sin, cos); + double invMag = 1.0/mag; + x = (float)(x*invMag); + y = (float)(y*invMag); + z = (float)(z*invMag); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + + + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0). + * @param m1 the matrix4d + */ + public final void set(Matrix4d m1) + { + Matrix3d m3d = new Matrix3d(); + + m1.get(m3d); + + + x = (float)(m3d.m21 - m3d.m12); + y = (float)(m3d.m02 - m3d.m20); + z = (float)(m3d.m10 - m3d.m01); + double mag = x*x + y*y + z*z; + + if (mag > EPS) { + mag = Math.sqrt(mag); + double sin = 0.5*mag; + double cos = 0.5*(m3d.m00 + m3d.m11 + m3d.m22 - 1.0); + angle = (float)Math.atan2(sin, cos); + + double invMag = 1.0/mag; + x = (float)(x*invMag); + y = (float)(y*invMag); + z = (float)(z*invMag); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0). + * @param m1 the matrix3f + */ + public final void set(Matrix3f m1) + { + x = (float)(m1.m21 - m1.m12); + y = (float)(m1.m02 - m1.m20); + z = (float)(m1.m10 - m1.m01); + double mag = x*x + y*y + z*z; + if (mag > EPS) { + mag = Math.sqrt(mag); + double sin = 0.5*mag; + double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0); + + angle = (float)Math.atan2(sin, cos); + + double invMag = 1.0/mag; + x = (float)(x*invMag); + y = (float)(y*invMag); + z = (float)(z*invMag); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + + } + + + /** + * Sets the value of this axis-angle to the rotational component of + * the passed matrix. + * If the specified matrix has no rotational component, the value + * of this AxisAngle4f is set to an angle of 0 about an axis of (0,1,0). + * @param m1 the matrix3d + */ + public final void set(Matrix3d m1) + { + + x = (float)(m1.m21 - m1.m12); + y = (float)(m1.m02 - m1.m20); + z = (float)(m1.m10 - m1.m01); + double mag = x*x + y*y + z*z; + + if (mag > EPS) { + mag = Math.sqrt(mag); + double sin = 0.5*mag; + double cos = 0.5*(m1.m00 + m1.m11 + m1.m22 - 1.0); + + angle = (float)Math.atan2(sin, cos); + + double invMag = 1.0/mag; + x = (float)(x*invMag); + y = (float)(y*invMag); + z = (float)(z*invMag); + } else { + x = 0.0f; + y = 1.0f; + z = 0.0f; + angle = 0.0f; + } + } + + + /** + * Returns a string that contains the values of this AxisAngle4f. + * The form is (x,y,z,angle). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.angle + ")"; + } + + + /** + * Returns true if all of the data members of AxisAngle4f a1 are + * equal to the corresponding data members in this AxisAngle4f. + * @param a1 the axis-angle with which the comparison is made + * @return true or false + */ + public boolean equals(AxisAngle4f a1) + { + try { + return(this.x == a1.x && this.y == a1.y && this.z == a1.z + && this.angle == a1.angle); + } + catch (NullPointerException e2) {return false;} + + } + + /** + * Returns true if the Object o1 is of type AxisAngle4f and all of the + * data members of o1 are equal to the corresponding data members in + * this AxisAngle4f. + * @param o1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object o1) + { + try { + AxisAngle4f a2 = (AxisAngle4f) o1; + return(this.x == a2.x && this.y == a2.y && this.z == a2.z + && this.angle == a2.angle); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + + } + + /** + * Returns true if the L-infinite distance between this axis-angle + * and axis-angle a1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(angle1-angle2)]. + * @param a1 the axis-angle to be compared to this axis-angle + * @param epsilon the threshold value + */ + public boolean epsilonEquals(AxisAngle4f a1, float epsilon) + { + float diff; + + diff = x - a1.x; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - a1.y; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = z - a1.z; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = angle - a1.angle; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different AxisAngle4f objects with identical data values + * (i.e., AxisAngle4f.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashFloatBits(bits, x); + bits = VecMathUtil.hashFloatBits(bits, y); + bits = VecMathUtil.hashFloatBits(bits, z); + bits = VecMathUtil.hashFloatBits(bits, angle); + return VecMathUtil.hashFinish(bits); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get the axis angle, in radians.<br> + * An axis angle is a rotation angle about the vector (x,y,z). + * + * @return Returns the angle, in radians. + * + * @since vecmath 1.5 + */ + public final float getAngle() { + return angle; + } + + + /** + * Set the axis angle, in radians.<br> + * An axis angle is a rotation angle about the vector (x,y,z). + * + * @param angle The angle to set, in radians. + * + * @since vecmath 1.5 + */ + public final void setAngle(float angle) { + this.angle = angle; + } + + + /** + * Get value of <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getX() { + return x; + } + + + /** + * Set a new value for <i>x</i> coordinate. + * + * @param x the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(float x) { + this.x = x; + } + + + /** + * Get value of <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate + * + * @since vecmath 1.5 + */ + public final float getY() { + return y; + } + + + /** + * Set a new value for <i>y</i> coordinate. + * + * @param y the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(float y) { + this.y = y; + } + + + /** + * Get value of <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getZ() { + return z; + } + + + /** + * Set a new value for <i>z</i> coordinate. + * + * @param z the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(float z) { + this.z = z; + } + +} diff --git a/src/org/jogamp/vecmath/Color3b.java b/src/org/jogamp/vecmath/Color3b.java new file mode 100644 index 0000000..3aa36b1 --- /dev/null +++ b/src/org/jogamp/vecmath/Color3b.java @@ -0,0 +1,149 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +import java.awt.Color; + + +/** + * A three-byte color value represented by byte x, y, and z values. The + * x, y, and z values represent the red, green, and blue values, + * respectively. + * <p> + * Note that Java defines a byte as a signed integer in the range + * [-128, 127]. However, colors are more typically represented by values + * in the range [0, 255]. Java 3D recognizes this and for color + * treats the bytes as if the range were [0, 255]---in other words, as + * if the bytes were unsigned. + * <p> + * Java 3D assumes that a linear (gamma-corrected) visual is used for + * all colors. + * + */ +public class Color3b extends Tuple3b implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = 6632576088353444794L; + + /** + * Constructs and initializes a Color3b from the specified three values. + * @param c1 the red color value + * @param c2 the green color value + * @param c3 the blue color value + */ + public Color3b(byte c1, byte c2, byte c3) { + super(c1,c2,c3); + } + + + /** + * Constructs and initializes a Color3b from input array of length 3. + * @param c the array of length 3 containing the r,g,b data in order + */ + public Color3b(byte[] c) { + super(c); + } + + + /** + * Constructs and initializes a Color3b from the specified Color3b. + * @param c1 the Color3b containing the initialization r,g,b data + */ + public Color3b(Color3b c1) { + super(c1); + } + + + /** + * Constructs and initializes a Color3b from the specified Tuple3b. + * @param t1 the Tuple3b containing the initialization r,g,b data + */ + public Color3b(Tuple3b t1) { + super(t1); + } + + + /** + * Constructs and initializes a Color3b from the specified AWT + * Color object. The alpha value of the AWT color is ignored. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color with which to initialize this + * Color3b object + * + * @since vecmath 1.2 + */ + public Color3b(Color color) { + super((byte)color.getRed(), + (byte)color.getGreen(), + (byte)color.getBlue()); + } + + + /** + * Constructs and initializes a Color3b to (0,0,0). + */ + public Color3b() { + super(); + } + + + /** + * Sets the r,g,b values of this Color3b object to those of the + * specified AWT Color object. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color to copy into this Color3b object + * + * @since vecmath 1.2 + */ + public final void set(Color color) { + x = (byte)color.getRed(); + y = (byte)color.getGreen(); + z = (byte)color.getBlue(); + } + + + /** + * Returns a new AWT color object initialized with the r,g,b + * values of this Color3b object. + * + * @return a new AWT Color object + * + * @since vecmath 1.2 + */ + public final Color get() { + int r = (int)x & 0xff; + int g = (int)y & 0xff; + int b = (int)z & 0xff; + + return new Color(r, g, b); + } + +} diff --git a/src/org/jogamp/vecmath/Color3f.java b/src/org/jogamp/vecmath/Color3f.java new file mode 100644 index 0000000..9e9a252 --- /dev/null +++ b/src/org/jogamp/vecmath/Color3f.java @@ -0,0 +1,153 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +import java.awt.Color; + + +/** + * A three-element color value represented by single precision floating + * point x,y,z values. The x,y,z values represent the red, green, and + * blue color values, respectively. Color components should be in the + * range of [0.0, 1.0]. + * <p> + * Java 3D assumes that a linear (gamma-corrected) visual is used for + * all colors. + * + */ +public class Color3f extends Tuple3f implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = -1861792981817493659L; + + /** + * Constructs and initializes a Color3f from the three xyz values. + * @param x the red color value + * @param y the green color value + * @param z the blue color value + */ + public Color3f(float x, float y, float z) { + super(x,y,z); + } + + + /** + * Constructs and initializes a Color3f from the array of length 3. + * @param v the array of length 3 containing xyz in order + */ + public Color3f(float[] v) { + super(v); + } + + + /** + * Constructs and initializes a Color3f from the specified Color3f. + * @param v1 the Color3f containing the initialization x y z data + */ + public Color3f(Color3f v1) { + super(v1); + } + + + /** + * Constructs and initializes a Color3f from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public Color3f(Tuple3f t1) { + super(t1); + } + + + /** + * Constructs and initializes a Color3f from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public Color3f(Tuple3d t1) { + super(t1); + } + + + /** + * Constructs and initializes a Color3f from the specified AWT + * Color object. The alpha value of the AWT color is ignored. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color with which to initialize this + * Color3f object + * + * @since vecmath 1.2 + */ + public Color3f(Color color) { + super((float)color.getRed() / 255.0f, + (float)color.getGreen() / 255.0f, + (float)color.getBlue() / 255.0f); + } + + + /** + * Constructs and initializes a Color3f to (0.0, 0.0, 0.0). + */ + public Color3f() { + super(); + } + + + /** + * Sets the r,g,b values of this Color3f object to those of the + * specified AWT Color object. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color to copy into this Color3f object + * + * @since vecmath 1.2 + */ + public final void set(Color color) { + x = (float)color.getRed() / 255.0f; + y = (float)color.getGreen() / 255.0f; + z = (float)color.getBlue() / 255.0f; + } + + + /** + * Returns a new AWT color object initialized with the r,g,b + * values of this Color3f object. + * + * @return a new AWT Color object + * + * @since vecmath 1.2 + */ + public final Color get() { + int r = Math.round(x * 255.0f); + int g = Math.round(y * 255.0f); + int b = Math.round(z * 255.0f); + + return new Color(r, g, b); + } + +} diff --git a/src/org/jogamp/vecmath/Color4b.java b/src/org/jogamp/vecmath/Color4b.java new file mode 100644 index 0000000..2bb3162 --- /dev/null +++ b/src/org/jogamp/vecmath/Color4b.java @@ -0,0 +1,155 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +import java.awt.Color; + + +/** + * A four-byte color value represented by byte x, y, z, and w values. + * The x, y, z, and w values represent the red, green, blue, and alpha + * values, respectively. + * <p> + * Note that Java defines a byte as a signed integer in the range + * [-128, 127]. However, colors are more typically represented by values + * in the range [0, 255]. Java 3D recognizes this and for color + * treats the bytes as if the range were [0, 255]---in other words, as + * if the bytes were unsigned. + * <p> + * Java 3D assumes that a linear (gamma-corrected) visual is used for + * all colors. + * + */ +public class Color4b extends Tuple4b implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = -105080578052502155L; + + /** + * Constructs and initializes a Color4b from the four specified values. + * @param b1 the red color value + * @param b2 the green color value + * @param b3 the blue color value + * @param b4 the alpha value + */ + public Color4b(byte b1, byte b2, byte b3, byte b4) { + super(b1,b2,b3,b4); + } + + + /** + * Constructs and initializes a Color4b from the array of length 4. + * @param c the array of length 4 containing r, g, b, and alpha in order + */ + public Color4b(byte[] c) { + super(c); + } + + + /** + * Constructs and initializes a Color4b from the specified Color4b. + * @param c1 the Color4b containing the initialization r,g,b,a + * data + */ + public Color4b(Color4b c1) { + super(c1); + } + + + /** + * Constructs and initializes a Color4b from the specified Tuple4b. + * @param t1 the Tuple4b containing the initialization r,g,b,a + * data + */ + public Color4b(Tuple4b t1) { + super(t1); + } + + + /** + * Constructs and initializes a Color4b from the specified AWT + * Color object. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color with which to initialize this + * Color4b object + * + * @since vecmath 1.2 + */ + public Color4b(Color color) { + super((byte)color.getRed(), + (byte)color.getGreen(), + (byte)color.getBlue(), + (byte)color.getAlpha()); + } + + + /** + * Constructs and initializes a Color4b to (0,0,0,0). + */ + public Color4b() { + super(); + } + + + /** + * Sets the r,g,b,a values of this Color4b object to those of the + * specified AWT Color object. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color to copy into this Color4b object + * + * @since vecmath 1.2 + */ + public final void set(Color color) { + x = (byte)color.getRed(); + y = (byte)color.getGreen(); + z = (byte)color.getBlue(); + w = (byte)color.getAlpha(); + } + + + /** + * Returns a new AWT color object initialized with the r,g,b,a + * values of this Color4b object. + * + * @return a new AWT Color object + * + * @since vecmath 1.2 + */ + public final Color get() { + int r = (int)x & 0xff; + int g = (int)y & 0xff; + int b = (int)z & 0xff; + int a = (int)w & 0xff; + + return new Color(r, g, b, a); + } + +} diff --git a/src/org/jogamp/vecmath/Color4f.java b/src/org/jogamp/vecmath/Color4f.java new file mode 100644 index 0000000..ac4c971 --- /dev/null +++ b/src/org/jogamp/vecmath/Color4f.java @@ -0,0 +1,158 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +import java.awt.Color; + + +/** + * A four-element color represented by single precision floating point + * x, y, z, and w values. The x, y, z, and w values represent the red, + * blue, green, and alpha color values, respectively. Color and alpha + * components should be in the range [0.0, 1.0]. + * <p> + * Java 3D assumes that a linear (gamma-corrected) visual is used for + * all colors. + * + */ +public class Color4f extends Tuple4f implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = 8577680141580006740L; + + /** + * Constructs and initializes a Color4f from the specified xyzw + * coordinates. + * @param x the red color value + * @param y the green color value + * @param z the blue color value + * @param w the alpha value + */ + public Color4f(float x, float y, float z, float w) { + super(x,y,z,w); + } + + + /** + * Constructs and initializes a Color4f from the array of length 4. + * @param c the array of length 4 containing r,g,b,a in order + */ + public Color4f(float[] c) { + super(c); + } + + + /** + * Constructs and initializes a Color4f from the specified Color4f. + * @param c1 the Color4f containing the initialization r,g,b,a data + */ + public Color4f(Color4f c1) { + super(c1); + } + + + /** + * Constructs and initializes a Color4f from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization r,g,b,a data + */ + public Color4f(Tuple4f t1) { + super(t1); + } + + + /** + * Constructs and initializes a Color4f from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization r,g,b,a data + */ + public Color4f(Tuple4d t1) { + super(t1); + } + + + /** + * Constructs and initializes a Color4f from the specified AWT + * Color object. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color with which to initialize this + * Color4f object + * + * @since vecmath 1.2 + */ + public Color4f(Color color) { + super((float)color.getRed() / 255.0f, + (float)color.getGreen() / 255.0f, + (float)color.getBlue() / 255.0f, + (float)color.getAlpha() / 255.0f); + } + + + /** + * Constructs and initializes a Color4f to (0.0, 0.0, 0.0, 0.0). + */ + public Color4f() { + super(); + } + + + /** + * Sets the r,g,b,a values of this Color4f object to those of the + * specified AWT Color object. + * No conversion is done on the color to compensate for + * gamma correction. + * + * @param color the AWT color to copy into this Color4f object + * + * @since vecmath 1.2 + */ + public final void set(Color color) { + x = (float)color.getRed() / 255.0f; + y = (float)color.getGreen() / 255.0f; + z = (float)color.getBlue() / 255.0f; + w = (float)color.getAlpha() / 255.0f; + } + + + /** + * Returns a new AWT color object initialized with the r,g,b,a + * values of this Color4f object. + * + * @return a new AWT Color object + * + * @since vecmath 1.2 + */ + public final Color get() { + int r = Math.round(x * 255.0f); + int g = Math.round(y * 255.0f); + int b = Math.round(z * 255.0f); + int a = Math.round(w * 255.0f); + + return new Color(r, g, b, a); + } + +} diff --git a/src/org/jogamp/vecmath/ExceptionStrings.properties b/src/org/jogamp/vecmath/ExceptionStrings.properties new file mode 100644 index 0000000..ca56746 --- /dev/null +++ b/src/org/jogamp/vecmath/ExceptionStrings.properties @@ -0,0 +1,86 @@ +Matrix3d0=Matrix3d setElement +Matrix3d1=Matrix3d getElement +Matrix3d2=Matrix3d getRow +Matrix3d4=Matrix3d getColumn +Matrix3d6=Matrix3d setRow +Matrix3d9=Matrix3d setColumn +Matrix3d12=cannot invert matrix +Matrix3d13=Logic error: imax < 0 +Matrix3f0=Matrix3f setElement +Matrix3f1=Matrix3d getRow +Matrix3f3=Matrix3d getColumn +Matrix3f5=Matrix3f getElement +Matrix3f6=Matrix3f setRow +Matrix3f9=Matrix3f setColumn +Matrix3f12=cannot invert matrix +Matrix3f13=Logic error: imax < 0 +Matrix4d0=Matrix4d setElement +Matrix4d1=Matrix4d getElement +Matrix4d2=Matrix4d getRow +Matrix4d3=Matrix4d getColumn +Matrix4d4=Matrix4d setRow +Matrix4d7=Matrix4d setColumn +Matrix4d10=cannot invert matrix +Matrix4d11=Logic error: imax < 0 +Matrix4f0=Matrix4f setElement +Matrix4f1=Matrix4f getElement +Matrix4f2=Matrix4f getRow +Matrix4f4=Matrix4f getColumn +Matrix4f6=Matrix4f setRow +Matrix4f9=Matrix4f setColumn +Matrix4f12=cannot invert matrix +Matrix4f13=Logic error: imax < 0 +GMatrix0=GMatrix.mul:array dimension mismatch +GMatrix1=GMatrix.mul(GMatrix, GMatrix) dimension mismatch +GMatrix2=GMatrix.mul(GVector, GVector): matrix does not have enough rows +GMatrix3=GMatrix.mul(GVector, GVector): matrix does not have enough columns +GMatrix4=GMatrix.add(GMatrix): row dimension mismatch +GMatrix5=GMatrix.add(GMatrix): column dimension mismatch +GMatrix6=GMatrix.add(GMatrix, GMatrix): row dimension mismatch +GMatrix7=GMatrix.add(GMatrix, GMatrix): column dimension mismatch +GMatrix8=GMatrix.add(GMatrix): input matrices dimensions do not match this matrix dimensions +GMatrix9=GMatrix.sub(GMatrix): row dimension mismatch +GMatrix10=GMatrix.sub(GMatrix, GMatrix): row dimension mismatch +GMatrix11=GMatrix.sub(GMatrix, GMatrix): column dimension mismatch +GMatrix12=GMatrix.sub(GMatrix, GMatrix): input matrix dimensions do not match dimensions for this matrix +GMatrix13=GMatrix.negate(GMatrix, GMatrix): input matrix dimensions do not match dimensions for this matrix +GMatrix14=GMatrix.mulTransposeBoth matrix dimension mismatch +GMatrix15=GMatrix.mulTransposeRight matrix dimension mismatch +GMatrix16=GMatrix.mulTransposeLeft matrix dimension mismatch +GMatrix17=GMatrix.transpose(GMatrix) mismatch in matrix dimensions +GMatrix18=GMatrix.SVD: dimension mismatch with V matrix +GMatrix19=cannot perform LU decomposition on a non square matrix +GMatrix20=row permutation must be same dimension as matrix +GMatrix21=cannot invert matrix +GMatrix22=cannot invert non square matrix +GMatrix24=Logic error: imax < 0 +GMatrix25=GMatrix.SVD: dimension mismatch with U matrix +GMatrix26=GMatrix.SVD: dimension mismatch with W matrix +GMatrix27=LU must have same dimensions as this matrix +GMatrix28=GMatrix.sub(GMatrix): column dimension mismatch +GVector0=GVector.normalize( GVector) input vector and this vector lengths not matched +GVector1=GVector.scale(double, GVector) input vector and this vector lengths not matched +GVector2=GVector.scaleAdd(GVector, GVector) input vector dimensions not matched +GVector3=GVector.scaleAdd(GVector, GVector) input vectors and this vector dimensions not matched +GVector4=GVector.add(GVector) input vectors and this vector dimensions not matched +GVector5=GVector.add(GVector, GVector) input vector dimensions not matched +GVector6=GVector.add(GVector, GVector) input vectors and this vector dimensions not matched +GVector7=GVector.sub(GVector) input vector and this vector dimensions not matched +GVector8=GVector.sub(GVector, GVector) input vector dimensions not matched +GVector9=GVector.sub(GMatrix, GVector) input vectors and this vector dimensions not matched +GVector10=GVector.mul(GMatrix, GVector) matrix and vector dimensions not matched +GVector11=GVector.mul(GMatrix, GVector) matrix this vector dimensions not matched +GVector12=GVector.mul(GVector, GMatrix) matrix and vector dimensions not matched +GVector13=GVector.mul(GVector, GMatrix) matrix this vector dimensions not matched +GVector14=GVector.dot(GVector) input vector and this vector have different sizes +GVector15=matrix dimensions are not compatible +GVector16=b vector does not match matrix dimension +GVector17=GVector.interpolate(GVector, GVector, float) input vectors have different lengths +GVector18=GVector.interpolate(GVector, GVector, float) input vectors and this vector have different lengths +GVector19=GVector.interpolate(GVector, float) input vector and this vector have different lengths +GVector20=GVector.interpolate(GVector, GVector, double) input vectors have different lengths +GVector21=GVector.interpolate(GVector, GVector, double) input vectors and this vector have different lengths +GVector22=GVector.interpolate(GVector, double) input vectors and this vector have different lengths +GVector23=matrix dimensions are not compatible +GVector24=permutation vector does not match matrix dimension +GVector25=LUDBackSolve non square matrix diff --git a/src/org/jogamp/vecmath/GMatrix.java b/src/org/jogamp/vecmath/GMatrix.java new file mode 100644 index 0000000..2c7a6ae --- /dev/null +++ b/src/org/jogamp/vecmath/GMatrix.java @@ -0,0 +1,3006 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A double precision, general, dynamically-resizable, + * two-dimensional matrix class. Row and column numbering begins with + * zero. The representation is row major. + */ + +public class GMatrix implements java.io.Serializable, Cloneable { + + // Compatible with 1.1 + static final long serialVersionUID = 2777097312029690941L; + private static final boolean debug = false; + + int nRow; + int nCol; + + // double dereference is slow + double[][] values; + + private static final double EPS = 1.0E-10; + + /** + * Constructs an nRow by NCol identity matrix. + * Note that because row and column numbering begins with + * zero, nRow and nCol will be one larger than the maximum + * possible matrix index values. + * @param nRow number of rows in this matrix. + * @param nCol number of columns in this matrix. + */ + public GMatrix(int nRow, int nCol) + { + values = new double[nRow][nCol]; + this.nRow = nRow; + this.nCol = nCol; + + int i, j; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = 0.0; + } + } + + int l; + if (nRow < nCol) + l = nRow; + else + l = nCol; + + for (i = 0; i < l; i++) { + values[i][i] = 1.0; + } + } + + /** + * Constructs an nRow by nCol matrix initialized to the values + * in the matrix array. The array values are copied in one row at + * a time in row major fashion. The array should be at least + * nRow*nCol in length. + * Note that because row and column numbering begins with + * zero, nRow and nCol will be one larger than the maximum + * possible matrix index values. + * @param nRow number of rows in this matrix. + * @param nCol number of columns in this matrix. + * @param matrix a 1D array that specifies a matrix in row major fashion + */ + public GMatrix(int nRow, int nCol, double[] matrix) + { + values = new double[nRow][nCol]; + this.nRow = nRow; + this.nCol = nCol; + + int i, j; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = matrix[i*nCol+j]; + } + } + } + + /** + * Constructs a new GMatrix and copies the initial values + * from the parameter matrix. + * @param matrix the source of the initial values of the new GMatrix + */ + public GMatrix(GMatrix matrix) + { + nRow = matrix.nRow; + nCol = matrix.nCol; + values = new double[nRow][nCol]; + + int i, j; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = matrix.values[i][j]; + } + } + } + + /** + * Sets the value of this matrix to the result of multiplying itself + * with matrix m1 (this = this * m1). + * @param m1 the other matrix + */ + public final void mul(GMatrix m1) + { + int i, j, k; + + if (nCol != m1.nRow || nCol != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix0")); + + double [][] tmp = new double[nRow][nCol]; + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + tmp[i][j] = 0.0; + for (k = 0; k < nCol; k++) { + tmp[i][j] += values[i][k]*m1.values[k][j]; + } + } + } + + values = tmp; + } + + /** + * Sets the value of this matrix to the result of multiplying + * the two argument matrices together (this = m1 * m2). + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void mul(GMatrix m1, GMatrix m2) + { + int i, j, k; + + if (m1.nCol != m2.nRow || nRow != m1.nRow || nCol != m2.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix1")); + + double[][] tmp = new double[nRow][nCol]; + + for (i = 0; i < m1.nRow; i++) { + for (j = 0; j < m2.nCol; j++) { + tmp[i][j] = 0.0; + for (k = 0; k < m1.nCol; k++) { + tmp[i][j] += m1.values[i][k]*m2.values[k][j]; + } + } + } + + values = tmp; + } + + /** + * Computes the outer product of the two vectors; multiplies the + * the first vector by the transpose of the second vector and places + * the matrix result into this matrix. This matrix must be + * be as big or bigger than getSize(v1)xgetSize(v2). + * @param v1 the first vector, treated as a row vector + * @param v2 the second vector, treated as a column vector + */ + public final void mul(GVector v1, GVector v2) + { + int i, j; + + if (nRow < v1.getSize()) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix2")); + + if (nCol < v2.getSize()) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix3")); + + for (i = 0; i < v1.getSize(); i++ ) { + for (j = 0; j < v2.getSize(); j++ ) { + values[i][j] = v1.values[i]*v2.values[j]; + } + } + } + + /** + * Sets the value of this matrix to sum of itself and matrix m1. + * @param m1 the other matrix + */ + public final void add(GMatrix m1) + { + int i, j; + + if (nRow != m1.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix4")); + + if (nCol != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix5")); + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = values[i][j] + m1.values[i][j]; + } + } + } + + /** + * Sets the value of this matrix to the matrix sum of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void add(GMatrix m1, GMatrix m2) + { + int i, j; + + if (m2.nRow != m1.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix6")); + + if (m2.nCol != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix7")); + + if (nCol != m1.nCol || nRow != m1.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix8")); + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = m1.values[i][j] + m2.values[i][j]; + } + } + } + + /** + * Sets the value of this matrix to the matrix difference of itself + * and matrix m1 (this = this - m1). + * @param m1 the other matrix + */ + public final void sub(GMatrix m1) + { + int i, j; + if (nRow != m1.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix9")); + + if (nCol != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix28")); + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = values[i][j] - m1.values[i][j]; + } + } + } + + /** + * Sets the value of this matrix to the matrix difference + * of matrices m1 and m2 (this = m1 - m2). + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void sub(GMatrix m1, GMatrix m2) + { + int i, j; + if (m2.nRow != m1.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix10")); + + if (m2.nCol != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix11")); + + if (nRow != m1.nRow || nCol != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix12")); + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = m1.values[i][j] - m2.values[i][j]; + } + } + } + + /** + * Negates the value of this matrix: this = -this. + */ + public final void negate() + { + int i, j; + for (i = 0; i < nRow; i++) { + for (j = 0;j < nCol; j++) { + values[i][j] = -values[i][j]; + } + } + } + + /** + * Sets the value of this matrix equal to the negation of + * of the GMatrix parameter. + * @param m1 The source matrix + */ + public final void negate(GMatrix m1) + { + int i, j; + if (nRow != m1.nRow || nCol != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix13")); + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = -m1.values[i][j]; + } + } + } + + /** + * Sets this GMatrix to the identity matrix. + */ + public final void setIdentity() + { + int i, j; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = 0.0; + } + } + + int l; + if (nRow < nCol) + l = nRow; + else + l = nCol; + + for (i = 0; i < l; i++) { + values[i][i] = 1.0; + } + } + + /** + * Sets all the values in this matrix to zero. + */ + public final void setZero() + { + int i, j; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = 0.0; + } + } + } + + /** + * Subtracts this matrix from the identity matrix and puts the values + * back into this (this = I - this). + */ + public final void identityMinus() + { + int i, j; + + for(i = 0; i < nRow; i++) { + for(j = 0; j < nCol; j++) { + values[i][j] = -values[i][j]; + } + } + + int l; + if( nRow < nCol) + l = nRow; + else + l = nCol; + + for(i = 0; i < l; i++) { + values[i][i] += 1.0; + } + } + + + /** + * Inverts this matrix in place. + */ + public final void invert() + { + invertGeneral(this); + } + + /** + * Inverts matrix m1 and places the new values into this matrix. Matrix + * m1 is not modified. + * @param m1 the matrix to be inverted + */ + public final void invert(GMatrix m1) + { + invertGeneral(m1); + } + + /** + * Copies a sub-matrix derived from this matrix into the target matrix. + * The upper left of the sub-matrix is located at (rowSource, colSource); + * the lower right of the sub-matrix is located at + * (lastRowSource,lastColSource). The sub-matrix is copied into the + * the target matrix starting at (rowDest, colDest). + * @param rowSource the top-most row of the sub-matrix + * @param colSource the left-most column of the sub-matrix + * @param numRow the number of rows in the sub-matrix + * @param numCol the number of columns in the sub-matrix + * @param rowDest the top-most row of the position of the copied + * sub-matrix within the target matrix + * @param colDest the left-most column of the position of the copied + * sub-matrix within the target matrix + * @param target the matrix into which the sub-matrix will be copied + */ + public final void copySubMatrix(int rowSource, int colSource, + int numRow, int numCol, int rowDest, + int colDest, GMatrix target) + { + int i, j; + + if (this != target) { + for (i = 0; i < numRow; i++) { + for (j = 0; j < numCol; j++) { + target.values[rowDest+i][colDest+j] = + values[rowSource+i][colSource+j]; + } + } + } else { + double[][] tmp = new double[numRow][numCol]; + for (i = 0; i < numRow; i++) { + for (j = 0; j < numCol; j++) { + tmp[i][j] = values[rowSource+i][colSource+j]; + } + } + for (i = 0; i < numRow; i++) { + for (j = 0; j < numCol; j++) { + target.values[rowDest+i][colDest+j] = tmp[i][j]; + } + } + } + } + + /** + * Changes the size of this matrix dynamically. If the size is increased + * no data values will be lost. If the size is decreased, only those data + * values whose matrix positions were eliminated will be lost. + * @param nRow number of desired rows in this matrix + * @param nCol number of desired columns in this matrix + */ + public final void setSize(int nRow, int nCol) + { + double[][] tmp = new double[nRow][nCol]; + int i, j, maxRow, maxCol; + + if (this.nRow < nRow) + maxRow = this.nRow; + else + maxRow = nRow; + + if (this.nCol < nCol) + maxCol = this.nCol; + else + maxCol = nCol; + + for (i = 0; i < maxRow; i++) { + for (j = 0; j < maxCol; j++) { + tmp[i][j] = values[i][j]; + } + } + + this.nRow = nRow; + this.nCol = nCol; + + values = tmp; + } + + /** + * Sets the value of this matrix to the values found in the array parameter. + * The values are copied in one row at a time, in row major + * fashion. The array should be at least equal in length to + * the number of matrix rows times the number of matrix columns + * in this matrix. + * @param matrix the row major source array + */ + public final void set(double[] matrix) + { + int i, j; + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = matrix[nCol*i+j]; + } + } + } + + /** + * Sets the value of this matrix to that of the Matrix3f provided. + * @param m1 the matrix + */ + public final void set(Matrix3f m1) + { + int i, j; + + if (nCol < 3 || nRow < 3) { // expand matrix if too small + nCol = 3; + nRow = 3; + values = new double[nRow][nCol]; + } + + values[0][0] = m1.m00; + values[0][1] = m1.m01; + values[0][2] = m1.m02; + + values[1][0] = m1.m10; + values[1][1] = m1.m11; + values[1][2] = m1.m12; + + values[2][0] = m1.m20; + values[2][1] = m1.m21; + values[2][2] = m1.m22; + + for (i = 3; i < nRow; i++) { // pad rest or matrix with zeros + for (j = 3; j < nCol; j++) { + values[i][j] = 0.0; + } + } + } + + /** + * Sets the value of this matrix to that of the Matrix3d provided. + * @param m1 the matrix + */ + public final void set(Matrix3d m1) + { + if (nRow < 3 || nCol < 3) { + values = new double[3][3]; + nRow = 3; + nCol = 3; + } + + values[0][0] = m1.m00; + values[0][1] = m1.m01; + values[0][2] = m1.m02; + + values[1][0] = m1.m10; + values[1][1] = m1.m11; + values[1][2] = m1.m12; + + values[2][0] = m1.m20; + values[2][1] = m1.m21; + values[2][2] = m1.m22; + + for (int i = 3; i < nRow; i++) { // pad rest or matrix with zeros + for(int j = 3; j < nCol; j++) { + values[i][j] = 0.0; + } + } + + } + + /** + * Sets the value of this matrix to that of the Matrix4f provided. + * @param m1 the matrix + */ + public final void set(Matrix4f m1) + { + if (nRow < 4 || nCol < 4) { + values = new double[4][4]; + nRow = 4; + nCol = 4; + } + + values[0][0] = m1.m00; + values[0][1] = m1.m01; + values[0][2] = m1.m02; + values[0][3] = m1.m03; + + values[1][0] = m1.m10; + values[1][1] = m1.m11; + values[1][2] = m1.m12; + values[1][3] = m1.m13; + + values[2][0] = m1.m20; + values[2][1] = m1.m21; + values[2][2] = m1.m22; + values[2][3] = m1.m23; + + values[3][0] = m1.m30; + values[3][1] = m1.m31; + values[3][2] = m1.m32; + values[3][3] = m1.m33; + + for (int i = 4 ; i < nRow; i++) { // pad rest or matrix with zeros + for (int j = 4; j < nCol; j++) { + values[i][j] = 0.0; + } + } + } + + /** + * Sets the value of this matrix to that of the Matrix4d provided. + * @param m1 the matrix + */ + public final void set(Matrix4d m1) + { + if (nRow < 4 || nCol < 4) { + values = new double[4][4]; + nRow = 4; + nCol = 4; + } + + values[0][0] = m1.m00; + values[0][1] = m1.m01; + values[0][2] = m1.m02; + values[0][3] = m1.m03; + + values[1][0] = m1.m10; + values[1][1] = m1.m11; + values[1][2] = m1.m12; + values[1][3] = m1.m13; + + values[2][0] = m1.m20; + values[2][1] = m1.m21; + values[2][2] = m1.m22; + values[2][3] = m1.m23; + + values[3][0] = m1.m30; + values[3][1] = m1.m31; + values[3][2] = m1.m32; + values[3][3] = m1.m33; + + for (int i = 4; i < nRow; i++) { // pad rest or matrix with zeros + for (int j = 4; j < nCol; j++) { + values[i][j] = 0.0; + } + } + } + + /** + * Sets the value of this matrix to the values found in matrix m1. + * @param m1 the source matrix + */ + public final void set(GMatrix m1) + { + int i, j; + + if (nRow < m1.nRow || nCol < m1.nCol) { + nRow = m1.nRow; + nCol = m1.nCol; + values = new double[nRow][nCol]; + } + + for (i = 0; i < Math.min(nRow, m1.nRow); i++) { + for (j = 0; j < Math.min(nCol, m1.nCol); j++) { + values[i][j] = m1.values[i][j]; + } + } + + for (i = m1.nRow; i < nRow; i++) { // pad rest or matrix with zeros + for (j = m1.nCol; j < nCol; j++) { + values[i][j] = 0.0; + } + } + } + + /** + * Returns the number of rows in this matrix. + * @return number of rows in this matrix + */ + public final int getNumRow() + { + return(nRow); + } + + /** + * Returns the number of colmuns in this matrix. + * @return number of columns in this matrix + */ + public final int getNumCol() + { + return(nCol); + } + + /** + * Retrieves the value at the specified row and column of this matrix. + * @param row the row number to be retrieved (zero indexed) + * @param column the column number to be retrieved (zero indexed) + * @return the value at the indexed element + */ + public final double getElement(int row, int column) + { + return(values[row][column]); + } + + + /** + * Modifies the value at the specified row and column of this matrix. + * @param row the row number to be modified (zero indexed) + * @param column the column number to be modified (zero indexed) + * @param value the new matrix element value + */ + public final void setElement(int row, int column, double value) + { + values[row][column] = value; + } + + /** + * Places the values of the specified row into the array parameter. + * @param row the target row number + * @param array the array into which the row values will be placed + */ + public final void getRow(int row, double[] array) + { + for (int i = 0; i < nCol; i++) { + array[i] = values[row][i]; + } + } + + /** + * Places the values of the specified row into the vector parameter. + * @param row the target row number + * @param vector the vector into which the row values will be placed + */ + public final void getRow(int row, GVector vector) + { + if (vector.getSize() < nCol) + vector.setSize(nCol); + + for (int i = 0; i < nCol; i++) { + vector.values[i] = values[row][i]; + } + } + + /** + * Places the values of the specified column into the array parameter. + * @param col the target column number + * @param array the array into which the column values will be placed + */ + public final void getColumn(int col, double[] array) + { + for (int i = 0; i < nRow; i++) { + array[i] = values[i][col]; + } + + } + + /** + * Places the values of the specified column into the vector parameter. + * @param col the target column number + * @param vector the vector into which the column values will be placed + */ + public final void getColumn(int col, GVector vector) + { + if (vector.getSize() < nRow) + vector.setSize(nRow); + + for (int i = 0; i < nRow; i++) { + vector.values[i] = values[i][col]; + } + } + + /** + * Places the values in the upper 3x3 of this GMatrix into + * the matrix m1. + * @param m1 The matrix that will hold the new values + */ + public final void get(Matrix3d m1) + { + if (nRow < 3 || nCol < 3) { + m1.setZero(); + if (nCol > 0) { + if (nRow > 0){ + m1.m00 = values[0][0]; + if (nRow > 1){ + m1.m10 = values[1][0]; + if( nRow > 2 ){ + m1.m20= values[2][0]; + } + } + } + if (nCol > 1) { + if (nRow > 0) { + m1.m01 = values[0][1]; + if (nRow > 1){ + m1.m11 = values[1][1]; + if (nRow > 2){ + m1.m21 = values[2][1]; + } + } + } + if (nCol > 2) { + if (nRow > 0) { + m1.m02 = values[0][2]; + if (nRow > 1) { + m1.m12 = values[1][2]; + if (nRow > 2) { + m1.m22 = values[2][2]; + } + } + } + } + } + } + } else { + m1.m00 = values[0][0]; + m1.m01 = values[0][1]; + m1.m02 = values[0][2]; + + m1.m10 = values[1][0]; + m1.m11 = values[1][1]; + m1.m12 = values[1][2]; + + m1.m20 = values[2][0]; + m1.m21 = values[2][1]; + m1.m22 = values[2][2]; + } + } + + /** + * Places the values in the upper 3x3 of this GMatrix into + * the matrix m1. + * @param m1 The matrix that will hold the new values + */ + public final void get(Matrix3f m1) + { + + if (nRow < 3 || nCol < 3) { + m1.setZero(); + if (nCol > 0) { + if (nRow > 0) { + m1.m00 = (float)values[0][0]; + if (nRow > 1) { + m1.m10 = (float)values[1][0]; + if (nRow > 2) { + m1.m20 = (float)values[2][0]; + } + } + } + if (nCol > 1) { + if (nRow > 0) { + m1.m01 = (float)values[0][1]; + if (nRow > 1){ + m1.m11 = (float)values[1][1]; + if (nRow > 2){ + m1.m21 = (float)values[2][1]; + } + } + } + if (nCol > 2) { + if (nRow > 0) { + m1.m02 = (float)values[0][2]; + if (nRow > 1) { + m1.m12 = (float)values[1][2]; + if (nRow > 2) { + m1.m22 = (float)values[2][2]; + } + } + } + } + } + } + } else { + m1.m00 = (float)values[0][0]; + m1.m01 = (float)values[0][1]; + m1.m02 = (float)values[0][2]; + + m1.m10 = (float)values[1][0]; + m1.m11 = (float)values[1][1]; + m1.m12 = (float)values[1][2]; + + m1.m20 = (float)values[2][0]; + m1.m21 = (float)values[2][1]; + m1.m22 = (float)values[2][2]; + } + } + + /** + * Places the values in the upper 4x4 of this GMatrix into + * the matrix m1. + * @param m1 The matrix that will hold the new values + */ + public final void get(Matrix4d m1) + { + if (nRow < 4 || nCol < 4) { + m1.setZero(); + if (nCol > 0) { + if (nRow > 0) { + m1.m00 = values[0][0]; + if (nRow > 1) { + m1.m10 = values[1][0]; + if (nRow > 2) { + m1.m20 = values[2][0]; + if (nRow > 3) { + m1.m30 = values[3][0]; + } + } + } + } + if (nCol > 1) { + if (nRow > 0) { + m1.m01 = values[0][1]; + if (nRow > 1) { + m1.m11 = values[1][1]; + if (nRow > 2) { + m1.m21 = values[2][1]; + if (nRow > 3) { + m1.m31 = values[3][1]; + } + } + } + } + if (nCol > 2) { + if (nRow > 0) { + m1.m02 = values[0][2]; + if (nRow > 1) { + m1.m12 = values[1][2]; + if (nRow > 2) { + m1.m22 = values[2][2]; + if (nRow > 3) { + m1.m32 = values[3][2]; + } + } + } + } + if (nCol > 3) { + if (nRow > 0) { + m1.m03 = values[0][3]; + if (nRow > 1) { + m1.m13 = values[1][3]; + if (nRow > 2) { + m1.m23 = values[2][3]; + if (nRow > 3) { + m1.m33 = values[3][3]; + } + } + } + } + } + } + } + } + } else { + m1.m00 = values[0][0]; + m1.m01 = values[0][1]; + m1.m02 = values[0][2]; + m1.m03 = values[0][3]; + + m1.m10 = values[1][0]; + m1.m11 = values[1][1]; + m1.m12 = values[1][2]; + m1.m13 = values[1][3]; + + m1.m20 = values[2][0]; + m1.m21 = values[2][1]; + m1.m22 = values[2][2]; + m1.m23 = values[2][3]; + + m1.m30 = values[3][0]; + m1.m31 = values[3][1]; + m1.m32 = values[3][2]; + m1.m33 = values[3][3]; + } + + } + + /** + * Places the values in the upper 4x4 of this GMatrix into + * the matrix m1. + * @param m1 The matrix that will hold the new values + */ + public final void get(Matrix4f m1) + { + + if (nRow < 4 || nCol < 4) { + m1.setZero(); + if (nCol > 0) { + if (nRow > 0) { + m1.m00 = (float)values[0][0]; + if (nRow > 1) { + m1.m10 = (float)values[1][0]; + if (nRow > 2) { + m1.m20 = (float)values[2][0]; + if (nRow > 3) { + m1.m30 = (float)values[3][0]; + } + } + } + } + if (nCol > 1) { + if (nRow > 0) { + m1.m01 = (float)values[0][1]; + if (nRow > 1) { + m1.m11 = (float)values[1][1]; + if (nRow > 2) { + m1.m21 = (float)values[2][1]; + if (nRow > 3) { + m1.m31 = (float)values[3][1]; + } + } + } + } + if (nCol > 2) { + if (nRow > 0) { + m1.m02 = (float)values[0][2]; + if (nRow > 1) { + m1.m12 = (float)values[1][2]; + if (nRow > 2) { + m1.m22 = (float)values[2][2]; + if (nRow > 3) { + m1.m32 = (float)values[3][2]; + } + } + } + } + if (nCol > 3) { + if (nRow > 0) { + m1.m03 = (float)values[0][3]; + if (nRow > 1) { + m1.m13 = (float)values[1][3]; + if (nRow > 2) { + m1.m23 = (float)values[2][3]; + if (nRow > 3) { + m1.m33 = (float)values[3][3]; + } + } + } + } + } + } + } + } + } else { + m1.m00 = (float)values[0][0]; + m1.m01 = (float)values[0][1]; + m1.m02 = (float)values[0][2]; + m1.m03 = (float)values[0][3]; + + m1.m10 = (float)values[1][0]; + m1.m11 = (float)values[1][1]; + m1.m12 = (float)values[1][2]; + m1.m13 = (float)values[1][3]; + + m1.m20 = (float)values[2][0]; + m1.m21 = (float)values[2][1]; + m1.m22 = (float)values[2][2]; + m1.m23 = (float)values[2][3]; + + m1.m30 = (float)values[3][0]; + m1.m31 = (float)values[3][1]; + m1.m32 = (float)values[3][2]; + m1.m33 = (float)values[3][3]; + } + } + + /** + * Places the values in the this GMatrix into the matrix m1; + * m1 should be at least as large as this GMatrix. + * @param m1 The matrix that will hold the new values + */ + public final void get(GMatrix m1) + { + int i, j, nc, nr; + + if (nCol < m1.nCol) + nc = nCol; + else + nc = m1.nCol; + + if (nRow < m1.nRow) + nr = nRow; + else + nr = m1.nRow; + + for (i = 0; i < nr; i++) { + for (j = 0; j < nc; j++) { + m1.values[i][j] = values[i][j]; + } + } + for (i = nr; i < m1.nRow; i++) { + for (j = 0; j < m1.nCol; j++) { + m1.values[i][j] = 0.0; + } + } + for (j = nc; j < m1.nCol; j++) { + for (i = 0; i < nr; i++) { + m1.values[i][j] = 0.0; + } + } + } + + /** + * Copy the values from the array into the specified row of this + * matrix. + * @param row the row of this matrix into which the array values + * will be copied. + * @param array the source array + */ + public final void setRow(int row, double[] array) + { + for (int i = 0; i < nCol; i++) { + values[row][i] = array[i]; + } + } + + /** + * Copy the values from the vector into the specified row of this + * matrix. + * @param row the row of this matrix into which the array values + * will be copied + * @param vector the source vector + */ + public final void setRow(int row, GVector vector) + { + for(int i = 0; i < nCol; i++) { + values[row][i] = vector.values[i]; + } + } + + /** + * Copy the values from the array into the specified column of this + * matrix. + * @param col the column of this matrix into which the array values + * will be copied + * @param array the source array + */ + public final void setColumn(int col, double[] array) + { + for(int i = 0; i < nRow; i++) { + values[i][col] = array[i]; + } + } + + /** + * Copy the values from the vector into the specified column of this + * matrix. + * @param col the column of this matrix into which the array values + * will be copied + * @param vector the source vector + */ + public final void setColumn(int col, GVector vector) + { + for(int i = 0; i < nRow; i++) { + values[i][col] = vector.values[i]; + } + + } + + /** + * Multiplies the transpose of matrix m1 times the transpose of matrix + * m2, and places the result into this. + * @param m1 The matrix on the left hand side of the multiplication + * @param m2 The matrix on the right hand side of the multiplication + */ + public final void mulTransposeBoth(GMatrix m1, GMatrix m2) + { + int i, j, k; + + if (m1.nRow != m2.nCol || nRow != m1.nCol || nCol != m2.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix14")); + + if (m1 == this || m2 == this) { + double[][] tmp = new double[nRow][nCol]; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + tmp[i][j] = 0.0; + for (k = 0; k < m1.nRow; k++) { + tmp[i][j] += m1.values[k][i]*m2.values[j][k]; + } + } + } + values = tmp; + } else { + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = 0.0; + for (k = 0; k < m1.nRow; k++) { + values[i][j] += m1.values[k][i]*m2.values[j][k]; + } + } + } + } + } + + /** + * Multiplies matrix m1 times the transpose of matrix m2, and + * places the result into this. + * @param m1 The matrix on the left hand side of the multiplication + * @param m2 The matrix on the right hand side of the multiplication + */ + public final void mulTransposeRight(GMatrix m1, GMatrix m2) + { + int i, j, k; + + if (m1.nCol != m2.nCol || nCol != m2.nRow || nRow != m1.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix15")); + + if (m1 == this || m2 == this) { + double[][] tmp = new double[nRow][nCol]; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + tmp[i][j] = 0.0; + for (k = 0; k < m1.nCol; k++) { + tmp[i][j] += m1.values[i][k]*m2.values[j][k]; + } + } + } + values = tmp; + } else { + for (i = 0; i < nRow; i++) { + for (j = 0;j < nCol; j++) { + values[i][j] = 0.0; + for (k = 0; k < m1.nCol; k++) { + values[i][j] += m1.values[i][k]*m2.values[j][k]; + } + } + } + } + + } + + + /** + * Multiplies the transpose of matrix m1 times matrix m2, and + * places the result into this. + * @param m1 The matrix on the left hand side of the multiplication + * @param m2 The matrix on the right hand side of the multiplication + */ + public final void mulTransposeLeft(GMatrix m1, GMatrix m2) + { + int i, j, k; + + if (m1.nRow != m2.nRow || nCol != m2.nCol || nRow != m1.nCol) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix16")); + + if (m1 == this || m2 == this) { + double[][] tmp = new double[nRow][nCol]; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + tmp[i][j] = 0.0; + for (k = 0; k < m1.nRow; k++) { + tmp[i][j] += m1.values[k][i]*m2.values[k][j]; + } + } + } + values = tmp; + } else { + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = 0.0; + for (k = 0; k < m1.nRow; k++) { + values[i][j] += m1.values[k][i]*m2.values[k][j]; + } + } + } + } + } + + + /** + * Transposes this matrix in place. + */ + public final void transpose() + { + int i, j; + + if (nRow != nCol) { + double[][] tmp; + i=nRow; + nRow = nCol; + nCol = i; + tmp = new double[nRow][nCol]; + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + tmp[i][j] = values[j][i]; + } + } + values = tmp; + } else { + double swap; + for (i = 0; i < nRow; i++) { + for (j = 0; j < i; j++) { + swap = values[i][j]; + values[i][j] = values[j][i]; + values[j][i] = swap; + } + } + } + } + + /** + * Places the matrix values of the transpose of matrix m1 into this matrix. + * @param m1 the matrix to be transposed (but not modified) + */ + public final void transpose(GMatrix m1) + { + int i, j; + + if (nRow != m1.nCol || nCol != m1.nRow) + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix17")); + + if (m1 != this) { + for (i = 0; i < nRow; i++) { + for (j = 0;j < nCol; j++) { + values[i][j] = m1.values[j][i]; + } + } + } else { + transpose(); + } + } + + /** + * Returns a string that contains the values of this GMatrix. + * @return the String representation + */ + @Override + public String toString() + { + StringBuffer buffer = new StringBuffer(nRow*nCol*8); + + int i, j; + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + buffer.append(values[i][j]).append(" "); + } + buffer.append("\n"); + } + + return buffer.toString(); + } + + private static void checkMatrix( GMatrix m) + { + int i, j; + + for (i = 0; i < m.nRow; i++) { + for (j = 0; j < m.nCol; j++) { + if (Math.abs(m.values[i][j]) < 0.0000000001) { + System.out.print(" 0.0 "); + } else { + System.out.print(" " + m.values[i][j]); + } + } + System.out.print("\n"); + } + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different GMatrix objects with identical data + * values (i.e., GMatrix.equals returns true) will return the + * same hash number. Two GMatrix objects with different data + * members may return the same hash value, although this is not + * likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + + bits = VecMathUtil.hashLongBits(bits, nRow); + bits = VecMathUtil.hashLongBits(bits, nCol); + + for (int i = 0; i < nRow; i++) { + for (int j = 0; j < nCol; j++) { + bits = VecMathUtil.hashDoubleBits(bits, values[i][j]); + } + } + + return VecMathUtil.hashFinish(bits); + } + + + /** + * Returns true if all of the data members of GMatrix m1 are + * equal to the corresponding data members in this GMatrix. + * @param m1 The matrix with which the comparison is made. + * @return true or false + */ + public boolean equals(GMatrix m1) + { + try { + int i, j; + + if (nRow != m1.nRow || nCol != m1.nCol) + return false; + + for (i = 0;i < nRow; i++) { + for (j = 0; j < nCol; j++) { + if (values[i][j] != m1.values[i][j]) + return false; + } + } + return true; + } + catch (NullPointerException e2) { + return false; + } + } + + /** + * Returns true if the Object o1 is of type GMatrix and all of the + * data members of o1 are equal to the corresponding data members in + * this GMatrix. + * @param o1 The object with which the comparison is made. + * @return true or false + */ + @Override + public boolean equals(Object o1) + { + try { + GMatrix m2 = (GMatrix) o1; + int i, j; + if (nRow != m2.nRow || nCol != m2.nCol) + return false; + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + if (values[i][j] != m2.values[i][j]) + return false; + } + } + return true; + } + catch (ClassCastException e1) { + return false; + } + catch (NullPointerException e2) { + return false; + } + } + + /** + * @deprecated Use epsilonEquals(GMatrix, double) instead + */ + public boolean epsilonEquals(GMatrix m1, float epsilon) { + return epsilonEquals(m1, (double)epsilon); + } + + /** + * Returns true if the L-infinite distance between this matrix + * and matrix m1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[i=0,1,2, . . .n ; j=0,1,2, . . .n ; abs(this.m(i,j) - m1.m(i,j)] + * @param m1 The matrix to be compared to this matrix + * @param epsilon the threshold value + */ + public boolean epsilonEquals(GMatrix m1, double epsilon) + { + int i, j; + double diff; + if (nRow != m1.nRow || nCol != m1.nCol) + return false; + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + diff = values[i][j] - m1.values[i][j]; + if ((diff < 0 ? -diff : diff) > epsilon) + return false; + } + } + return true; + } + + /** + * Returns the trace of this matrix. + * @return the trace of this matrix + */ + public final double trace() + { + int i, l; + double t; + + if (nRow < nCol) + l = nRow; + else + l = nCol; + + t = 0.0; + for (i = 0; i < l; i++) { + t += values[i][i]; + } + return t; + } + + /** + * Finds the singular value decomposition (SVD) of this matrix + * such that this = U*W*transpose(V); and returns the rank of + * this matrix; the values of U,W,V are all overwritten. Note + * that the matrix V is output as V, and + * not transpose(V). If this matrix is mxn, then U is mxm, W + * is a diagonal matrix that is mxn, and V is nxn. Using the + * notation W = diag(w), then the inverse of this matrix is: + * inverse(this) = V*diag(1/w)*tranpose(U), where diag(1/w) + * is the same matrix as W except that the reciprocal of each + * of the diagonal components is used. + * @param U The computed U matrix in the equation this = U*W*transpose(V) + * @param W The computed W matrix in the equation this = U*W*transpose(V) + * @param V The computed V matrix in the equation this = U*W*transpose(V) + * @return The rank of this matrix. + */ + public final int SVD(GMatrix U, GMatrix W, GMatrix V) + { + // check for consistancy in dimensions + if (nCol != V.nCol || nCol != V.nRow) { + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix18")); + } + + if (nRow != U.nRow || nRow != U.nCol) { + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix25")); + } + + if (nRow != W.nRow || nCol != W.nCol) { + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix26")); + } + + // Fix ArrayIndexOutOfBounds for 2x2 matrices, which partially + // addresses bug 4348562 for J3D 1.2.1. + // + // Does *not* fix the following problems reported in 4348562, + // which will wait for J3D 1.3: + // + // 1) no output of W + // 2) wrong transposition of U + // 3) wrong results for 4x4 matrices + // 4) slow performance + if (nRow == 2 && nCol == 2) { + if (values[1][0] == 0.0) { + U.setIdentity(); + V.setIdentity(); + + if (values[0][1] == 0.0) { + return 2; + } + + double[] sinl = new double[1]; + double[] sinr = new double[1]; + double[] cosl = new double[1]; + double[] cosr = new double[1]; + double[] single_values = new double[2]; + + single_values[0] = values[0][0]; + single_values[1] = values[1][1]; + + compute_2X2(values[0][0], values[0][1], values[1][1], + single_values, sinl, cosl, sinr, cosr, 0); + + update_u(0, U, cosl, sinl); + update_v(0, V, cosr, sinr); + + return 2; + } + // else call computeSVD() and check for 2x2 there + } + + return computeSVD(this, U, W, V); + } + + /** + * LU Decomposition: this matrix must be a square matrix and the + * LU GMatrix parameter must be the same size as this matrix. + * The matrix LU will be overwritten as the combination of a + * lower diagonal and upper diagonal matrix decompostion of this + * matrix; the diagonal + * elements of L (unity) are not stored. The GVector parameter + * records the row permutation effected by the partial pivoting, + * and is used as a parameter to the GVector method LUDBackSolve + * to solve sets of linear equations. + * This method returns +/- 1 depending on whether the number + * of row interchanges was even or odd, respectively. + * @param LU The matrix into which the lower and upper decompositions + * will be placed. + * @param permutation The row permutation effected by the partial + * pivoting + * @return +-1 depending on whether the number of row interchanges + * was even or odd respectively + */ + public final int LUD(GMatrix LU, GVector permutation) + { + int size = LU.nRow*LU.nCol; + double[] temp = new double[size]; + int[] even_row_exchange = new int[1]; + int[] row_perm = new int[LU.nRow]; + int i, j; + + if (nRow != nCol) { + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix19")); + } + + if (nRow != LU.nRow) { + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix27")); + } + + if (nCol != LU.nCol) { + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix27")); + } + + if (LU.nRow != permutation.getSize()) { + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix20")); + } + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + temp[i*nCol+j] = values[i][j]; + } + } + + // Calculate LU decomposition: Is the matrix singular? + if (!luDecomposition(LU.nRow, temp, row_perm, even_row_exchange)) { + // Matrix has no inverse + throw new SingularMatrixException + (VecMathI18N.getString("GMatrix21")); + } + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + LU.values[i][j] = temp[i*nCol+j]; + } + } + + for (i = 0; i < LU.nRow; i++){ + permutation.values[i] = (double)row_perm[i]; + } + + return even_row_exchange[0]; + } + + /** + * Sets this matrix to a uniform scale matrix; all of the + * values are reset. + * @param scale The new scale value + */ + public final void setScale(double scale) + { + int i, j, l; + + if (nRow < nCol) + l = nRow; + else + l = nCol; + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = 0.0; + } + } + + for (i = 0; i < l; i++) { + values[i][i] = scale; + } + } + + /** + * General invert routine. Inverts m1 and places the result in "this". + * Note that this routine handles both the "this" version and the + * non-"this" version. + * + * Also note that since this routine is slow anyway, we won't worry + * about allocating a little bit of garbage. + */ + final void invertGeneral(GMatrix m1) { + int size = m1.nRow*m1.nCol; + double temp[] = new double[size]; + double result[] = new double[size]; + int row_perm[] = new int[m1.nRow]; + int[] even_row_exchange = new int[1]; + int i, j; + + // Use LU decomposition and backsubstitution code specifically + // for floating-point nxn matrices. + if (m1.nRow != m1.nCol) { + // Matrix is either under or over determined + throw new MismatchedSizeException + (VecMathI18N.getString("GMatrix22")); + } + + // Copy source matrix to temp + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + temp[i*nCol+j] = m1.values[i][j]; + } + } + + // Calculate LU decomposition: Is the matrix singular? + if (!luDecomposition(m1.nRow, temp, row_perm, even_row_exchange)) { + // Matrix has no inverse + throw new SingularMatrixException + (VecMathI18N.getString("GMatrix21")); + } + + // Perform back substitution on the identity matrix + for (i = 0; i < size; i++) + result[i] = 0.0; + + for (i = 0; i < nCol; i++) + result[i+i*nCol] = 1.0; + + luBacksubstitution(m1.nRow, temp, row_perm, result); + + for (i = 0; i < nRow; i++) { + for (j = 0; j < nCol; j++) { + values[i][j] = result[i*nCol+j]; + } + } + } + + /** + * Given a nxn array "matrix0", this function replaces it with the + * LU decomposition of a row-wise permutation of itself. The input + * parameters are "matrix0" and "dim". The array "matrix0" is also + * an output parameter. The vector "row_perm[]" is an output + * parameter that contains the row permutations resulting from partial + * pivoting. The output parameter "even_row_xchg" is 1 when the + * number of row exchanges is even, or -1 otherwise. Assumes data + * type is always double. + * + * @return true if the matrix is nonsingular, or false otherwise. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 40-45. + // + static boolean luDecomposition(int dim, double[] matrix0, + int[] row_perm, int[] even_row_xchg) { + + double row_scale[] = new double[dim]; + + // Determine implicit scaling information by looping over rows + int i, j; + int ptr, rs, mtx; + double big, temp; + + ptr = 0; + rs = 0; + even_row_xchg[0] = 1; + + // For each row ... + i = dim; + while (i-- != 0) { + big = 0.0; + + // For each column, find the largest element in the row + j = dim; + while (j-- != 0) { + temp = matrix0[ptr++]; + temp = Math.abs(temp); + if (temp > big) { + big = temp; + } + } + + // Is the matrix singular? + if (big == 0.0) { + return false; + } + row_scale[rs++] = 1.0 / big; + } + + // For all columns, execute Crout's method + mtx = 0; + for (j = 0; j < dim; j++) { + int imax, k; + int target, p1, p2; + double sum; + + // Determine elements of upper diagonal matrix U + for (i = 0; i < j; i++) { + target = mtx + (dim*i) + j; + sum = matrix0[target]; + k = i; + p1 = mtx + (dim*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += dim; + } + matrix0[target] = sum; + } + + // Search for largest pivot element and calculate + // intermediate elements of lower diagonal matrix L. + big = 0.0; + imax = -1; + for (i = j; i < dim; i++) { + target = mtx + (dim*i) + j; + sum = matrix0[target]; + k = j; + p1 = mtx + (dim*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += dim; + } + matrix0[target] = sum; + + // Is this the best pivot so far? + if ((temp = row_scale[i] * Math.abs(sum)) >= big) { + big = temp; + imax = i; + } + } + + if (imax < 0) { + throw new RuntimeException(VecMathI18N.getString("GMatrix24")); + } + + // Is a row exchange necessary? + if (j != imax) { + // Yes: exchange rows + k = dim; + p1 = mtx + (dim*imax); + p2 = mtx + (dim*j); + while (k-- != 0) { + temp = matrix0[p1]; + matrix0[p1++] = matrix0[p2]; + matrix0[p2++] = temp; + } + + // Record change in scale factor + row_scale[imax] = row_scale[j]; + even_row_xchg[0] = -even_row_xchg[0]; // change exchange parity + } + + // Record row permutation + row_perm[j] = imax; + + // Is the matrix singular + if (matrix0[(mtx + (dim*j) + j)] == 0.0) { + return false; + } + + // Divide elements of lower diagonal matrix L by pivot + if (j != (dim-1)) { + temp = 1.0 / (matrix0[(mtx + (dim*j) + j)]); + target = mtx + (dim*(j+1)) + j; + i = (dim-1) - j; + while (i-- != 0) { + matrix0[target] *= temp; + target += dim; + } + } + + } + + return true; + } + + /** + * Solves a set of linear equations. The input parameters "matrix1", + * and "row_perm" come from luDecompostion and do not change + * here. The parameter "matrix2" is a set of column vectors assembled + * into a nxn matrix of floating-point values. The procedure takes each + * column of "matrix2" in turn and treats it as the right-hand side of the + * matrix equation Ax = LUx = b. The solution vector replaces the + * original column of the matrix. + * + * If "matrix2" is the identity matrix, the procedure replaces its contents + * with the inverse of the matrix from which "matrix1" was originally + * derived. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 44-45. + // + static void luBacksubstitution(int dim, double[] matrix1, + int[] row_perm, + double[] matrix2) { + + int i, ii, ip, j, k; + int rp; + int cv, rv, ri; + double tt; + + // rp = row_perm; + rp = 0; + + // For each column vector of matrix2 ... + for (k = 0; k < dim; k++) { + // cv = &(matrix2[0][k]); + cv = k; + ii = -1; + + // Forward substitution + for (i = 0; i < dim; i++) { + double sum; + + ip = row_perm[rp+i]; + sum = matrix2[cv+dim*ip]; + matrix2[cv+dim*ip] = matrix2[cv+dim*i]; + if (ii >= 0) { + // rv = &(matrix1[i][0]); + rv = i*dim; + for (j = ii; j <= i-1; j++) { + sum -= matrix1[rv+j] * matrix2[cv+dim*j]; + } + } + else if (sum != 0.0) { + ii = i; + } + matrix2[cv+dim*i] = sum; + } + + // Backsubstitution + for (i = 0; i < dim; i++) { + ri = (dim-1-i); + rv = dim*(ri); + tt = 0.0; + for(j=1;j<=i;j++) { + tt += matrix1[rv+dim-j] * matrix2[cv+dim*(dim-j)]; + } + matrix2[cv+dim*ri]= (matrix2[cv+dim*ri] - tt) / matrix1[rv+ri]; + } + } + } + + static int computeSVD(GMatrix mat, GMatrix U, GMatrix W, GMatrix V) { + int i, j, k; + int nr, nc, si; + + int converged, rank; + double cs, sn, r, mag,scale, t; + int eLength, sLength, vecLength; + + GMatrix tmp = new GMatrix(mat.nRow, mat.nCol); + GMatrix u = new GMatrix(mat.nRow, mat.nCol); + GMatrix v = new GMatrix(mat.nRow, mat.nCol); + GMatrix m = new GMatrix(mat); + + // compute the number of singular values + if (m.nRow >= m.nCol) { + sLength = m.nCol; + eLength = m.nCol-1; + }else { + sLength = m.nRow; + eLength = m.nRow; + } + + if (m.nRow > m.nCol) + vecLength = m.nRow; + else + vecLength = m.nCol; + + double[] vec = new double[vecLength]; + double[] single_values = new double[sLength]; + double[] e = new double[eLength]; + + if(debug) { + System.out.println("input to compute_svd = \n"+m.toString()); + } + + rank = 0; + + U.setIdentity(); + V.setIdentity(); + + nr = m.nRow; + nc = m.nCol; + + // householder reduction + for (si = 0; si < sLength; si++) { + // for each singular value + + if (nr > 1) { + // zero out column + if (debug) + System.out.println + ("*********************** U ***********************\n"); + + // compute reflector + mag = 0.0; + for (i = 0; i < nr; i++) { + mag += m.values[i+si][si] * m.values[i+si][si]; + if (debug) + System.out.println + ("mag = " + mag + " matrix.dot = " + + m.values[i+si][si] * m.values[i+si][si]); + } + + mag = Math.sqrt(mag); + if (m.values[si][si] == 0.0) { + vec[0] = mag; + } else { + vec[0] = m.values[si][si] + d_sign(mag, m.values[si][si]); + } + + for (i = 1; i < nr; i++) { + vec[i] = m.values[si+i][si]; + } + + scale = 0.0; + for (i = 0; i < nr; i++) { + if (debug) + System.out.println("vec["+i+"]="+vec[i]); + + scale += vec[i]*vec[i]; + } + + scale = 2.0/scale; + if (debug) + System.out.println("scale = "+scale); + + for (j = si; j < m.nRow; j++) { + for (k = si; k < m.nRow; k++) { + u.values[j][k] = -scale * vec[j-si]*vec[k-si]; + } + } + + for (i = si; i < m.nRow; i++){ + u.values[i][i] += 1.0; + } + + // compute s + t = 0.0; + for (i = si; i < m.nRow; i++){ + t += u.values[si][i] * m.values[i][si]; + } + m.values[si][si] = t; + + // apply reflector + for (j = si; j < m.nRow; j++) { + for (k = si+1; k < m.nCol; k++) { + tmp.values[j][k] = 0.0; + for (i = si; i < m.nCol; i++) { + tmp.values[j][k] += u.values[j][i] * m.values[i][k]; + } + } + } + + for (j = si; j < m.nRow; j++) { + for (k = si+1; k < m.nCol; k++) { + m.values[j][k] = tmp.values[j][k]; + } + } + + if (debug) { + System.out.println("U =\n" + U.toString()); + System.out.println("u =\n" + u.toString()); + } + + // update U matrix + for (j = si; j < m.nRow; j++) { + for (k = 0; k < m.nCol; k++) { + tmp.values[j][k] = 0.0; + for (i = si; i < m.nCol; i++) { + tmp.values[j][k] += u.values[j][i] * U.values[i][k]; + } + } + } + + for (j = si; j < m.nRow; j++) { + for (k = 0; k < m.nCol; k++) { + U.values[j][k] = tmp.values[j][k]; + } + } + + if (debug) { + System.out.println("single_values["+si+"] =\n" + + single_values[si]); + System.out.println("m =\n" + m.toString()); + System.out.println("U =\n" + U.toString()); + } + + nr--; + } + + if( nc > 2 ) { + // zero out row + if (debug) + System.out.println + ("*********************** V ***********************\n"); + + mag = 0.0; + for (i = 1; i < nc; i++){ + mag += m.values[si][si+i] * m.values[si][si+i]; + } + + if (debug) + System.out.println("mag = " + mag); + + // generate the reflection vector, compute the first entry and + // copy the rest from the row to be zeroed + mag = Math.sqrt(mag); + if (m.values[si][si+1] == 0.0) { + vec[0] = mag; + } else { + vec[0] = m.values[si][si+1] + + d_sign(mag, m.values[si][si+1]); + } + + for (i = 1; i < nc - 1; i++){ + vec[i] = m.values[si][si+i+1]; + } + + // use reflection vector to compute v matrix + scale = 0.0; + for (i = 0; i < nc - 1; i++){ + if( debug )System.out.println("vec["+i+"]="+vec[i]); + scale += vec[i]*vec[i]; + } + + scale = 2.0/scale; + if (debug) + System.out.println("scale = "+scale); + + for (j = si + 1; j < nc; j++) { + for (k = si+1; k < m.nCol; k++) { + v.values[j][k] = -scale * vec[j-si-1]*vec[k-si-1]; + } + } + + for (i = si + 1; i < m.nCol; i++){ + v.values[i][i] += 1.0; + } + + t=0.0; + for (i = si; i < m.nCol; i++){ + t += v.values[i][si+1] * m.values[si][i]; + } + m.values[si][si+1]=t; + + // apply reflector + for (j = si + 1; j < m.nRow; j++) { + for (k = si + 1; k < m.nCol; k++) { + tmp.values[j][k] = 0.0; + for (i = si + 1; i < m.nCol; i++) { + tmp.values[j][k] += v.values[i][k] * m.values[j][i]; + } + } + } + + for (j = si + 1; j < m.nRow; j++) { + for (k = si + 1; k < m.nCol; k++) { + m.values[j][k] = tmp.values[j][k]; + } + } + + if (debug) { + System.out.println("V =\n" + V.toString()); + System.out.println("v =\n" + v.toString()); + System.out.println("tmp =\n" + tmp.toString()); + } + + // update V matrix + for (j = 0; j < m.nRow; j++) { + for (k = si + 1; k < m.nCol; k++) { + tmp.values[j][k] = 0.0; + for (i = si + 1; i < m.nCol; i++) { + tmp.values[j][k] += v.values[i][k] * V.values[j][i]; + } + } + } + + if (debug) + System.out.println("tmp =\n" + tmp.toString()); + + for (j = 0;j < m.nRow; j++) { + for (k = si + 1; k < m.nCol; k++) { + V.values[j][k] = tmp.values[j][k]; + } + } + + if (debug) { + System.out.println("m =\n" + m.toString()); + System.out.println("V =\n" + V.toString()); + } + + nc--; + } + } + + for (i = 0; i < sLength; i++){ + single_values[i] = m.values[i][i]; + } + + for (i = 0; i < eLength; i++){ + e[i] = m.values[i][i+1]; + } + + // Fix ArrayIndexOutOfBounds for 2x2 matrices, which partially + // addresses bug 4348562 for J3D 1.2.1. + // + // Does *not* fix the following problems reported in 4348562, + // which will wait for J3D 1.3: + // + // 1) no output of W + // 2) wrong transposition of U + // 3) wrong results for 4x4 matrices + // 4) slow performance + if (m.nRow == 2 && m.nCol == 2) { + double[] cosl = new double[1]; + double[] cosr = new double[1]; + double[] sinl = new double[1]; + double[] sinr = new double[1]; + + compute_2X2(single_values[0], e[0], single_values[1], + single_values, sinl, cosl, sinr, cosr, 0); + + update_u(0, U, cosl, sinl); + update_v(0, V, cosr, sinr); + + return 2; + } + + // compute_qr causes ArrayIndexOutOfBounds for 2x2 matrices + compute_qr (0, e.length-1, single_values, e, U, V); + + // compute rank = number of non zero singular values + rank = single_values.length; + + // sort by order of size of single values + // and check for zero's + return rank; + } + + static void compute_qr(int start, int end, double[] s, double[] e, + GMatrix u, GMatrix v) { + + int i, j, k, n, sl; + boolean converged; + double shift, r, utemp, vtemp, f, g; + double[] cosl = new double[1]; + double[] cosr = new double[1]; + double[] sinl = new double[1]; + double[] sinr = new double[1]; + GMatrix m = new GMatrix(u.nCol, v.nRow); + + final int MAX_INTERATIONS = 2; + final double CONVERGE_TOL = 4.89E-15; + + if (debug) { + System.out.println("start =" + start); + System.out.println("s =\n"); + for(i=0;i<s.length;i++) { + System.out.println(s[i]); + } + + System.out.println("\nes =\n"); + for (i = 0; i < e.length; i++) { + System.out.println(e[i]); + } + + for (i = 0; i < s.length; i++) { + m.values[i][i] = s[i]; + } + + for (i = 0; i < e.length; i++) { + m.values[i][i+1] = e[i]; + } + System.out.println("\nm =\n" + m.toString()); + } + + double c_b48 = 1.0; + double c_b71 = -1.0; + converged = false; + + if (debug) + print_svd(s, e, u, v); + + f = 0.0; + g = 0.0; + + for (k = 0; k < MAX_INTERATIONS && !converged;k++) { + for (i = start; i <= end; i++) { + + // if at start of iterfaction compute shift + if (i == start) { + if (e.length == s.length) + sl = end; + else + sl = end + 1; + + shift = compute_shift(s[sl-1], e[end], s[sl]); + + f = (Math.abs(s[i]) - shift) * + (d_sign(c_b48, s[i]) + shift/s[i]); + g = e[i]; + } + + r = compute_rot(f, g, sinr, cosr); + if (i != start) + e[i-1] = r; + + f = cosr[0] * s[i] + sinr[0] * e[i]; + e[i] = cosr[0] * e[i] - sinr[0] * s[i]; + g = sinr[0] * s[i+1]; + s[i+1] = cosr[0] * s[i+1]; + + // if (debug) print_se(s,e); + update_v (i, v, cosr, sinr); + if (debug) + print_m(m,u,v); + + r = compute_rot(f, g, sinl, cosl); + s[i] = r; + f = cosl[0] * e[i] + sinl[0] * s[i+1]; + s[i+1] = cosl[0] * s[i+1] - sinl[0] * e[i]; + + if( i < end) { + // if not last + g = sinl[0] * e[i+1]; + e[i+1] = cosl[0] * e[i+1]; + } + //if (debug) print_se(s,e); + + update_u(i, u, cosl, sinl); + if (debug) + print_m(m,u,v); + } + + // if extra off diagonal perform one more right side rotation + if (s.length == e.length) { + r = compute_rot(f, g, sinr, cosr); + f = cosr[0] * s[i] + sinr[0] * e[i]; + e[i] = cosr[0] * e[i] - sinr[0] * s[i]; + s[i+1] = cosr[0] * s[i+1]; + + update_v(i, v, cosr, sinr); + if (debug) + print_m(m,u,v); + } + + if (debug) { + System.out.println + ("\n*********************** iteration #" + k + + " ***********************\n"); + print_svd(s, e, u, v); + } + + // check for convergence on off diagonals and reduce + while ((end-start > 1) && (Math.abs(e[end]) < CONVERGE_TOL)) { + end--; + } + + // check if need to split + for (n = end - 2; n > start; n--) { + if (Math.abs(e[n]) < CONVERGE_TOL) { // split + compute_qr(n + 1, end, s, e, u, v); // do lower matrix + end = n - 1; // do upper matrix + + // check for convergence on off diagonals and reduce + while ((end - start > 1) && + (Math.abs(e[end]) < CONVERGE_TOL)) { + end--; + } + } + } + + if (debug) + System.out.println("start = " + start); + + if ((end - start <= 1) && (Math.abs(e[start+1]) < CONVERGE_TOL)) { + converged = true; + } else { + // check if zero on the diagonal + } + + } + + if (debug) + System.out.println("\n****call compute_2X2 ********************\n"); + + if (Math.abs(e[1]) < CONVERGE_TOL) { + compute_2X2(s[start], e[start], s[start+1], s, + sinl, cosl, sinr, cosr, 0); + e[start] = 0.0; + e[start+1] = 0.0; + } else { + } + + i = start; + update_u(i, u, cosl, sinl); + update_v(i, v, cosr, sinr); + + if(debug) { + System.out.println + ("\n*******after call compute_2X2 **********************\n"); + print_svd(s, e, u, v); + } + + return; + } + + private static void print_se(double[] s, double[] e) { + System.out.println("\ns =" + s[0] + " " + s[1] + " " + s[2]); + System.out.println("e =" + e[0] + " " + e[1]); + } + + private static void update_v(int index, GMatrix v, + double[] cosr, double[] sinr) { + int j; + double vtemp; + + for (j = 0; j < v.nRow; j++) { + vtemp = v.values[j][index]; + v.values[j][index] = + cosr[0]*vtemp + sinr[0]*v.values[j][index+1]; + v.values[j][index+1] = + -sinr[0]*vtemp + cosr[0]*v.values[j][index+1]; + } + } + + private static void chase_up(double[] s, double[] e, int k, GMatrix v) { + double f, g, r; + double[] cosr = new double[1]; + double[] sinr = new double[1]; + int i; + GMatrix t = new GMatrix(v.nRow, v.nCol); + GMatrix m = new GMatrix(v.nRow, v.nCol); + + if (debug) { + m.setIdentity(); + for (i = 0; i < s.length; i++) { + m.values[i][i] = s[i]; + } + for (i = 0; i < e.length; i++) { + m.values[i][i+1] = e[i]; + } + } + + f = e[k]; + g = s[k]; + + for (i = k; i > 0; i--) { + r = compute_rot(f, g, sinr, cosr); + f = -e[i-1] * sinr[0]; + g = s[i-1]; + s[i] = r; + e[i-1] = e[i-1] * cosr[0]; + update_v_split(i, k+1, v, cosr, sinr, t, m); + } + + s[i+1] = compute_rot(f, g, sinr, cosr); + update_v_split(i, k+1, v, cosr, sinr, t, m); + } + + private static void chase_across(double[] s, double[] e, int k, GMatrix u) { + double f, g, r; + double[] cosl = new double[1]; + double[] sinl = new double[1]; + int i; + GMatrix t = new GMatrix(u.nRow, u.nCol); + GMatrix m = new GMatrix(u.nRow, u.nCol); + + if (debug) { + m.setIdentity(); + for (i = 0; i < s.length; i++) { + m.values[i][i] = s[i]; + } + for (i = 0; i < e.length; i++) { + m.values[i][i+1] = e[i]; + } + } + + g = e[k]; + f = s[k+1]; + + for (i = k; i < u.nCol-2; i++){ + r = compute_rot(f, g, sinl, cosl); + g = -e[i+1] * sinl[0]; + f = s[i+2]; + s[i+1] = r; + e[i+1] = e[i+1] * cosl[0]; + update_u_split(k, i + 1, u, cosl, sinl, t, m); + } + + s[i+1] = compute_rot(f, g, sinl, cosl); + update_u_split(k, i + 1, u, cosl, sinl, t, m); + } + + private static void update_v_split(int topr, int bottomr, GMatrix v, + double[] cosr, double[] sinr, + GMatrix t, GMatrix m) { + int j; + double vtemp; + + for (j = 0; j < v.nRow; j++) { + vtemp = v.values[j][topr]; + v.values[j][topr] = cosr[0]*vtemp - sinr[0]*v.values[j][bottomr]; + v.values[j][bottomr] = sinr[0]*vtemp + cosr[0]*v.values[j][bottomr]; + } + + if (debug) { + t.setIdentity(); + for (j = 0; j < v.nRow; j++) { + vtemp = t.values[j][topr]; + t.values[j][topr] = + cosr[0]*vtemp - sinr[0]*t.values[j][bottomr]; + t.values[j][bottomr] = + sinr[0]*vtemp + cosr[0]*t.values[j][bottomr]; + } + } + + System.out.println("topr =" + topr); + System.out.println("bottomr =" + bottomr); + System.out.println("cosr =" + cosr[0]); + System.out.println("sinr =" + sinr[0]); + System.out.println("\nm ="); + checkMatrix(m); + System.out.println("\nv ="); + checkMatrix(t); + m.mul(m,t); + System.out.println("\nt*m ="); + checkMatrix(m); + } + + private static void update_u_split(int topr, int bottomr, GMatrix u, + double[] cosl, double[] sinl, + GMatrix t, GMatrix m) { + int j; + double utemp; + + for (j = 0; j < u.nCol; j++) { + utemp = u.values[topr][j]; + u.values[topr][j] = cosl[0]*utemp - sinl[0]*u.values[bottomr][j]; + u.values[bottomr][j] = sinl[0]*utemp + cosl[0]*u.values[bottomr][j]; + } + + if(debug) { + t.setIdentity(); + for (j = 0;j < u.nCol; j++) { + utemp = t.values[topr][j]; + t.values[topr][j] = + cosl[0]*utemp - sinl[0]*t.values[bottomr][j]; + t.values[bottomr][j] = + sinl[0]*utemp + cosl[0]*t.values[bottomr][j]; + } + } + System.out.println("\nm="); + checkMatrix(m); + System.out.println("\nu="); + checkMatrix(t); + m.mul(t,m); + System.out.println("\nt*m="); + checkMatrix(m); + } + + private static void update_u(int index, GMatrix u, + double[] cosl, double[] sinl) { + int j; + double utemp; + + for (j = 0; j < u.nCol; j++) { + utemp = u.values[index][j]; + u.values[index][j] = + cosl[0]*utemp + sinl[0]*u.values[index+1][j]; + u.values[index+1][j] = + -sinl[0]*utemp + cosl[0]*u.values[index+1][j]; + } + } + + private static void print_m(GMatrix m, GMatrix u, GMatrix v) { + GMatrix mtmp = new GMatrix(m.nCol, m.nRow); + + mtmp.mul(u, mtmp); + mtmp.mul(mtmp, v); + System.out.println("\n m = \n" + mtmp.toString(mtmp)); + + } + + private static String toString(GMatrix m) + { + StringBuffer buffer = new StringBuffer(m.nRow * m.nCol * 8); + int i, j; + + for (i = 0; i < m.nRow; i++) { + for(j = 0; j < m.nCol; j++) { + if (Math.abs(m.values[i][j]) < .000000001) { + buffer.append("0.0000 "); + } else { + buffer.append(m.values[i][j]).append(" "); + } + } + buffer.append("\n"); + } + return buffer.toString(); + } + + private static void print_svd(double[] s, double[] e, + GMatrix u, GMatrix v) { + int i; + GMatrix mtmp = new GMatrix(u.nCol, v.nRow); + + System.out.println(" \ns = "); + for (i = 0; i < s.length; i++) { + System.out.println(" " + s[i]); + } + + System.out.println(" \ne = "); + for (i = 0; i < e.length; i++) { + System.out.println(" " + e[i]); + } + + System.out.println(" \nu = \n" + u.toString()); + System.out.println(" \nv = \n" + v.toString()); + + mtmp.setIdentity(); + for (i = 0; i < s.length; i++) { + mtmp.values[i][i] = s[i]; + } + for (i = 0; i < e.length; i++) { + mtmp.values[i][i+1] = e[i]; + } + System.out.println(" \nm = \n"+mtmp.toString()); + + mtmp.mulTransposeLeft(u, mtmp); + mtmp.mulTransposeRight(mtmp, v); + + System.out.println(" \n u.transpose*m*v.transpose = \n" + + mtmp.toString()); + } + + static double max(double a, double b) { + if (a > b) + return a; + else + return b; + } + + static double min(double a, double b) { + if (a < b) + return a; + else + return b; + } + + static double compute_shift(double f, double g, double h) { + double d__1, d__2; + double fhmn, fhmx, c, fa, ga, ha, as, at, au; + double ssmin; + + fa = Math.abs(f); + ga = Math.abs(g); + ha = Math.abs(h); + fhmn = min(fa,ha); + fhmx = max(fa,ha); + + if (fhmn == 0.0) { + ssmin = 0.0; + if (fhmx == 0.0) { + } else { + d__1 = min(fhmx,ga) / max(fhmx,ga); + } + } else { + if (ga < fhmx) { + as = fhmn / fhmx + 1.0; + at = (fhmx - fhmn) / fhmx; + d__1 = ga / fhmx; + au = d__1 * d__1; + c = 2.0 / (Math.sqrt(as * as + au) + Math.sqrt(at * at + au)); + ssmin = fhmn * c; + } else { + au = fhmx / ga; + if (au == 0.0) { + ssmin = fhmn * fhmx / ga; + } else { + as = fhmn / fhmx + 1.0; + at = (fhmx - fhmn) / fhmx; + d__1 = as * au; + d__2 = at * au; + c = 1.0 / (Math.sqrt(d__1 * d__1 + 1.0) + + Math.sqrt(d__2 * d__2 + 1.0)); + ssmin = fhmn * c * au; + ssmin += ssmin; + } + } + } + + return ssmin; + } + + static int compute_2X2(double f, double g, double h, + double[] single_values, double[] snl, double[] csl, + double[] snr, double[] csr, int index) { + + double c_b3 = 2.0; + double c_b4 = 1.0; + + double d__1; + int pmax; + double temp; + boolean swap; + double a, d, l, m, r, s, t, tsign, fa, ga, ha; + double ft, gt, ht, mm; + boolean gasmal; + double tt, clt, crt, slt, srt; + double ssmin,ssmax; + + ssmax = single_values[0]; + ssmin = single_values[1]; + clt = 0.0; + crt = 0.0; + slt = 0.0; + srt = 0.0; + tsign = 0.0; + + ft = f; + fa = Math.abs(ft); + ht = h; + ha = Math.abs(h); + + pmax = 1; + if (ha > fa) + swap = true; + else + swap = false; + + if (swap) { + pmax = 3; + temp = ft; + ft = ht; + ht = temp; + temp = fa; + fa = ha; + ha = temp; + + } + + gt = g; + ga = Math.abs(gt); + if (ga == 0.0) { + single_values[1] = ha; + single_values[0] = fa; + clt = 1.0; + crt = 1.0; + slt = 0.0; + srt = 0.0; + } else { + gasmal = true; + if (ga > fa) { + pmax = 2; + if (fa / ga < EPS) { + gasmal = false; + ssmax = ga; + + if (ha > 1.0) { + ssmin = fa / (ga / ha); + } else { + ssmin = fa / ga * ha; + } + clt = 1.0; + slt = ht / gt; + srt = 1.0; + crt = ft / gt; + } + } + if (gasmal) { + d = fa - ha; + if (d == fa) { + + l = 1.0; + } else { + l = d / fa; + } + + m = gt / ft; + t = 2.0 - l; + mm = m * m; + tt = t * t; + s = Math.sqrt(tt + mm); + + if (l == 0.0) { + r = Math.abs(m); + } else { + r = Math.sqrt(l * l + mm); + } + + a = (s + r) * 0.5; + if (ga > fa) { + pmax = 2; + if (fa / ga < EPS) { + gasmal = false; + ssmax = ga; + if (ha > 1.0) { + ssmin = fa / (ga / ha); + } else { + ssmin = fa / ga * ha; + } + clt = 1.0; + slt = ht / gt; + srt = 1.0; + crt = ft / gt; + } + } + if (gasmal) { + d = fa - ha; + if (d == fa) { + l = 1.0; + } else { + l = d / fa; + } + + m = gt / ft; + t = 2.0 - l; + + mm = m * m; + tt = t * t; + s = Math.sqrt(tt + mm); + + if (l == 0.) { + r = Math.abs(m); + } else { + r = Math.sqrt(l * l + mm); + } + + a = (s + r) * 0.5; + ssmin = ha / a; + ssmax = fa * a; + + if (mm == 0.0) { + if (l == 0.0) { + t = d_sign(c_b3, ft) * d_sign(c_b4, gt); + } else { + t = gt / d_sign(d, ft) + m / t; + } + } else { + t = (m / (s + t) + m / (r + l)) * (a + 1.0); + } + + l = Math.sqrt(t * t + 4.0); + crt = 2.0 / l; + srt = t / l; + clt = (crt + srt * m) / a; + slt = ht / ft * srt / a; + } + } + if (swap) { + csl[0] = srt; + snl[0] = crt; + csr[0] = slt; + snr[0] = clt; + } else { + csl[0] = clt; + snl[0] = slt; + csr[0] = crt; + snr[0] = srt; + } + + if (pmax == 1) { + tsign = d_sign(c_b4, csr[0]) * + d_sign(c_b4, csl[0]) * d_sign(c_b4, f); + } + if (pmax == 2) { + tsign = d_sign(c_b4, snr[0]) * + d_sign(c_b4, csl[0]) * d_sign(c_b4, g); + } + if (pmax == 3) { + tsign = d_sign(c_b4, snr[0]) * + d_sign(c_b4, snl[0]) * d_sign(c_b4, h); + } + + single_values[index] = d_sign(ssmax, tsign); + d__1 = tsign * d_sign(c_b4, f) * d_sign(c_b4, h); + single_values[index+1] = d_sign(ssmin, d__1); + } + + return 0; + } + + static double compute_rot(double f, double g, double[] sin, double[] cos) { + int i__1; + double d__1, d__2; + double cs, sn; + int i; + double scale; + int count; + double f1, g1; + double r; + final double safmn2 = 2.002083095183101E-146; + final double safmx2 = 4.994797680505588E+145; + + if (g == 0.0) { + cs = 1.0; + sn = 0.0; + r = f; + } else if (f == 0.0) { + cs = 0.0; + sn = 1.0; + r = g; + } else { + f1 = f; + g1 = g; + scale = max(Math.abs(f1),Math.abs(g1)); + if (scale >= safmx2) { + count = 0; + while(scale >= safmx2) { + ++count; + f1 *= safmn2; + g1 *= safmn2; + scale = max(Math.abs(f1), Math.abs(g1)); + } + r = Math.sqrt(f1*f1 + g1*g1); + cs = f1 / r; + sn = g1 / r; + i__1 = count; + for (i = 1; i <= count; ++i) { + r *= safmx2; + } + } else if (scale <= safmn2) { + count = 0; + while(scale <= safmn2) { + ++count; + f1 *= safmx2; + g1 *= safmx2; + scale = max(Math.abs(f1), Math.abs(g1)); + } + r = Math.sqrt(f1*f1 + g1*g1); + cs = f1 / r; + sn = g1 / r; + i__1 = count; + for (i = 1; i <= count; ++i) { + r *= safmn2; + } + } else { + r = Math.sqrt(f1*f1 + g1*g1); + cs = f1 / r; + sn = g1 / r; + } + if (Math.abs(f) > Math.abs(g) && cs < 0.0) { + cs = -cs; + sn = -sn; + r = -r; + } + } + sin[0] = sn; + cos[0] = cs; + return r; + } + + static double d_sign(double a, double b) { + double x; + x = (a >= 0 ? a : - a); + return (b >= 0 ? x : -x); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + GMatrix m1 = null; + try { + m1 = (GMatrix)super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + + // Also need to clone array of values + m1.values = new double[nRow][nCol]; + for (int i = 0; i < nRow; i++) { + for(int j = 0; j < nCol; j++) { + m1.values[i][j] = values[i][j]; + } + } + + return m1; + } + +} diff --git a/src/org/jogamp/vecmath/GVector.java b/src/org/jogamp/vecmath/GVector.java new file mode 100644 index 0000000..de44ed1 --- /dev/null +++ b/src/org/jogamp/vecmath/GVector.java @@ -0,0 +1,931 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A double precision, general, dynamically-resizable, + * one-dimensional vector class. Index numbering begins with zero. + */ + +public class GVector implements java.io.Serializable, Cloneable { + + private int length; + double[] values; + + // Compatible with 1.1 + static final long serialVersionUID = 1398850036893875112L; + + /** + * Constructs a new GVector of the specified + * length with all vector elements initialized to 0. + * @param length the number of elements in this GVector. + */ + public GVector(int length) + { + int i; + + this.length = length; + values = new double[length]; + for(i = 0; i < length; i++) values[i] = 0.0; + } + + /** + * Constructs a new GVector from the specified array elements. + * The length of this GVector is set to the length of the + * specified array. The array elements are copied into this new + * GVector. + * @param vector the values for the new GVector. + */ + public GVector(double[] vector) + { + int i; + + length = vector.length; + values = new double[vector.length]; + for(i = 0; i < length; i++) values[i] = vector[i]; + } + + /** + * Constructs a new GVector from the specified vector. + * The vector elements are copied into this new GVector. + * @param vector the source GVector for this new GVector. + */ + public GVector(GVector vector) + { + int i; + + values = new double[vector.length]; + length = vector.length; + for(i = 0; i < length; i++) values[i] = vector.values[i]; + } + + /** + * Constructs a new GVector and copies the initial values + * from the specified tuple. + * @param tuple the source for the new GVector's initial values + */ + public GVector(Tuple2f tuple) + { + values = new double[2]; + values[0] = (double)tuple.x; + values[1] = (double)tuple.y; + length = 2; + } + + /** + * Constructs a new GVector and copies the initial values + * from the specified tuple. + * @param tuple the source for the new GVector's initial values + */ + public GVector(Tuple3f tuple) + { + values = new double[3]; + values[0] = (double)tuple.x; + values[1] = (double)tuple.y; + values[2] = (double)tuple.z; + length = 3; + } + + /** + * Constructs a new GVector and copies the initial values + * from the specified tuple. + * @param tuple the source for the new GVector's initial values + */ + public GVector(Tuple3d tuple) + { + values = new double[3]; + values[0] = tuple.x; + values[1] = tuple.y; + values[2] = tuple.z; + length = 3; + } + + /** + * Constructs a new GVector and copies the initial values + * from the specified tuple. + * @param tuple the source for the new GVector's initial values + */ + public GVector(Tuple4f tuple) + { + values = new double[4]; + values[0] = (double)tuple.x; + values[1] = (double)tuple.y; + values[2] = (double)tuple.z; + values[3] = (double)tuple.w; + length = 4; + } + + /** + * Constructs a new GVector and copies the initial values + * from the specified tuple. + * @param tuple the source for the new GVector's initial values + */ + public GVector(Tuple4d tuple) + { + values = new double[4]; + values[0] = tuple.x; + values[1] = tuple.y; + values[2] = tuple.z; + values[3] = tuple.w; + length = 4; + } + + /** + * Constructs a new GVector of the specified length and + * initializes it by copying the specified number of elements from + * the specified array. The array must contain at least + * <code>length</code> elements (i.e., <code>vector.length</code> >= + * <code>length</code>. The length of this new GVector is set to + * the specified length. + * @param vector The array from which the values will be copied. + * @param length The number of values copied from the array. + */ + public GVector(double vector[], int length) { + int i; + + this.length = length; + values = new double [length]; + for(i=0;i<length;i++) { + values[i] = vector[i]; + } + } + + /** + * Returns the square root of the sum of the squares of this + * vector (its length in n-dimensional space). + * @return length of this vector + */ + + public final double norm() + { + double sq = 0.0; + int i; + + for(i=0;i<length;i++) { + sq += values[i]*values[i]; + } + + return(Math.sqrt(sq)); + + } + + /** + * Returns the sum of the squares of this + * vector (its length squared in n-dimensional space). + * @return length squared of this vector + */ + public final double normSquared() + { + double sq = 0.0; + int i; + + for(i=0;i<length;i++) { + sq += values[i]*values[i]; + } + + return(sq); + } + + /** + * Sets the value of this vector to the normalization of vector v1. + * @param v1 the un-normalized vector + */ + public final void normalize(GVector v1) + { + double sq = 0.0; + int i; + + if( length != v1.length) + throw new MismatchedSizeException(VecMathI18N.getString("GVector0")); + + for(i=0;i<length;i++) { + sq += v1.values[i]*v1.values[i]; + } + + double invMag; + invMag = 1.0/Math.sqrt(sq); + + for(i=0;i<length;i++) { + values[i] = v1.values[i]*invMag; + } + } + + + /** + * Normalizes this vector in place. + */ + public final void normalize() + { + double sq = 0.0; + int i; + + for(i=0;i<length;i++) { + sq += values[i]*values[i]; + } + + double invMag; + invMag = 1.0/Math.sqrt(sq); + + for(i=0;i<length;i++) { + values[i] = values[i]*invMag; + } + + } + + /** + * Sets the value of this vector to the scalar multiplication + * of the scale factor with the vector v1. + * @param s the scalar value + * @param v1 the source vector + */ + public final void scale(double s, GVector v1) + { + int i; + if( length != v1.length) + throw new MismatchedSizeException(VecMathI18N.getString("GVector1")); + + for(i=0;i<length;i++) { + values[i] = v1.values[i]*s; + } + } + + /** + * Scales this vector by the scale factor s. + * @param s the scalar value + */ + public final void scale(double s) + { + int i; + + for(i=0;i<length;i++) { + values[i] = values[i]*s; + } + } + + /** + * Sets the value of this vector to the scalar multiplication by s + * of vector v1 plus vector v2 (this = s*v1 + v2). + * @param s the scalar value + * @param v1 the vector to be multiplied + * @param v2 the vector to be added + */ + public final void scaleAdd(double s, GVector v1, GVector v2) + { + + int i; + + if( v2.length != v1.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector2")); + + if( length != v1.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector3")); + + for(i=0;i<length;i++) { + values[i] = v1.values[i]*s + v2.values[i]; + } + } + + /** + * Sets the value of this vector to sum of itself and the specified + * vector + * @param vector the second vector + */ + public final void add(GVector vector) + { + int i; + + if( length != vector.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector4")); + + for(i = 0; i < length; i++) { + this.values[i] += vector.values[i]; + } + } + + /** + * Sets the value of this vector to the vector sum of vectors vector1 + * and vector2. + * @param vector1 the first vector + * @param vector2 the second vector + */ + public final void add(GVector vector1, GVector vector2) + { + int i; + + if( vector1.length != vector2.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector5")); + + if( length != vector1.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector6")); + + for(i = 0; i < length; i++) + this.values[i] = vector1.values[i] + vector2.values[i]; + } + + /** + * Sets the value of this vector to the vector difference of itself + * and vector (this = this - vector). + * @param vector the other vector + */ + public final void sub(GVector vector) + { + int i; + + if( length != vector.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector7")); + + for(i = 0; i < length; i++) { + this.values[i] -= vector.values[i]; + } + } + + /** + * Sets the value of this vector to the vector difference + * of vectors vector1 and vector2 (this = vector1 - vector2). + * @param vector1 the first vector + * @param vector2 the second vector + */ + public final void sub(GVector vector1, GVector vector2) + { + int i,l; + + + if( vector1.length != vector2.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector8")); + + if( length != vector1.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector9")); + + for(i = 0; i < length; i++) + this.values[i] = vector1.values[i] - vector2.values[i]; + } + + /** + * Multiplies matrix m1 times Vector v1 and places the result + * into this vector (this = m1*v1). + * @param m1 The matrix in the multiplication + * @param v1 The vector that is multiplied + */ + public final void mul(GMatrix m1, GVector v1) { + if (m1.getNumCol() != v1.length) + throw new MismatchedSizeException(VecMathI18N.getString("GVector10")); + + if (length != m1.getNumRow()) + throw new MismatchedSizeException(VecMathI18N.getString("GVector11")); + + double v[]; + if (v1 != this) { + v = v1.values; + } else { + v = (double []) values.clone(); + } + + for(int j=length-1; j>=0; j--){ + values[j] = 0.0; + for(int i=v1.length-1;i>=0; i--){ + values[j] += m1.values[j][i] * v[i]; + } + } + } + + /** + * Multiplies the transpose of vector v1 (ie, v1 becomes a row + * vector with respect to the multiplication) times matrix m1 + * and places the result into this vector + * (this = transpose(v1)*m1). The result is technically a + * row vector, but the GVector class only knows about column + * vectors, and so the result is stored as a column vector. + * @param m1 The matrix in the multiplication + * @param v1 The vector that is temporarily transposed + */ + public final void mul(GVector v1, GMatrix m1) { + if (m1.getNumRow() != v1.length) + throw new MismatchedSizeException(VecMathI18N.getString("GVector12")); + + if (length != m1.getNumCol()) + throw new MismatchedSizeException(VecMathI18N.getString("GVector13")); + + double v[]; + if (v1 != this) { + v = v1.values; + } else { + v = (double []) values.clone(); + } + + for (int j=length-1; j>=0; j--){ + values[j] = 0.0; + for(int i=v1.length-1; i>=0; i--){ + values[j] += m1.values[i][j] * v[i]; + } + } + } + + /** + * Negates the value of this vector: this = -this. + */ + public final void negate() { + for(int i=length-1; i>=0; i--) { + this.values[i] *= -1.0; + } + } + + /** + * Sets all the values in this vector to zero. + */ + public final void zero() { + for (int i=0; i < this.length; i++) { + this.values[i] = 0.0; + } + } + + /** + * Changes the size of this vector dynamically. If the size is increased + * no data values will be lost. If the size is decreased, only those data + * values whose vector positions were eliminated will be lost. + * @param length number of desired elements in this vector + */ + public final void setSize(int length) { + double[] tmp = new double[length]; + int i,max; + + if( this.length < length) + max = this.length; + else + max = length; + + for(i=0;i<max;i++) { + tmp[i] = values[i]; + } + this.length = length; + + values = tmp; + + } + + /** + * Sets the value of this vector to the values found in the array + * parameter. The array should be at least equal in length to + * the number of elements in the vector. + * @param vector the source array + */ + public final void set(double[] vector) { + for(int i = length-1; i >=0; i--) + values[i] = vector[i]; + } + + /** + * Sets the value of this vector to the values found in vector vector. + * @param vector the source vector + */ + public final void set(GVector vector) { + int i; + + if (length < vector.length) { + length = vector.length; + values = new double[length]; + for(i = 0; i < length; i++) + values[i] = vector.values[i]; + }else { + for(i = 0; i < vector.length; i++) + values[i] = vector.values[i]; + for(i = vector.length; i < length; i++) + values[i] = 0.0; + } + } + + /** + * Sets the value of this vector to the values in tuple + * @param tuple the source for the new GVector's new values + */ + public final void set(Tuple2f tuple) + { + if (length < 2) { + length = 2; + values = new double[2]; + } + values[0] = (double)tuple.x; + values[1] = (double)tuple.y; + for(int i = 2; i < length; i++) values[i] = 0.0; + + } + + /** + * Sets the value of this vector to the values in tuple + * @param tuple the source for the new GVector's new values + */ + public final void set(Tuple3f tuple) + { + if (length < 3) { + length = 3; + values = new double[3]; + } + values[0] = (double)tuple.x; + values[1] = (double)tuple.y; + values[2] = (double)tuple.z; + for(int i = 3; i < length; i++) values[i] = 0.0; + } + + /** + * Sets the value of this vector to the values in tuple + * @param tuple the source for the new GVector's new values + */ + public final void set(Tuple3d tuple) + { + if (length < 3) { + length = 3; + values = new double[3]; + } + values[0] = tuple.x; + values[1] = tuple.y; + values[2] = tuple.z; + for(int i = 3; i < length; i++) values[i] = 0.0; + } + + /** + * Sets the value of this vector to the values in tuple + * @param tuple the source for the new GVector's new values + */ + public final void set(Tuple4f tuple) + { + if (length < 4) { + length = 4; + values = new double[4]; + } + values[0] = (double)tuple.x; + values[1] = (double)tuple.y; + values[2] = (double)tuple.z; + values[3] = (double)tuple.w; + for(int i = 4; i < length; i++) values[i] = 0.0; + } + + /** + * Sets the value of this vector to the values in tuple + * @param tuple the source for the new GVector's new values + */ + public final void set(Tuple4d tuple) + { + if (length < 4) { + length = 4; + values = new double[4]; + } + values[0] = tuple.x; + values[1] = tuple.y; + values[2] = tuple.z; + values[3] = tuple.w; + for(int i = 4; i < length; i++) values[i] = 0.0; + } + + /** + * Returns the number of elements in this vector. + * @return number of elements in this vector + */ + public final int getSize() + { + return values.length; + } + + /** + * Retrieves the value at the specified index value of this vector. + * @param index the index of the element to retrieve (zero indexed) + * @return the value at the indexed element + */ + public final double getElement(int index) + { + return values[index]; + } + + + /** + * Modifies the value at the specified index of this vector. + * @param index the index if the element to modify (zero indexed) + * @param value the new vector element value + */ + public final void setElement(int index, double value) + { + values[index] = value; + } + + /** + * Returns a string that contains the values of this GVector. + * @return the String representation + */ + @Override + public String toString() { + StringBuffer buffer = new StringBuffer(length*8); + + int i; + + for(i=0;i<length;i++) { + buffer.append(values[i]).append(" "); + } + + return buffer.toString(); + + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different GVector objects with identical data + * values (i.e., GVector.equals returns true) will return the + * same hash number. Two GVector objects with different data + * members may return the same hash value, although this is not + * likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + + for (int i = 0; i < length; i++) { + bits = VecMathUtil.hashDoubleBits(bits, values[i]); + } + + return VecMathUtil.hashFinish(bits); + } + + + /** + * Returns true if all of the data members of GVector vector1 are + * equal to the corresponding data members in this GVector. + * @param vector1 The vector with which the comparison is made. + * @return true or false + */ + public boolean equals(GVector vector1) + { + try { + if( length != vector1.length) return false; + + for(int i = 0;i<length;i++) { + if( values[i] != vector1.values[i]) return false; + } + + return true; + } + catch (NullPointerException e2) { return false; } + + } + /** + * Returns true if the Object o1 is of type GMatrix and all of the + * data members of o1 are equal to the corresponding data members in + * this GMatrix. + * @param o1 The object with which the comparison is made. + * @return true or false + */ + @Override + public boolean equals(Object o1) + { + try { + GVector v2 = (GVector) o1; + + if( length != v2.length) return false; + + for(int i = 0;i<length;i++) { + if( values[i] != v2.values[i]) return false; + } + return true; + } + catch (ClassCastException e1) { return false; } + catch (NullPointerException e2) { return false; } + + } + + /** + * Returns true if the L-infinite distance between this vector + * and vector v1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), . . . ]. + * @param v1 The vector to be compared to this vector + * @param epsilon the threshold value + */ + public boolean epsilonEquals(GVector v1, double epsilon) + { + double diff; + + if( length != v1.length) return false; + + for(int i = 0;i<length;i++) { + diff = values[i] - v1.values[i]; + if( (diff<0?-diff:diff) > epsilon) return false; + } + return true; + } + + /** + * Returns the dot product of this vector and vector v1. + * @param v1 the other vector + * @return the dot product of this and v1 + */ + public final double dot(GVector v1) + { + if( length != v1.length) + throw new MismatchedSizeException(VecMathI18N.getString("GVector14")); + + double result = 0.0; + for(int i = 0;i<length;i++) { + result += values[i] * v1.values[i]; + } + return result; + } + + + /** + * Solves for x in Ax = b, where x is this vector (nx1), A is mxn, + * b is mx1, and A = U*W*transpose(V); U,W,V must + * be precomputed and can be found by taking the singular value + * decomposition (SVD) of A using the method SVD found in the + * GMatrix class. + * @param U The U matrix produced by the GMatrix method SVD + * @param W The W matrix produced by the GMatrix method SVD + * @param V The V matrix produced by the GMatrix method SVD + * @param b The b vector in the linear equation Ax = b + */ + public final void SVDBackSolve(GMatrix U, GMatrix W, GMatrix V, GVector b) + { + if( !(U.nRow == b.getSize() && + U.nRow == U.nCol && + U.nRow == W.nRow ) ) { + throw new MismatchedSizeException(VecMathI18N.getString("GVector15")); + } + + if( !(W.nCol == values.length && + W.nCol == V.nCol && + W.nCol == V.nRow ) ) { + throw new MismatchedSizeException(VecMathI18N.getString("GVector23")); + } + + GMatrix tmp = new GMatrix( U.nRow, W.nCol); + tmp.mul( U, V); + tmp.mulTransposeRight( U, W); + tmp.invert(); + mul(tmp, b); + + } + + /** + * LU Decomposition Back Solve; this method takes the LU matrix + * and the permutation vector produced by the GMatrix method LUD + * and solves the equation (LU)*x = b by placing the solution vector + * x into this vector. This vector should be the same length or + * longer than b. + * @param LU The matrix into which the lower and upper decompostions + * have been placed + * @param b The b vector in the equation (LU)*x = b + * @param permutation The row permuations that were necessary to + * produce the LU matrix parameter + */ + public final void LUDBackSolve(GMatrix LU, GVector b, GVector permutation) + { + int size = LU.nRow*LU.nCol; + + double[] temp = new double[size]; + double[] result = new double[size]; + int[] row_perm = new int[b.getSize()]; + int i,j; + + if( LU.nRow != b.getSize() ) { + throw new MismatchedSizeException(VecMathI18N.getString("GVector16")); + } + + if( LU.nRow != permutation.getSize() ) { + throw new MismatchedSizeException(VecMathI18N.getString("GVector24")); + } + + if (LU.nRow != LU.nCol) { + throw new MismatchedSizeException(VecMathI18N.getString("GVector25")); + } + + for(i=0;i<LU.nRow;i++) { + for(j=0;j<LU.nCol;j++) { + temp[i*LU.nCol+j] = LU.values[i][j]; + } + } + + for(i=0;i<size;i++) result[i] = 0.0; + for(i=0;i<LU.nRow;i++) result[i*LU.nCol] = b.values[i]; + for(i=0;i<LU.nCol;i++) row_perm[i] = (int)permutation.values[i]; + + GMatrix.luBacksubstitution(LU.nRow, temp, row_perm, result); + + for(i=0;i<LU.nRow;i++) this.values[i] = result[i*LU.nCol]; + } + + /** + * Returns the (n-space) angle in radians between this vector and + * the vector parameter; the return value is constrained to the + * range [0,PI]. + * @param v1 The other vector + * @return The angle in radians in the range [0,PI] + */ + public final double angle(GVector v1) + { + return( Math.acos( this.dot(v1) / ( this.norm()*v1.norm() ) ) ); + } + + + /** + * @deprecated Use interpolate(GVector, GVector, double) instead + */ + public final void interpolate(GVector v1, GVector v2, float alpha) { + interpolate(v1, v2, (double)alpha); + } + + + /** + * @deprecated Use interpolate(GVector, double) instead + */ + public final void interpolate(GVector v1, float alpha) { + interpolate(v1, (double)alpha); + } + + + /** + * Linearly interpolates between vectors v1 and v2 and places the + * result into this tuple: this = (1-alpha)*v1 + alpha*v2. + * @param v1 the first vector + * @param v2 the second vector + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(GVector v1, GVector v2, double alpha) + { + if( v2.length != v1.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector20")); + + if( length != v1.length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector21")); + + for(int i=0;i<length;i++) { + values[i] = (1-alpha)*v1.values[i] + alpha*v2.values[i]; + } + } + + /** + * Linearly interpolates between this vector and vector v1 and + * places the result into this tuple: this = (1-alpha)*this + alpha*v1. + * @param v1 the first vector + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(GVector v1, double alpha) + { + if( v1.length != length ) + throw new MismatchedSizeException(VecMathI18N.getString("GVector22")); + + for(int i=0;i<length;i++) { + values[i] = (1-alpha)*values[i] + alpha*v1.values[i]; + } + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + GVector v1 = null; + try { + v1 = (GVector)super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + + // Also need to clone array of values + v1.values = new double[length]; + for (int i = 0; i < length; i++) { + v1.values[i] = values[i]; + } + + return v1; + } + +} diff --git a/src/org/jogamp/vecmath/Matrix3d.java b/src/org/jogamp/vecmath/Matrix3d.java new file mode 100644 index 0000000..afd88f9 --- /dev/null +++ b/src/org/jogamp/vecmath/Matrix3d.java @@ -0,0 +1,3317 @@ +/* + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A double precision floating point 3 by 3 matrix. + * Primarily to support 3D rotations. + * + */ +public class Matrix3d implements java.io.Serializable, Cloneable { + + // Compatible with 1.1 + static final long serialVersionUID = 6837536777072402710L; + + /** + * The first matrix element in the first row. + */ + public double m00; + + /** + * The second matrix element in the first row. + */ + public double m01; + + /** + * The third matrix element in the first row. + */ + public double m02; + + /** + * The first matrix element in the second row. + */ + public double m10; + + /** + * The second matrix element in the second row. + */ + public double m11; + + /** + * The third matrix element in the second row. + */ + public double m12; + + /** + * The first matrix element in the third row. + */ + public double m20; + + /** + * The second matrix element in the third row. + */ + public double m21; + + /** + * The third matrix element in the third row. + */ + public double m22; + + //double[] tmp = new double[9]; // scratch matrix + //double[] tmp_rot = new double[9]; // scratch matrix + //double[] tmp_scale = new double[3]; // scratch matrix + private static final double EPS = 1.110223024E-16; + + /** + * Constructs and initializes a Matrix3d from the specified nine values. + * @param m00 the [0][0] element + * @param m01 the [0][1] element + * @param m02 the [0][2] element + * @param m10 the [1][0] element + * @param m11 the [1][1] element + * @param m12 the [1][2] element + * @param m20 the [2][0] element + * @param m21 the [2][1] element + * @param m22 the [2][2] element + */ + public Matrix3d(double m00, double m01, double m02, + double m10, double m11, double m12, + double m20, double m21, double m22) + { + this.m00 = m00; + this.m01 = m01; + this.m02 = m02; + + this.m10 = m10; + this.m11 = m11; + this.m12 = m12; + + this.m20 = m20; + this.m21 = m21; + this.m22 = m22; + + } + + /** + * Constructs and initializes a Matrix3d from the specified nine- + * element array. + * @param v the array of length 9 containing in order + */ + public Matrix3d(double[] v) + { + this.m00 = v[0]; + this.m01 = v[1]; + this.m02 = v[2]; + + this.m10 = v[3]; + this.m11 = v[4]; + this.m12 = v[5]; + + this.m20 = v[6]; + this.m21 = v[7]; + this.m22 = v[8]; + + } + + /** + * Constructs a new matrix with the same values as the + * Matrix3d parameter. + * @param m1 the source matrix + */ + public Matrix3d(Matrix3d m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + + } + + /** + * Constructs a new matrix with the same values as the + * Matrix3f parameter. + * @param m1 the source matrix + */ + public Matrix3d(Matrix3f m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + + } + + /** + * Constructs and initializes a Matrix3d to all zeros. + */ + public Matrix3d() + { + this.m00 = 0.0; + this.m01 = 0.0; + this.m02 = 0.0; + + this.m10 = 0.0; + this.m11 = 0.0; + this.m12 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = 0.0; + + } + + /** + * Returns a string that contains the values of this Matrix3d. + * @return the String representation + */ + @Override + public String toString() { + return + this.m00 + ", " + this.m01 + ", " + this.m02 + "\n" + + this.m10 + ", " + this.m11 + ", " + this.m12 + "\n" + + this.m20 + ", " + this.m21 + ", " + this.m22 + "\n"; + } + + /** + * Sets this Matrix3d to identity. + */ + public final void setIdentity() + { + this.m00 = 1.0; + this.m01 = 0.0; + this.m02 = 0.0; + + this.m10 = 0.0; + this.m11 = 1.0; + this.m12 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = 1.0; + } + + /** + * Sets the scale component of the current matrix by factoring + * out the current scale (by doing an SVD) and multiplying by + * the new scale. + * @param scale the new scale amount + */ + public final void setScale(double scale) + { + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate(tmp_scale, tmp_rot); + + this.m00 = tmp_rot[0] * scale; + this.m01 = tmp_rot[1] * scale; + this.m02 = tmp_rot[2] * scale; + + this.m10 = tmp_rot[3] * scale; + this.m11 = tmp_rot[4] * scale; + this.m12 = tmp_rot[5] * scale; + + this.m20 = tmp_rot[6] * scale; + this.m21 = tmp_rot[7] * scale; + this.m22 = tmp_rot[8] * scale; + } + + /** + * Sets the specified element of this matrix3f to the value provided. + * @param row the row number to be modified (zero indexed) + * @param column the column number to be modified (zero indexed) + * @param value the new value + */ + public final void setElement(int row, int column, double value) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + this.m00 = value; + break; + case 1: + this.m01 = value; + break; + case 2: + this.m02 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0")); + } + break; + + case 1: + switch(column) + { + case 0: + this.m10 = value; + break; + case 1: + this.m11 = value; + break; + case 2: + this.m12 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0")); + } + break; + + + case 2: + switch(column) + { + case 0: + this.m20 = value; + break; + case 1: + this.m21 = value; + break; + case 2: + this.m22 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0")); + } + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0")); + } + } + + /** + * Retrieves the value at the specified row and column of the specified + * matrix. + * @param row the row number to be retrieved (zero indexed) + * @param column the column number to be retrieved (zero indexed) + * @return the value at the indexed element. + */ + public final double getElement(int row, int column) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + return(this.m00); + case 1: + return(this.m01); + case 2: + return(this.m02); + default: + break; + } + break; + case 1: + switch(column) + { + case 0: + return(this.m10); + case 1: + return(this.m11); + case 2: + return(this.m12); + default: + break; + } + break; + + case 2: + switch(column) + { + case 0: + return(this.m20); + case 1: + return(this.m21); + case 2: + return(this.m22); + default: + break; + } + break; + + default: + break; + } + + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d1")); + } + + /** + * Copies the matrix values in the specified row into the vector parameter. + * @param row the matrix row + * @param v the vector into which the matrix row values will be copied + */ + public final void getRow(int row, Vector3d v) { + if( row == 0 ) { + v.x = m00; + v.y = m01; + v.z = m02; + } else if(row == 1) { + v.x = m10; + v.y = m11; + v.z = m12; + } else if(row == 2) { + v.x = m20; + v.y = m21; + v.z = m22; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d2")); + } + + } + + /** + * Copies the matrix values in the specified row into the array parameter. + * @param row the matrix row + * @param v the array into which the matrix row values will be copied + */ + public final void getRow(int row, double v[]) { + if( row == 0 ) { + v[0] = m00; + v[1] = m01; + v[2] = m02; + } else if(row == 1) { + v[0] = m10; + v[1] = m11; + v[2] = m12; + } else if(row == 2) { + v[0] = m20; + v[1] = m21; + v[2] = m22; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d2")); + } + + } + + /** + * Copies the matrix values in the specified column into the vector + * parameter. + * @param column the matrix column + * @param v the vector into which the matrix row values will be copied + */ + public final void getColumn(int column, Vector3d v) { + if( column == 0 ) { + v.x = m00; + v.y = m10; + v.z = m20; + } else if(column == 1) { + v.x = m01; + v.y = m11; + v.z = m21; + }else if(column == 2){ + v.x = m02; + v.y = m12; + v.z = m22; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d4")); + } + + } + + /** + * Copies the matrix values in the specified column into the array + * parameter. + * @param column the matrix column + * @param v the array into which the matrix row values will be copied + */ + public final void getColumn(int column, double v[]) { + if( column == 0 ) { + v[0] = m00; + v[1] = m10; + v[2] = m20; + } else if(column == 1) { + v[0] = m01; + v[1] = m11; + v[2] = m21; + }else if(column == 2) { + v[0] = m02; + v[1] = m12; + v[2] = m22; + }else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d4")); + } + + } + + + /** + * Sets the specified row of this matrix3d to the 4 values provided. + * @param row the row number to be modified (zero indexed) + * @param x the first column element + * @param y the second column element + * @param z the third column element + */ + public final void setRow(int row, double x, double y, double z) + { + switch (row) { + case 0: + this.m00 = x; + this.m01 = y; + this.m02 = z; + break; + + case 1: + this.m10 = x; + this.m11 = y; + this.m12 = z; + break; + + case 2: + this.m20 = x; + this.m21 = y; + this.m22 = z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6")); + } + } + + /** + * Sets the specified row of this matrix3d to the Vector provided. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, Vector3d v) + { + switch (row) { + case 0: + this.m00 = v.x; + this.m01 = v.y; + this.m02 = v.z; + break; + + case 1: + this.m10 = v.x; + this.m11 = v.y; + this.m12 = v.z; + break; + + case 2: + this.m20 = v.x; + this.m21 = v.y; + this.m22 = v.z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6")); + } + } + + /** + * Sets the specified row of this matrix3d to the three values provided. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, double v[]) + { + switch (row) { + case 0: + this.m00 = v[0]; + this.m01 = v[1]; + this.m02 = v[2]; + break; + + case 1: + this.m10 = v[0]; + this.m11 = v[1]; + this.m12 = v[2]; + break; + + case 2: + this.m20 = v[0]; + this.m21 = v[1]; + this.m22 = v[2]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6")); + } + } + + /** + * Sets the specified column of this matrix3d to the three values provided. + * @param column the column number to be modified (zero indexed) + * @param x the first row element + * @param y the second row element + * @param z the third row element + */ + public final void setColumn(int column, double x, double y, double z) + { + switch (column) { + case 0: + this.m00 = x; + this.m10 = y; + this.m20 = z; + break; + + case 1: + this.m01 = x; + this.m11 = y; + this.m21 = z; + break; + + case 2: + this.m02 = x; + this.m12 = y; + this.m22 = z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9")); + } + } + + /** + * Sets the specified column of this matrix3d to the vector provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, Vector3d v) + { + switch (column) { + case 0: + this.m00 = v.x; + this.m10 = v.y; + this.m20 = v.z; + break; + + case 1: + this.m01 = v.x; + this.m11 = v.y; + this.m21 = v.z; + break; + + case 2: + this.m02 = v.x; + this.m12 = v.y; + this.m22 = v.z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9")); + } + } + + /** + * Sets the specified column of this matrix3d to the three values provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, double v[]) + { + switch (column) { + case 0: + this.m00 = v[0]; + this.m10 = v[1]; + this.m20 = v[2]; + break; + + case 1: + this.m01 = v[0]; + this.m11 = v[1]; + this.m21 = v[2]; + break; + + case 2: + this.m02 = v[0]; + this.m12 = v[1]; + this.m22 = v[2]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9")); + } + } + + /** + * Performs an SVD normalization of this matrix to calculate + * and return the uniform scale factor. If the matrix has non-uniform + * scale factors, the largest of the x, y, and z scale factors will + * be returned. This matrix is not modified. + * @return the scale factor of this matrix + */ + public final double getScale() + { + + double[] tmp_scale = new double[3]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + getScaleRotate(tmp_scale, tmp_rot); + + return( max3(tmp_scale) ); + + } + + /** + * Adds a scalar to each component of this matrix. + * @param scalar the scalar adder + */ + public final void add(double scalar) + { + m00 += scalar; + m01 += scalar; + m02 += scalar; + + m10 += scalar; + m11 += scalar; + m12 += scalar; + + m20 += scalar; + m21 += scalar; + m22 += scalar; + + } + + /** + * Adds a scalar to each component of the matrix m1 and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar adder + * @param m1 the original matrix values + */ + public final void add(double scalar, Matrix3d m1) + { + this.m00 = m1.m00 + scalar; + this.m01 = m1.m01 + scalar; + this.m02 = m1.m02 + scalar; + + this.m10 = m1.m10 + scalar; + this.m11 = m1.m11 + scalar; + this.m12 = m1.m12 + scalar; + + this.m20 = m1.m20 + scalar; + this.m21 = m1.m21 + scalar; + this.m22 = m1.m22 + scalar; + } + + /** + * Sets the value of this matrix to the matrix sum of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void add(Matrix3d m1, Matrix3d m2) + { + this.m00 = m1.m00 + m2.m00; + this.m01 = m1.m01 + m2.m01; + this.m02 = m1.m02 + m2.m02; + + this.m10 = m1.m10 + m2.m10; + this.m11 = m1.m11 + m2.m11; + this.m12 = m1.m12 + m2.m12; + + this.m20 = m1.m20 + m2.m20; + this.m21 = m1.m21 + m2.m21; + this.m22 = m1.m22 + m2.m22; + } + + /** + * Sets the value of this matrix to the sum of itself and matrix m1. + * @param m1 the other matrix + */ + public final void add(Matrix3d m1) + { + this.m00 += m1.m00; + this.m01 += m1.m01; + this.m02 += m1.m02; + + this.m10 += m1.m10; + this.m11 += m1.m11; + this.m12 += m1.m12; + + this.m20 += m1.m20; + this.m21 += m1.m21; + this.m22 += m1.m22; + } + + /** + * Sets the value of this matrix to the matrix difference + * of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void sub(Matrix3d m1, Matrix3d m2) + { + this.m00 = m1.m00 - m2.m00; + this.m01 = m1.m01 - m2.m01; + this.m02 = m1.m02 - m2.m02; + + this.m10 = m1.m10 - m2.m10; + this.m11 = m1.m11 - m2.m11; + this.m12 = m1.m12 - m2.m12; + + this.m20 = m1.m20 - m2.m20; + this.m21 = m1.m21 - m2.m21; + this.m22 = m1.m22 - m2.m22; + } + + /** + * Sets the value of this matrix to the matrix difference of itself and + * matrix m1 (this = this - m1). + * @param m1 the other matrix + */ + public final void sub(Matrix3d m1) + { + this.m00 -= m1.m00; + this.m01 -= m1.m01; + this.m02 -= m1.m02; + + this.m10 -= m1.m10; + this.m11 -= m1.m11; + this.m12 -= m1.m12; + + this.m20 -= m1.m20; + this.m21 -= m1.m21; + this.m22 -= m1.m22; + } + + /** + * Sets the value of this matrix to its transpose. + */ + public final void transpose() + { + double temp; + + temp = this.m10; + this.m10 = this.m01; + this.m01 = temp; + + temp = this.m20; + this.m20 = this.m02; + this.m02 = temp; + + temp = this.m21; + this.m21 = this.m12; + this.m12 = temp; + } + + /** + * Sets the value of this matrix to the transpose of the argument matrix. + * @param m1 the matrix to be transposed + */ + public final void transpose(Matrix3d m1) + { + if (this != m1) { + this.m00 = m1.m00; + this.m01 = m1.m10; + this.m02 = m1.m20; + + this.m10 = m1.m01; + this.m11 = m1.m11; + this.m12 = m1.m21; + + this.m20 = m1.m02; + this.m21 = m1.m12; + this.m22 = m1.m22; + } else + this.transpose(); + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * double precision quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4d q1) + { + this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * double precision axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4d a1) + { + double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + + if( mag < EPS ) { + m00 = 1.0; + m01 = 0.0; + m02 = 0.0; + + m10 = 0.0; + m11 = 1.0; + m12 = 0.0; + + m20 = 0.0; + m21 = 0.0; + m22 = 1.0; + } else { + mag = 1.0/mag; + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + + double sinTheta = Math.sin(a1.angle); + double cosTheta = Math.cos(a1.angle); + double t = 1.0 - cosTheta; + + double xz = ax * az; + double xy = ax * ay; + double yz = ay * az; + + m00 = t * ax * ax + cosTheta; + m01 = t * xy - sinTheta * az; + m02 = t * xz + sinTheta * ay; + + m10 = t * xy + sinTheta * az; + m11 = t * ay * ay + cosTheta; + m12 = t * yz - sinTheta * ax; + + m20 = t * xz - sinTheta * ay; + m21 = t * yz + sinTheta * ax; + m22 = t * az * az + cosTheta; + } + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * single precision quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4f q1) + { + this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * single precision axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4f a1) + { + double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + if( mag < EPS ) { + m00 = 1.0; + m01 = 0.0; + m02 = 0.0; + + m10 = 0.0; + m11 = 1.0; + m12 = 0.0; + + m20 = 0.0; + m21 = 0.0; + m22 = 1.0; + } else { + mag = 1.0/mag; + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + double sinTheta = Math.sin(a1.angle); + double cosTheta = Math.cos(a1.angle); + double t = 1.0 - cosTheta; + + double xz = ax * az; + double xy = ax * ay; + double yz = ay * az; + + m00 = t * ax * ax + cosTheta; + m01 = t * xy - sinTheta * az; + m02 = t * xz + sinTheta * ay; + + m10 = t * xy + sinTheta * az; + m11 = t * ay * ay + cosTheta; + m12 = t * yz - sinTheta * ax; + + m20 = t * xz - sinTheta * ay; + m21 = t * yz + sinTheta * ax; + m22 = t * az * az + cosTheta; + } + } + + /** + * Sets the value of this matrix to the double value of the Matrix3f + * argument. + * @param m1 the matrix3d to be converted to double + */ + public final void set(Matrix3f m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + } + + /** + * Sets the value of this matrix to the value of the Matrix3d + * argument. + * @param m1 the source matrix3d + */ + public final void set(Matrix3d m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + } + + /** + * Sets the values in this Matrix3d equal to the row-major + * array parameter (ie, the first three elements of the + * array will be copied into the first row of this matrix, etc.). + * @param m the double precision array of length 9 + */ + public final void set(double[] m) + { + m00 = m[0]; + m01 = m[1]; + m02 = m[2]; + + m10 = m[3]; + m11 = m[4]; + m12 = m[5]; + + m20 = m[6]; + m21 = m[7]; + m22 = m[8]; + + } + + /** + * Sets the value of this matrix to the matrix inverse + * of the passed matrix m1. + * @param m1 the matrix to be inverted + */ + public final void invert(Matrix3d m1) + { + invertGeneral( m1 ); + } + + /** + * Inverts this matrix in place. + */ + public final void invert() + { + invertGeneral( this ); + } + + /** + * General invert routine. Inverts m1 and places the result in "this". + * Note that this routine handles both the "this" version and the + * non-"this" version. + * + * Also note that since this routine is slow anyway, we won't worry + * about allocating a little bit of garbage. + */ + private final void invertGeneral(Matrix3d m1) { + double result[] = new double[9]; + int row_perm[] = new int[3]; + int i; + double[] tmp = new double[9]; // scratch matrix + + // Use LU decomposition and backsubstitution code specifically + // for floating-point 3x3 matrices. + + // Copy source matrix to t1tmp + tmp[0] = m1.m00; + tmp[1] = m1.m01; + tmp[2] = m1.m02; + + tmp[3] = m1.m10; + tmp[4] = m1.m11; + tmp[5] = m1.m12; + + tmp[6] = m1.m20; + tmp[7] = m1.m21; + tmp[8] = m1.m22; + + + // Calculate LU decomposition: Is the matrix singular? + if (!luDecomposition(tmp, row_perm)) { + // Matrix has no inverse + throw new SingularMatrixException(VecMathI18N.getString("Matrix3d12")); + } + + // Perform back substitution on the identity matrix + for(i=0;i<9;i++) result[i] = 0.0; + result[0] = 1.0; result[4] = 1.0; result[8] = 1.0; + luBacksubstitution(tmp, row_perm, result); + + this.m00 = result[0]; + this.m01 = result[1]; + this.m02 = result[2]; + + this.m10 = result[3]; + this.m11 = result[4]; + this.m12 = result[5]; + + this.m20 = result[6]; + this.m21 = result[7]; + this.m22 = result[8]; + + } + + /** + * Given a 3x3 array "matrix0", this function replaces it with the + * LU decomposition of a row-wise permutation of itself. The input + * parameters are "matrix0" and "dimen". The array "matrix0" is also + * an output parameter. The vector "row_perm[3]" is an output + * parameter that contains the row permutations resulting from partial + * pivoting. The output parameter "even_row_xchg" is 1 when the + * number of row exchanges is even, or -1 otherwise. Assumes data + * type is always double. + * + * This function is similar to luDecomposition, except that it + * is tuned specifically for 3x3 matrices. + * + * @return true if the matrix is nonsingular, or false otherwise. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 40-45. + // + static boolean luDecomposition(double[] matrix0, + int[] row_perm) { + + double row_scale[] = new double[3]; + + // Determine implicit scaling information by looping over rows + { + int i, j; + int ptr, rs; + double big, temp; + + ptr = 0; + rs = 0; + + // For each row ... + i = 3; + while (i-- != 0) { + big = 0.0; + + // For each column, find the largest element in the row + j = 3; + while (j-- != 0) { + temp = matrix0[ptr++]; + temp = Math.abs(temp); + if (temp > big) { + big = temp; + } + } + + // Is the matrix singular? + if (big == 0.0) { + return false; + } + row_scale[rs++] = 1.0 / big; + } + } + + { + int j; + int mtx; + + mtx = 0; + + // For all columns, execute Crout's method + for (j = 0; j < 3; j++) { + int i, imax, k; + int target, p1, p2; + double sum, big, temp; + + // Determine elements of upper diagonal matrix U + for (i = 0; i < j; i++) { + target = mtx + (3*i) + j; + sum = matrix0[target]; + k = i; + p1 = mtx + (3*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 3; + } + matrix0[target] = sum; + } + + // Search for largest pivot element and calculate + // intermediate elements of lower diagonal matrix L. + big = 0.0; + imax = -1; + for (i = j; i < 3; i++) { + target = mtx + (3*i) + j; + sum = matrix0[target]; + k = j; + p1 = mtx + (3*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 3; + } + matrix0[target] = sum; + + // Is this the best pivot so far? + if ((temp = row_scale[i] * Math.abs(sum)) >= big) { + big = temp; + imax = i; + } + } + + if (imax < 0) { + throw new RuntimeException(VecMathI18N.getString("Matrix3d13")); + } + + // Is a row exchange necessary? + if (j != imax) { + // Yes: exchange rows + k = 3; + p1 = mtx + (3*imax); + p2 = mtx + (3*j); + while (k-- != 0) { + temp = matrix0[p1]; + matrix0[p1++] = matrix0[p2]; + matrix0[p2++] = temp; + } + + // Record change in scale factor + row_scale[imax] = row_scale[j]; + } + + // Record row permutation + row_perm[j] = imax; + + // Is the matrix singular + if (matrix0[(mtx + (3*j) + j)] == 0.0) { + return false; + } + + // Divide elements of lower diagonal matrix L by pivot + if (j != (3-1)) { + temp = 1.0 / (matrix0[(mtx + (3*j) + j)]); + target = mtx + (3*(j+1)) + j; + i = 2 - j; + while (i-- != 0) { + matrix0[target] *= temp; + target += 3; + } + } + } + } + + return true; + } + + /** + * Solves a set of linear equations. The input parameters "matrix1", + * and "row_perm" come from luDecompostionD3x3 and do not change + * here. The parameter "matrix2" is a set of column vectors assembled + * into a 3x3 matrix of floating-point values. The procedure takes each + * column of "matrix2" in turn and treats it as the right-hand side of the + * matrix equation Ax = LUx = b. The solution vector replaces the + * original column of the matrix. + * + * If "matrix2" is the identity matrix, the procedure replaces its contents + * with the inverse of the matrix from which "matrix1" was originally + * derived. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 44-45. + // + static void luBacksubstitution(double[] matrix1, + int[] row_perm, + double[] matrix2) { + + int i, ii, ip, j, k; + int rp; + int cv, rv; + + // rp = row_perm; + rp = 0; + + // For each column vector of matrix2 ... + for (k = 0; k < 3; k++) { + // cv = &(matrix2[0][k]); + cv = k; + ii = -1; + + // Forward substitution + for (i = 0; i < 3; i++) { + double sum; + + ip = row_perm[rp+i]; + sum = matrix2[cv+3*ip]; + matrix2[cv+3*ip] = matrix2[cv+3*i]; + if (ii >= 0) { + // rv = &(matrix1[i][0]); + rv = i*3; + for (j = ii; j <= i-1; j++) { + sum -= matrix1[rv+j] * matrix2[cv+3*j]; + } + } + else if (sum != 0.0) { + ii = i; + } + matrix2[cv+3*i] = sum; + } + + // Backsubstitution + // rv = &(matrix1[3][0]); + rv = 2*3; + matrix2[cv+3*2] /= matrix1[rv+2]; + + rv -= 3; + matrix2[cv+3*1] = (matrix2[cv+3*1] - + matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+1]; + + rv -= 3; + matrix2[cv+4*0] = (matrix2[cv+3*0] - + matrix1[rv+1] * matrix2[cv+3*1] - + matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+0]; + + } + } + + /** + * Computes the determinant of this matrix. + * @return the determinant of the matrix + */ + public final double determinant() + { + double total; + + total = this.m00*(this.m11*this.m22 - this.m12*this.m21) + + this.m01*(this.m12*this.m20 - this.m10*this.m22) + + this.m02*(this.m10*this.m21 - this.m11*this.m20); + return total; + } + + /** + * Sets the value of this matrix to a scale matrix with + * the passed scale amount. + * @param scale the scale factor for the matrix + */ + public final void set(double scale) + { + this.m00 = scale; + this.m01 = 0.0; + this.m02 = 0.0; + + this.m10 = 0.0; + this.m11 = scale; + this.m12 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = scale; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the x axis. + * @param angle the angle to rotate about the X axis in radians + */ + public final void rotX(double angle) + { + double sinAngle, cosAngle; + + sinAngle = Math.sin(angle); + cosAngle = Math.cos(angle); + + this.m00 = 1.0; + this.m01 = 0.0; + this.m02 = 0.0; + + this.m10 = 0.0; + this.m11 = cosAngle; + this.m12 = -sinAngle; + + this.m20 = 0.0; + this.m21 = sinAngle; + this.m22 = cosAngle; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the y axis. + * @param angle the angle to rotate about the Y axis in radians + */ + public final void rotY(double angle) + { + double sinAngle, cosAngle; + + sinAngle = Math.sin(angle); + cosAngle = Math.cos(angle); + + this.m00 = cosAngle; + this.m01 = 0.0; + this.m02 = sinAngle; + + this.m10 = 0.0; + this.m11 = 1.0; + this.m12 = 0.0; + + this.m20 = -sinAngle; + this.m21 = 0.0; + this.m22 = cosAngle; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the z axis. + * @param angle the angle to rotate about the Z axis in radians + */ + public final void rotZ(double angle) + { + double sinAngle, cosAngle; + + sinAngle = Math.sin(angle); + cosAngle = Math.cos(angle); + + this.m00 = cosAngle; + this.m01 = -sinAngle; + this.m02 = 0.0; + + this.m10 = sinAngle; + this.m11 = cosAngle; + this.m12 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = 1.0; + } + + /** + * Multiplies each element of this matrix by a scalar. + * @param scalar The scalar multiplier. + */ + public final void mul(double scalar) + { + m00 *= scalar; + m01 *= scalar; + m02 *= scalar; + + m10 *= scalar; + m11 *= scalar; + m12 *= scalar; + + m20 *= scalar; + m21 *= scalar; + m22 *= scalar; + + } + + /** + * Multiplies each element of matrix m1 by a scalar and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar multiplier + * @param m1 the original matrix + */ + public final void mul(double scalar, Matrix3d m1) + { + this.m00 = scalar * m1.m00; + this.m01 = scalar * m1.m01; + this.m02 = scalar * m1.m02; + + this.m10 = scalar * m1.m10; + this.m11 = scalar * m1.m11; + this.m12 = scalar * m1.m12; + + this.m20 = scalar * m1.m20; + this.m21 = scalar * m1.m21; + this.m22 = scalar * m1.m22; + + } + + /** + * Sets the value of this matrix to the result of multiplying itself + * with matrix m1. + * @param m1 the other matrix + */ + public final void mul(Matrix3d m1) + { + double m00, m01, m02, + m10, m11, m12, + m20, m21, m22; + + m00 = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20; + m01 = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21; + m02 = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22; + + m10 = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20; + m11 = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21; + m12 = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22; + + m20 = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20; + m21 = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21; + m22 = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + + /** + * Sets the value of this matrix to the result of multiplying + * the two argument matrices together. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void mul(Matrix3d m1, Matrix3d m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20; + this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21; + this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20; + this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; + this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20; + this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; + this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; + } else { + double m00, m01, m02, + m10, m11, m12, + m20, m21, m22; // vars for temp result matrix + + m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20; + m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21; + m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20; + m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; + m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20; + m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; + m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + } + + /** + * Multiplies this matrix by matrix m1, does an SVD normalization + * of the result, and places the result back into this matrix + * this = SVDnorm(this*m1). + * @param m1 the matrix on the right hand side of the multiplication + */ + public final void mulNormalize(Matrix3d m1){ + + double[] tmp = new double[9]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + tmp[0] = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20; + tmp[1] = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21; + tmp[2] = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22; + + tmp[3] = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20; + tmp[4] = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21; + tmp[5] = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22; + + tmp[6] = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20; + tmp[7] = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21; + tmp[8] = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22; + + compute_svd( tmp, tmp_scale, tmp_rot); + + this.m00 = tmp_rot[0]; + this.m01 = tmp_rot[1]; + this.m02 = tmp_rot[2]; + + this.m10 = tmp_rot[3]; + this.m11 = tmp_rot[4]; + this.m12 = tmp_rot[5]; + + this.m20 = tmp_rot[6]; + this.m21 = tmp_rot[7]; + this.m22 = tmp_rot[8]; + + } + + + /** + * Multiplies matrix m1 by matrix m2, does an SVD normalization + * of the result, and places the result into this matrix + * this = SVDnorm(m1*m2). + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulNormalize(Matrix3d m1, Matrix3d m2){ + + double[] tmp = new double[9]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + tmp[0] = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20; + tmp[1] = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21; + tmp[2] = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22; + + tmp[3] = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20; + tmp[4] = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; + tmp[5] = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; + + tmp[6] = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20; + tmp[7] = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; + tmp[8] = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; + + compute_svd( tmp, tmp_scale, tmp_rot); + + this.m00 = tmp_rot[0]; + this.m01 = tmp_rot[1]; + this.m02 = tmp_rot[2]; + + this.m10 = tmp_rot[3]; + this.m11 = tmp_rot[4]; + this.m12 = tmp_rot[5]; + + this.m20 = tmp_rot[6]; + this.m21 = tmp_rot[7]; + this.m22 = tmp_rot[8]; + + } + + /** + * Multiplies the transpose of matrix m1 times the transpose of matrix + * m2, and places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeBoth(Matrix3d m1, Matrix3d m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02; + this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12; + this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02; + this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12; + this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02; + this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12; + this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22; + } else { + double m00, m01, m02, + m10, m11, m12, + m20, m21, m22; // vars for temp result matrix + + m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02; + m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12; + m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02; + m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12; + m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02; + m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12; + m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + + } + + /** + * Multiplies matrix m1 times the transpose of matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeRight(Matrix3d m1, Matrix3d m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02; + this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12; + this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02; + this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12; + this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02; + this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12; + this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22; + } else { + double m00, m01, m02, + m10, m11, m12, + m20, m21, m22; // vars for temp result matrix + + m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02; + m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12; + m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02; + m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12; + m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02; + m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12; + m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + } + + + /** + * Multiplies the transpose of matrix m1 times matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeLeft(Matrix3d m1, Matrix3d m2) { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20; + this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21; + this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20; + this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21; + this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20; + this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21; + this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22; + } else { + double m00, m01, m02, + m10, m11, m12, + m20, m21, m22; // vars for temp result matrix + + m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20; + m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21; + m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20; + m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21; + m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20; + m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21; + m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + } + + + + /** + * Performs singular value decomposition normalization of this matrix. + */ + public final void normalize(){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + this.m00 = tmp_rot[0]; + this.m01 = tmp_rot[1]; + this.m02 = tmp_rot[2]; + + this.m10 = tmp_rot[3]; + this.m11 = tmp_rot[4]; + this.m12 = tmp_rot[5]; + + this.m20 = tmp_rot[6]; + this.m21 = tmp_rot[7]; + this.m22 = tmp_rot[8]; + + } + + + /** + * Perform singular value decomposition normalization of matrix m1 and + * place the normalized values into this. + * @param m1 Provides the matrix values to be normalized + */ + public final void normalize(Matrix3d m1){ + + double[] tmp = new double[9]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + tmp[0] = m1.m00; + tmp[1] = m1.m01; + tmp[2] = m1.m02; + + tmp[3] = m1.m10; + tmp[4] = m1.m11; + tmp[5] = m1.m12; + + tmp[6] = m1.m20; + tmp[7] = m1.m21; + tmp[8] = m1.m22; + + compute_svd( tmp, tmp_scale, tmp_rot); + + this.m00 = tmp_rot[0]; + this.m01 = tmp_rot[1]; + this.m02 = tmp_rot[2]; + + this.m10 = tmp_rot[3]; + this.m11 = tmp_rot[4]; + this.m12 = tmp_rot[5]; + + this.m20 = tmp_rot[6]; + this.m21 = tmp_rot[7]; + this.m22 = tmp_rot[8]; + } + + + /** + * Perform cross product normalization of this matrix. + */ + + public final void normalizeCP() + { + double mag = 1.0/Math.sqrt(m00*m00 + m10*m10 + m20*m20); + m00 = m00*mag; + m10 = m10*mag; + m20 = m20*mag; + + mag = 1.0/Math.sqrt(m01*m01 + m11*m11 + m21*m21); + m01 = m01*mag; + m11 = m11*mag; + m21 = m21*mag; + + m02 = m10*m21 - m11*m20; + m12 = m01*m20 - m00*m21; + m22 = m00*m11 - m01*m10; + } + + + /** + * Perform cross product normalization of matrix m1 and place the + * normalized values into this. + * @param m1 Provides the matrix values to be normalized + */ + public final void normalizeCP(Matrix3d m1) + { + double mag = 1.0/Math.sqrt(m1.m00*m1.m00 + m1.m10*m1.m10 + m1.m20*m1.m20); + m00 = m1.m00*mag; + m10 = m1.m10*mag; + m20 = m1.m20*mag; + + mag = 1.0/Math.sqrt(m1.m01*m1.m01 + m1.m11*m1.m11 + m1.m21*m1.m21); + m01 = m1.m01*mag; + m11 = m1.m11*mag; + m21 = m1.m21*mag; + + m02 = m10*m21 - m11*m20; + m12 = m01*m20 - m00*m21; + m22 = m00*m11 - m01*m10; + } + + /** + * Returns true if all of the data members of Matrix3d m1 are + * equal to the corresponding data members in this Matrix3d. + * @param m1 the matrix with which the comparison is made + * @return true or false + */ + public boolean equals(Matrix3d m1) + { + try { + return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02 + && this.m10 == m1.m10 && this.m11 == m1.m11 && this.m12 == m1.m12 + && this.m20 == m1.m20 && this.m21 == m1.m21 && this.m22 == m1.m22); + } + catch (NullPointerException e2) { return false; } + + } + + /** + * Returns true if the Object t1 is of type Matrix3d and all of the + * data members of t1 are equal to the corresponding data members in + * this Matrix3d. + * @param t1 the matrix with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Matrix3d m2 = (Matrix3d) t1; + return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02 + && this.m10 == m2.m10 && this.m11 == m2.m11 && this.m12 == m2.m12 + && this.m20 == m2.m20 && this.m21 == m2.m21 && this.m22 == m2.m22); + } + catch (ClassCastException e1) { return false; } + catch (NullPointerException e2) { return false; } + + } + + /** + * Returns true if the L-infinite distance between this matrix + * and matrix m1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[i=0,1,2 ; j=0,1,2 ; abs(this.m(i,j) - m1.m(i,j)] + * @param m1 the matrix to be compared to this matrix + * @param epsilon the threshold value + */ + public boolean epsilonEquals(Matrix3d m1, double epsilon) + { + double diff; + + diff = m00 - m1.m00; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m01 - m1.m01; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m02 - m1.m02; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m10 - m1.m10; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m11 - m1.m11; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m12 - m1.m12; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m20 - m1.m20; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m21 - m1.m21; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m22 - m1.m22; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Matrix3d objects with identical data values + * (i.e., Matrix3d.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashDoubleBits(bits, m00); + bits = VecMathUtil.hashDoubleBits(bits, m01); + bits = VecMathUtil.hashDoubleBits(bits, m02); + bits = VecMathUtil.hashDoubleBits(bits, m10); + bits = VecMathUtil.hashDoubleBits(bits, m11); + bits = VecMathUtil.hashDoubleBits(bits, m12); + bits = VecMathUtil.hashDoubleBits(bits, m20); + bits = VecMathUtil.hashDoubleBits(bits, m21); + bits = VecMathUtil.hashDoubleBits(bits, m22); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Sets this matrix to all zeros. + */ + public final void setZero() + { + m00 = 0.0; + m01 = 0.0; + m02 = 0.0; + + m10 = 0.0; + m11 = 0.0; + m12 = 0.0; + + m20 = 0.0; + m21 = 0.0; + m22 = 0.0; + + } + + /** + * Negates the value of this matrix: this = -this. + */ + public final void negate() + { + this.m00 = -this.m00; + this.m01 = -this.m01; + this.m02 = -this.m02; + + this.m10 = -this.m10; + this.m11 = -this.m11; + this.m12 = -this.m12; + + this.m20 = -this.m20; + this.m21 = -this.m21; + this.m22 = -this.m22; + + } + + /** + * Sets the value of this matrix equal to the negation of + * of the Matrix3d parameter. + * @param m1 the source matrix + */ + public final void negate(Matrix3d m1) + { + this.m00 = -m1.m00; + this.m01 = -m1.m01; + this.m02 = -m1.m02; + + this.m10 = -m1.m10; + this.m11 = -m1.m11; + this.m12 = -m1.m12; + + this.m20 = -m1.m20; + this.m21 = -m1.m21; + this.m22 = -m1.m22; + + } + + /** + * Multiply this matrix by the tuple t and place the result + * back into the tuple (t = this*t). + * @param t the tuple to be multiplied by this matrix and then replaced + */ + public final void transform(Tuple3d t) { + double x,y,z; + x = m00* t.x + m01*t.y + m02*t.z; + y = m10* t.x + m11*t.y + m12*t.z; + z = m20* t.x + m21*t.y + m22*t.z; + t.set(x,y,z); + } + + /** + * Multiply this matrix by the tuple t and and place the result + * into the tuple "result" (result = this*t). + * @param t the tuple to be multiplied by this matrix + * @param result the tuple into which the product is placed + */ + public final void transform(Tuple3d t, Tuple3d result) { + double x,y,z; + x = m00* t.x + m01*t.y + m02*t.z; + y = m10* t.x + m11*t.y + m12*t.z; + result.z = m20* t.x + m21*t.y + m22*t.z; + result.x = x; + result.y = y; + } + + /** + * perform SVD (if necessary to get rotational component + */ + final void getScaleRotate(double scales[], double rots[]) { + + double[] tmp = new double[9]; // scratch matrix + + tmp[0] = m00; + tmp[1] = m01; + tmp[2] = m02; + + tmp[3] = m10; + tmp[4] = m11; + tmp[5] = m12; + + tmp[6] = m20; + tmp[7] = m21; + tmp[8] = m22; + compute_svd( tmp, scales, rots); + + return; + } + + static void compute_svd( double[] m, double[] outScale, double[] outRot) { + int i,j; + double g,scale; + double[] u1 = new double[9]; + double[] v1 = new double[9]; + double[] t1 = new double[9]; + double[] t2 = new double[9]; + + double[] tmp = t1; + double[] single_values = t2; + + double[] rot = new double[9]; + double[] e = new double[3]; + double[] scales = new double[3]; + + int converged, negCnt=0; + double cs,sn; + double c1,c2,c3,c4; + double s1,s2,s3,s4; + double cl1,cl2,cl3; + + + for(i=0; i<9; i++) + rot[i] = m[i]; + + // u1 + + if( m[3]*m[3] < EPS ) { + u1[0] = 1.0; u1[1] = 0.0; u1[2] = 0.0; + u1[3] = 0.0; u1[4] = 1.0; u1[5] = 0.0; + u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0; + } else if( m[0]*m[0] < EPS ) { + tmp[0] = m[0]; + tmp[1] = m[1]; + tmp[2] = m[2]; + m[0] = m[3]; + m[1] = m[4]; + m[2] = m[5]; + + m[3] = -tmp[0]; // zero + m[4] = -tmp[1]; + m[5] = -tmp[2]; + + u1[0] = 0.0; u1[1] = 1.0; u1[2] = 0.0; + u1[3] = -1.0; u1[4] = 0.0; u1[5] = 0.0; + u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0; + } else { + g = 1.0/Math.sqrt(m[0]*m[0] + m[3]*m[3]); + c1 = m[0]*g; + s1 = m[3]*g; + tmp[0] = c1*m[0] + s1*m[3]; + tmp[1] = c1*m[1] + s1*m[4]; + tmp[2] = c1*m[2] + s1*m[5]; + + m[3] = -s1*m[0] + c1*m[3]; // zero + m[4] = -s1*m[1] + c1*m[4]; + m[5] = -s1*m[2] + c1*m[5]; + + m[0] = tmp[0]; + m[1] = tmp[1]; + m[2] = tmp[2]; + u1[0] = c1; u1[1] = s1; u1[2] = 0.0; + u1[3] = -s1; u1[4] = c1; u1[5] = 0.0; + u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0; + } + + // u2 + + if( m[6]*m[6] < EPS ) { + } else if( m[0]*m[0] < EPS ){ + tmp[0] = m[0]; + tmp[1] = m[1]; + tmp[2] = m[2]; + m[0] = m[6]; + m[1] = m[7]; + m[2] = m[8]; + + m[6] = -tmp[0]; // zero + m[7] = -tmp[1]; + m[8] = -tmp[2]; + + tmp[0] = u1[0]; + tmp[1] = u1[1]; + tmp[2] = u1[2]; + u1[0] = u1[6]; + u1[1] = u1[7]; + u1[2] = u1[8]; + + u1[6] = -tmp[0]; // zero + u1[7] = -tmp[1]; + u1[8] = -tmp[2]; + } else { + g = 1.0/Math.sqrt(m[0]*m[0] + m[6]*m[6]); + c2 = m[0]*g; + s2 = m[6]*g; + tmp[0] = c2*m[0] + s2*m[6]; + tmp[1] = c2*m[1] + s2*m[7]; + tmp[2] = c2*m[2] + s2*m[8]; + + m[6] = -s2*m[0] + c2*m[6]; + m[7] = -s2*m[1] + c2*m[7]; + m[8] = -s2*m[2] + c2*m[8]; + m[0] = tmp[0]; + m[1] = tmp[1]; + m[2] = tmp[2]; + + tmp[0] = c2*u1[0]; + tmp[1] = c2*u1[1]; + u1[2] = s2; + + tmp[6] = -u1[0]*s2; + tmp[7] = -u1[1]*s2; + u1[8] = c2; + u1[0] = tmp[0]; + u1[1] = tmp[1]; + u1[6] = tmp[6]; + u1[7] = tmp[7]; + } + + // v1 + + if( m[2]*m[2] < EPS ) { + v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0; + v1[3] = 0.0; v1[4] = 1.0; v1[5] = 0.0; + v1[6] = 0.0; v1[7] = 0.0; v1[8] = 1.0; + } else if( m[1]*m[1] < EPS ) { + tmp[2] = m[2]; + tmp[5] = m[5]; + tmp[8] = m[8]; + m[2] = -m[1]; + m[5] = -m[4]; + m[8] = -m[7]; + + m[1] = tmp[2]; // zero + m[4] = tmp[5]; + m[7] = tmp[8]; + + v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0; + v1[3] = 0.0; v1[4] = 0.0; v1[5] =-1.0; + v1[6] = 0.0; v1[7] = 1.0; v1[8] = 0.0; + } else { + g = 1.0/Math.sqrt(m[1]*m[1] + m[2]*m[2]); + c3 = m[1]*g; + s3 = m[2]*g; + tmp[1] = c3*m[1] + s3*m[2]; // can assign to m[1]? + m[2] =-s3*m[1] + c3*m[2]; // zero + m[1] = tmp[1]; + + tmp[4] = c3*m[4] + s3*m[5]; + m[5] =-s3*m[4] + c3*m[5]; + m[4] = tmp[4]; + + tmp[7] = c3*m[7] + s3*m[8]; + m[8] =-s3*m[7] + c3*m[8]; + m[7] = tmp[7]; + + v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0; + v1[3] = 0.0; v1[4] = c3; v1[5] = -s3; + v1[6] = 0.0; v1[7] = s3; v1[8] = c3; + } + + // u3 + + if( m[7]*m[7] < EPS ) { + } else if( m[4]*m[4] < EPS ) { + tmp[3] = m[3]; + tmp[4] = m[4]; + tmp[5] = m[5]; + m[3] = m[6]; // zero + m[4] = m[7]; + m[5] = m[8]; + + m[6] = -tmp[3]; // zero + m[7] = -tmp[4]; // zero + m[8] = -tmp[5]; + + tmp[3] = u1[3]; + tmp[4] = u1[4]; + tmp[5] = u1[5]; + u1[3] = u1[6]; + u1[4] = u1[7]; + u1[5] = u1[8]; + + u1[6] = -tmp[3]; // zero + u1[7] = -tmp[4]; + u1[8] = -tmp[5]; + + } else { + g = 1.0/Math.sqrt(m[4]*m[4] + m[7]*m[7]); + c4 = m[4]*g; + s4 = m[7]*g; + tmp[3] = c4*m[3] + s4*m[6]; + m[6] =-s4*m[3] + c4*m[6]; // zero + m[3] = tmp[3]; + + tmp[4] = c4*m[4] + s4*m[7]; + m[7] =-s4*m[4] + c4*m[7]; + m[4] = tmp[4]; + + tmp[5] = c4*m[5] + s4*m[8]; + m[8] =-s4*m[5] + c4*m[8]; + m[5] = tmp[5]; + + tmp[3] = c4*u1[3] + s4*u1[6]; + u1[6] =-s4*u1[3] + c4*u1[6]; + u1[3] = tmp[3]; + + tmp[4] = c4*u1[4] + s4*u1[7]; + u1[7] =-s4*u1[4] + c4*u1[7]; + u1[4] = tmp[4]; + + tmp[5] = c4*u1[5] + s4*u1[8]; + u1[8] =-s4*u1[5] + c4*u1[8]; + u1[5] = tmp[5]; + } + + single_values[0] = m[0]; + single_values[1] = m[4]; + single_values[2] = m[8]; + e[0] = m[1]; + e[1] = m[5]; + + if( e[0]*e[0]<EPS && e[1]*e[1]<EPS ) { + + } else { + compute_qr( single_values, e, u1, v1); + } + + scales[0] = single_values[0]; + scales[1] = single_values[1]; + scales[2] = single_values[2]; + + + // Do some optimization here. If scale is unity, simply return the rotation matric. + if(almostEqual(Math.abs(scales[0]), 1.0) && + almostEqual(Math.abs(scales[1]), 1.0) && + almostEqual(Math.abs(scales[2]), 1.0)) { + // System.out.println("Scale components almost to 1.0"); + + for(i=0;i<3;i++) + if(scales[i]<0.0) + negCnt++; + + if((negCnt==0)||(negCnt==2)) { + //System.out.println("Optimize!!"); + outScale[0] = outScale[1] = outScale[2] = 1.0; + for(i=0;i<9;i++) + outRot[i] = rot[i]; + + return; + } + } + + + transpose_mat(u1, t1); + transpose_mat(v1, t2); + + /* + System.out.println("t1 is \n" + t1); + System.out.println("t1="+t1[0]+" "+t1[1]+" "+t1[2]); + System.out.println("t1="+t1[3]+" "+t1[4]+" "+t1[5]); + System.out.println("t1="+t1[6]+" "+t1[7]+" "+t1[8]); + + System.out.println("t2 is \n" + t2); + System.out.println("t2="+t2[0]+" "+t2[1]+" "+t2[2]); + System.out.println("t2="+t2[3]+" "+t2[4]+" "+t2[5]); + System.out.println("t2="+t2[6]+" "+t2[7]+" "+t2[8]); + */ + + svdReorder( m, t1, t2, scales, outRot, outScale); + + } + + static void svdReorder( double[] m, double[] t1, double[] t2, double[] scales, + double[] outRot, double[] outScale) { + + int[] out = new int[3]; + int[] in = new int[3]; + int in0, in1, in2, index, i; + double[] mag = new double[3]; + double[] rot = new double[9]; + + + // check for rotation information in the scales + if(scales[0] < 0.0 ) { // move the rotation info to rotation matrix + scales[0] = -scales[0]; + t2[0] = -t2[0]; + t2[1] = -t2[1]; + t2[2] = -t2[2]; + } + if(scales[1] < 0.0 ) { // move the rotation info to rotation matrix + scales[1] = -scales[1]; + t2[3] = -t2[3]; + t2[4] = -t2[4]; + t2[5] = -t2[5]; + } + if(scales[2] < 0.0 ) { // move the rotation info to rotation matrix + scales[2] = -scales[2]; + t2[6] = -t2[6]; + t2[7] = -t2[7]; + t2[8] = -t2[8]; + } + + mat_mul(t1,t2,rot); + + // check for equal scales case and do not reorder + if(almostEqual(Math.abs(scales[0]), Math.abs(scales[1])) && + almostEqual(Math.abs(scales[1]), Math.abs(scales[2])) ){ + for(i=0;i<9;i++){ + outRot[i] = rot[i]; + } + for(i=0;i<3;i++){ + outScale[i] = scales[i]; + } + + }else { + + // sort the order of the results of SVD + if( scales[0] > scales[1]) { + if( scales[0] > scales[2] ) { + if( scales[2] > scales[1] ) { + out[0] = 0; out[1] = 2; out[2] = 1; // xzy + } else { + out[0] = 0; out[1] = 1; out[2] = 2; // xyz + } + } else { + out[0] = 2; out[1] = 0; out[2] = 1; // zxy + } + } else { // y > x + if( scales[1] > scales[2] ) { + if( scales[2] > scales[0] ) { + out[0] = 1; out[1] = 2; out[2] = 0; // yzx + } else { + out[0] = 1; out[1] = 0; out[2] = 2; // yxz + } + } else { + out[0] = 2; out[1] = 1; out[2] = 0; // zyx + } + } + + /* + System.out.println("\nscales="+scales[0]+" "+scales[1]+" "+scales[2]); + System.out.println("\nrot="+rot[0]+" "+rot[1]+" "+rot[2]); + System.out.println("rot="+rot[3]+" "+rot[4]+" "+rot[5]); + System.out.println("rot="+rot[6]+" "+rot[7]+" "+rot[8]); + */ + + // sort the order of the input matrix + mag[0] = (m[0]*m[0] + m[1]*m[1] + m[2]*m[2]); + mag[1] = (m[3]*m[3] + m[4]*m[4] + m[5]*m[5]); + mag[2] = (m[6]*m[6] + m[7]*m[7] + m[8]*m[8]); + + if( mag[0] > mag[1]) { + if( mag[0] > mag[2] ) { + if( mag[2] > mag[1] ) { + // 0 - 2 - 1 + in0 = 0; in2 = 1; in1 = 2;// xzy + } else { + // 0 - 1 - 2 + in0 = 0; in1 = 1; in2 = 2; // xyz + } + } else { + // 2 - 0 - 1 + in2 = 0; in0 = 1; in1 = 2; // zxy + } + } else { // y > x 1>0 + if( mag[1] > mag[2] ) { + if( mag[2] > mag[0] ) { + // 1 - 2 - 0 + in1 = 0; in2 = 1; in0 = 2; // yzx + } else { + // 1 - 0 - 2 + in1 = 0; in0 = 1; in2 = 2; // yxz + } + } else { + // 2 - 1 - 0 + in2 = 0; in1 = 1; in0 = 2; // zyx + } + } + + + index = out[in0]; + outScale[0] = scales[index]; + + index = out[in1]; + outScale[1] = scales[index]; + + index = out[in2]; + outScale[2] = scales[index]; + + + index = out[in0]; + outRot[0] = rot[index]; + + index = out[in0]+3; + outRot[0+3] = rot[index]; + + index = out[in0]+6; + outRot[0+6] = rot[index]; + + index = out[in1]; + outRot[1] = rot[index]; + + index = out[in1]+3; + outRot[1+3] = rot[index]; + + index = out[in1]+6; + outRot[1+6] = rot[index]; + + index = out[in2]; + outRot[2] = rot[index]; + + index = out[in2]+3; + outRot[2+3] = rot[index]; + + index = out[in2]+6; + outRot[2+6] = rot[index]; + } + } + + static int compute_qr( double[] s, double[] e, double[] u, double[] v) { + + int i,j,k; + boolean converged; + double shift,ssmin,ssmax,r; + double[] cosl = new double[2]; + double[] cosr = new double[2]; + double[] sinl = new double[2]; + double[] sinr = new double[2]; + double[] m = new double[9]; + + double utemp,vtemp; + double f,g; + + final int MAX_INTERATIONS = 10; + final double CONVERGE_TOL = 4.89E-15; + + double c_b48 = 1.; + double c_b71 = -1.; + int first; + converged = false; + + + first = 1; + + if( Math.abs(e[1]) < CONVERGE_TOL || Math.abs(e[0]) < CONVERGE_TOL) converged = true; + + for(k=0;k<MAX_INTERATIONS && !converged;k++) { + shift = compute_shift( s[1], e[1], s[2]); + f = (Math.abs(s[0]) - shift) * (d_sign(c_b48, s[0]) + shift/s[0]); + g = e[0]; + r = compute_rot(f, g, sinr, cosr, 0, first); + f = cosr[0] * s[0] + sinr[0] * e[0]; + e[0] = cosr[0] * e[0] - sinr[0] * s[0]; + g = sinr[0] * s[1]; + s[1] = cosr[0] * s[1]; + + r = compute_rot(f, g, sinl, cosl, 0, first); + first = 0; + s[0] = r; + f = cosl[0] * e[0] + sinl[0] * s[1]; + s[1] = cosl[0] * s[1] - sinl[0] * e[0]; + g = sinl[0] * e[1]; + e[1] = cosl[0] * e[1]; + + r = compute_rot(f, g, sinr, cosr, 1, first); + e[0] = r; + f = cosr[1] * s[1] + sinr[1] * e[1]; + e[1] = cosr[1] * e[1] - sinr[1] * s[1]; + g = sinr[1] * s[2]; + s[2] = cosr[1] * s[2]; + + r = compute_rot(f, g, sinl, cosl, 1, first); + s[1] = r; + f = cosl[1] * e[1] + sinl[1] * s[2]; + s[2] = cosl[1] * s[2] - sinl[1] * e[1]; + e[1] = f; + + // update u matrices + utemp = u[0]; + u[0] = cosl[0]*utemp + sinl[0]*u[3]; + u[3] = -sinl[0]*utemp + cosl[0]*u[3]; + utemp = u[1]; + u[1] = cosl[0]*utemp + sinl[0]*u[4]; + u[4] = -sinl[0]*utemp + cosl[0]*u[4]; + utemp = u[2]; + u[2] = cosl[0]*utemp + sinl[0]*u[5]; + u[5] = -sinl[0]*utemp + cosl[0]*u[5]; + + utemp = u[3]; + u[3] = cosl[1]*utemp + sinl[1]*u[6]; + u[6] = -sinl[1]*utemp + cosl[1]*u[6]; + utemp = u[4]; + u[4] = cosl[1]*utemp + sinl[1]*u[7]; + u[7] = -sinl[1]*utemp + cosl[1]*u[7]; + utemp = u[5]; + u[5] = cosl[1]*utemp + sinl[1]*u[8]; + u[8] = -sinl[1]*utemp + cosl[1]*u[8]; + + // update v matrices + + vtemp = v[0]; + v[0] = cosr[0]*vtemp + sinr[0]*v[1]; + v[1] = -sinr[0]*vtemp + cosr[0]*v[1]; + vtemp = v[3]; + v[3] = cosr[0]*vtemp + sinr[0]*v[4]; + v[4] = -sinr[0]*vtemp + cosr[0]*v[4]; + vtemp = v[6]; + v[6] = cosr[0]*vtemp + sinr[0]*v[7]; + v[7] = -sinr[0]*vtemp + cosr[0]*v[7]; + + vtemp = v[1]; + v[1] = cosr[1]*vtemp + sinr[1]*v[2]; + v[2] = -sinr[1]*vtemp + cosr[1]*v[2]; + vtemp = v[4]; + v[4] = cosr[1]*vtemp + sinr[1]*v[5]; + v[5] = -sinr[1]*vtemp + cosr[1]*v[5]; + vtemp = v[7]; + v[7] = cosr[1]*vtemp + sinr[1]*v[8]; + v[8] = -sinr[1]*vtemp + cosr[1]*v[8]; + + + m[0] = s[0]; m[1] = e[0]; m[2] = 0.0; + m[3] = 0.0; m[4] = s[1]; m[5] =e[1]; + m[6] = 0.0; m[7] = 0.0; m[8] =s[2]; + + if( Math.abs(e[1]) < CONVERGE_TOL || Math.abs(e[0]) < CONVERGE_TOL) converged = true; + } + + if( Math.abs(e[1]) < CONVERGE_TOL ) { + compute_2X2( s[0],e[0],s[1],s,sinl,cosl,sinr,cosr, 0); + + utemp = u[0]; + u[0] = cosl[0]*utemp + sinl[0]*u[3]; + u[3] = -sinl[0]*utemp + cosl[0]*u[3]; + utemp = u[1]; + u[1] = cosl[0]*utemp + sinl[0]*u[4]; + u[4] = -sinl[0]*utemp + cosl[0]*u[4]; + utemp = u[2]; + u[2] = cosl[0]*utemp + sinl[0]*u[5]; + u[5] = -sinl[0]*utemp + cosl[0]*u[5]; + + // update v matrices + + vtemp = v[0]; + v[0] = cosr[0]*vtemp + sinr[0]*v[1]; + v[1] = -sinr[0]*vtemp + cosr[0]*v[1]; + vtemp = v[3]; + v[3] = cosr[0]*vtemp + sinr[0]*v[4]; + v[4] = -sinr[0]*vtemp + cosr[0]*v[4]; + vtemp = v[6]; + v[6] = cosr[0]*vtemp + sinr[0]*v[7]; + v[7] = -sinr[0]*vtemp + cosr[0]*v[7]; + } else { + compute_2X2( s[1],e[1],s[2],s,sinl,cosl,sinr,cosr,1); + + utemp = u[3]; + u[3] = cosl[0]*utemp + sinl[0]*u[6]; + u[6] = -sinl[0]*utemp + cosl[0]*u[6]; + utemp = u[4]; + u[4] = cosl[0]*utemp + sinl[0]*u[7]; + u[7] = -sinl[0]*utemp + cosl[0]*u[7]; + utemp = u[5]; + u[5] = cosl[0]*utemp + sinl[0]*u[8]; + u[8] = -sinl[0]*utemp + cosl[0]*u[8]; + + // update v matrices + + vtemp = v[1]; + v[1] = cosr[0]*vtemp + sinr[0]*v[2]; + v[2] = -sinr[0]*vtemp + cosr[0]*v[2]; + vtemp = v[4]; + v[4] = cosr[0]*vtemp + sinr[0]*v[5]; + v[5] = -sinr[0]*vtemp + cosr[0]*v[5]; + vtemp = v[7]; + v[7] = cosr[0]*vtemp + sinr[0]*v[8]; + v[8] = -sinr[0]*vtemp + cosr[0]*v[8]; + } + + return(0); +} +static double max( double a, double b) { + if( a > b) + return( a); + else + return( b); +} +static double min( double a, double b) { + if( a < b) + return( a); + else + return( b); +} +static double d_sign(double a, double b) { +double x; +x = (a >= 0 ? a : - a); +return( b >= 0 ? x : -x); +} + +static double compute_shift( double f, double g, double h) { + double d__1, d__2; + double fhmn, fhmx, c, fa, ga, ha, as, at, au; + double ssmin; + + fa = Math.abs(f); + ga = Math.abs(g); + ha = Math.abs(h); + fhmn = min(fa,ha); + fhmx = max(fa,ha); + if (fhmn == 0.) { + ssmin = 0.; + if (fhmx == 0.) { + } else { + d__1 = min(fhmx,ga) / max(fhmx,ga); + } + } else { + if (ga < fhmx) { + as = fhmn / fhmx + 1.; + at = (fhmx - fhmn) / fhmx; + d__1 = ga / fhmx; + au = d__1 * d__1; + c = 2. / (Math.sqrt(as * as + au) + Math.sqrt(at * at + au)); + ssmin = fhmn * c; + } else { + au = fhmx / ga; + if (au == 0.) { + ssmin = fhmn * fhmx / ga; + } else { + as = fhmn / fhmx + 1.; + at = (fhmx - fhmn) / fhmx; + d__1 = as * au; + d__2 = at * au; + c = 1. / (Math.sqrt(d__1 * d__1 + 1.) + Math.sqrt(d__2 * d__2 + 1.)); + ssmin = fhmn * c * au; + ssmin += ssmin; + } + } + } + + return(ssmin); +} +static int compute_2X2( double f, double g, double h, double[] single_values, + double[] snl, double[] csl, double[] snr, double[] csr, int index) { + + double c_b3 = 2.; + double c_b4 = 1.; + + double d__1; + int pmax; + double temp; + boolean swap; + double a, d, l, m, r, s, t, tsign, fa, ga, ha; + double ft, gt, ht, mm; + boolean gasmal; + double tt, clt, crt, slt, srt; + double ssmin,ssmax; + + ssmax = single_values[0]; + ssmin = single_values[1]; + clt = 0.0; + crt = 0.0; + slt = 0.0; + srt = 0.0; + tsign = 0.0; + + ft = f; + fa = Math.abs(ft); + ht = h; + ha = Math.abs(h); + + pmax = 1; + if( ha > fa) + swap = true; + else + swap = false; + + if (swap) { + pmax = 3; + temp = ft; + ft = ht; + ht = temp; + temp = fa; + fa = ha; + ha = temp; + + } + gt = g; + ga = Math.abs(gt); + if (ga == 0.) { + + single_values[1] = ha; + single_values[0] = fa; + clt = 1.; + crt = 1.; + slt = 0.; + srt = 0.; + } else { + gasmal = true; + + if (ga > fa) { + pmax = 2; + if (fa / ga < EPS) { + + gasmal = false; + ssmax = ga; + if (ha > 1.) { + ssmin = fa / (ga / ha); + } else { + ssmin = fa / ga * ha; + } + clt = 1.; + slt = ht / gt; + srt = 1.; + crt = ft / gt; + } + } + if (gasmal) { + + d = fa - ha; + if (d == fa) { + + l = 1.; + } else { + l = d / fa; + } + + m = gt / ft; + + t = 2. - l; + + mm = m * m; + tt = t * t; + s = Math.sqrt(tt + mm); + + if (l == 0.) { + r = Math.abs(m); + } else { + r = Math.sqrt(l * l + mm); + } + + a = (s + r) * .5; + + if (ga > fa) { + pmax = 2; + if (fa / ga < EPS) { + + gasmal = false; + ssmax = ga; + if (ha > 1.) { + ssmin = fa / (ga / ha); + } else { + ssmin = fa / ga * ha; + } + clt = 1.; + slt = ht / gt; + srt = 1.; + crt = ft / gt; + } + } + if (gasmal) { + + d = fa - ha; + if (d == fa) { + + l = 1.; + } else { + l = d / fa; + } + + m = gt / ft; + + t = 2. - l; + + mm = m * m; + tt = t * t; + s = Math.sqrt(tt + mm); + + if (l == 0.) { + r = Math.abs(m); + } else { + r = Math.sqrt(l * l + mm); + } + + a = (s + r) * .5; + + + ssmin = ha / a; + ssmax = fa * a; + if (mm == 0.) { + + if (l == 0.) { + t = d_sign(c_b3, ft) * d_sign(c_b4, gt); + } else { + t = gt / d_sign(d, ft) + m / t; + } + } else { + t = (m / (s + t) + m / (r + l)) * (a + 1.); + } + l = Math.sqrt(t * t + 4.); + crt = 2. / l; + srt = t / l; + clt = (crt + srt * m) / a; + slt = ht / ft * srt / a; + } + } + if (swap) { + csl[0] = srt; + snl[0] = crt; + csr[0] = slt; + snr[0] = clt; + } else { + csl[0] = clt; + snl[0] = slt; + csr[0] = crt; + snr[0] = srt; + } + + if (pmax == 1) { + tsign = d_sign(c_b4, csr[0]) * d_sign(c_b4, csl[0]) * d_sign(c_b4, f); + } + if (pmax == 2) { + tsign = d_sign(c_b4, snr[0]) * d_sign(c_b4, csl[0]) * d_sign(c_b4, g); + } + if (pmax == 3) { + tsign = d_sign(c_b4, snr[0]) * d_sign(c_b4, snl[0]) * d_sign(c_b4, h); + } + single_values[index] = d_sign(ssmax, tsign); + d__1 = tsign * d_sign(c_b4, f) * d_sign(c_b4, h); + single_values[index+1] = d_sign(ssmin, d__1); + + + } + return 0; + } + static double compute_rot( double f, double g, double[] sin, double[] cos, int index, int first) { + int i__1; + double d__1, d__2; + double cs,sn; + int i; + double scale; + int count; + double f1, g1; + double r; + final double safmn2 = 2.002083095183101E-146; + final double safmx2 = 4.994797680505588E+145; + + if (g == 0.) { + cs = 1.; + sn = 0.; + r = f; + } else if (f == 0.) { + cs = 0.; + sn = 1.; + r = g; + } else { + f1 = f; + g1 = g; + scale = max(Math.abs(f1),Math.abs(g1)); + if (scale >= safmx2) { + count = 0; + while(scale >= safmx2) { + ++count; + f1 *= safmn2; + g1 *= safmn2; + scale = max(Math.abs(f1),Math.abs(g1)); + } + r = Math.sqrt(f1*f1 + g1*g1); + cs = f1 / r; + sn = g1 / r; + i__1 = count; + for (i = 1; i <= count; ++i) { + r *= safmx2; + } + } else if (scale <= safmn2) { + count = 0; + while(scale <= safmn2) { + ++count; + f1 *= safmx2; + g1 *= safmx2; + scale = max(Math.abs(f1),Math.abs(g1)); + } + r = Math.sqrt(f1*f1 + g1*g1); + cs = f1 / r; + sn = g1 / r; + i__1 = count; + for (i = 1; i <= count; ++i) { + r *= safmn2; + } + } else { + r = Math.sqrt(f1*f1 + g1*g1); + cs = f1 / r; + sn = g1 / r; + } + if (Math.abs(f) > Math.abs(g) && cs < 0.) { + cs = -cs; + sn = -sn; + r = -r; + } + } + sin[index] = sn; + cos[index] = cs; + return r; + + } +static void print_mat( double[] mat) { +int i; + for(i=0;i<3;i++){ + System.out.println(mat[i*3+0]+" "+mat[i*3+1]+" "+mat[i*3+2]+"\n"); + } + +} +static void print_det( double[] mat) { +double det; + + det = mat[0]*mat[4]*mat[8] + + mat[1]*mat[5]*mat[6] + + mat[2]*mat[3]*mat[7] - + mat[2]*mat[4]*mat[6] - + mat[0]*mat[5]*mat[7] - + mat[1]*mat[3]*mat[8]; + System.out.println("det= "+det); +} +static void mat_mul(double[] m1, double[] m2, double[] m3) { + int i; + double[] tmp = new double[9]; + + tmp[0] = m1[0]*m2[0] + m1[1]*m2[3] + m1[2]*m2[6]; + tmp[1] = m1[0]*m2[1] + m1[1]*m2[4] + m1[2]*m2[7]; + tmp[2] = m1[0]*m2[2] + m1[1]*m2[5] + m1[2]*m2[8]; + + tmp[3] = m1[3]*m2[0] + m1[4]*m2[3] + m1[5]*m2[6]; + tmp[4] = m1[3]*m2[1] + m1[4]*m2[4] + m1[5]*m2[7]; + tmp[5] = m1[3]*m2[2] + m1[4]*m2[5] + m1[5]*m2[8]; + + tmp[6] = m1[6]*m2[0] + m1[7]*m2[3] + m1[8]*m2[6]; + tmp[7] = m1[6]*m2[1] + m1[7]*m2[4] + m1[8]*m2[7]; + tmp[8] = m1[6]*m2[2] + m1[7]*m2[5] + m1[8]*m2[8]; + + for(i=0;i<9;i++) { + m3[i] = tmp[i]; + } +} +static void transpose_mat(double[] in, double[] out) { + out[0] = in[0]; + out[1] = in[3]; + out[2] = in[6]; + + out[3] = in[1]; + out[4] = in[4]; + out[5] = in[7]; + + out[6] = in[2]; + out[7] = in[5]; + out[8] = in[8]; +} +static double max3( double[] values) { + if( values[0] > values[1] ) { + if( values[0] > values[2] ) + return(values[0]); + else + return(values[2]); + } else { + if( values[1] > values[2] ) + return(values[1]); + else + return(values[2]); + } + } + + private static final boolean almostEqual(double a, double b) { + if (a == b) + return true; + + final double EPSILON_ABSOLUTE = 1.0e-6; + final double EPSILON_RELATIVE = 1.0e-4; + double diff = Math.abs(a-b); + double absA = Math.abs(a); + double absB = Math.abs(b); + double max = (absA >= absB) ? absA : absB; + + if (diff < EPSILON_ABSOLUTE) + return true; + + if ((diff / max) < EPSILON_RELATIVE) + return true; + + return false; + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + Matrix3d m1 = null; + try { + m1 = (Matrix3d)super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + + // Also need to create new tmp arrays (no need to actually clone them) + return m1; + } + + /** + * Get the first matrix element in the first row. + * @return Returns the m00. + * @since vecmath 1.5 + */ + public final double getM00() { + return m00; + } + + /** + * Set the first matrix element in the first row. + * + * @param m00 The m00 to set. + * + * @since vecmath 1.5 + */ + public final void setM00(double m00) { + this.m00 = m00; + } + + /** + * Get the second matrix element in the first row. + * + * @return Returns the m01. + * + * @since vecmath 1.5 + */ + public final double getM01() { + return m01; + } + + /** + * Set the second matrix element in the first row. + * + * @param m01 The m01 to set. + * + * @since vecmath 1.5 + */ + public final void setM01(double m01) { + this.m01 = m01; + } + + /** + * Get the third matrix element in the first row. + * + * @return Returns the m02. + * + * @since vecmath 1.5 + */ + public final double getM02() { + return m02; + } + + /** + * Set the third matrix element in the first row. + * + * @param m02 The m02 to set. + * + * @since vecmath 1.5 + */ + public final void setM02(double m02) { + this.m02 = m02; + } + + /** + * Get first matrix element in the second row. + * + * @return Returns the m10. + * + * @since vecmath 1.5 + */ + public final double getM10() { + return m10; + } + + /** + * Set first matrix element in the second row. + * + * @param m10 The m10 to set. + * + * @since vecmath 1.5 + */ + public final void setM10(double m10) { + this.m10 = m10; + } + + /** + * Get second matrix element in the second row. + * + * @return Returns the m11. + * + * @since vecmath 1.5 + */ + public final double getM11() { + return m11; + } + + /** + * Set the second matrix element in the second row. + * + * @param m11 The m11 to set. + * + * @since vecmath 1.5 + */ + public final void setM11(double m11) { + this.m11 = m11; + } + + /** + * Get the third matrix element in the second row. + * + * @return Returns the m12. + * + * @since vecmath 1.5 + */ + public final double getM12() { + return m12; + } + + /** + * Set the third matrix element in the second row. + * + * @param m12 The m12 to set. + * + * @since vecmath 1.5 + */ + public final void setM12(double m12) { + this.m12 = m12; + } + + /** + * Get the first matrix element in the third row. + * + * @return Returns the m20. + * + * @since vecmath 1.5 + */ + public final double getM20() { + return m20; + } + + /** + * Set the first matrix element in the third row. + * + * @param m20 The m20 to set. + * + * @since vecmath 1.5 + */ + public final void setM20(double m20) { + this.m20 = m20; + } + + /** + * Get the second matrix element in the third row. + * + * @return Returns the m21. + * + * @since vecmath 1.5 + */ + public final double getM21() { + return m21; + } + + /** + * Set the second matrix element in the third row. + * + * @param m21 The m21 to set. + * + * @since vecmath 1.5 + */ + public final void setM21(double m21) { + this.m21 = m21; + } + + /** + * Get the third matrix element in the third row . + * + * @return Returns the m22. + * + * @since vecmath 1.5 + */ + public final double getM22() { + return m22; + } + + /** + * Set the third matrix element in the third row. + * + * @param m22 The m22 to set. + * + * @since vecmath 1.5 + */ + public final void setM22(double m22) { + this.m22 = m22; + } + +} diff --git a/src/org/jogamp/vecmath/Matrix3f.java b/src/org/jogamp/vecmath/Matrix3f.java new file mode 100644 index 0000000..9b2ebb3 --- /dev/null +++ b/src/org/jogamp/vecmath/Matrix3f.java @@ -0,0 +1,2311 @@ +/* + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A single precision floating point 3 by 3 matrix. + * Primarily to support 3D rotations. + * + */ +public class Matrix3f implements java.io.Serializable, Cloneable { + + // Compatible with 1.1 + static final long serialVersionUID = 329697160112089834L; + + /** + * The first matrix element in the first row. + */ + public float m00; + + /** + * The second matrix element in the first row. + */ + public float m01; + + /** + * The third matrix element in the first row. + */ + public float m02; + + /** + * The first matrix element in the second row. + */ + public float m10; + + /** + * The second matrix element in the second row. + */ + public float m11; + + /** + * The third matrix element in the second row. + */ + public float m12; + + /** + * The first matrix element in the third row. + */ + public float m20; + + /** + * The second matrix element in the third row. + */ + public float m21; + + /** + * The third matrix element in the third row. + */ + public float m22; + /* + double[] tmp = new double[9]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + */ + private static final double EPS = 1.0E-8; + + + + /** + * Constructs and initializes a Matrix3f from the specified nine values. + * @param m00 the [0][0] element + * @param m01 the [0][1] element + * @param m02 the [0][2] element + * @param m10 the [1][0] element + * @param m11 the [1][1] element + * @param m12 the [1][2] element + * @param m20 the [2][0] element + * @param m21 the [2][1] element + * @param m22 the [2][2] element + */ + public Matrix3f(float m00, float m01, float m02, + float m10, float m11, float m12, + float m20, float m21, float m22) + { + this.m00 = m00; + this.m01 = m01; + this.m02 = m02; + + this.m10 = m10; + this.m11 = m11; + this.m12 = m12; + + this.m20 = m20; + this.m21 = m21; + this.m22 = m22; + + } + + /** + * Constructs and initializes a Matrix3f from the specified + * nine-element array. this.m00 =v[0], this.m01=v[1], etc. + * @param v the array of length 9 containing in order + */ + public Matrix3f(float[] v) + { + this.m00 = v[ 0]; + this.m01 = v[ 1]; + this.m02 = v[ 2]; + + this.m10 = v[ 3]; + this.m11 = v[ 4]; + this.m12 = v[ 5]; + + this.m20 = v[ 6]; + this.m21 = v[ 7]; + this.m22 = v[ 8]; + + } + + /** + * Constructs a new matrix with the same values as the + * Matrix3d parameter. + * @param m1 the source matrix + */ + public Matrix3f(Matrix3d m1) + { + this.m00 = (float)m1.m00; + this.m01 = (float)m1.m01; + this.m02 = (float)m1.m02; + + this.m10 = (float)m1.m10; + this.m11 = (float)m1.m11; + this.m12 = (float)m1.m12; + + this.m20 = (float)m1.m20; + this.m21 = (float)m1.m21; + this.m22 = (float)m1.m22; + + } + + + /** + * Constructs a new matrix with the same values as the + * Matrix3f parameter. + * @param m1 the source matrix + */ + public Matrix3f(Matrix3f m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + + } + + + /** + * Constructs and initializes a Matrix3f to all zeros. + */ + public Matrix3f() + { + this.m00 = (float) 0.0; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = (float) 0.0; + this.m12 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = (float) 0.0; + + } + + /** + * Returns a string that contains the values of this Matrix3f. + * @return the String representation + */ + @Override + public String toString() { + return + this.m00 + ", " + this.m01 + ", " + this.m02 + "\n" + + this.m10 + ", " + this.m11 + ", " + this.m12 + "\n" + + this.m20 + ", " + this.m21 + ", " + this.m22 + "\n"; + } + + /** + * Sets this Matrix3f to identity. + */ + public final void setIdentity() + { + this.m00 = (float) 1.0; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = (float) 1.0; + this.m12 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = (float) 1.0; + } + + /** + * Sets the scale component of the current matrix by factoring + * out the current scale (by doing an SVD) and multiplying by + * the new scale. + * @param scale the new scale amount + */ + public final void setScale(float scale) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + this.m00 = (float)(tmp_rot[0] * scale); + this.m01 = (float)(tmp_rot[1] * scale); + this.m02 = (float)(tmp_rot[2] * scale); + + this.m10 = (float)(tmp_rot[3] * scale); + this.m11 = (float)(tmp_rot[4] * scale); + this.m12 = (float)(tmp_rot[5] * scale); + + this.m20 = (float)(tmp_rot[6] * scale); + this.m21 = (float)(tmp_rot[7] * scale); + this.m22 = (float)(tmp_rot[8] * scale); + + } + + /** + * Sets the specified element of this matrix3f to the value provided. + * @param row the row number to be modified (zero indexed) + * @param column the column number to be modified (zero indexed) + * @param value the new value + */ + public final void setElement(int row, int column, float value) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + this.m00 = value; + break; + case 1: + this.m01 = value; + break; + case 2: + this.m02 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0")); + } + break; + + case 1: + switch(column) + { + case 0: + this.m10 = value; + break; + case 1: + this.m11 = value; + break; + case 2: + this.m12 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0")); + } + break; + + case 2: + switch(column) + { + case 0: + this.m20 = value; + break; + case 1: + this.m21 = value; + break; + case 2: + this.m22 = value; + break; + default: + + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0")); + } + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f0")); + } + } + + /** + * Copies the matrix values in the specified row into the vector parameter. + * @param row the matrix row + * @param v the vector into which the matrix row values will be copied + */ + public final void getRow(int row, Vector3f v) { + if( row == 0 ) { + v.x = m00; + v.y = m01; + v.z = m02; + } else if(row == 1) { + v.x = m10; + v.y = m11; + v.z = m12; + } else if(row == 2) { + v.x = m20; + v.y = m21; + v.z = m22; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f1")); + } + + } + + /** + * Copies the matrix values in the specified row into the array parameter. + * @param row the matrix row + * @param v the array into which the matrix row values will be copied + */ + public final void getRow(int row, float v[]) { + if( row == 0 ) { + v[0] = m00; + v[1] = m01; + v[2] = m02; + } else if(row == 1) { + v[0] = m10; + v[1] = m11; + v[2] = m12; + } else if(row == 2) { + v[0] = m20; + v[1] = m21; + v[2] = m22; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f1")); + } + + } + + /** + * Copies the matrix values in the specified column into the vector + * parameter. + * @param column the matrix column + * @param v the vector into which the matrix row values will be copied + */ + public final void getColumn(int column, Vector3f v) { + if( column == 0 ) { + v.x = m00; + v.y = m10; + v.z = m20; + } else if(column == 1) { + v.x = m01; + v.y = m11; + v.z = m21; + }else if(column == 2){ + v.x = m02; + v.y = m12; + v.z = m22; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f3")); + } + + } + + /** + * Copies the matrix values in the specified column into the array + * parameter. + * @param column the matrix column + * @param v the array into which the matrix row values will be copied + */ + public final void getColumn(int column, float v[]) { + if( column == 0 ) { + v[0] = m00; + v[1] = m10; + v[2] = m20; + } else if(column == 1) { + v[0] = m01; + v[1] = m11; + v[2] = m21; + }else if(column == 2) { + v[0] = m02; + v[1] = m12; + v[2] = m22; + }else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f3")); + } + } + + /** + * Retrieves the value at the specified row and column of this + * matrix. + * @param row the row number to be retrieved (zero indexed) + * @param column the column number to be retrieved (zero indexed) + * @return the value at the indexed element. + */ + public final float getElement(int row, int column) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + return(this.m00); + case 1: + return(this.m01); + case 2: + return(this.m02); + default: + break; + } + break; + case 1: + switch(column) + { + case 0: + return(this.m10); + case 1: + return(this.m11); + case 2: + return(this.m12); + default: + break; + } + break; + + case 2: + switch(column) + { + case 0: + return(this.m20); + case 1: + return(this.m21); + case 2: + return(this.m22); + default: + break; + } + break; + + default: + break; + } + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f5")); + } + + /** + * Sets the specified row of this matrix3f to the three values provided. + * @param row the row number to be modified (zero indexed) + * @param x the first column element + * @param y the second column element + * @param z the third column element + */ + public final void setRow(int row, float x, float y, float z) + { + switch (row) { + case 0: + this.m00 = x; + this.m01 = y; + this.m02 = z; + break; + + case 1: + this.m10 = x; + this.m11 = y; + this.m12 = z; + break; + + case 2: + this.m20 = x; + this.m21 = y; + this.m22 = z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f6")); + } + } + + /** + * Sets the specified row of this matrix3f to the Vector provided. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, Vector3f v) + { + switch (row) { + case 0: + this.m00 = v.x; + this.m01 = v.y; + this.m02 = v.z; + break; + + case 1: + this.m10 = v.x; + this.m11 = v.y; + this.m12 = v.z; + break; + + case 2: + this.m20 = v.x; + this.m21 = v.y; + this.m22 = v.z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f6")); + } + } + + /** + * Sets the specified row of this matrix3f to the three values provided. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, float v[]) + { + switch (row) { + case 0: + this.m00 = v[0]; + this.m01 = v[1]; + this.m02 = v[2]; + break; + + case 1: + this.m10 = v[0]; + this.m11 = v[1]; + this.m12 = v[2]; + break; + + case 2: + this.m20 = v[0]; + this.m21 = v[1]; + this.m22 = v[2]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f6")); + } + } + + /** + * Sets the specified column of this matrix3f to the three values provided. + * @param column the column number to be modified (zero indexed) + * @param x the first row element + * @param y the second row element + * @param z the third row element + */ + public final void setColumn(int column, float x, float y, float z) + { + switch (column) { + case 0: + this.m00 = x; + this.m10 = y; + this.m20 = z; + break; + + case 1: + this.m01 = x; + this.m11 = y; + this.m21 = z; + break; + + case 2: + this.m02 = x; + this.m12 = y; + this.m22 = z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f9")); + } + } + + /** + * Sets the specified column of this matrix3f to the vector provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, Vector3f v) + { + switch (column) { + case 0: + this.m00 = v.x; + this.m10 = v.y; + this.m20 = v.z; + break; + + case 1: + this.m01 = v.x; + this.m11 = v.y; + this.m21 = v.z; + break; + + case 2: + this.m02 = v.x; + this.m12 = v.y; + this.m22 = v.z; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f9")); + } + } + + /** + * Sets the specified column of this matrix3f to the three values provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, float v[]) + { + switch (column) { + case 0: + this.m00 = v[0]; + this.m10 = v[1]; + this.m20 = v[2]; + break; + + case 1: + this.m01 = v[0]; + this.m11 = v[1]; + this.m21 = v[2]; + break; + + case 2: + this.m02 = v[0]; + this.m12 = v[1]; + this.m22 = v[2]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3f9")); + } + } + + /** + * Performs an SVD normalization of this matrix to calculate + * and return the uniform scale factor. If the matrix has non-uniform + * scale factors, the largest of the x, y, and z scale factors will + * be returned. This matrix is not modified. + * @return the scale factor of this matrix + */ + public final float getScale() + { + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate(tmp_scale, tmp_rot); + + return( (float)Matrix3d.max3(tmp_scale )); + + } + + /** + * Adds a scalar to each component of this matrix. + * @param scalar the scalar adder + */ + public final void add(float scalar) + { + m00 += scalar; + m01 += scalar; + m02 += scalar; + m10 += scalar; + m11 += scalar; + m12 += scalar; + m20 += scalar; + m21 += scalar; + m22 += scalar; + } + + /** + * Adds a scalar to each component of the matrix m1 and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar adder. + * @param m1 the original matrix values + */ + public final void add(float scalar, Matrix3f m1) + { + this.m00 = m1.m00 + scalar; + this.m01 = m1.m01 + scalar; + this.m02 = m1.m02 + scalar; + this.m10 = m1.m10 + scalar; + this.m11 = m1.m11 + scalar; + this.m12 = m1.m12 + scalar; + this.m20 = m1.m20 + scalar; + this.m21 = m1.m21 + scalar; + this.m22 = m1.m22 + scalar; + } + + /** + * Sets the value of this matrix to the matrix sum of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void add(Matrix3f m1, Matrix3f m2) + { + this.m00 = m1.m00 + m2.m00; + this.m01 = m1.m01 + m2.m01; + this.m02 = m1.m02 + m2.m02; + + this.m10 = m1.m10 + m2.m10; + this.m11 = m1.m11 + m2.m11; + this.m12 = m1.m12 + m2.m12; + + this.m20 = m1.m20 + m2.m20; + this.m21 = m1.m21 + m2.m21; + this.m22 = m1.m22 + m2.m22; + } + + /** + * Sets the value of this matrix to the matrix sum of itself and + * matrix m1. + * @param m1 the other matrix + */ + public final void add(Matrix3f m1) + { + this.m00 += m1.m00; + this.m01 += m1.m01; + this.m02 += m1.m02; + + this.m10 += m1.m10; + this.m11 += m1.m11; + this.m12 += m1.m12; + + this.m20 += m1.m20; + this.m21 += m1.m21; + this.m22 += m1.m22; + } + + /** + * Sets the value of this matrix to the matrix difference + * of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void sub(Matrix3f m1, Matrix3f m2) + { + this.m00 = m1.m00 - m2.m00; + this.m01 = m1.m01 - m2.m01; + this.m02 = m1.m02 - m2.m02; + + this.m10 = m1.m10 - m2.m10; + this.m11 = m1.m11 - m2.m11; + this.m12 = m1.m12 - m2.m12; + + this.m20 = m1.m20 - m2.m20; + this.m21 = m1.m21 - m2.m21; + this.m22 = m1.m22 - m2.m22; + } + + /** + * Sets the value of this matrix to the matrix difference + * of itself and matrix m1 (this = this - m1). + * @param m1 the other matrix + */ + public final void sub(Matrix3f m1) + { + this.m00 -= m1.m00; + this.m01 -= m1.m01; + this.m02 -= m1.m02; + + this.m10 -= m1.m10; + this.m11 -= m1.m11; + this.m12 -= m1.m12; + + this.m20 -= m1.m20; + this.m21 -= m1.m21; + this.m22 -= m1.m22; + } + + /** + * Sets the value of this matrix to its transpose. + */ + public final void transpose() + { + float temp; + + temp = this.m10; + this.m10 = this.m01; + this.m01 = temp; + + temp = this.m20; + this.m20 = this.m02; + this.m02 = temp; + + temp = this.m21; + this.m21 = this.m12; + this.m12 = temp; + } + + /** + * Sets the value of this matrix to the transpose of the argument matrix. + * @param m1 the matrix to be transposed + */ + public final void transpose(Matrix3f m1) + { + if (this != m1) { + this.m00 = m1.m00; + this.m01 = m1.m10; + this.m02 = m1.m20; + + this.m10 = m1.m01; + this.m11 = m1.m11; + this.m12 = m1.m21; + + this.m20 = m1.m02; + this.m21 = m1.m12; + this.m22 = m1.m22; + } else + this.transpose(); + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * (single precision) quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4f q1) + { + this.m00 = 1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z; + this.m10 = 2.0f*(q1.x*q1.y + q1.w*q1.z); + this.m20 = 2.0f*(q1.x*q1.z - q1.w*q1.y); + + this.m01 = 2.0f*(q1.x*q1.y - q1.w*q1.z); + this.m11 = 1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z; + this.m21 = 2.0f*(q1.y*q1.z + q1.w*q1.x); + + this.m02 = 2.0f*(q1.x*q1.z + q1.w*q1.y); + this.m12 = 2.0f*(q1.y*q1.z - q1.w*q1.x); + this.m22 = 1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * (single precision) axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4f a1) + { + float mag = (float)Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + if( mag < EPS ) { + m00 = 1.0f; + m01 = 0.0f; + m02 = 0.0f; + + m10 = 0.0f; + m11 = 1.0f; + m12 = 0.0f; + + m20 = 0.0f; + m21 = 0.0f; + m22 = 1.0f; + } else { + mag = 1.0f/mag; + float ax = a1.x*mag; + float ay = a1.y*mag; + float az = a1.z*mag; + + float sinTheta = (float)Math.sin((float)a1.angle); + float cosTheta = (float)Math.cos((float)a1.angle); + float t = (float)1.0 - cosTheta; + + float xz = ax * az; + float xy = ax * ay; + float yz = ay * az; + + m00 = t * ax * ax + cosTheta; + m01 = t * xy - sinTheta * az; + m02 = t * xz + sinTheta * ay; + + m10 = t * xy + sinTheta * az; + m11 = t * ay * ay + cosTheta; + m12 = t * yz - sinTheta * ax; + + m20 = t * xz - sinTheta * ay; + m21 = t * yz + sinTheta * ax; + m22 = t * az * az + cosTheta; + } + + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * (double precision) axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4d a1) + { + double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + if( mag < EPS ) { + m00 = 1.0f; + m01 = 0.0f; + m02 = 0.0f; + + m10 = 0.0f; + m11 = 1.0f; + m12 = 0.0f; + + m20 = 0.0f; + m21 = 0.0f; + m22 = 1.0f; + } else { + mag = 1.0/mag; + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + + double sinTheta = Math.sin(a1.angle); + double cosTheta = Math.cos(a1.angle); + double t = 1.0 - cosTheta; + + double xz = ax * az; + double xy = ax * ay; + double yz = ay * az; + + m00 = (float)(t * ax * ax + cosTheta); + m01 = (float)(t * xy - sinTheta * az); + m02 = (float)(t * xz + sinTheta * ay); + + m10 = (float)(t * xy + sinTheta * az); + m11 = (float)(t * ay * ay + cosTheta); + m12 = (float)(t * yz - sinTheta * ax); + + m20 = (float)(t * xz - sinTheta * ay); + m21 = (float)(t * yz + sinTheta * ax); + m22 = (float)(t * az * az + cosTheta); + } + + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * (single precision) quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4d q1) + { + this.m00 = (float) (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = (float) (2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = (float) (2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = (float) (2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = (float) (2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = (float) (2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = (float) (2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + } + + /** + * Sets the values in this Matrix3f equal to the row-major + * array parameter (ie, the first three elements of the + * array will be copied into the first row of this matrix, etc.). + * @param m the single precision array of length 9 + */ + public final void set(float[] m) + { + m00 = m[0]; + m01 = m[1]; + m02 = m[2]; + + m10 = m[3]; + m11 = m[4]; + m12 = m[5]; + + m20 = m[6]; + m21 = m[7]; + m22 = m[8]; + + + } + + /** + * Sets the value of this matrix to the value of the Matrix3f + * argument. + * @param m1 the source matrix3f + */ + public final void set(Matrix3f m1) { + + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + + } + + + /** + * Sets the value of this matrix to the float value of the Matrix3d + * argument. + * @param m1 the source matrix3d + */ + public final void set(Matrix3d m1) { + + this.m00 = (float)m1.m00; + this.m01 = (float)m1.m01; + this.m02 = (float)m1.m02; + + this.m10 = (float)m1.m10; + this.m11 = (float)m1.m11; + this.m12 = (float)m1.m12; + + this.m20 = (float)m1.m20; + this.m21 = (float)m1.m21; + this.m22 = (float)m1.m22; + + } + + + /** + * Sets the value of this matrix to the matrix inverse + * of the passed matrix m1. + * @param m1 the matrix to be inverted + */ + public final void invert(Matrix3f m1) + { + invertGeneral( m1); + } + + /** + * Inverts this matrix in place. + */ + public final void invert() + { + invertGeneral( this ); + } + + /** + * General invert routine. Inverts m1 and places the result in "this". + * Note that this routine handles both the "this" version and the + * non-"this" version. + * + * Also note that since this routine is slow anyway, we won't worry + * about allocating a little bit of garbage. + */ + private final void invertGeneral(Matrix3f m1) { + double temp[] = new double[9]; + double result[] = new double[9]; + int row_perm[] = new int[3]; + int i, r, c; + + // Use LU decomposition and backsubstitution code specifically + // for floating-point 3x3 matrices. + + // Copy source matrix to t1tmp + temp[0] = (double)m1.m00; + temp[1] = (double)m1.m01; + temp[2] = (double)m1.m02; + + temp[3] = (double)m1.m10; + temp[4] = (double)m1.m11; + temp[5] = (double)m1.m12; + + temp[6] = (double)m1.m20; + temp[7] = (double)m1.m21; + temp[8] = (double)m1.m22; + + + // Calculate LU decomposition: Is the matrix singular? + if (!luDecomposition(temp, row_perm)) { + // Matrix has no inverse + throw new SingularMatrixException(VecMathI18N.getString("Matrix3f12")); + } + + // Perform back substitution on the identity matrix + for(i=0;i<9;i++) result[i] = 0.0; + result[0] = 1.0; result[4] = 1.0; result[8] = 1.0; + luBacksubstitution(temp, row_perm, result); + + this.m00 = (float)result[0]; + this.m01 = (float)result[1]; + this.m02 = (float)result[2]; + + this.m10 = (float)result[3]; + this.m11 = (float)result[4]; + this.m12 = (float)result[5]; + + this.m20 = (float)result[6]; + this.m21 = (float)result[7]; + this.m22 = (float)result[8]; + + } + + /** + * Given a 3x3 array "matrix0", this function replaces it with the + * LU decomposition of a row-wise permutation of itself. The input + * parameters are "matrix0" and "dimen". The array "matrix0" is also + * an output parameter. The vector "row_perm[3]" is an output + * parameter that contains the row permutations resulting from partial + * pivoting. The output parameter "even_row_xchg" is 1 when the + * number of row exchanges is even, or -1 otherwise. Assumes data + * type is always double. + * + * This function is similar to luDecomposition, except that it + * is tuned specifically for 3x3 matrices. + * + * @return true if the matrix is nonsingular, or false otherwise. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 40-45. + // + static boolean luDecomposition(double[] matrix0, + int[] row_perm) { + + double row_scale[] = new double[3]; + + // Determine implicit scaling information by looping over rows + { + int i, j; + int ptr, rs; + double big, temp; + + ptr = 0; + rs = 0; + + // For each row ... + i = 3; + while (i-- != 0) { + big = 0.0; + + // For each column, find the largest element in the row + j = 3; + while (j-- != 0) { + temp = matrix0[ptr++]; + temp = Math.abs(temp); + if (temp > big) { + big = temp; + } + } + + // Is the matrix singular? + if (big == 0.0) { + return false; + } + row_scale[rs++] = 1.0 / big; + } + } + + { + int j; + int mtx; + + mtx = 0; + + // For all columns, execute Crout's method + for (j = 0; j < 3; j++) { + int i, imax, k; + int target, p1, p2; + double sum, big, temp; + + // Determine elements of upper diagonal matrix U + for (i = 0; i < j; i++) { + target = mtx + (3*i) + j; + sum = matrix0[target]; + k = i; + p1 = mtx + (3*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 3; + } + matrix0[target] = sum; + } + + // Search for largest pivot element and calculate + // intermediate elements of lower diagonal matrix L. + big = 0.0; + imax = -1; + for (i = j; i < 3; i++) { + target = mtx + (3*i) + j; + sum = matrix0[target]; + k = j; + p1 = mtx + (3*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 3; + } + matrix0[target] = sum; + + // Is this the best pivot so far? + if ((temp = row_scale[i] * Math.abs(sum)) >= big) { + big = temp; + imax = i; + } + } + + if (imax < 0) { + throw new RuntimeException(VecMathI18N.getString("Matrix3f13")); + } + + // Is a row exchange necessary? + if (j != imax) { + // Yes: exchange rows + k = 3; + p1 = mtx + (3*imax); + p2 = mtx + (3*j); + while (k-- != 0) { + temp = matrix0[p1]; + matrix0[p1++] = matrix0[p2]; + matrix0[p2++] = temp; + } + + // Record change in scale factor + row_scale[imax] = row_scale[j]; + } + + // Record row permutation + row_perm[j] = imax; + + // Is the matrix singular + if (matrix0[(mtx + (3*j) + j)] == 0.0) { + return false; + } + + // Divide elements of lower diagonal matrix L by pivot + if (j != (3-1)) { + temp = 1.0 / (matrix0[(mtx + (3*j) + j)]); + target = mtx + (3*(j+1)) + j; + i = 2 - j; + while (i-- != 0) { + matrix0[target] *= temp; + target += 3; + } + } + } + } + + return true; + } + + /** + * Solves a set of linear equations. The input parameters "matrix1", + * and "row_perm" come from luDecompostionD3x3 and do not change + * here. The parameter "matrix2" is a set of column vectors assembled + * into a 3x3 matrix of floating-point values. The procedure takes each + * column of "matrix2" in turn and treats it as the right-hand side of the + * matrix equation Ax = LUx = b. The solution vector replaces the + * original column of the matrix. + * + * If "matrix2" is the identity matrix, the procedure replaces its contents + * with the inverse of the matrix from which "matrix1" was originally + * derived. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 44-45. + // + static void luBacksubstitution(double[] matrix1, + int[] row_perm, + double[] matrix2) { + + int i, ii, ip, j, k; + int rp; + int cv, rv; + + // rp = row_perm; + rp = 0; + + // For each column vector of matrix2 ... + for (k = 0; k < 3; k++) { + // cv = &(matrix2[0][k]); + cv = k; + ii = -1; + + // Forward substitution + for (i = 0; i < 3; i++) { + double sum; + + ip = row_perm[rp+i]; + sum = matrix2[cv+3*ip]; + matrix2[cv+3*ip] = matrix2[cv+3*i]; + if (ii >= 0) { + // rv = &(matrix1[i][0]); + rv = i*3; + for (j = ii; j <= i-1; j++) { + sum -= matrix1[rv+j] * matrix2[cv+3*j]; + } + } + else if (sum != 0.0) { + ii = i; + } + matrix2[cv+3*i] = sum; + } + + // Backsubstitution + // rv = &(matrix1[3][0]); + rv = 2*3; + matrix2[cv+3*2] /= matrix1[rv+2]; + + rv -= 3; + matrix2[cv+3*1] = (matrix2[cv+3*1] - + matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+1]; + + rv -= 3; + matrix2[cv+4*0] = (matrix2[cv+3*0] - + matrix1[rv+1] * matrix2[cv+3*1] - + matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+0]; + + } + } + /** + * Computes the determinant of this matrix. + * @return the determinant of this matrix + */ + public final float determinant() + { + float total; + total = this.m00*(this.m11*this.m22 - this.m12*this.m21) + + this.m01*(this.m12*this.m20 - this.m10*this.m22) + + this.m02*(this.m10*this.m21 - this.m11*this.m20); + return total; + } + + /** + * Sets the value of this matrix to a scale matrix with + * the passed scale amount. + * @param scale the scale factor for the matrix + */ + public final void set(float scale) + { + this.m00 = scale; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = scale; + this.m12 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = scale; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the x axis. + * @param angle the angle to rotate about the X axis in radians + */ + public final void rotX(float angle) + { + float sinAngle, cosAngle; + + sinAngle = (float) Math.sin((double) angle); + cosAngle = (float) Math.cos((double) angle); + + this.m00 = (float) 1.0; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = cosAngle; + this.m12 = -sinAngle; + + this.m20 = (float) 0.0; + this.m21 = sinAngle; + this.m22 = cosAngle; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the y axis. + * @param angle the angle to rotate about the Y axis in radians + */ + public final void rotY(float angle) + { + float sinAngle, cosAngle; + + sinAngle = (float) Math.sin((double) angle); + cosAngle = (float) Math.cos((double) angle); + + this.m00 = cosAngle; + this.m01 = (float) 0.0; + this.m02 = sinAngle; + + this.m10 = (float) 0.0; + this.m11 = (float) 1.0; + this.m12 = (float) 0.0; + + this.m20 = -sinAngle; + this.m21 = (float) 0.0; + this.m22 = cosAngle; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the z axis. + * @param angle the angle to rotate about the Z axis in radians + */ + public final void rotZ(float angle) + { + float sinAngle, cosAngle; + + sinAngle = (float) Math.sin((double) angle); + cosAngle = (float) Math.cos((double) angle); + + this.m00 = cosAngle; + this.m01 = -sinAngle; + this.m02 = (float) 0.0; + + this.m10 = sinAngle; + this.m11 = cosAngle; + this.m12 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = (float) 1.0; + } + + /** + * Multiplies each element of this matrix by a scalar. + * @param scalar the scalar multiplier + */ + public final void mul(float scalar) + { + m00 *= scalar; + m01 *= scalar; + m02 *= scalar; + + m10 *= scalar; + m11 *= scalar; + m12 *= scalar; + + m20 *= scalar; + m21 *= scalar; + m22 *= scalar; + } + + /** + * Multiplies each element of matrix m1 by a scalar and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar multiplier + * @param m1 the original matrix + */ + public final void mul(float scalar, Matrix3f m1) + { + this.m00 = scalar * m1.m00; + this.m01 = scalar * m1.m01; + this.m02 = scalar * m1.m02; + + this.m10 = scalar * m1.m10; + this.m11 = scalar * m1.m11; + this.m12 = scalar * m1.m12; + + this.m20 = scalar * m1.m20; + this.m21 = scalar * m1.m21; + this.m22 = scalar * m1.m22; + + } + + /** + * Sets the value of this matrix to the result of multiplying itself + * with matrix m1. + * @param m1 the other matrix + */ + public final void mul(Matrix3f m1) + { + float m00, m01, m02, + m10, m11, m12, + m20, m21, m22; + + m00 = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20; + m01 = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21; + m02 = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22; + + m10 = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20; + m11 = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21; + m12 = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22; + + m20 = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20; + m21 = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21; + m22 = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + + /** + * Sets the value of this matrix to the result of multiplying + * the two argument matrices together. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void mul(Matrix3f m1, Matrix3f m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20; + this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21; + this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20; + this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; + this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20; + this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; + this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; + } else { + float m00, m01, m02, + m10, m11, m12, + m20, m21, m22; + + m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20; + m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21; + m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20; + m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; + m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20; + m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; + m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + } + + /** + * Multiplies this matrix by matrix m1, does an SVD normalization + * of the result, and places the result back into this matrix. + * this = SVDnorm(this*m1). + * @param m1 the matrix on the right hand side of the multiplication + */ + public final void mulNormalize(Matrix3f m1){ + + double[] tmp = new double[9]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + tmp[0] = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20; + tmp[1] = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21; + tmp[2] = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22; + + tmp[3] = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20; + tmp[4] = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21; + tmp[5] = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22; + + tmp[6] = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20; + tmp[7] = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21; + tmp[8] = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22; + + Matrix3d.compute_svd( tmp, tmp_scale, tmp_rot); + + this.m00 = (float)(tmp_rot[0]); + this.m01 = (float)(tmp_rot[1]); + this.m02 = (float)(tmp_rot[2]); + + this.m10 = (float)(tmp_rot[3]); + this.m11 = (float)(tmp_rot[4]); + this.m12 = (float)(tmp_rot[5]); + + this.m20 = (float)(tmp_rot[6]); + this.m21 = (float)(tmp_rot[7]); + this.m22 = (float)(tmp_rot[8]); + + } + + /** + * Multiplies matrix m1 by matrix m2, does an SVD normalization + * of the result, and places the result into this matrix. + * this = SVDnorm(m1*m2). + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulNormalize(Matrix3f m1, Matrix3f m2){ + + double[] tmp = new double[9]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + + tmp[0] = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20; + tmp[1] = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21; + tmp[2] = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22; + + tmp[3] = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20; + tmp[4] = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21; + tmp[5] = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22; + + tmp[6] = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20; + tmp[7] = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21; + tmp[8] = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22; + + Matrix3d.compute_svd( tmp, tmp_scale, tmp_rot); + + this.m00 = (float)(tmp_rot[0]); + this.m01 = (float)(tmp_rot[1]); + this.m02 = (float)(tmp_rot[2]); + + this.m10 = (float)(tmp_rot[3]); + this.m11 = (float)(tmp_rot[4]); + this.m12 = (float)(tmp_rot[5]); + + this.m20 = (float)(tmp_rot[6]); + this.m21 = (float)(tmp_rot[7]); + this.m22 = (float)(tmp_rot[8]); + } + + /** + * Multiplies the transpose of matrix m1 times the transpose of matrix + * m2, and places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeBoth(Matrix3f m1, Matrix3f m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02; + this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12; + this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02; + this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12; + this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02; + this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12; + this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22; + } else { + float m00, m01, m02, + m10, m11, m12, + m20, m21, m22; // vars for temp result matrix + + m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02; + m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12; + m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02; + m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12; + m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02; + m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12; + m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + + } + + + /** + * Multiplies matrix m1 times the transpose of matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeRight(Matrix3f m1, Matrix3f m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02; + this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12; + this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02; + this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12; + this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02; + this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12; + this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22; + } else { + float m00, m01, m02, + m10, m11, m12, + m20, m21, m22; // vars for temp result matrix + + m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02; + m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12; + m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02; + m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12; + m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02; + m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12; + m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + } + + /** + * Multiplies the transpose of matrix m1 times matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeLeft(Matrix3f m1, Matrix3f m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20; + this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21; + this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20; + this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21; + this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20; + this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21; + this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22; + } else { + float m00, m01, m02, + m10, m11, m12, + m20, m21, m22; // vars for temp result matrix + + m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20; + m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21; + m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20; + m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21; + m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20; + m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21; + m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; + this.m10 = m10; this.m11 = m11; this.m12 = m12; + this.m20 = m20; this.m21 = m21; this.m22 = m22; + } + } + + /** + * Performs singular value decomposition normalization of this matrix. + */ + public final void normalize(){ + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + this.m00 = (float)tmp_rot[0]; + this.m01 = (float)tmp_rot[1]; + this.m02 = (float)tmp_rot[2]; + + this.m10 = (float)tmp_rot[3]; + this.m11 = (float)tmp_rot[4]; + this.m12 = (float)tmp_rot[5]; + + this.m20 = (float)tmp_rot[6]; + this.m21 = (float)tmp_rot[7]; + this.m22 = (float)tmp_rot[8]; + + } + + /** + * Perform singular value decomposition normalization of matrix m1 + * and place the normalized values into this. + * @param m1 the matrix values to be normalized + */ + public final void normalize(Matrix3f m1){ + double[] tmp = new double[9]; // scratch matrix + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + tmp[0] = m1.m00; + tmp[1] = m1.m01; + tmp[2] = m1.m02; + + tmp[3] = m1.m10; + tmp[4] = m1.m11; + tmp[5] = m1.m12; + + tmp[6] = m1.m20; + tmp[7] = m1.m21; + tmp[8] = m1.m22; + + Matrix3d.compute_svd( tmp, tmp_scale, tmp_rot ); + + this.m00 = (float)(tmp_rot[0]); + this.m01 = (float)(tmp_rot[1]); + this.m02 = (float)(tmp_rot[2]); + + this.m10 = (float)(tmp_rot[3]); + this.m11 = (float)(tmp_rot[4]); + this.m12 = (float)(tmp_rot[5]); + + this.m20 = (float)(tmp_rot[6]); + this.m21 = (float)(tmp_rot[7]); + this.m22 = (float)(tmp_rot[8]); + + } + + /** + * Perform cross product normalization of this matrix. + */ + public final void normalizeCP() + { + float mag = 1.0f/(float)Math.sqrt(m00*m00 + m10*m10 + m20*m20); + m00 = m00*mag; + m10 = m10*mag; + m20 = m20*mag; + + mag = 1.0f/(float)Math.sqrt(m01*m01 + m11*m11 + m21*m21); + m01 = m01*mag; + m11 = m11*mag; + m21 = m21*mag; + + m02 = m10*m21 - m11*m20; + m12 = m01*m20 - m00*m21; + m22 = m00*m11 - m01*m10; + + } + + /** + * Perform cross product normalization of matrix m1 and place the + * normalized values into this. + * @param m1 Provides the matrix values to be normalized + */ + public final void normalizeCP(Matrix3f m1) + { + float mag = 1.0f/(float)Math.sqrt(m1.m00*m1.m00 + m1.m10*m1.m10 + m1.m20*m1.m20); + m00 = m1.m00*mag; + m10 = m1.m10*mag; + m20 = m1.m20*mag; + + mag = 1.0f/(float)Math.sqrt(m1.m01*m1.m01 + m1.m11*m1.m11 + m1.m21*m1.m21); + m01 = m1.m01*mag; + m11 = m1.m11*mag; + m21 = m1.m21*mag; + + m02 = m10*m21 - m11*m20; + m12 = m01*m20 - m00*m21; + m22 = m00*m11 - m01*m10; + + } + + /** + * Returns true if all of the data members of Matrix3f m1 are + * equal to the corresponding data members in this Matrix3f. + * @param m1 the matrix with which the comparison is made + * @return true or false + */ + public boolean equals(Matrix3f m1) + { + try { + + return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02 + && this.m10 == m1.m10 && this.m11 == m1.m11 && this.m12 == m1.m12 + && this.m20 == m1.m20 && this.m21 == m1.m21 && this.m22 == m1.m22); + } + catch (NullPointerException e2) { return false; } + + } + + /** + * Returns true if the Object o1 is of type Matrix3f and all of the + * data members of o1 are equal to the corresponding data members in + * this Matrix3f. + * @param o1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object o1) + { + try { + + Matrix3f m2 = (Matrix3f) o1; + return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02 + && this.m10 == m2.m10 && this.m11 == m2.m11 && this.m12 == m2.m12 + && this.m20 == m2.m20 && this.m21 == m2.m21 && this.m22 == m2.m22); + } + catch (ClassCastException e1) { return false; } + catch (NullPointerException e2) { return false; } + } + + /** + * Returns true if the L-infinite distance between this matrix + * and matrix m1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[i=0,1,2 ; j=0,1,2 ; abs(this.m(i,j) - m1.m(i,j)] + * @param m1 the matrix to be compared to this matrix + * @param epsilon the threshold value + */ + public boolean epsilonEquals(Matrix3f m1, float epsilon) + { + boolean status = true; + + if( Math.abs( this.m00 - m1.m00) > epsilon) status = false; + if( Math.abs( this.m01 - m1.m01) > epsilon) status = false; + if( Math.abs( this.m02 - m1.m02) > epsilon) status = false; + + if( Math.abs( this.m10 - m1.m10) > epsilon) status = false; + if( Math.abs( this.m11 - m1.m11) > epsilon) status = false; + if( Math.abs( this.m12 - m1.m12) > epsilon) status = false; + + if( Math.abs( this.m20 - m1.m20) > epsilon) status = false; + if( Math.abs( this.m21 - m1.m21) > epsilon) status = false; + if( Math.abs( this.m22 - m1.m22) > epsilon) status = false; + + return( status ); + + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Matrix3f objects with identical data values + * (i.e., Matrix3f.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashFloatBits(bits, m00); + bits = VecMathUtil.hashFloatBits(bits, m01); + bits = VecMathUtil.hashFloatBits(bits, m02); + bits = VecMathUtil.hashFloatBits(bits, m10); + bits = VecMathUtil.hashFloatBits(bits, m11); + bits = VecMathUtil.hashFloatBits(bits, m12); + bits = VecMathUtil.hashFloatBits(bits, m20); + bits = VecMathUtil.hashFloatBits(bits, m21); + bits = VecMathUtil.hashFloatBits(bits, m22); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Sets this matrix to all zeros. + */ + public final void setZero() + { + m00 = 0.0f; + m01 = 0.0f; + m02 = 0.0f; + + m10 = 0.0f; + m11 = 0.0f; + m12 = 0.0f; + + m20 = 0.0f; + m21 = 0.0f; + m22 = 0.0f; + + } + + /** + * Negates the value of this matrix: this = -this. + */ + public final void negate() + { + this.m00 = -this.m00; + this.m01 = -this.m01; + this.m02 = -this.m02; + + this.m10 = -this.m10; + this.m11 = -this.m11; + this.m12 = -this.m12; + + this.m20 = -this.m20; + this.m21 = -this.m21; + this.m22 = -this.m22; + + } + + /** + * Sets the value of this matrix equal to the negation of + * of the Matrix3f parameter. + * @param m1 the source matrix + */ + public final void negate(Matrix3f m1) + { + this.m00 = -m1.m00; + this.m01 = -m1.m01; + this.m02 = -m1.m02; + + this.m10 = -m1.m10; + this.m11 = -m1.m11; + this.m12 = -m1.m12; + + this.m20 = -m1.m20; + this.m21 = -m1.m21; + this.m22 = -m1.m22; + + } + + /** + * Multiply this matrix by the tuple t and place the result + * back into the tuple (t = this*t). + * @param t the tuple to be multiplied by this matrix and then replaced + */ + public final void transform(Tuple3f t) { + float x,y,z; + x = m00* t.x + m01*t.y + m02*t.z; + y = m10* t.x + m11*t.y + m12*t.z; + z = m20* t.x + m21*t.y + m22*t.z; + t.set(x,y,z); + } + + /** + * Multiply this matrix by the tuple t and and place the result + * into the tuple "result" (result = this*t). + * @param t the tuple to be multiplied by this matrix + * @param result the tuple into which the product is placed + */ + public final void transform(Tuple3f t, Tuple3f result) { + float x,y,z; + x = m00* t.x + m01*t.y + m02*t.z; + y = m10* t.x + m11*t.y + m12*t.z; + result.z = m20* t.x + m21*t.y + m22*t.z; + result.x = x; + result.y = y; + } + + /** + * perform SVD (if necessary to get rotational component + */ + void getScaleRotate( double[] scales, double[] rot ) { + + double[] tmp = new double[9]; // scratch matrix + tmp[0] = m00; + tmp[1] = m01; + tmp[2] = m02; + tmp[3] = m10; + tmp[4] = m11; + tmp[5] = m12; + tmp[6] = m20; + tmp[7] = m21; + tmp[8] = m22; + Matrix3d.compute_svd(tmp, scales, rot); + + return; + + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + Matrix3f m1 = null; + try { + m1 = (Matrix3f)super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + return m1; + } + + + /** + * Get the first matrix element in the first row. + * + * @return Returns the m00. + * + * @since vecmath 1.5 + */ + public final float getM00() { + return m00; + } + + /** + * Set the first matrix element in the first row. + * + * @param m00 The m00 to set. + * + * @since vecmath 1.5 + */ + public final void setM00(float m00) { + this.m00 = m00; + } + + /** + * Get the second matrix element in the first row. + * + * @return Returns the m01. + * + * + * @since vecmath 1.5 + */ + public final float getM01() { + return m01; + } + + /** + * Set the second matrix element in the first row. + * + * @param m01 The m01 to set. + * + * @since vecmath 1.5 + */ + public final void setM01(float m01) { + this.m01 = m01; + } + + /** + * Get the third matrix element in the first row. + * + * @return Returns the m02. + * + * @since vecmath 1.5 + */ + public final float getM02() { + return m02; + } + + /** + * Set the third matrix element in the first row. + * + * @param m02 The m02 to set. + * + * @since vecmath 1.5 + */ + public final void setM02(float m02) { + this.m02 = m02; + } + + /** + * Get first matrix element in the second row. + * + * @return Returns the m10. + * + * @since vecmath 1.5 + */ + public final float getM10() { + return m10; + } + + /** + * Set first matrix element in the second row. + * + * @param m10 The m10 to set. + * + * @since vecmath 1.5 + */ + public final void setM10(float m10) { + this.m10 = m10; + } + + /** + * Get second matrix element in the second row. + * + * @return Returns the m11. + * + * @since vecmath 1.5 + */ + public final float getM11() { + return m11; + } + + /** + * Set the second matrix element in the second row. + * + * @param m11 The m11 to set. + * + * @since vecmath 1.5 + */ + public final void setM11(float m11) { + this.m11 = m11; + } + + /** + * Get the third matrix element in the second row. + * + * @return Returns the m12. + * + * @since vecmath 1.5 + */ + public final float getM12() { + return m12; + } + + /** + * Set the third matrix element in the second row. + * @param m12 The m12 to set. + * @since vecmath 1.5 + */ + public final void setM12(float m12) { + this.m12 = m12; + } + + /** + * Get the first matrix element in the third row. + * + * @return Returns the m20. + * + * @since vecmath 1.5 + */ + public final float getM20() { + return m20; + } + + /** + * Set the first matrix element in the third row. + * + * @param m20 The m20 to set. + * + * @since vecmath 1.5 + */ + public final void setM20(float m20) { + this.m20 = m20; + } + + /** + * Get the second matrix element in the third row. + * + * @return Returns the m21. + * + * @since vecmath 1.5 + */ + public final float getM21() { + return m21; + } + + /** + * Set the second matrix element in the third row. + * + * @param m21 The m21 to set. + * + * @since vecmath 1.5 + */ + public final void setM21(float m21) { + this.m21 = m21; + } + + /** + * Get the third matrix element in the third row . + * + * @return Returns the m22. + * + * @since vecmath 1.5 + */ + public final float getM22() { + return m22; + } + + /** + * Set the third matrix element in the third row. + * + * @param m22 The m22 to set. + * + * @since vecmath 1.5 + */ + public final void setM22(float m22) { + this.m22 = m22; + } + +} diff --git a/src/org/jogamp/vecmath/Matrix4d.java b/src/org/jogamp/vecmath/Matrix4d.java new file mode 100644 index 0000000..b39d79d --- /dev/null +++ b/src/org/jogamp/vecmath/Matrix4d.java @@ -0,0 +1,3956 @@ +/* + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A double precision floating point 4 by 4 matrix. + * Primarily to support 3D rotations. + * + */ +public class Matrix4d implements java.io.Serializable, Cloneable { + + // Compatible with 1.1 + static final long serialVersionUID = 8223903484171633710L; + + /** + * The first element of the first row. + */ + public double m00; + + /** + * The second element of the first row. + */ + public double m01; + + /** + * The third element of the first row. + */ + public double m02; + + /** + * The fourth element of the first row. + */ + public double m03; + + /** + * The first element of the second row. + */ + public double m10; + + /** + * The second element of the second row. + */ + public double m11; + + /** + * The third element of the second row. + */ + public double m12; + + /** + * The fourth element of the second row. + */ + public double m13; + + /** + * The first element of the third row. + */ + public double m20; + + /** + * The second element of the third row. + */ + public double m21; + + /** + * The third element of the third row. + */ + public double m22; + + /** + * The fourth element of the third row. + */ + public double m23; + + /** + * The first element of the fourth row. + */ + public double m30; + + /** + * The second element of the fourth row. + */ + public double m31; + + /** + * The third element of the fourth row. + */ + public double m32; + + /** + * The fourth element of the fourth row. + */ + public double m33; + /* + double[] tmp = new double[16]; + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + */ + private static final double EPS = 1.0E-10; + + + /** + * Constructs and initializes a Matrix4d from the specified 16 values. + * @param m00 the [0][0] element + * @param m01 the [0][1] element + * @param m02 the [0][2] element + * @param m03 the [0][3] element + * @param m10 the [1][0] element + * @param m11 the [1][1] element + * @param m12 the [1][2] element + * @param m13 the [1][3] element + * @param m20 the [2][0] element + * @param m21 the [2][1] element + * @param m22 the [2][2] element + * @param m23 the [2][3] element + * @param m30 the [3][0] element + * @param m31 the [3][1] element + * @param m32 the [3][2] element + * @param m33 the [3][3] element + */ + public Matrix4d(double m00, double m01, double m02, double m03, + double m10, double m11, double m12, double m13, + double m20, double m21, double m22, double m23, + double m30, double m31, double m32, double m33) + { + this.m00 = m00; + this.m01 = m01; + this.m02 = m02; + this.m03 = m03; + + this.m10 = m10; + this.m11 = m11; + this.m12 = m12; + this.m13 = m13; + + this.m20 = m20; + this.m21 = m21; + this.m22 = m22; + this.m23 = m23; + + this.m30 = m30; + this.m31 = m31; + this.m32 = m32; + this.m33 = m33; + + } + + /** + * Constructs and initializes a Matrix4d from the specified 16 + * element array. this.m00 =v[0], this.m01=v[1], etc. + * @param v the array of length 16 containing in order + */ + public Matrix4d(double[] v) + { + this.m00 = v[ 0]; + this.m01 = v[ 1]; + this.m02 = v[ 2]; + this.m03 = v[ 3]; + + this.m10 = v[ 4]; + this.m11 = v[ 5]; + this.m12 = v[ 6]; + this.m13 = v[ 7]; + + this.m20 = v[ 8]; + this.m21 = v[ 9]; + this.m22 = v[10]; + this.m23 = v[11]; + + this.m30 = v[12]; + this.m31 = v[13]; + this.m32 = v[14]; + this.m33 = v[15]; + + } + + /** + * Constructs and initializes a Matrix4d from the quaternion, + * translation, and scale values; the scale is applied only to the + * rotational components of the matrix (upper 3x3) and not to the + * translational components. + * @param q1 the quaternion value representing the rotational component + * @param t1 the translational component of the matrix + * @param s the scale value applied to the rotational components + */ + public Matrix4d(Quat4d q1, Vector3d t1, double s) + { + m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z)); + m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y)); + + m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z)); + m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x)); + + m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y)); + m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x)); + m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + m03 = t1.x; + m13 = t1.y; + m23 = t1.z; + + m30 = 0.0; + m31 = 0.0; + m32 = 0.0; + m33 = 1.0; + + } + + /** + * Constructs and initializes a Matrix4d from the quaternion, + * translation, and scale values; the scale is applied only to the + * rotational components of the matrix (upper 3x3) and not to the + * translational components. + * @param q1 the quaternion value representing the rotational component + * @param t1 the translational component of the matrix + * @param s the scale value applied to the rotational components + */ + public Matrix4d(Quat4f q1, Vector3d t1, double s) + { + m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z)); + m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y)); + + m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z)); + m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x)); + + m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y)); + m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x)); + m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + m03 = t1.x; + m13 = t1.y; + m23 = t1.z; + + m30 = 0.0; + m31 = 0.0; + m32 = 0.0; + m33 = 1.0; + + } + + /** + * Constructs a new matrix with the same values as the + * Matrix4d parameter. + * @param m1 the source matrix + */ + public Matrix4d(Matrix4d m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + this.m03 = m1.m03; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + this.m13 = m1.m13; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + this.m23 = m1.m23; + + this.m30 = m1.m30; + this.m31 = m1.m31; + this.m32 = m1.m32; + this.m33 = m1.m33; + + } + + /** + * Constructs a new matrix with the same values as the + * Matrix4f parameter. + * @param m1 the source matrix + */ + public Matrix4d(Matrix4f m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + this.m03 = m1.m03; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + this.m13 = m1.m13; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + this.m23 = m1.m23; + + this.m30 = m1.m30; + this.m31 = m1.m31; + this.m32 = m1.m32; + this.m33 = m1.m33; + + } + + /** + * Constructs and initializes a Matrix4d from the rotation matrix, + * translation, and scale values; the scale is applied only to the + * rotational components of the matrix (upper 3x3) and not to the + * translational components of the matrix. + * @param m1 the rotation matrix representing the rotational components + * @param t1 the translational components of the matrix + * @param s the scale value applied to the rotational components + */ + public Matrix4d(Matrix3f m1, Vector3d t1, double s) + { + this.m00 = m1.m00*s; + this.m01 = m1.m01*s; + this.m02 = m1.m02*s; + this.m03 = t1.x; + + this.m10 = m1.m10*s; + this.m11 = m1.m11*s; + this.m12 = m1.m12*s; + this.m13 = t1.y; + + this.m20 = m1.m20*s; + this.m21 = m1.m21*s; + this.m22 = m1.m22*s; + this.m23 = t1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + + } + + /** + * Constructs and initializes a Matrix4f from the rotation matrix, + * translation, and scale values; the scale is applied only to the + * rotational components of the matrix (upper 3x3) and not to the + * translational components of the matrix. + * @param m1 the rotation matrix representing the rotational components + * @param t1 the translational components of the matrix + * @param s the scale value applied to the rotational components + */ + public Matrix4d(Matrix3d m1, Vector3d t1, double s) + { + this.m00 = m1.m00*s; + this.m01 = m1.m01*s; + this.m02 = m1.m02*s; + this.m03 = t1.x; + + this.m10 = m1.m10*s; + this.m11 = m1.m11*s; + this.m12 = m1.m12*s; + this.m13 = t1.y; + + this.m20 = m1.m20*s; + this.m21 = m1.m21*s; + this.m22 = m1.m22*s; + this.m23 = t1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + + } + + /** + * Constructs and initializes a Matrix4d to all zeros. + */ + public Matrix4d() + { + this.m00 = 0.0; + this.m01 = 0.0; + this.m02 = 0.0; + this.m03 = 0.0; + + this.m10 = 0.0; + this.m11 = 0.0; + this.m12 = 0.0; + this.m13 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = 0.0; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 0.0; + + } + + /** + * Returns a string that contains the values of this Matrix4d. + * @return the String representation + */ + @Override + public String toString() { + return + this.m00 + ", " + this.m01 + ", " + this.m02 + ", " + this.m03 + "\n" + + this.m10 + ", " + this.m11 + ", " + this.m12 + ", " + this.m13 + "\n" + + this.m20 + ", " + this.m21 + ", " + this.m22 + ", " + this.m23 + "\n" + + this.m30 + ", " + this.m31 + ", " + this.m32 + ", " + this.m33 + "\n"; + } + + /** + * Sets this Matrix4d to identity. + */ + public final void setIdentity() + { + this.m00 = 1.0; + this.m01 = 0.0; + this.m02 = 0.0; + this.m03 = 0.0; + + this.m10 = 0.0; + this.m11 = 1.0; + this.m12 = 0.0; + this.m13 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = 1.0; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the specified element of this matrix4f to the value provided. + * @param row the row number to be modified (zero indexed) + * @param column the column number to be modified (zero indexed) + * @param value the new value + */ + public final void setElement(int row, int column, double value) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + this.m00 = value; + break; + case 1: + this.m01 = value; + break; + case 2: + this.m02 = value; + break; + case 3: + this.m03 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0")); + } + break; + + case 1: + switch(column) + { + case 0: + this.m10 = value; + break; + case 1: + this.m11 = value; + break; + case 2: + this.m12 = value; + break; + case 3: + this.m13 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0")); + } + break; + + case 2: + switch(column) + { + case 0: + this.m20 = value; + break; + case 1: + this.m21 = value; + break; + case 2: + this.m22 = value; + break; + case 3: + this.m23 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0")); + } + break; + + case 3: + switch(column) + { + case 0: + this.m30 = value; + break; + case 1: + this.m31 = value; + break; + case 2: + this.m32 = value; + break; + case 3: + this.m33 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0")); + } + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d0")); + } + } + + /** + * Retrieves the value at the specified row and column of this matrix. + * @param row the row number to be retrieved (zero indexed) + * @param column the column number to be retrieved (zero indexed) + * @return the value at the indexed element + */ + public final double getElement(int row, int column) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + return(this.m00); + case 1: + return(this.m01); + case 2: + return(this.m02); + case 3: + return(this.m03); + default: + break; + } + break; + case 1: + switch(column) + { + case 0: + return(this.m10); + case 1: + return(this.m11); + case 2: + return(this.m12); + case 3: + return(this.m13); + default: + break; + } + break; + + case 2: + switch(column) + { + case 0: + return(this.m20); + case 1: + return(this.m21); + case 2: + return(this.m22); + case 3: + return(this.m23); + default: + break; + } + break; + + case 3: + switch(column) + { + case 0: + return(this.m30); + case 1: + return(this.m31); + case 2: + return(this.m32); + case 3: + return(this.m33); + default: + break; + } + break; + + default: + break; + } + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d1")); + } + + /** + * Copies the matrix values in the specified row into the vector parameter. + * @param row the matrix row + * @param v the vector into which the matrix row values will be copied + */ + public final void getRow(int row, Vector4d v) { + if( row == 0 ) { + v.x = m00; + v.y = m01; + v.z = m02; + v.w = m03; + } else if(row == 1) { + v.x = m10; + v.y = m11; + v.z = m12; + v.w = m13; + } else if(row == 2) { + v.x = m20; + v.y = m21; + v.z = m22; + v.w = m23; + } else if(row == 3) { + v.x = m30; + v.y = m31; + v.z = m32; + v.w = m33; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d2")); + } + } + + + /** + * Copies the matrix values in the specified row into the array parameter. + * @param row the matrix row + * @param v the array into which the matrix row values will be copied + */ + public final void getRow(int row, double v[]) { + if( row == 0 ) { + v[0] = m00; + v[1] = m01; + v[2] = m02; + v[3] = m03; + } else if(row == 1) { + v[0] = m10; + v[1] = m11; + v[2] = m12; + v[3] = m13; + } else if(row == 2) { + v[0] = m20; + v[1] = m21; + v[2] = m22; + v[3] = m23; + } else if(row == 3) { + v[0] = m30; + v[1] = m31; + v[2] = m32; + v[3] = m33; + } else { + + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d2")); + } + } + + + + /** + * Copies the matrix values in the specified column into the vector + * parameter. + * @param column the matrix column + * @param v the vector into which the matrix column values will be copied + */ + public final void getColumn(int column, Vector4d v) { + if( column == 0 ) { + v.x = m00; + v.y = m10; + v.z = m20; + v.w = m30; + } else if(column == 1) { + v.x = m01; + v.y = m11; + v.z = m21; + v.w = m31; + } else if(column == 2) { + v.x = m02; + v.y = m12; + v.z = m22; + v.w = m32; + } else if(column == 3) { + v.x = m03; + v.y = m13; + v.z = m23; + v.w = m33; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d3")); + + } + + } + + + + /** + * Copies the matrix values in the specified column into the array + * parameter. + * @param column the matrix column + * @param v the array into which the matrix column values will be copied + */ + public final void getColumn(int column, double v[]) { + if( column == 0 ) { + v[0] = m00; + v[1] = m10; + v[2] = m20; + v[3] = m30; + } else if(column == 1) { + v[0] = m01; + v[1] = m11; + v[2] = m21; + v[3] = m31; + } else if(column == 2) { + v[0] = m02; + v[1] = m12; + v[2] = m22; + v[3] = m32; + } else if(column == 3) { + v[0] = m03; + v[1] = m13; + v[2] = m23; + v[3] = m33; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d3")); + + } + + } + + + /** + * Performs an SVD normalization of this matrix in order to acquire + * the normalized rotational component; the values are placed into + * the Matrix3d parameter. + * @param m1 the matrix into which the rotational component is placed + */ + public final void get(Matrix3d m1) + { + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m1.m00 = tmp_rot[0]; + m1.m01 = tmp_rot[1]; + m1.m02 = tmp_rot[2]; + + m1.m10 = tmp_rot[3]; + m1.m11 = tmp_rot[4]; + m1.m12 = tmp_rot[5]; + + m1.m20 = tmp_rot[6]; + m1.m21 = tmp_rot[7]; + m1.m22 = tmp_rot[8]; + + } + + + /** + * Performs an SVD normalization of this matrix in order to acquire + * the normalized rotational component; the values are placed into + * the Matrix3f parameter. + * @param m1 the matrix into which the rotational component is placed + */ + public final void get(Matrix3f m1) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m1.m00 = (float)tmp_rot[0]; + m1.m01 = (float)tmp_rot[1]; + m1.m02 = (float)tmp_rot[2]; + + m1.m10 = (float)tmp_rot[3]; + m1.m11 = (float)tmp_rot[4]; + m1.m12 = (float)tmp_rot[5]; + + m1.m20 = (float)tmp_rot[6]; + m1.m21 = (float)tmp_rot[7]; + m1.m22 = (float)tmp_rot[8]; + } + + /** + * Performs an SVD normalization of this matrix to calculate + * the rotation as a 3x3 matrix, the translation, and the scale. + * None of the matrix values are modified. + * @param m1 the normalized matrix representing the rotation + * @param t1 the translation component + * @return the scale component of this transform + */ + public final double get(Matrix3d m1, Vector3d t1) + { + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m1.m00 = tmp_rot[0]; + m1.m01 = tmp_rot[1]; + m1.m02 = tmp_rot[2]; + + m1.m10 = tmp_rot[3]; + m1.m11 = tmp_rot[4]; + m1.m12 = tmp_rot[5]; + + m1.m20 = tmp_rot[6]; + m1.m21 = tmp_rot[7]; + m1.m22 = tmp_rot[8]; + + t1.x = m03; + t1.y = m13; + t1.z = m23; + + return( Matrix3d.max3( tmp_scale )); + + } + + /** + * Performs an SVD normalization of this matrix to calculate + * the rotation as a 3x3 matrix, the translation, and the scale. + * None of the matrix values are modified. + * @param m1 the normalized matrix representing the rotation + * @param t1 the translation component + * @return the scale component of this transform + */ + public final double get(Matrix3f m1, Vector3d t1){ + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m1.m00 = (float)tmp_rot[0]; + m1.m01 = (float)tmp_rot[1]; + m1.m02 = (float)tmp_rot[2]; + + m1.m10 = (float)tmp_rot[3]; + m1.m11 = (float)tmp_rot[4]; + m1.m12 = (float)tmp_rot[5]; + + m1.m20 = (float)tmp_rot[6]; + m1.m21 = (float)tmp_rot[7]; + m1.m22 = (float)tmp_rot[8]; + + t1.x = m03; + t1.y = m13; + t1.z = m23; + + return( Matrix3d.max3( tmp_scale )); + + } + + /** + * Performs an SVD normalization of this matrix in order to acquire + * the normalized rotational component; the values are placed into + * the Quat4f parameter. + * @param q1 quaternion into which the rotation component is placed + */ + public final void get(Quat4f q1) + { + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + double ww; + + ww = 0.25*(1.0 + tmp_rot[0] + tmp_rot[4] + tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.w = (float)Math.sqrt(ww); + ww = 0.25/q1.w; + q1.x = (float)((tmp_rot[7] - tmp_rot[5])*ww); + q1.y = (float)((tmp_rot[2] - tmp_rot[6])*ww); + q1.z = (float)((tmp_rot[3] - tmp_rot[1])*ww); + return; + } + + q1.w = 0.0f; + ww = -0.5*(tmp_rot[4] + tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.x = (float)Math.sqrt(ww); + ww = 0.5/q1.x; + q1.y = (float)(tmp_rot[3]*ww); + q1.z = (float)(tmp_rot[6]*ww); + return; + } + + q1.x = 0.0f; + ww = 0.5*(1.0 - tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.y = (float)(Math.sqrt(ww)); + q1.z = (float)(tmp_rot[7]/(2.0*q1.y)); + return; + } + + q1.y = 0.0f; + q1.z = 1.0f; + + } + + /** + * Performs an SVD normalization of q1 matrix in order to acquire + * the normalized rotational component; the values are placed into + * the Quat4d parameter. + * @param q1 the quaternion into which the rotation component is placed + */ + public final void get(Quat4d q1) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + double ww; + + ww = 0.25*(1.0 + tmp_rot[0] + tmp_rot[4] + tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.w = Math.sqrt(ww); + ww = 0.25/q1.w; + q1.x = (tmp_rot[7] - tmp_rot[5])*ww; + q1.y = (tmp_rot[2] - tmp_rot[6])*ww; + q1.z = (tmp_rot[3] - tmp_rot[1])*ww; + return; + } + + q1.w = 0.0f; + ww = -0.5*(tmp_rot[4] + tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.x = Math.sqrt(ww); + ww = 0.5/q1.x; + q1.y = tmp_rot[3]*ww; + q1.z = tmp_rot[6]*ww; + return; + } + + q1.x = 0.0; + ww = 0.5*(1.0 - tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.y = Math.sqrt(ww); + q1.z = tmp_rot[7]/(2.0*q1.y); + return; + } + + q1.y = 0.0; + q1.z = 1.0; + } + + /** + * Retrieves the translational components of this matrix. + * @param trans the vector that will receive the translational component + */ + public final void get(Vector3d trans) + { + trans.x = m03; + trans.y = m13; + trans.z = m23; + } + + /** + * Gets the upper 3x3 values of this matrix and places them into + * the matrix m1. + * @param m1 the matrix that will hold the values + */ + public final void getRotationScale(Matrix3f m1) + { + m1.m00 = (float)m00; m1.m01 = (float)m01; m1.m02 = (float)m02; + m1.m10 = (float)m10; m1.m11 = (float)m11; m1.m12 = (float)m12; + m1.m20 = (float)m20; m1.m21 = (float)m21; m1.m22 = (float)m22; + } + + /** + * Gets the upper 3x3 values of this matrix and places them into + * the matrix m1. + * @param m1 the matrix that will hold the values + */ + public final void getRotationScale(Matrix3d m1) + { + m1.m00 = m00; m1.m01 = m01; m1.m02 = m02; + m1.m10 = m10; m1.m11 = m11; m1.m12 = m12; + m1.m20 = m20; m1.m21 = m21; m1.m22 = m22; + } + + /** + * Performs an SVD normalization of this matrix to calculate + * and return the uniform scale factor. If the matrix has non-uniform + * scale factors, the largest of the x, y, and z scale factors will + * be returned. This matrix is not modified. + * @return the scale factor of this matrix + */ + public final double getScale() + { + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + return( Matrix3d.max3( tmp_scale )); + + } + + /** + * Replaces the upper 3x3 matrix values of this matrix with the + * values in the matrix m1. + * @param m1 the matrix that will be the new upper 3x3 + */ + public final void setRotationScale(Matrix3d m1) + { + m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; + m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; + m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; + } + + /** + * Replaces the upper 3x3 matrix values of this matrix with the + * values in the matrix m1. + * @param m1 the matrix that will be the new upper 3x3 + */ + public final void setRotationScale(Matrix3f m1) + { + m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; + m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; + m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; + } + + /** + * Sets the scale component of the current matrix by factoring + * out the current scale (by doing an SVD) from the rotational + * component and multiplying by the new scale. + * @param scale the new scale amount + */ + public final void setScale(double scale) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = tmp_rot[0]*scale; + m01 = tmp_rot[1]*scale; + m02 = tmp_rot[2]*scale; + + m10 = tmp_rot[3]*scale; + m11 = tmp_rot[4]*scale; + m12 = tmp_rot[5]*scale; + + m20 = tmp_rot[6]*scale; + m21 = tmp_rot[7]*scale; + m22 = tmp_rot[8]*scale; + + } + + /** + * Sets the specified row of this matrix4d to the four values provided. + * @param row the row number to be modified (zero indexed) + * @param x the first column element + * @param y the second column element + * @param z the third column element + * @param w the fourth column element + */ + public final void setRow(int row, double x, double y, double z, double w) + { + switch (row) { + case 0: + this.m00 = x; + this.m01 = y; + this.m02 = z; + this.m03 = w; + break; + + case 1: + this.m10 = x; + this.m11 = y; + this.m12 = z; + this.m13 = w; + break; + + case 2: + this.m20 = x; + this.m21 = y; + this.m22 = z; + this.m23 = w; + break; + + case 3: + this.m30 = x; + this.m31 = y; + this.m32 = z; + this.m33 = w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d4")); + + } + } + + /** + * Sets the specified row of this matrix4d to the Vector provided. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, Vector4d v) + { + switch (row) { + case 0: + this.m00 = v.x; + this.m01 = v.y; + this.m02 = v.z; + this.m03 = v.w; + break; + + case 1: + this.m10 = v.x; + this.m11 = v.y; + this.m12 = v.z; + this.m13 = v.w; + break; + + case 2: + this.m20 = v.x; + this.m21 = v.y; + this.m22 = v.z; + this.m23 = v.w; + break; + + case 3: + this.m30 = v.x; + this.m31 = v.y; + this.m32 = v.z; + this.m33 = v.w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d4")); + } + } + + /** + * Sets the specified row of this matrix4d to the four values provided. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, double v[]) + { + switch (row) { + case 0: + this.m00 = v[0]; + this.m01 = v[1]; + this.m02 = v[2]; + this.m03 = v[3]; + break; + + case 1: + this.m10 = v[0]; + this.m11 = v[1]; + this.m12 = v[2]; + this.m13 = v[3]; + break; + + case 2: + this.m20 = v[0]; + this.m21 = v[1]; + this.m22 = v[2]; + this.m23 = v[3]; + break; + + case 3: + this.m30 = v[0]; + this.m31 = v[1]; + this.m32 = v[2]; + this.m33 = v[3]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d4")); + } + } + + /** + * Sets the specified column of this matrix4d to the four values provided. + * @param column the column number to be modified (zero indexed) + * @param x the first row element + * @param y the second row element + * @param z the third row element + * @param w the fourth row element + */ + public final void setColumn(int column, double x, double y, double z, double w) + { + switch (column) { + case 0: + this.m00 = x; + this.m10 = y; + this.m20 = z; + this.m30 = w; + break; + + case 1: + this.m01 = x; + this.m11 = y; + this.m21 = z; + this.m31 = w; + break; + + case 2: + this.m02 = x; + this.m12 = y; + this.m22 = z; + this.m32 = w; + break; + + case 3: + this.m03 = x; + this.m13 = y; + this.m23 = z; + this.m33 = w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d7")); + } + } + + /** + * Sets the specified column of this matrix4d to the vector provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, Vector4d v) + { + switch (column) { + case 0: + this.m00 = v.x; + this.m10 = v.y; + this.m20 = v.z; + this.m30 = v.w; + break; + + case 1: + this.m01 = v.x; + this.m11 = v.y; + this.m21 = v.z; + this.m31 = v.w; + break; + + case 2: + this.m02 = v.x; + this.m12 = v.y; + this.m22 = v.z; + this.m32 = v.w; + break; + + case 3: + this.m03 = v.x; + this.m13 = v.y; + this.m23 = v.z; + this.m33 = v.w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d7")); + } + } + + /** + * Sets the specified column of this matrix4d to the four values provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, double v[]) + { + switch (column) { + case 0: + this.m00 = v[0]; + this.m10 = v[1]; + this.m20 = v[2]; + this.m30 = v[3]; + break; + + case 1: + this.m01 = v[0]; + this.m11 = v[1]; + this.m21 = v[2]; + this.m31 = v[3]; + break; + + case 2: + this.m02 = v[0]; + this.m12 = v[1]; + this.m22 = v[2]; + this.m32 = v[3]; + break; + + case 3: + this.m03 = v[0]; + this.m13 = v[1]; + this.m23 = v[2]; + this.m33 = v[3]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4d7")); + } + } + + /** + * Adds a scalar to each component of this matrix. + * @param scalar the scalar adder + */ + public final void add(double scalar) + { + m00 += scalar; + m01 += scalar; + m02 += scalar; + m03 += scalar; + m10 += scalar; + m11 += scalar; + m12 += scalar; + m13 += scalar; + m20 += scalar; + m21 += scalar; + m22 += scalar; + m23 += scalar; + m30 += scalar; + m31 += scalar; + m32 += scalar; + m33 += scalar; + } + + /** + * Adds a scalar to each component of the matrix m1 and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar adder + * @param m1 the original matrix values + */ + public final void add(double scalar, Matrix4d m1) + { + this.m00 = m1.m00 + scalar; + this.m01 = m1.m01 + scalar; + this.m02 = m1.m02 + scalar; + this.m03 = m1.m03 + scalar; + this.m10 = m1.m10 + scalar; + this.m11 = m1.m11 + scalar; + this.m12 = m1.m12 + scalar; + this.m13 = m1.m13 + scalar; + this.m20 = m1.m20 + scalar; + this.m21 = m1.m21 + scalar; + this.m22 = m1.m22 + scalar; + this.m23 = m1.m23 + scalar; + this.m30 = m1.m30 + scalar; + this.m31 = m1.m31 + scalar; + this.m32 = m1.m32 + scalar; + this.m33 = m1.m33 + scalar; + } + + /** + * Sets the value of this matrix to the matrix sum of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void add(Matrix4d m1, Matrix4d m2) + { + this.m00 = m1.m00 + m2.m00; + this.m01 = m1.m01 + m2.m01; + this.m02 = m1.m02 + m2.m02; + this.m03 = m1.m03 + m2.m03; + + this.m10 = m1.m10 + m2.m10; + this.m11 = m1.m11 + m2.m11; + this.m12 = m1.m12 + m2.m12; + this.m13 = m1.m13 + m2.m13; + + this.m20 = m1.m20 + m2.m20; + this.m21 = m1.m21 + m2.m21; + this.m22 = m1.m22 + m2.m22; + this.m23 = m1.m23 + m2.m23; + + this.m30 = m1.m30 + m2.m30; + this.m31 = m1.m31 + m2.m31; + this.m32 = m1.m32 + m2.m32; + this.m33 = m1.m33 + m2.m33; + } + + /** + * Sets the value of this matrix to sum of itself and matrix m1. + * @param m1 the other matrix + */ + public final void add(Matrix4d m1) + { + this.m00 += m1.m00; + this.m01 += m1.m01; + this.m02 += m1.m02; + this.m03 += m1.m03; + + this.m10 += m1.m10; + this.m11 += m1.m11; + this.m12 += m1.m12; + this.m13 += m1.m13; + + this.m20 += m1.m20; + this.m21 += m1.m21; + this.m22 += m1.m22; + this.m23 += m1.m23; + + this.m30 += m1.m30; + this.m31 += m1.m31; + this.m32 += m1.m32; + this.m33 += m1.m33; + } + + /** + * Sets the value of this matrix to the matrix difference + * of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void sub(Matrix4d m1, Matrix4d m2) + { + this.m00 = m1.m00 - m2.m00; + this.m01 = m1.m01 - m2.m01; + this.m02 = m1.m02 - m2.m02; + this.m03 = m1.m03 - m2.m03; + + this.m10 = m1.m10 - m2.m10; + this.m11 = m1.m11 - m2.m11; + this.m12 = m1.m12 - m2.m12; + this.m13 = m1.m13 - m2.m13; + + this.m20 = m1.m20 - m2.m20; + this.m21 = m1.m21 - m2.m21; + this.m22 = m1.m22 - m2.m22; + this.m23 = m1.m23 - m2.m23; + + this.m30 = m1.m30 - m2.m30; + this.m31 = m1.m31 - m2.m31; + this.m32 = m1.m32 - m2.m32; + this.m33 = m1.m33 - m2.m33; + } + + + /** + * Sets the value of this matrix to the matrix difference of itself + * and matrix m1 (this = this - m1). + * @param m1 the other matrix + */ + public final void sub(Matrix4d m1) + { + this.m00 -= m1.m00; + this.m01 -= m1.m01; + this.m02 -= m1.m02; + this.m03 -= m1.m03; + + this.m10 -= m1.m10; + this.m11 -= m1.m11; + this.m12 -= m1.m12; + this.m13 -= m1.m13; + + this.m20 -= m1.m20; + this.m21 -= m1.m21; + this.m22 -= m1.m22; + this.m23 -= m1.m23; + + this.m30 -= m1.m30; + this.m31 -= m1.m31; + this.m32 -= m1.m32; + this.m33 -= m1.m33; + } + + /** + * Sets the value of this matrix to its transpose. + */ + public final void transpose() + { + double temp; + + temp = this.m10; + this.m10 = this.m01; + this.m01 = temp; + + temp = this.m20; + this.m20 = this.m02; + this.m02 = temp; + + temp = this.m30; + this.m30 = this.m03; + this.m03 = temp; + + temp = this.m21; + this.m21 = this.m12; + this.m12 = temp; + + temp = this.m31; + this.m31 = this.m13; + this.m13 = temp; + + temp = this.m32; + this.m32 = this.m23; + this.m23 = temp; + } + + /** + * Sets the value of this matrix to the transpose of the argument matrix + * @param m1 the matrix to be transposed + */ + public final void transpose(Matrix4d m1) + { + if (this != m1) { + this.m00 = m1.m00; + this.m01 = m1.m10; + this.m02 = m1.m20; + this.m03 = m1.m30; + + this.m10 = m1.m01; + this.m11 = m1.m11; + this.m12 = m1.m21; + this.m13 = m1.m31; + + this.m20 = m1.m02; + this.m21 = m1.m12; + this.m22 = m1.m22; + this.m23 = m1.m32; + + this.m30 = m1.m03; + this.m31 = m1.m13; + this.m32 = m1.m23; + this.m33 = m1.m33; + } else + this.transpose(); + } + + /** + * Sets the values in this Matrix4d equal to the row-major + * array parameter (ie, the first four elements of the + * array will be copied into the first row of this matrix, etc.). + * @param m the double precision array of length 16 + */ + public final void set(double[] m) + { + m00 = m[0]; + m01 = m[1]; + m02 = m[2]; + m03 = m[3]; + m10 = m[4]; + m11 = m[5]; + m12 = m[6]; + m13 = m[7]; + m20 = m[8]; + m21 = m[9]; + m22 = m[10]; + m23 = m[11]; + m30 = m[12]; + m31 = m[13]; + m32 = m[14]; + m33 = m[15]; + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the single precision Matrix3f argument; the other + * elements of this matrix are initialized as if this were an identity + * matrix (i.e., affine matrix with no translational component). + * @param m1 the double precision 3x3 matrix + */ + public final void set(Matrix3f m1) + { + m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; m03 = 0.0; + m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; m13 = 0.0; + m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; m23 = 0.0; + m30 = 0.0; m31 = 0.0 ; m32 = 0.0 ; m33 = 1.0; + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the double precision Matrix3d argument; the other + * elements of this matrix are initialized as if this were an identity + * matrix (i.e., affine matrix with no translational component). + * @param m1 the double precision 3x3 matrix + */ + public final void set(Matrix3d m1) + { + m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; m03 = 0.0; + m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; m13 = 0.0; + m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; m23 = 0.0; + m30 = 0.0; m31 = 0.0 ; m32 = 0.0 ; m33 = 1.0; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * (double precision) quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4d q1) + { + this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + this.m03 = 0.0; + this.m13 = 0.0; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * double precision axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4d a1) + { + double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + + if( mag < EPS ) { + m00 = 1.0; + m01 = 0.0; + m02 = 0.0; + + m10 = 0.0; + m11 = 1.0; + m12 = 0.0; + + m20 = 0.0; + m21 = 0.0; + m22 = 1.0; + } else { + mag = 1.0/mag; + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + + double sinTheta = Math.sin(a1.angle); + double cosTheta = Math.cos(a1.angle); + double t = 1.0 - cosTheta; + + double xz = ax * az; + double xy = ax * ay; + double yz = ay * az; + + m00 = t * ax * ax + cosTheta; + m01 = t * xy - sinTheta * az; + m02 = t * xz + sinTheta * ay; + + m10 = t * xy + sinTheta * az; + m11 = t * ay * ay + cosTheta; + m12 = t * yz - sinTheta * ax; + + m20 = t * xz - sinTheta * ay; + m21 = t * yz + sinTheta * ax; + m22 = t * az * az + cosTheta; + } + + m03 = 0.0; + m13 = 0.0; + m23 = 0.0; + + m30 = 0.0; + m31 = 0.0; + m32 = 0.0; + m33 = 1.0; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * single precision quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4f q1) + { + this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + this.m03 = 0.0; + this.m13 = 0.0; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * single precision axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4f a1) + { + double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + + if( mag < EPS ) { + m00 = 1.0; + m01 = 0.0; + m02 = 0.0; + + m10 = 0.0; + m11 = 1.0; + m12 = 0.0; + + m20 = 0.0; + m21 = 0.0; + m22 = 1.0; + } else { + mag = 1.0/mag; + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + + double sinTheta = Math.sin((double)a1.angle); + double cosTheta = Math.cos((double)a1.angle); + double t = 1.0 - cosTheta; + + double xz = ax * az; + double xy = ax * ay; + double yz = ay * az; + + m00 = t * ax * ax + cosTheta; + m01 = t * xy - sinTheta * az; + m02 = t * xz + sinTheta * ay; + + m10 = t * xy + sinTheta * az; + m11 = t * ay * ay + cosTheta; + m12 = t * yz - sinTheta * ax; + + m20 = t * xz - sinTheta * ay; + m21 = t * yz + sinTheta * ax; + m22 = t * az * az + cosTheta; + } + m03 = 0.0; + m13 = 0.0; + m23 = 0.0; + + m30 = 0.0; + m31 = 0.0; + m32 = 0.0; + m33 = 1.0; + } + + /** + * Sets the value of this matrix from the rotation expressed + * by the quaternion q1, the translation t1, and the scale s. + * @param q1 the rotation expressed as a quaternion + * @param t1 the translation + * @param s the scale value + */ + public final void set(Quat4d q1, Vector3d t1, double s) + { + this.m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + this.m03 = t1.x; + this.m13 = t1.y; + this.m23 = t1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix from the rotation expressed + * by the quaternion q1, the translation t1, and the scale s. + * @param q1 the rotation expressed as a quaternion + * @param t1 the translation + * @param s the scale value + */ + public final void set(Quat4f q1, Vector3d t1, double s) + { + this.m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + this.m03 = t1.x; + this.m13 = t1.y; + this.m23 = t1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix from the rotation expressed + * by the quaternion q1, the translation t1, and the scale s. + * @param q1 the rotation expressed as a quaternion + * @param t1 the translation + * @param s the scale value + */ + public final void set(Quat4f q1, Vector3f t1, float s) + { + this.m00 = s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = s*(2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = s*(2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = s*(2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = s*(2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = s*(2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = s*(2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + this.m03 = t1.x; + this.m13 = t1.y; + this.m23 = t1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix to a copy of the + * passed matrix m1. + * @param m1 the matrix4f + */ + public final void set(Matrix4f m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + this.m03 = m1.m03; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + this.m13 = m1.m13; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + this.m23 = m1.m23; + + this.m30 = m1.m30; + this.m31 = m1.m31; + this.m32 = m1.m32; + this.m33 = m1.m33; + } + + /** + * Sets the value of this matrix to a copy of the + * passed matrix m1. + * @param m1 the matrix to be copied + */ + public final void set(Matrix4d m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + this.m03 = m1.m03; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + this.m13 = m1.m13; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + this.m23 = m1.m23; + + this.m30 = m1.m30; + this.m31 = m1.m31; + this.m32 = m1.m32; + this.m33 = m1.m33; + } + + /** + * Sets the value of this matrix to the matrix inverse + * of the passed (user declared) matrix m1. + * @param m1 the matrix to be inverted + */ + public final void invert(Matrix4d m1) + { + + invertGeneral( m1); + } + + /** + * Inverts this matrix in place. + */ + public final void invert() + { + invertGeneral( this ); + } + + /** + * General invert routine. Inverts m1 and places the result in "this". + * Note that this routine handles both the "this" version and the + * non-"this" version. + * + * Also note that since this routine is slow anyway, we won't worry + * about allocating a little bit of garbage. + */ + final void invertGeneral(Matrix4d m1) { + double result[] = new double[16]; + int row_perm[] = new int[4]; + int i, r, c; + + // Use LU decomposition and backsubstitution code specifically + // for floating-point 4x4 matrices. + double[] tmp = new double[16]; // scratch matrix + // Copy source matrix to t1tmp + tmp[0] = m1.m00; + tmp[1] = m1.m01; + tmp[2] = m1.m02; + tmp[3] = m1.m03; + + tmp[4] = m1.m10; + tmp[5] = m1.m11; + tmp[6] = m1.m12; + tmp[7] = m1.m13; + + tmp[8] = m1.m20; + tmp[9] = m1.m21; + tmp[10] = m1.m22; + tmp[11] = m1.m23; + + tmp[12] = m1.m30; + tmp[13] = m1.m31; + tmp[14] = m1.m32; + tmp[15] = m1.m33; + + // Calculate LU decomposition: Is the matrix singular? + if (!luDecomposition(tmp, row_perm)) { + // Matrix has no inverse + throw new SingularMatrixException(VecMathI18N.getString("Matrix4d10")); + } + + // Perform back substitution on the identity matrix + for(i=0;i<16;i++) result[i] = 0.0; + result[0] = 1.0; result[5] = 1.0; result[10] = 1.0; result[15] = 1.0; + luBacksubstitution(tmp, row_perm, result); + + this.m00 = result[0]; + this.m01 = result[1]; + this.m02 = result[2]; + this.m03 = result[3]; + + this.m10 = result[4]; + this.m11 = result[5]; + this.m12 = result[6]; + this.m13 = result[7]; + + this.m20 = result[8]; + this.m21 = result[9]; + this.m22 = result[10]; + this.m23 = result[11]; + + this.m30 = result[12]; + this.m31 = result[13]; + this.m32 = result[14]; + this.m33 = result[15]; + + } + + /** + * Given a 4x4 array "matrix0", this function replaces it with the + * LU decomposition of a row-wise permutation of itself. The input + * parameters are "matrix0" and "dimen". The array "matrix0" is also + * an output parameter. The vector "row_perm[4]" is an output + * parameter that contains the row permutations resulting from partial + * pivoting. The output parameter "even_row_xchg" is 1 when the + * number of row exchanges is even, or -1 otherwise. Assumes data + * type is always double. + * + * This function is similar to luDecomposition, except that it + * is tuned specifically for 4x4 matrices. + * + * @return true if the matrix is nonsingular, or false otherwise. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 40-45. + // + static boolean luDecomposition(double[] matrix0, + int[] row_perm) { + + double row_scale[] = new double[4]; + + // Determine implicit scaling information by looping over rows + { + int i, j; + int ptr, rs; + double big, temp; + + ptr = 0; + rs = 0; + + // For each row ... + i = 4; + while (i-- != 0) { + big = 0.0; + + // For each column, find the largest element in the row + j = 4; + while (j-- != 0) { + temp = matrix0[ptr++]; + temp = Math.abs(temp); + if (temp > big) { + big = temp; + } + } + + // Is the matrix singular? + if (big == 0.0) { + return false; + } + row_scale[rs++] = 1.0 / big; + } + } + + { + int j; + int mtx; + + mtx = 0; + + // For all columns, execute Crout's method + for (j = 0; j < 4; j++) { + int i, imax, k; + int target, p1, p2; + double sum, big, temp; + + // Determine elements of upper diagonal matrix U + for (i = 0; i < j; i++) { + target = mtx + (4*i) + j; + sum = matrix0[target]; + k = i; + p1 = mtx + (4*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 4; + } + matrix0[target] = sum; + } + + // Search for largest pivot element and calculate + // intermediate elements of lower diagonal matrix L. + big = 0.0; + imax = -1; + for (i = j; i < 4; i++) { + target = mtx + (4*i) + j; + sum = matrix0[target]; + k = j; + p1 = mtx + (4*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 4; + } + matrix0[target] = sum; + + // Is this the best pivot so far? + if ((temp = row_scale[i] * Math.abs(sum)) >= big) { + big = temp; + imax = i; + } + } + + if (imax < 0) { + throw new RuntimeException(VecMathI18N.getString("Matrix4d11")); + } + + // Is a row exchange necessary? + if (j != imax) { + // Yes: exchange rows + k = 4; + p1 = mtx + (4*imax); + p2 = mtx + (4*j); + while (k-- != 0) { + temp = matrix0[p1]; + matrix0[p1++] = matrix0[p2]; + matrix0[p2++] = temp; + } + + // Record change in scale factor + row_scale[imax] = row_scale[j]; + } + + // Record row permutation + row_perm[j] = imax; + + // Is the matrix singular + if (matrix0[(mtx + (4*j) + j)] == 0.0) { + return false; + } + + // Divide elements of lower diagonal matrix L by pivot + if (j != (4-1)) { + temp = 1.0 / (matrix0[(mtx + (4*j) + j)]); + target = mtx + (4*(j+1)) + j; + i = 3 - j; + while (i-- != 0) { + matrix0[target] *= temp; + target += 4; + } + } + } + } + + return true; + } + + /** + * Solves a set of linear equations. The input parameters "matrix1", + * and "row_perm" come from luDecompostionD4x4 and do not change + * here. The parameter "matrix2" is a set of column vectors assembled + * into a 4x4 matrix of floating-point values. The procedure takes each + * column of "matrix2" in turn and treats it as the right-hand side of the + * matrix equation Ax = LUx = b. The solution vector replaces the + * original column of the matrix. + * + * If "matrix2" is the identity matrix, the procedure replaces its contents + * with the inverse of the matrix from which "matrix1" was originally + * derived. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 44-45. + // + static void luBacksubstitution(double[] matrix1, + int[] row_perm, + double[] matrix2) { + + int i, ii, ip, j, k; + int rp; + int cv, rv; + + // rp = row_perm; + rp = 0; + + // For each column vector of matrix2 ... + for (k = 0; k < 4; k++) { + // cv = &(matrix2[0][k]); + cv = k; + ii = -1; + + // Forward substitution + for (i = 0; i < 4; i++) { + double sum; + + ip = row_perm[rp+i]; + sum = matrix2[cv+4*ip]; + matrix2[cv+4*ip] = matrix2[cv+4*i]; + if (ii >= 0) { + // rv = &(matrix1[i][0]); + rv = i*4; + for (j = ii; j <= i-1; j++) { + sum -= matrix1[rv+j] * matrix2[cv+4*j]; + } + } + else if (sum != 0.0) { + ii = i; + } + matrix2[cv+4*i] = sum; + } + + // Backsubstitution + // rv = &(matrix1[3][0]); + rv = 3*4; + matrix2[cv+4*3] /= matrix1[rv+3]; + + rv -= 4; + matrix2[cv+4*2] = (matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+2]; + + rv -= 4; + matrix2[cv+4*1] = (matrix2[cv+4*1] - + matrix1[rv+2] * matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+1]; + + rv -= 4; + matrix2[cv+4*0] = (matrix2[cv+4*0] - + matrix1[rv+1] * matrix2[cv+4*1] - + matrix1[rv+2] * matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+0]; + } + } + + /** + * Computes the determinant of this matrix. + * @return the determinant of the matrix + */ + public final double determinant() + { + double det; + + // cofactor exapainsion along first row + + det = m00*(m11*m22*m33+ m12*m23*m31 + m13*m21*m32 + - m13*m22*m31 -m11*m23*m32 - m12*m21*m33); + det -= m01*(m10*m22*m33+ m12*m23*m30 + m13*m20*m32 + - m13*m22*m30 -m10*m23*m32 - m12*m20*m33); + det += m02*(m10*m21*m33+ m11*m23*m30 + m13*m20*m31 + - m13*m21*m30 -m10*m23*m31 - m11*m20*m33); + det -= m03*(m10*m21*m32+ m11*m22*m30 + m12*m20*m31 + - m12*m21*m30 -m10*m22*m31 - m11*m20*m32); + + return( det ); + } + + /** + * Sets the value of this matrix to a scale matrix with the + * passed scale amount. + * @param scale the scale factor for the matrix + */ + public final void set(double scale) + { + this.m00 = scale; + this.m01 = 0.0; + this.m02 = 0.0; + this.m03 = 0.0; + + this.m10 = 0.0; + this.m11 = scale; + this.m12 = 0.0; + this.m13 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = scale; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix to a translate matrix by the + * passed translation value. + * @param v1 the translation amount + */ + public final void set(Vector3d v1) + { + this.m00 = 1.0; + this.m01 = 0.0; + this.m02 = 0.0; + this.m03 = v1.x; + + this.m10 = 0.0; + this.m11 = 1.0; + this.m12 = 0.0; + this.m13 = v1.y; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = 1.0; + this.m23 = v1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this transform to a scale and translation matrix; + * the scale is not applied to the translation and all of the matrix + * values are modified. + * @param scale the scale factor for the matrix + * @param v1 the translation amount + */ + public final void set(double scale, Vector3d v1) + { + this.m00 = scale; + this.m01 = 0.0; + this.m02 = 0.0; + this.m03 = v1.x; + + this.m10 = 0.0; + this.m11 = scale; + this.m12 = 0.0; + this.m13 = v1.y; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = scale; + this.m23 = v1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this transform to a scale and translation matrix; + * the translation is scaled by the scale factor and all of the matrix + * values are modified. + * @param v1 the translation amount + * @param scale the scale factor for the matrix + */ + public final void set(Vector3d v1, double scale) + { + this.m00 = scale; + this.m01 = 0.0; + this.m02 = 0.0; + this.m03 = scale*v1.x; + + this.m10 = 0.0; + this.m11 = scale; + this.m12 = 0.0; + this.m13 = scale*v1.y; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = scale; + this.m23 = scale*v1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix from the rotation expressed by + * the rotation matrix m1, the translation t1, and the scale factor. + * The translation is not modified by the scale. + * @param m1 the rotation component + * @param t1 the translation component + * @param scale the scale component + */ + public final void set(Matrix3f m1, Vector3f t1, float scale) + { + this.m00 = m1.m00*scale; + this.m01 = m1.m01*scale; + this.m02 = m1.m02*scale; + this.m03 = t1.x; + + this.m10 = m1.m10*scale; + this.m11 = m1.m11*scale; + this.m12 = m1.m12*scale; + this.m13 = t1.y; + + this.m20 = m1.m20*scale; + this.m21 = m1.m21*scale; + this.m22 = m1.m22*scale; + this.m23 = t1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + + /** + * Sets the value of this matrix from the rotation expressed by + * the rotation matrix m1, the translation t1, and the scale factor. + * The translation is not modified by the scale. + * @param m1 the rotation component + * @param t1 the translation component + * @param scale the scale component + */ + public final void set(Matrix3d m1, Vector3d t1, double scale) + { + this.m00 = m1.m00*scale; + this.m01 = m1.m01*scale; + this.m02 = m1.m02*scale; + this.m03 = t1.x; + + this.m10 = m1.m10*scale; + this.m11 = m1.m11*scale; + this.m12 = m1.m12*scale; + this.m13 = t1.y; + + this.m20 = m1.m20*scale; + this.m21 = m1.m21*scale; + this.m22 = m1.m22*scale; + this.m23 = t1.z; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Modifies the translational components of this matrix to the values + * of the Vector3d argument; the other values of this matrix are not + * modified. + * @param trans the translational component + */ + public final void setTranslation(Vector3d trans) + { + m03 = trans.x; + m13 = trans.y; + m23 = trans.z; + } + + /** + * Sets the value of this matrix to a counter-clockwise rotation + * about the x axis. + * @param angle the angle to rotate about the X axis in radians + */ + public final void rotX(double angle) + { + double sinAngle, cosAngle; + + sinAngle = Math.sin(angle); + cosAngle = Math.cos(angle); + + this.m00 = 1.0; + this.m01 = 0.0; + this.m02 = 0.0; + this.m03 = 0.0; + + this.m10 = 0.0; + this.m11 = cosAngle; + this.m12 = -sinAngle; + this.m13 = 0.0; + + this.m20 = 0.0; + this.m21 = sinAngle; + this.m22 = cosAngle; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix to a counter-clockwise rotation + * about the y axis. + * @param angle the angle to rotate about the Y axis in radians + */ + public final void rotY(double angle) + { + double sinAngle, cosAngle; + + sinAngle = Math.sin(angle); + cosAngle = Math.cos(angle); + + this.m00 = cosAngle; + this.m01 = 0.0; + this.m02 = sinAngle; + this.m03 = 0.0; + + this.m10 = 0.0; + this.m11 = 1.0; + this.m12 = 0.0; + this.m13 = 0.0; + + this.m20 = -sinAngle; + this.m21 = 0.0; + this.m22 = cosAngle; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Sets the value of this matrix to a counter-clockwise rotation + * about the z axis. + * @param angle the angle to rotate about the Z axis in radians + */ + public final void rotZ(double angle) + { + double sinAngle, cosAngle; + + sinAngle = Math.sin(angle); + cosAngle = Math.cos(angle); + + this.m00 = cosAngle; + this.m01 = -sinAngle; + this.m02 = 0.0; + this.m03 = 0.0; + + this.m10 = sinAngle; + this.m11 = cosAngle; + this.m12 = 0.0; + this.m13 = 0.0; + + this.m20 = 0.0; + this.m21 = 0.0; + this.m22 = 1.0; + this.m23 = 0.0; + + this.m30 = 0.0; + this.m31 = 0.0; + this.m32 = 0.0; + this.m33 = 1.0; + } + + /** + * Multiplies each element of this matrix by a scalar. + * @param scalar the scalar multiplier. + */ + public final void mul(double scalar) + { + m00 *= scalar; + m01 *= scalar; + m02 *= scalar; + m03 *= scalar; + m10 *= scalar; + m11 *= scalar; + m12 *= scalar; + m13 *= scalar; + m20 *= scalar; + m21 *= scalar; + m22 *= scalar; + m23 *= scalar; + m30 *= scalar; + m31 *= scalar; + m32 *= scalar; + m33 *= scalar; + } + + /** + * Multiplies each element of matrix m1 by a scalar and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar multiplier + * @param m1 the original matrix + */ + public final void mul(double scalar, Matrix4d m1) + { + this.m00 = m1.m00 * scalar; + this.m01 = m1.m01 * scalar; + this.m02 = m1.m02 * scalar; + this.m03 = m1.m03 * scalar; + this.m10 = m1.m10 * scalar; + this.m11 = m1.m11 * scalar; + this.m12 = m1.m12 * scalar; + this.m13 = m1.m13 * scalar; + this.m20 = m1.m20 * scalar; + this.m21 = m1.m21 * scalar; + this.m22 = m1.m22 * scalar; + this.m23 = m1.m23 * scalar; + this.m30 = m1.m30 * scalar; + this.m31 = m1.m31 * scalar; + this.m32 = m1.m32 * scalar; + this.m33 = m1.m33 * scalar; + } + + /** + * Sets the value of this matrix to the result of multiplying itself + * with matrix m1. + * @param m1 the other matrix + */ + public final void mul(Matrix4d m1) + { + double m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33; // vars for temp result matrix + + m00 = this.m00*m1.m00 + this.m01*m1.m10 + + this.m02*m1.m20 + this.m03*m1.m30; + m01 = this.m00*m1.m01 + this.m01*m1.m11 + + this.m02*m1.m21 + this.m03*m1.m31; + m02 = this.m00*m1.m02 + this.m01*m1.m12 + + this.m02*m1.m22 + this.m03*m1.m32; + m03 = this.m00*m1.m03 + this.m01*m1.m13 + + this.m02*m1.m23 + this.m03*m1.m33; + + m10 = this.m10*m1.m00 + this.m11*m1.m10 + + this.m12*m1.m20 + this.m13*m1.m30; + m11 = this.m10*m1.m01 + this.m11*m1.m11 + + this.m12*m1.m21 + this.m13*m1.m31; + m12 = this.m10*m1.m02 + this.m11*m1.m12 + + this.m12*m1.m22 + this.m13*m1.m32; + m13 = this.m10*m1.m03 + this.m11*m1.m13 + + this.m12*m1.m23 + this.m13*m1.m33; + + m20 = this.m20*m1.m00 + this.m21*m1.m10 + + this.m22*m1.m20 + this.m23*m1.m30; + m21 = this.m20*m1.m01 + this.m21*m1.m11 + + this.m22*m1.m21 + this.m23*m1.m31; + m22 = this.m20*m1.m02 + this.m21*m1.m12 + + this.m22*m1.m22 + this.m23*m1.m32; + m23 = this.m20*m1.m03 + this.m21*m1.m13 + + this.m22*m1.m23 + this.m23*m1.m33; + + m30 = this.m30*m1.m00 + this.m31*m1.m10 + + this.m32*m1.m20 + this.m33*m1.m30; + m31 = this.m30*m1.m01 + this.m31*m1.m11 + + this.m32*m1.m21 + this.m33*m1.m31; + m32 = this.m30*m1.m02 + this.m31*m1.m12 + + this.m32*m1.m22 + this.m33*m1.m32; + m33 = this.m30*m1.m03 + this.m31*m1.m13 + + this.m32*m1.m23 + this.m33*m1.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + + /** + * Sets the value of this matrix to the result of multiplying + * the two argument matrices together. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void mul(Matrix4d m1, Matrix4d m2) + { + if (this != m1 && this != m2) { + // code for mat mul + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + + m1.m02*m2.m20 + m1.m03*m2.m30; + this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + + m1.m02*m2.m21 + m1.m03*m2.m31; + this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + + m1.m02*m2.m22 + m1.m03*m2.m32; + this.m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + + m1.m02*m2.m23 + m1.m03*m2.m33; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + + m1.m12*m2.m20 + m1.m13*m2.m30; + this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + + m1.m12*m2.m21 + m1.m13*m2.m31; + this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + + m1.m12*m2.m22 + m1.m13*m2.m32; + this.m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + + m1.m12*m2.m23 + m1.m13*m2.m33; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + + m1.m22*m2.m20 + m1.m23*m2.m30; + this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + + m1.m22*m2.m21 + m1.m23*m2.m31; + this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + + m1.m22*m2.m22 + m1.m23*m2.m32; + this.m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + + m1.m22*m2.m23 + m1.m23*m2.m33; + + this.m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + + m1.m32*m2.m20 + m1.m33*m2.m30; + this.m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + + m1.m32*m2.m21 + m1.m33*m2.m31; + this.m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + + m1.m32*m2.m22 + m1.m33*m2.m32; + this.m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + + m1.m32*m2.m23 + m1.m33*m2.m33; + } else { + double m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33; // vars for temp result matrix + + // code for mat mul + m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20 + m1.m03*m2.m30; + m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21 + m1.m03*m2.m31; + m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22 + m1.m03*m2.m32; + m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + m1.m02*m2.m23 + m1.m03*m2.m33; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20 + m1.m13*m2.m30; + m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21 + m1.m13*m2.m31; + m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22 + m1.m13*m2.m32; + m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + m1.m12*m2.m23 + m1.m13*m2.m33; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20 + m1.m23*m2.m30; + m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21 + m1.m23*m2.m31; + m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22 + m1.m23*m2.m32; + m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + m1.m22*m2.m23 + m1.m23*m2.m33; + + m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + m1.m32*m2.m20 + m1.m33*m2.m30; + m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + m1.m32*m2.m21 + m1.m33*m2.m31; + m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + m1.m32*m2.m22 + m1.m33*m2.m32; + m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + m1.m32*m2.m23 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + + } + } + + /** + * Multiplies the transpose of matrix m1 times the transpose of matrix + * m2, and places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeBoth(Matrix4d m1, Matrix4d m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03; + this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13; + this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23; + this.m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03; + this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13; + this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23; + this.m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03; + this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13; + this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23; + this.m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33; + + this.m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03; + this.m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13; + this.m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23; + this.m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33; + } else { + double m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, // vars for temp result matrix + m30, m31, m32, m33; + + m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03; + m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13; + m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23; + m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03; + m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13; + m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23; + m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03; + m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13; + m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23; + m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33; + + m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03; + m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13; + m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23; + m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + + } + + + + /** + * Multiplies matrix m1 times the transpose of matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeRight(Matrix4d m1, Matrix4d m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03; + this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13; + this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23; + this.m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03; + this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13; + this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23; + this.m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03; + this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13; + this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23; + this.m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33; + + this.m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03; + this.m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13; + this.m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23; + this.m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33; + } else { + double m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, // vars for temp result matrix + m30, m31, m32, m33; + + m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03; + m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13; + m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23; + m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03; + m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13; + m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23; + m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03; + m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13; + m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23; + m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33; + + m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03; + m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13; + m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23; + m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } +} + + + /** + * Multiplies the transpose of matrix m1 times matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeLeft(Matrix4d m1, Matrix4d m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30; + this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31; + this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32; + this.m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30; + this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31; + this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32; + this.m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30; + this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31; + this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32; + this.m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33; + + this.m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30; + this.m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31; + this.m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32; + this.m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33; + } else { + double m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, // vars for temp result matrix + m30, m31, m32, m33; + + + + m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30; + m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31; + m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32; + m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30; + m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31; + m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32; + m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30; + m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31; + m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32; + m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33; + + m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30; + m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31; + m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32; + m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + + } + + + /** + * Returns true if all of the data members of Matrix4d m1 are + * equal to the corresponding data members in this Matrix4d. + * @param m1 the matrix with which the comparison is made + * @return true or false + */ + public boolean equals(Matrix4d m1) + { + try { + return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02 + && this.m03 == m1.m03 && this.m10 == m1.m10 && this.m11 == m1.m11 + && this.m12 == m1.m12 && this.m13 == m1.m13 && this.m20 == m1.m20 + && this.m21 == m1.m21 && this.m22 == m1.m22 && this.m23 == m1.m23 + && this.m30 == m1.m30 && this.m31 == m1.m31 && this.m32 == m1.m32 + && this.m33 == m1.m33); + } + catch (NullPointerException e2) { return false; } + + } + + /** + * Returns true if the Object t1 is of type Matrix4d and all of the + * data members of t1 are equal to the corresponding data members in + * this Matrix4d. + * @param t1 the matrix with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Matrix4d m2 = (Matrix4d) t1; + return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02 + && this.m03 == m2.m03 && this.m10 == m2.m10 && this.m11 == m2.m11 + && this.m12 == m2.m12 && this.m13 == m2.m13 && this.m20 == m2.m20 + && this.m21 == m2.m21 && this.m22 == m2.m22 && this.m23 == m2.m23 + && this.m30 == m2.m30 && this.m31 == m2.m31 && this.m32 == m2.m32 + && this.m33 == m2.m33); + } + catch (ClassCastException e1) { return false; } + catch (NullPointerException e2) { return false; } + } + + /** + * @deprecated Use epsilonEquals(Matrix4d,double) instead + */ + public boolean epsilonEquals(Matrix4d m1, float epsilon) { + return epsilonEquals(m1, (double)epsilon); + } + + /** + * Returns true if the L-infinite distance between this matrix + * and matrix m1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[i=0,1,2,3 ; j=0,1,2,3 ; abs(this.m(i,j) - m1.m(i,j)] + * @param m1 the matrix to be compared to this matrix + * @param epsilon the threshold value + */ + public boolean epsilonEquals(Matrix4d m1, double epsilon) { + double diff; + + diff = m00 - m1.m00; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m01 - m1.m01; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m02 - m1.m02; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m03 - m1.m03; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m10 - m1.m10; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m11 - m1.m11; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m12 - m1.m12; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m13 - m1.m13; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m20 - m1.m20; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m21 - m1.m21; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m22 - m1.m22; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m23 - m1.m23; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m30 - m1.m30; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m31 - m1.m31; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m32 - m1.m32; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = m33 - m1.m33; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + } + + /** + * Returns a hash code value based on the data values in this + * object. Two different Matrix4d objects with identical data values + * (i.e., Matrix4d.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashDoubleBits(bits, m00); + bits = VecMathUtil.hashDoubleBits(bits, m01); + bits = VecMathUtil.hashDoubleBits(bits, m02); + bits = VecMathUtil.hashDoubleBits(bits, m03); + bits = VecMathUtil.hashDoubleBits(bits, m10); + bits = VecMathUtil.hashDoubleBits(bits, m11); + bits = VecMathUtil.hashDoubleBits(bits, m12); + bits = VecMathUtil.hashDoubleBits(bits, m13); + bits = VecMathUtil.hashDoubleBits(bits, m20); + bits = VecMathUtil.hashDoubleBits(bits, m21); + bits = VecMathUtil.hashDoubleBits(bits, m22); + bits = VecMathUtil.hashDoubleBits(bits, m23); + bits = VecMathUtil.hashDoubleBits(bits, m30); + bits = VecMathUtil.hashDoubleBits(bits, m31); + bits = VecMathUtil.hashDoubleBits(bits, m32); + bits = VecMathUtil.hashDoubleBits(bits, m33); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Transform the vector vec using this Matrix4d and place the + * result into vecOut. + * @param vec the double precision vector to be transformed + * @param vecOut the vector into which the transformed values are placed + */ + public final void transform(Tuple4d vec, Tuple4d vecOut) + { + double x,y,z,w; + x = (m00*vec.x + m01*vec.y + + m02*vec.z + m03*vec.w); + y = (m10*vec.x + m11*vec.y + + m12*vec.z + m13*vec.w); + z = (m20*vec.x + m21*vec.y + + m22*vec.z + m23*vec.w); + vecOut.w = (m30*vec.x + m31*vec.y + + m32*vec.z + m33*vec.w); + vecOut.x = x; + vecOut.y = y; + vecOut.z = z; + } + + /** + * Transform the vector vec using this Matrix4d and place the + * result back into vec. + * @param vec the double precision vector to be transformed + */ + public final void transform(Tuple4d vec) + { + double x,y,z; + + x = (m00*vec.x + m01*vec.y + + m02*vec.z + m03*vec.w); + y = (m10*vec.x + m11*vec.y + + m12*vec.z + m13*vec.w); + z = (m20*vec.x + m21*vec.y + + m22*vec.z + m23*vec.w); + vec.w = (m30*vec.x + m31*vec.y + + m32*vec.z + m33*vec.w); + vec.x = x; + vec.y = y; + vec.z = z; + } + + /** + * Transform the vector vec using this Matrix4d and place the + * result into vecOut. + * @param vec the single precision vector to be transformed + * @param vecOut the vector into which the transformed values are placed + */ + public final void transform(Tuple4f vec, Tuple4f vecOut) + { + float x,y,z; + x = (float) (m00*vec.x + m01*vec.y + + m02*vec.z + m03*vec.w); + y = (float) (m10*vec.x + m11*vec.y + + m12*vec.z + m13*vec.w); + z = (float) (m20*vec.x + m21*vec.y + + m22*vec.z + m23*vec.w); + vecOut.w = (float) (m30*vec.x + m31*vec.y + + m32*vec.z + m33*vec.w); + vecOut.x = x; + vecOut.y = y; + vecOut.z = z; + } + + /** + * Transform the vector vec using this Transform and place the + * result back into vec. + * @param vec the single precision vector to be transformed + */ + public final void transform(Tuple4f vec) + { + float x,y,z; + + x = (float) (m00*vec.x + m01*vec.y + + m02*vec.z + m03*vec.w); + y = (float) (m10*vec.x + m11*vec.y + + m12*vec.z + m13*vec.w); + z = (float) (m20*vec.x + m21*vec.y + + m22*vec.z + m23*vec.w); + vec.w = (float) (m30*vec.x + m31*vec.y + + m32*vec.z + m33*vec.w); + vec.x = x; + vec.y = y; + vec.z = z; + } + + + /** + * Transforms the point parameter with this Matrix4d and + * places the result into pointOut. The fourth element of the + * point input parameter is assumed to be one. + * @param point the input point to be transformed. + * @param pointOut the transformed point + */ + public final void transform(Point3d point, Point3d pointOut) + { + double x,y; + x = m00*point.x + m01*point.y + m02*point.z + m03; + y = m10*point.x + m11*point.y + m12*point.z + m13; + pointOut.z = m20*point.x + m21*point.y + m22*point.z + m23; + pointOut.x = x; + pointOut.y = y; + + } + + + /** + * Transforms the point parameter with this Matrix4d and + * places the result back into point. The fourth element of the + * point input parameter is assumed to be one. + * @param point the input point to be transformed. + */ + public final void transform(Point3d point) + { + double x, y; + x = m00*point.x + m01*point.y + m02*point.z + m03; + y = m10*point.x + m11*point.y + m12*point.z + m13; + point.z = m20*point.x + m21*point.y + m22*point.z + m23; + point.x = x; + point.y = y; + } + + + /** + * Transforms the point parameter with this Matrix4d and + * places the result into pointOut. The fourth element of the + * point input parameter is assumed to be one. + * @param point the input point to be transformed. + * @param pointOut the transformed point + */ + public final void transform(Point3f point, Point3f pointOut) + { + float x,y; + + x = (float) (m00*point.x + m01*point.y + m02*point.z + m03); + y = (float) (m10*point.x + m11*point.y + m12*point.z + m13); + pointOut.z = (float) (m20*point.x + m21*point.y + m22*point.z + m23); + pointOut.x = x; + pointOut.y = y; + } + + + /** + * Transforms the point parameter with this Matrix4d and + * places the result back into point. The fourth element of the + * point input parameter is assumed to be one. + * @param point the input point to be transformed. + */ + public final void transform(Point3f point) + { + float x, y; + x = (float) (m00*point.x + m01*point.y + m02*point.z + m03); + y = (float) (m10*point.x + m11*point.y + m12*point.z + m13); + point.z = (float) (m20*point.x + m21*point.y + m22*point.z + m23); + point.x = x; + point.y = y; + } + + + /** + * Transforms the normal parameter by this Matrix4d and places the value + * into normalOut. The fourth element of the normal is assumed to be zero. + * @param normal the input normal to be transformed. + * @param normalOut the transformed normal + */ + public final void transform(Vector3d normal, Vector3d normalOut) + { + double x,y; + x = m00*normal.x + m01*normal.y + m02*normal.z; + y = m10*normal.x + m11*normal.y + m12*normal.z; + normalOut.z = m20*normal.x + m21*normal.y + m22*normal.z; + normalOut.x = x; + normalOut.y = y; + } + + + /** + * Transforms the normal parameter by this transform and places the value + * back into normal. The fourth element of the normal is assumed to be zero. + * @param normal the input normal to be transformed. + */ + public final void transform(Vector3d normal) + { + double x, y; + + x = m00*normal.x + m01*normal.y + m02*normal.z; + y = m10*normal.x + m11*normal.y + m12*normal.z; + normal.z = m20*normal.x + m21*normal.y + m22*normal.z; + normal.x = x; + normal.y = y; + } + + + /** + * Transforms the normal parameter by this Matrix4d and places the value + * into normalOut. The fourth element of the normal is assumed to be zero. + * @param normal the input normal to be transformed. + * @param normalOut the transformed normal + */ + public final void transform(Vector3f normal, Vector3f normalOut) + { + float x,y; + x = (float) (m00*normal.x + m01*normal.y + m02*normal.z); + y = (float) (m10*normal.x + m11*normal.y + m12*normal.z); + normalOut.z = (float) (m20*normal.x + m21*normal.y + m22*normal.z); + normalOut.x = x; + normalOut.y = y; + } + + + /** + * Transforms the normal parameter by this transform and places the value + * back into normal. The fourth element of the normal is assumed to be zero. + * @param normal the input normal to be transformed. + */ + public final void transform(Vector3f normal) + { + float x, y; + + x = (float) (m00*normal.x + m01*normal.y + m02*normal.z); + y = (float) (m10*normal.x + m11*normal.y + m12*normal.z); + normal.z = (float) (m20*normal.x + m21*normal.y + m22*normal.z); + normal.x = x; + normal.y = y; + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the double precision Matrix3d argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the passed rotation components, + * and then the scale is reapplied to the rotational components. + * @param m1 double precision 3x3 matrix + */ + public final void setRotation( Matrix3d m1){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = m1.m00*tmp_scale[0]; + m01 = m1.m01*tmp_scale[1]; + m02 = m1.m02*tmp_scale[2]; + + m10 = m1.m10*tmp_scale[0]; + m11 = m1.m11*tmp_scale[1]; + m12 = m1.m12*tmp_scale[2]; + + m20 = m1.m20*tmp_scale[0]; + m21 = m1.m21*tmp_scale[1]; + m22 = m1.m22*tmp_scale[2]; + + } + + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the single precision Matrix3f argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the passed rotation components, + * and then the scale is reapplied to the rotational components. + * @param m1 single precision 3x3 matrix + */ + public final void setRotation( Matrix3f m1) + { + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = m1.m00*tmp_scale[0]; + m01 = m1.m01*tmp_scale[1]; + m02 = m1.m02*tmp_scale[2]; + + m10 = m1.m10*tmp_scale[0]; + m11 = m1.m11*tmp_scale[1]; + m12 = m1.m12*tmp_scale[2]; + + m20 = m1.m20*tmp_scale[0]; + m21 = m1.m21*tmp_scale[1]; + m22 = m1.m22*tmp_scale[2]; + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix equivalent values of the quaternion argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the matrix equivalent of the quaternion, + * and then the scale is reapplied to the rotational components. + * @param q1 the quaternion that specifies the rotation + */ + public final void setRotation(Quat4f q1){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = (1.0 - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0]; + m10 = (2.0*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0]; + m20 = (2.0*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0]; + + m01 = (2.0*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1]; + m11 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1]; + m21 = (2.0*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1]; + + m02 = (2.0*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2]; + m12 = (2.0*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2]; + m22 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2]; + + } + + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix equivalent values of the quaternion argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the matrix equivalent of the quaternion, + * and then the scale is reapplied to the rotational components. + * @param q1 the quaternion that specifies the rotation + */ + public final void setRotation(Quat4d q1){ + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = (1.0 - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0]; + m10 = (2.0*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0]; + m20 = (2.0*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0]; + + m01 = (2.0*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1]; + m11 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1]; + m21 = (2.0*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1]; + + m02 = (2.0*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2]; + m12 = (2.0*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2]; + m22 = (1.0 - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2]; + + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix equivalent values of the axis-angle argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the matrix equivalent of the axis-angle, + * and then the scale is reapplied to the rotational components. + * @param a1 the axis-angle to be converted (x, y, z, angle) + */ + public final void setRotation(AxisAngle4d a1) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + double mag = 1.0/Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + + double sinTheta = Math.sin(a1.angle); + double cosTheta = Math.cos(a1.angle); + double t = 1.0 - cosTheta; + + double xz = a1.x * a1.z; + double xy = a1.x * a1.y; + double yz = a1.y * a1.z; + + m00 = (t * ax * ax + cosTheta)*tmp_scale[0]; + m01 = (t * xy - sinTheta * az)*tmp_scale[1]; + m02 = (t * xz + sinTheta * ay)*tmp_scale[2]; + + m10 = (t * xy + sinTheta * az)*tmp_scale[0]; + m11 = (t * ay * ay + cosTheta)*tmp_scale[1]; + m12 = (t * yz - sinTheta * ax)*tmp_scale[2]; + + m20 = (t * xz - sinTheta * ay)*tmp_scale[0]; + m21 = (t * yz + sinTheta * ax)*tmp_scale[1]; + m22 = (t * az * az + cosTheta)*tmp_scale[2]; + + } + + /** + * Sets this matrix to all zeros. + */ + public final void setZero() + { + m00 = 0.0; + m01 = 0.0; + m02 = 0.0; + m03 = 0.0; + m10 = 0.0; + m11 = 0.0; + m12 = 0.0; + m13 = 0.0; + m20 = 0.0; + m21 = 0.0; + m22 = 0.0; + m23 = 0.0; + m30 = 0.0; + m31 = 0.0; + m32 = 0.0; + m33 = 0.0; + } + + /** + * Negates the value of this matrix: this = -this. + */ + public final void negate() + { + m00 = -m00; + m01 = -m01; + m02 = -m02; + m03 = -m03; + m10 = -m10; + m11 = -m11; + m12 = -m12; + m13 = -m13; + m20 = -m20; + m21 = -m21; + m22 = -m22; + m23 = -m23; + m30 = -m30; + m31 = -m31; + m32 = -m32; + m33 = -m33; + } + + /** + * Sets the value of this matrix equal to the negation of + * of the Matrix4d parameter. + * @param m1 the source matrix + */ + public final void negate(Matrix4d m1) + { + this.m00 = -m1.m00; + this.m01 = -m1.m01; + this.m02 = -m1.m02; + this.m03 = -m1.m03; + this.m10 = -m1.m10; + this.m11 = -m1.m11; + this.m12 = -m1.m12; + this.m13 = -m1.m13; + this.m20 = -m1.m20; + this.m21 = -m1.m21; + this.m22 = -m1.m22; + this.m23 = -m1.m23; + this.m30 = -m1.m30; + this.m31 = -m1.m31; + this.m32 = -m1.m32; + this.m33 = -m1.m33; + } + private final void getScaleRotate(double scales[], double rots[]) { + double[] tmp = new double[9]; // scratch matrix + tmp[0] = m00; + tmp[1] = m01; + tmp[2] = m02; + + tmp[3] = m10; + tmp[4] = m11; + tmp[5] = m12; + + tmp[6] = m20; + tmp[7] = m21; + tmp[8] = m22; + + Matrix3d.compute_svd( tmp, scales, rots); + + return; + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + Matrix4d m1 = null; + try { + m1 = (Matrix4d)super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + + return m1; + } + + /** + * Get the first matrix element in the first row. + * + * @return Returns the m00. + * + * @since vecmath 1.5 + */ + public final double getM00() { + return m00; + } + + /** + * Set the first matrix element in the first row. + * + * @param m00 The m00 to set. + * + * + * @since vecmath 1.5 + */ + public final void setM00(double m00) { + this.m00 = m00; + } + + /** + * Get the second matrix element in the first row. + * + * @return Returns the m01. + * + * @since vecmath 1.5 + */ + public final double getM01() { + return m01; + } + + /** + * Set the second matrix element in the first row. + * + * @param m01 The m01 to set. + * + * @since vecmath 1.5 + */ + public final void setM01(double m01) { + this.m01 = m01; + } + + /** + * Get the third matrix element in the first row. + * + * @return Returns the m02. + * + * @since vecmath 1.5 + */ + public final double getM02() { + return m02; + } + + /** + * Set the third matrix element in the first row. + * + * @param m02 The m02 to set. + * + * @since vecmath 1.5 + */ + public final void setM02(double m02) { + this.m02 = m02; + } + + /** + * Get first matrix element in the second row. + * + * @return Returns the m10. + * + * @since vecmath 1.5 + */ + public final double getM10() { + return m10; + } + + /** + * Set first matrix element in the second row. + * + * @param m10 The m10 to set. + * + * @since vecmath 1.5 + */ + public final void setM10(double m10) { + this.m10 = m10; + } + + /** + * Get second matrix element in the second row. + * + * @return Returns the m11. + * + * @since vecmath 1.5 + */ + public final double getM11() { + return m11; + } + + /** + * Set the second matrix element in the second row. + * + * @param m11 The m11 to set. + * + * @since vecmath 1.5 + */ + public final void setM11(double m11) { + this.m11 = m11; + } + + /** + * Get the third matrix element in the second row. + * + * @return Returns the m12. + * + * @since vecmath 1.5 + */ + public final double getM12() { + return m12; + } + + /** + * Set the third matrix element in the second row. + * + * @param m12 The m12 to set. + * + * + * @since vecmath 1.5 + */ + public final void setM12(double m12) { + this.m12 = m12; + } + + /** + * Get the first matrix element in the third row. + * + * @return Returns the m20. + * + * @since vecmath 1.5 + */ + public final double getM20() { + return m20; + } + + /** + * Set the first matrix element in the third row. + * + * @param m20 The m20 to set. + * + * @since vecmath 1.5 + */ + public final void setM20(double m20) { + this.m20 = m20; + } + + /** + * Get the second matrix element in the third row. + * + * @return Returns the m21. + * + * @since vecmath 1.5 + */ + public final double getM21() { + return m21; + } + + /** + * Set the second matrix element in the third row. + * + * @param m21 The m21 to set. + * + * @since vecmath 1.5 + */ + public final void setM21(double m21) { + this.m21 = m21; + } + + /** + * Get the third matrix element in the third row. + * + * @return Returns the m22. + * + * @since vecmath 1.5 + */ + public final double getM22() { + return m22; + } + + /** + * Set the third matrix element in the third row. + * + * @param m22 The m22 to set. + * + * @since vecmath 1.5 + */ + public final void setM22(double m22) { + this.m22 = m22; + } + + /** + * Get the fourth element of the first row. + * + * @return Returns the m03. + * + * @since vecmath 1.5 + */ + public final double getM03() { + return m03; + } + + /** + * Set the fourth element of the first row. + * + * @param m03 The m03 to set. + * + * @since vecmath 1.5 + */ + public final void setM03(double m03) { + this.m03 = m03; + } + + /** + * Get the fourth element of the second row. + * + * @return Returns the m13. + * + * @since vecmath 1.5 + */ + public final double getM13() { + return m13; + } + + /** + * Set the fourth element of the second row. + * + * @param m13 The m13 to set. + * + * @since vecmath 1.5 + */ + public final void setM13(double m13) { + this.m13 = m13; + } + + /** + * Get the fourth element of the third row. + * + * @return Returns the m23. + * + * @since vecmath 1.5 + */ + public final double getM23() { + return m23; + } + + /** + * Set the fourth element of the third row. + * + * @param m23 The m23 to set. + * + * @since vecmath 1.5 + */ + public final void setM23(double m23) { + this.m23 = m23; + } + + /** + * Get the first element of the fourth row. + * + * @return Returns the m30. + * + * @since vecmath 1.5 + */ + public final double getM30() { + return m30; + } + + /** + * Set the first element of the fourth row. + * + * @param m30 The m30 to set. + * + * @since vecmath 1.5 + */ + public final void setM30(double m30) { + this.m30 = m30; + } + + /** + * Get the second element of the fourth row. + * + * @return Returns the m31. + * + * @since vecmath 1.5 + */ + public final double getM31() { + return m31; + } + + /** + * Set the second element of the fourth row. + * + * @param m31 The m31 to set. + * + * @since vecmath 1.5 + */ + public final void setM31(double m31) { + this.m31 = m31; + } + + /** + * Get the third element of the fourth row. + * + * @return Returns the m32. + * + * + * @since vecmath 1.5 + */ + public final double getM32() { + return m32; + } + + /** + * Set the third element of the fourth row. + * + * @param m32 The m32 to set. + * + * @since vecmath 1.5 + */ + public final void setM32(double m32) { + this.m32 = m32; + } + + /** + * Get the fourth element of the fourth row. + * + * @return Returns the m33. + * + * @since vecmath 1.5 + */ + public final double getM33() { + return m33; + } + + /** + * Set the fourth element of the fourth row. + * + * @param m33 The m33 to set. + * + * @since vecmath 1.5 + */ + public final void setM33(double m33) { + this.m33 = m33; + } +} diff --git a/src/org/jogamp/vecmath/Matrix4f.java b/src/org/jogamp/vecmath/Matrix4f.java new file mode 100644 index 0000000..bd831d1 --- /dev/null +++ b/src/org/jogamp/vecmath/Matrix4f.java @@ -0,0 +1,3615 @@ +/* + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A single precision floating point 4 by 4 matrix. + * Primarily to support 3D rotations. + * + */ +public class Matrix4f implements java.io.Serializable, Cloneable { + + // Compatible with 1.1 + static final long serialVersionUID = -8405036035410109353L; + + /** + * The first element of the first row. + */ + public float m00; + + /** + * The second element of the first row. + */ + public float m01; + + /** + * The third element of the first row. + */ + public float m02; + + /** + * The fourth element of the first row. + */ + public float m03; + + /** + * The first element of the second row. + */ + public float m10; + + /** + * The second element of the second row. + */ + public float m11; + + /** + * The third element of the second row. + */ + public float m12; + + /** + * The fourth element of the second row. + */ + public float m13; + + /** + * The first element of the third row. + */ + public float m20; + + /** + * The second element of the third row. + */ + public float m21; + + /** + * The third element of the third row. + */ + public float m22; + + /** + * The fourth element of the third row. + */ + public float m23; + + /** + * The first element of the fourth row. + */ + public float m30; + + /** + * The second element of the fourth row. + */ + public float m31; + + /** + * The third element of the fourth row. + */ + public float m32; + + /** + * The fourth element of the fourth row. + */ + public float m33; + /* + double[] tmp = new double[9]; + double[] tmp_scale = new double[3]; + double[] tmp_rot = new double[9]; + */ + private static final double EPS = 1.0E-8; + + /** + * Constructs and initializes a Matrix4f from the specified 16 values. + * @param m00 the [0][0] element + * @param m01 the [0][1] element + * @param m02 the [0][2] element + * @param m03 the [0][3] element + * @param m10 the [1][0] element + * @param m11 the [1][1] element + * @param m12 the [1][2] element + * @param m13 the [1][3] element + * @param m20 the [2][0] element + * @param m21 the [2][1] element + * @param m22 the [2][2] element + * @param m23 the [2][3] element + * @param m30 the [3][0] element + * @param m31 the [3][1] element + * @param m32 the [3][2] element + * @param m33 the [3][3] element + */ + public Matrix4f(float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + this.m00 = m00; + this.m01 = m01; + this.m02 = m02; + this.m03 = m03; + + this.m10 = m10; + this.m11 = m11; + this.m12 = m12; + this.m13 = m13; + + this.m20 = m20; + this.m21 = m21; + this.m22 = m22; + this.m23 = m23; + + this.m30 = m30; + this.m31 = m31; + this.m32 = m32; + this.m33 = m33; + + } + + /** + * Constructs and initializes a Matrix4f from the specified 16 + * element array. this.m00 =v[0], this.m01=v[1], etc. + * @param v the array of length 16 containing in order + */ + public Matrix4f(float[] v) + { + this.m00 = v[ 0]; + this.m01 = v[ 1]; + this.m02 = v[ 2]; + this.m03 = v[ 3]; + + this.m10 = v[ 4]; + this.m11 = v[ 5]; + this.m12 = v[ 6]; + this.m13 = v[ 7]; + + this.m20 = v[ 8]; + this.m21 = v[ 9]; + this.m22 = v[10]; + this.m23 = v[11]; + + this.m30 = v[12]; + this.m31 = v[13]; + this.m32 = v[14]; + this.m33 = v[15]; + + } + + /** + * Constructs and initializes a Matrix4f from the quaternion, + * translation, and scale values; the scale is applied only to the + * rotational components of the matrix (upper 3x3) and not to the + * translational components. + * @param q1 the quaternion value representing the rotational component + * @param t1 the translational component of the matrix + * @param s the scale value applied to the rotational components + */ + public Matrix4f(Quat4f q1, Vector3f t1, float s) + { + m00 = (float)(s*(1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z)); + m10 = (float)(s*(2.0*(q1.x*q1.y + q1.w*q1.z))); + m20 = (float)(s*(2.0*(q1.x*q1.z - q1.w*q1.y))); + + m01 = (float)(s*(2.0*(q1.x*q1.y - q1.w*q1.z))); + m11 = (float)(s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z)); + m21 = (float)(s*(2.0*(q1.y*q1.z + q1.w*q1.x))); + + m02 = (float)(s*(2.0*(q1.x*q1.z + q1.w*q1.y))); + m12 = (float)(s*(2.0*(q1.y*q1.z - q1.w*q1.x))); + m22 = (float)(s*(1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y)); + + m03 = t1.x; + m13 = t1.y; + m23 = t1.z; + + m30 = 0.0f; + m31 = 0.0f; + m32 = 0.0f; + m33 = 1.0f; + + } + + /** + * Constructs a new matrix with the same values as the + * Matrix4d parameter. + * @param m1 the source matrix + */ + public Matrix4f(Matrix4d m1) + { + this.m00 = (float)m1.m00; + this.m01 = (float)m1.m01; + this.m02 = (float)m1.m02; + this.m03 = (float)m1.m03; + + this.m10 = (float)m1.m10; + this.m11 = (float)m1.m11; + this.m12 = (float)m1.m12; + this.m13 = (float)m1.m13; + + this.m20 = (float)m1.m20; + this.m21 = (float)m1.m21; + this.m22 = (float)m1.m22; + this.m23 = (float)m1.m23; + + this.m30 = (float)m1.m30; + this.m31 = (float)m1.m31; + this.m32 = (float)m1.m32; + this.m33 = (float)m1.m33; + + } + + + /** + * Constructs a new matrix with the same values as the + * Matrix4f parameter. + * @param m1 the source matrix + */ + public Matrix4f(Matrix4f m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + this.m03 = m1.m03; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + this.m13 = m1.m13; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + this.m23 = m1.m23; + + this.m30 = m1.m30; + this.m31 = m1.m31; + this.m32 = m1.m32; + this.m33 = m1.m33; + + } + + + /** + * Constructs and initializes a Matrix4f from the rotation matrix, + * translation, and scale values; the scale is applied only to the + * rotational components of the matrix (upper 3x3) and not to the + * translational components of the matrix. + * @param m1 the rotation matrix representing the rotational components + * @param t1 the translational components of the matrix + * @param s the scale value applied to the rotational components + */ + public Matrix4f(Matrix3f m1, Vector3f t1, float s) + { + this.m00 = m1.m00*s; + this.m01 = m1.m01*s; + this.m02 = m1.m02*s; + this.m03 = t1.x; + + this.m10 = m1.m10*s; + this.m11 = m1.m11*s; + this.m12 = m1.m12*s; + this.m13 = t1.y; + + this.m20 = m1.m20*s; + this.m21 = m1.m21*s; + this.m22 = m1.m22*s; + this.m23 = t1.z; + + this.m30 = 0.0f; + this.m31 = 0.0f; + this.m32 = 0.0f; + this.m33 = 1.0f; + + } + + + /** + * Constructs and initializes a Matrix4f to all zeros. + */ + public Matrix4f() + { + this.m00 = (float) 0.0; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + this.m03 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = (float) 0.0; + this.m12 = (float) 0.0; + this.m13 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = (float) 0.0; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 0.0; + + } + + /** + * Returns a string that contains the values of this Matrix4f. + * @return the String representation + */ + @Override + public String toString() { + return + this.m00 + ", " + this.m01 + ", " + this.m02 + ", " + this.m03 + "\n" + + this.m10 + ", " + this.m11 + ", " + this.m12 + ", " + this.m13 + "\n" + + this.m20 + ", " + this.m21 + ", " + this.m22 + ", " + this.m23 + "\n" + + this.m30 + ", " + this.m31 + ", " + this.m32 + ", " + this.m33 + "\n"; + } + + /** + * Sets this Matrix4f to identity. + */ + public final void setIdentity() + { + this.m00 = (float) 1.0; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + this.m03 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = (float) 1.0; + this.m12 = (float) 0.0; + this.m13 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = (float) 1.0; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the specified element of this matrix4f to the value provided. + * @param row the row number to be modified (zero indexed) + * @param column the column number to be modified (zero indexed) + * @param value the new value + */ + public final void setElement(int row, int column, float value) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + this.m00 = value; + break; + case 1: + this.m01 = value; + break; + case 2: + this.m02 = value; + break; + case 3: + this.m03 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0")); + } + break; + + case 1: + switch(column) + { + case 0: + this.m10 = value; + break; + case 1: + this.m11 = value; + break; + case 2: + this.m12 = value; + break; + case 3: + this.m13 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0")); + } + break; + + case 2: + switch(column) + { + case 0: + this.m20 = value; + break; + case 1: + this.m21 = value; + break; + case 2: + this.m22 = value; + break; + case 3: + this.m23 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0")); + } + break; + + case 3: + switch(column) + { + case 0: + this.m30 = value; + break; + case 1: + this.m31 = value; + break; + case 2: + this.m32 = value; + break; + case 3: + this.m33 = value; + break; + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0")); + } + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f0")); + } + } + + /** + * Retrieves the value at the specified row and column of this matrix. + * @param row the row number to be retrieved (zero indexed) + * @param column the column number to be retrieved (zero indexed) + * @return the value at the indexed element + */ + public final float getElement(int row, int column) + { + switch (row) + { + case 0: + switch(column) + { + case 0: + return(this.m00); + case 1: + return(this.m01); + case 2: + return(this.m02); + case 3: + return(this.m03); + default: + break; + } + break; + case 1: + switch(column) + { + case 0: + return(this.m10); + case 1: + return(this.m11); + case 2: + return(this.m12); + case 3: + return(this.m13); + default: + break; + } + break; + + case 2: + switch(column) + { + case 0: + return(this.m20); + case 1: + return(this.m21); + case 2: + return(this.m22); + case 3: + return(this.m23); + default: + break; + } + break; + + case 3: + switch(column) + { + case 0: + return(this.m30); + case 1: + return(this.m31); + case 2: + return(this.m32); + case 3: + return(this.m33); + default: + break; + } + break; + + default: + break; + } + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f1")); + } + + /** + * Copies the matrix values in the specified row into the vector parameter. + * @param row the matrix row + * @param v the vector into which the matrix row values will be copied + */ + public final void getRow(int row, Vector4f v) { + if( row == 0 ) { + v.x = m00; + v.y = m01; + v.z = m02; + v.w = m03; + } else if(row == 1) { + v.x = m10; + v.y = m11; + v.z = m12; + v.w = m13; + } else if(row == 2) { + v.x = m20; + v.y = m21; + v.z = m22; + v.w = m23; + } else if(row == 3) { + v.x = m30; + v.y = m31; + v.z = m32; + v.w = m33; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f2")); + } + + } + + /** + * Copies the matrix values in the specified row into the array parameter. + * @param row the matrix row + * @param v the array into which the matrix row values will be copied + */ + public final void getRow(int row, float v[]) { + if( row == 0 ) { + v[0] = m00; + v[1] = m01; + v[2] = m02; + v[3] = m03; + } else if(row == 1) { + v[0] = m10; + v[1] = m11; + v[2] = m12; + v[3] = m13; + } else if(row == 2) { + v[0] = m20; + v[1] = m21; + v[2] = m22; + v[3] = m23; + } else if(row == 3) { + v[0] = m30; + v[1] = m31; + v[2] = m32; + v[3] = m33; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f2")); + } + + } + + /** + * Copies the matrix values in the specified column into the vector + * parameter. + * @param column the matrix column + * @param v the vector into which the matrix row values will be copied + */ + public final void getColumn(int column, Vector4f v) { + if( column == 0 ) { + v.x = m00; + v.y = m10; + v.z = m20; + v.w = m30; + } else if(column == 1) { + v.x = m01; + v.y = m11; + v.z = m21; + v.w = m31; + } else if(column == 2) { + v.x = m02; + v.y = m12; + v.z = m22; + v.w = m32; + } else if(column == 3) { + v.x = m03; + v.y = m13; + v.z = m23; + v.w = m33; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f4")); + } + + } + + /** + * Copies the matrix values in the specified column into the array + * parameter. + * @param column the matrix column + * @param v the array into which the matrix row values will be copied + */ + public final void getColumn(int column, float v[]) { + if( column == 0 ) { + v[0] = m00; + v[1] = m10; + v[2] = m20; + v[3] = m30; + } else if(column == 1) { + v[0] = m01; + v[1] = m11; + v[2] = m21; + v[3] = m31; + } else if(column == 2) { + v[0] = m02; + v[1] = m12; + v[2] = m22; + v[3] = m32; + } else if(column == 3) { + v[0] = m03; + v[1] = m13; + v[2] = m23; + v[3] = m33; + } else { + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f4")); + } + + } + + + /** + * Sets the scale component of the current matrix by factoring + * out the current scale (by doing an SVD) from the rotational + * component and multiplying by the new scale. + * @param scale the new scale amount + */ + public final void setScale(float scale){ + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = (float)(tmp_rot[0]*scale); + m01 = (float)(tmp_rot[1]*scale); + m02 = (float)(tmp_rot[2]*scale); + + m10 = (float)(tmp_rot[3]*scale); + m11 = (float)(tmp_rot[4]*scale); + m12 = (float)(tmp_rot[5]*scale); + + m20 = (float)(tmp_rot[6]*scale); + m21 = (float)(tmp_rot[7]*scale); + m22 = (float)(tmp_rot[8]*scale); + + } + + /** + * Performs an SVD normalization of this matrix in order to acquire + * the normalized rotational component; the values are placed into + * the Matrix3d parameter. + * @param m1 matrix into which the rotational component is placed + */ + public final void get(Matrix3d m1){ + + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m1.m00 = tmp_rot[0]; + m1.m01 = tmp_rot[1]; + m1.m02 = tmp_rot[2]; + + m1.m10 = tmp_rot[3]; + m1.m11 = tmp_rot[4]; + m1.m12 = tmp_rot[5]; + + m1.m20 = tmp_rot[6]; + m1.m21 = tmp_rot[7]; + m1.m22 = tmp_rot[8]; + + } + + /** + * Performs an SVD normalization of this matrix in order to acquire + * the normalized rotational component; the values are placed into + * the Matrix3f parameter. + * @param m1 matrix into which the rotational component is placed + */ + public final void get(Matrix3f m1) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m1.m00 = (float)tmp_rot[0]; + m1.m01 = (float)tmp_rot[1]; + m1.m02 = (float)tmp_rot[2]; + + m1.m10 = (float)tmp_rot[3]; + m1.m11 = (float)tmp_rot[4]; + m1.m12 = (float)tmp_rot[5]; + + m1.m20 = (float)tmp_rot[6]; + m1.m21 = (float)tmp_rot[7]; + m1.m22 = (float)tmp_rot[8]; + + } + + + /** + * Performs an SVD normalization of this matrix to calculate + * the rotation as a 3x3 matrix, the translation, and the scale. + * None of the matrix values are modified. + * @param m1 the normalized matrix representing the rotation + * @param t1 the translation component + * @return the scale component of this transform + */ + public final float get(Matrix3f m1, Vector3f t1) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m1.m00 = (float)tmp_rot[0]; + m1.m01 = (float)tmp_rot[1]; + m1.m02 = (float)tmp_rot[2]; + + m1.m10 = (float)tmp_rot[3]; + m1.m11 = (float)tmp_rot[4]; + m1.m12 = (float)tmp_rot[5]; + + m1.m20 = (float)tmp_rot[6]; + m1.m21 = (float)tmp_rot[7]; + m1.m22 = (float)tmp_rot[8]; + + t1.x = m03; + t1.y = m13; + t1.z = m23; + + return( (float)Matrix3d.max3( tmp_scale )); + + } + + + /** + * Performs an SVD normalization of this matrix in order to acquire + * the normalized rotational component; the values are placed into + * the Quat4f parameter. + * @param q1 quaternion into which the rotation component is placed + */ + public final void get(Quat4f q1){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + double ww; + + ww = 0.25*(1.0 + tmp_rot[0] + tmp_rot[4] + tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.w = (float)Math.sqrt(ww); + ww = 0.25/q1.w; + q1.x = (float)((tmp_rot[7] - tmp_rot[5])*ww); + q1.y = (float)((tmp_rot[2] - tmp_rot[6])*ww); + q1.z = (float)((tmp_rot[3] - tmp_rot[1])*ww); + return; + } + + q1.w = 0.0f; + ww = -0.5*(tmp_rot[4] + tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.x = (float)Math.sqrt(ww); + ww = 0.5/q1.x; + q1.y = (float)(tmp_rot[3]*ww); + q1.z = (float)(tmp_rot[6]*ww); + return; + } + + q1.x = 0.0f; + ww = 0.5*(1.0 - tmp_rot[8]); + if(!((ww<0?-ww:ww) < 1.0e-30)) { + q1.y = (float)(Math.sqrt(ww)); + q1.z = (float)(tmp_rot[7]/(2.0*q1.y)); + return; + } + + q1.y = 0.0f; + q1.z = 1.0f; + + } + + + /** + * Retrieves the translational components of this matrix. + * @param trans the vector that will receive the translational component + */ + public final void get(Vector3f trans) + { + trans.x = m03; + trans.y = m13; + trans.z = m23; + } + + /** + * Gets the upper 3x3 values of this matrix and places them into + * the matrix m1. + * @param m1 the matrix that will hold the values + */ + public final void getRotationScale(Matrix3f m1) + { + m1.m00 = m00; m1.m01 = m01; m1.m02 = m02; + m1.m10 = m10; m1.m11 = m11; m1.m12 = m12; + m1.m20 = m20; m1.m21 = m21; m1.m22 = m22; + } + + /** + * Performs an SVD normalization of this matrix to calculate + * and return the uniform scale factor. If the matrix has non-uniform + * scale factors, the largest of the x, y, and z scale factors will + * be returned. This matrix is not modified. + * @return the scale factor of this matrix + */ + public final float getScale() + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + return( (float)Matrix3d.max3( tmp_scale )); + + } + + + /** + * Replaces the upper 3x3 matrix values of this matrix with the + * values in the matrix m1. + * @param m1 the matrix that will be the new upper 3x3 + */ + public final void setRotationScale(Matrix3f m1) + { + m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; + m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; + m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; + } + + + /** + * Sets the specified row of this matrix4f to the four values provided. + * @param row the row number to be modified (zero indexed) + * @param x the first column element + * @param y the second column element + * @param z the third column element + * @param w the fourth column element + */ + public final void setRow(int row, float x, float y, float z, float w) + { + switch (row) { + case 0: + this.m00 = x; + this.m01 = y; + this.m02 = z; + this.m03 = w; + break; + + case 1: + this.m10 = x; + this.m11 = y; + this.m12 = z; + this.m13 = w; + break; + + case 2: + this.m20 = x; + this.m21 = y; + this.m22 = z; + this.m23 = w; + break; + + case 3: + this.m30 = x; + this.m31 = y; + this.m32 = z; + this.m33 = w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f6")); + } + } + + /** + * Sets the specified row of this matrix4f to the Vector provided. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, Vector4f v) + { + switch (row) { + case 0: + this.m00 = v.x; + this.m01 = v.y; + this.m02 = v.z; + this.m03 = v.w; + break; + + case 1: + this.m10 = v.x; + this.m11 = v.y; + this.m12 = v.z; + this.m13 = v.w; + break; + + case 2: + this.m20 = v.x; + this.m21 = v.y; + this.m22 = v.z; + this.m23 = v.w; + break; + + case 3: + this.m30 = v.x; + this.m31 = v.y; + this.m32 = v.z; + this.m33 = v.w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f6")); + } + } + + /** + * Sets the specified row of this matrix4f to the four values provided + * in the passed array. + * @param row the row number to be modified (zero indexed) + * @param v the replacement row + */ + public final void setRow(int row, float v[]) + { + switch (row) { + case 0: + this.m00 = v[0]; + this.m01 = v[1]; + this.m02 = v[2]; + this.m03 = v[3]; + break; + + case 1: + this.m10 = v[0]; + this.m11 = v[1]; + this.m12 = v[2]; + this.m13 = v[3]; + break; + + case 2: + this.m20 = v[0]; + this.m21 = v[1]; + this.m22 = v[2]; + this.m23 = v[3]; + break; + + case 3: + this.m30 = v[0]; + this.m31 = v[1]; + this.m32 = v[2]; + this.m33 = v[3]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f6")); + } + } + + /** + * Sets the specified column of this matrix4f to the four values provided. + * @param column the column number to be modified (zero indexed) + * @param x the first row element + * @param y the second row element + * @param z the third row element + * @param w the fourth row element + */ + public final void setColumn(int column, float x, float y, float z, float w) + { + switch (column) { + case 0: + this.m00 = x; + this.m10 = y; + this.m20 = z; + this.m30 = w; + break; + + case 1: + this.m01 = x; + this.m11 = y; + this.m21 = z; + this.m31 = w; + break; + + case 2: + this.m02 = x; + this.m12 = y; + this.m22 = z; + this.m32 = w; + break; + + case 3: + this.m03 = x; + this.m13 = y; + this.m23 = z; + this.m33 = w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f9")); + } + } + + /** + * Sets the specified column of this matrix4f to the vector provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, Vector4f v) + { + switch (column) { + case 0: + this.m00 = v.x; + this.m10 = v.y; + this.m20 = v.z; + this.m30 = v.w; + break; + + case 1: + this.m01 = v.x; + this.m11 = v.y; + this.m21 = v.z; + this.m31 = v.w; + break; + + case 2: + this.m02 = v.x; + this.m12 = v.y; + this.m22 = v.z; + this.m32 = v.w; + break; + + case 3: + this.m03 = v.x; + this.m13 = v.y; + this.m23 = v.z; + this.m33 = v.w; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f9")); + } + } + + /** + * Sets the specified column of this matrix4f to the four values provided. + * @param column the column number to be modified (zero indexed) + * @param v the replacement column + */ + public final void setColumn(int column, float v[]) + { + switch (column) { + case 0: + this.m00 = v[0]; + this.m10 = v[1]; + this.m20 = v[2]; + this.m30 = v[3]; + break; + + case 1: + this.m01 = v[0]; + this.m11 = v[1]; + this.m21 = v[2]; + this.m31 = v[3]; + break; + + case 2: + this.m02 = v[0]; + this.m12 = v[1]; + this.m22 = v[2]; + this.m32 = v[3]; + break; + + case 3: + this.m03 = v[0]; + this.m13 = v[1]; + this.m23 = v[2]; + this.m33 = v[3]; + break; + + default: + throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix4f9")); + } + } + + /** + * Adds a scalar to each component of this matrix. + * @param scalar the scalar adder + */ + public final void add(float scalar) + { + m00 += scalar; + m01 += scalar; + m02 += scalar; + m03 += scalar; + m10 += scalar; + m11 += scalar; + m12 += scalar; + m13 += scalar; + m20 += scalar; + m21 += scalar; + m22 += scalar; + m23 += scalar; + m30 += scalar; + m31 += scalar; + m32 += scalar; + m33 += scalar; + } + + /** + * Adds a scalar to each component of the matrix m1 and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar adder + * @param m1 the original matrix values + */ + public final void add(float scalar, Matrix4f m1) + { + this.m00 = m1.m00 + scalar; + this.m01 = m1.m01 + scalar; + this.m02 = m1.m02 + scalar; + this.m03 = m1.m03 + scalar; + this.m10 = m1.m10 + scalar; + this.m11 = m1.m11 + scalar; + this.m12 = m1.m12 + scalar; + this.m13 = m1.m13 + scalar; + this.m20 = m1.m20 + scalar; + this.m21 = m1.m21 + scalar; + this.m22 = m1.m22 + scalar; + this.m23 = m1.m23 + scalar; + this.m30 = m1.m30 + scalar; + this.m31 = m1.m31 + scalar; + this.m32 = m1.m32 + scalar; + this.m33 = m1.m33 + scalar; + } + + /** + * Sets the value of this matrix to the matrix sum of matrices m1 and m2. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void add(Matrix4f m1, Matrix4f m2) + { + this.m00 = m1.m00 + m2.m00; + this.m01 = m1.m01 + m2.m01; + this.m02 = m1.m02 + m2.m02; + this.m03 = m1.m03 + m2.m03; + + this.m10 = m1.m10 + m2.m10; + this.m11 = m1.m11 + m2.m11; + this.m12 = m1.m12 + m2.m12; + this.m13 = m1.m13 + m2.m13; + + this.m20 = m1.m20 + m2.m20; + this.m21 = m1.m21 + m2.m21; + this.m22 = m1.m22 + m2.m22; + this.m23 = m1.m23 + m2.m23; + + this.m30 = m1.m30 + m2.m30; + this.m31 = m1.m31 + m2.m31; + this.m32 = m1.m32 + m2.m32; + this.m33 = m1.m33 + m2.m33; + } + + + /** + * Sets the value of this matrix to the sum of itself and matrix m1. + * @param m1 the other matrix + */ + public final void add(Matrix4f m1) + { + this.m00 += m1.m00; + this.m01 += m1.m01; + this.m02 += m1.m02; + this.m03 += m1.m03; + + this.m10 += m1.m10; + this.m11 += m1.m11; + this.m12 += m1.m12; + this.m13 += m1.m13; + + this.m20 += m1.m20; + this.m21 += m1.m21; + this.m22 += m1.m22; + this.m23 += m1.m23; + + this.m30 += m1.m30; + this.m31 += m1.m31; + this.m32 += m1.m32; + this.m33 += m1.m33; + } + + /** + * Performs an element-by-element subtraction of matrix m2 from + * matrix m1 and places the result into matrix this (this = + * m2 - m1). + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void sub(Matrix4f m1, Matrix4f m2) + { + this.m00 = m1.m00 - m2.m00; + this.m01 = m1.m01 - m2.m01; + this.m02 = m1.m02 - m2.m02; + this.m03 = m1.m03 - m2.m03; + + this.m10 = m1.m10 - m2.m10; + this.m11 = m1.m11 - m2.m11; + this.m12 = m1.m12 - m2.m12; + this.m13 = m1.m13 - m2.m13; + + this.m20 = m1.m20 - m2.m20; + this.m21 = m1.m21 - m2.m21; + this.m22 = m1.m22 - m2.m22; + this.m23 = m1.m23 - m2.m23; + + this.m30 = m1.m30 - m2.m30; + this.m31 = m1.m31 - m2.m31; + this.m32 = m1.m32 - m2.m32; + this.m33 = m1.m33 - m2.m33; + } + + /** + * Sets this matrix to the matrix difference of itself and + * matrix m1 (this = this - m1). + * @param m1 the other matrix + */ + public final void sub(Matrix4f m1) + { + this.m00 -= m1.m00; + this.m01 -= m1.m01; + this.m02 -= m1.m02; + this.m03 -= m1.m03; + + this.m10 -= m1.m10; + this.m11 -= m1.m11; + this.m12 -= m1.m12; + this.m13 -= m1.m13; + + this.m20 -= m1.m20; + this.m21 -= m1.m21; + this.m22 -= m1.m22; + this.m23 -= m1.m23; + + this.m30 -= m1.m30; + this.m31 -= m1.m31; + this.m32 -= m1.m32; + this.m33 -= m1.m33; + } + + /** + * Sets the value of this matrix to its transpose in place. + */ + public final void transpose() + { + float temp; + + temp = this.m10; + this.m10 = this.m01; + this.m01 = temp; + + temp = this.m20; + this.m20 = this.m02; + this.m02 = temp; + + temp = this.m30; + this.m30 = this.m03; + this.m03 = temp; + + temp = this.m21; + this.m21 = this.m12; + this.m12 = temp; + + temp = this.m31; + this.m31 = this.m13; + this.m13 = temp; + + temp = this.m32; + this.m32 = this.m23; + this.m23 = temp; + } + + /** + * Sets the value of this matrix to the transpose of the argument matrix. + * @param m1 the matrix to be transposed + */ + public final void transpose(Matrix4f m1) + { + if (this != m1) { + this.m00 = m1.m00; + this.m01 = m1.m10; + this.m02 = m1.m20; + this.m03 = m1.m30; + + this.m10 = m1.m01; + this.m11 = m1.m11; + this.m12 = m1.m21; + this.m13 = m1.m31; + + this.m20 = m1.m02; + this.m21 = m1.m12; + this.m22 = m1.m22; + this.m23 = m1.m32; + + this.m30 = m1.m03; + this.m31 = m1.m13; + this.m32 = m1.m23; + this.m33 = m1.m33; + } else + this.transpose(); + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * single precision quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4f q1) + { + this.m00 = (1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z); + this.m10 = (2.0f*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = (2.0f*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = (2.0f*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = (1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z); + this.m21 = (2.0f*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = (2.0f*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = (2.0f*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = (1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y); + + this.m03 = (float) 0.0; + this.m13 = (float) 0.0; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * (single precision) axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4f a1) + { + float mag = (float)Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + if( mag < EPS ) { + m00 = 1.0f; + m01 = 0.0f; + m02 = 0.0f; + + m10 = 0.0f; + m11 = 1.0f; + m12 = 0.0f; + + m20 = 0.0f; + m21 = 0.0f; + m22 = 1.0f; + } else { + mag = 1.0f/mag; + float ax = a1.x*mag; + float ay = a1.y*mag; + float az = a1.z*mag; + + float sinTheta = (float)Math.sin((double)a1.angle); + float cosTheta = (float)Math.cos((double)a1.angle); + float t = 1.0f - cosTheta; + + float xz = ax * az; + float xy = ax * ay; + float yz = ay * az; + + m00 = t * ax * ax + cosTheta; + m01 = t * xy - sinTheta * az; + m02 = t * xz + sinTheta * ay; + + m10 = t * xy + sinTheta * az; + m11 = t * ay * ay + cosTheta; + m12 = t * yz - sinTheta * ax; + + m20 = t * xz - sinTheta * ay; + m21 = t * yz + sinTheta * ax; + m22 = t * az * az + cosTheta; + } + m03 = 0.0f; + m13 = 0.0f; + m23 = 0.0f; + + m30 = 0.0f; + m31 = 0.0f; + m32 = 0.0f; + m33 = 1.0f; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * double precision quaternion argument. + * @param q1 the quaternion to be converted + */ + public final void set(Quat4d q1) + { + this.m00 = (float) (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z); + this.m10 = (float) (2.0*(q1.x*q1.y + q1.w*q1.z)); + this.m20 = (float) (2.0*(q1.x*q1.z - q1.w*q1.y)); + + this.m01 = (float) (2.0*(q1.x*q1.y - q1.w*q1.z)); + this.m11 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z); + this.m21 = (float) (2.0*(q1.y*q1.z + q1.w*q1.x)); + + this.m02 = (float) (2.0*(q1.x*q1.z + q1.w*q1.y)); + this.m12 = (float) (2.0*(q1.y*q1.z - q1.w*q1.x)); + this.m22 = (float) (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y); + + this.m03 = (float) 0.0; + this.m13 = (float) 0.0; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this matrix to the matrix conversion of the + * double precision axis and angle argument. + * @param a1 the axis and angle to be converted + */ + public final void set(AxisAngle4d a1) + { + double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + + if( mag < EPS ) { + m00 = 1.0f; + m01 = 0.0f; + m02 = 0.0f; + + m10 = 0.0f; + m11 = 1.0f; + m12 = 0.0f; + + m20 = 0.0f; + m21 = 0.0f; + m22 = 1.0f; + } else { + mag = 1.0/mag; + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + + float sinTheta = (float) Math.sin(a1.angle); + float cosTheta = (float) Math.cos(a1.angle); + float t = 1.0f - cosTheta; + + float xz = (float) (ax * az); + float xy = (float) (ax * ay); + float yz = (float) (ay * az); + + this.m00 = t * (float)(ax * ax) + cosTheta; + this.m01 = t * xy - sinTheta * (float)az; + this.m02 = t * xz + sinTheta * (float)ay; + + this.m10 = t * xy + sinTheta * (float)az; + this.m11 = t * (float)(ay * ay) + cosTheta; + this.m12 = t * yz - sinTheta * (float)ax; + + this.m20 = t * xz - sinTheta * (float)ay; + this.m21 = t * yz + sinTheta * (float)ax; + this.m22 = t * (float)(az * az) + cosTheta; + } + this.m03 = 0.0f; + this.m13 = 0.0f; + this.m23 = 0.0f; + + this.m30 = 0.0f; + this.m31 = 0.0f; + this.m32 = 0.0f; + this.m33 = 1.0f; + } + + /** + * Sets the value of this matrix from the rotation expressed + * by the quaternion q1, the translation t1, and the scale s. + * @param q1 the rotation expressed as a quaternion + * @param t1 the translation + * @param s the scale value + */ + public final void set(Quat4d q1, Vector3d t1, double s) + { + this.m00 = (float) (s*(1.0 - 2.0*q1.y*q1.y -2.0*q1.z*q1.z)); + this.m10 = (float) (s*(2.0*(q1.x*q1.y + q1.w*q1.z))); + this.m20 = (float) (s*(2.0*(q1.x*q1.z - q1.w*q1.y))); + + this.m01 = (float) (s*(2.0*(q1.x*q1.y - q1.w*q1.z))); + this.m11 = (float) (s*(1.0 - 2.0*q1.x*q1.x -2.0*q1.z*q1.z)); + this.m21 = (float) (s*(2.0*(q1.y*q1.z + q1.w*q1.x))); + + this.m02 = (float) (s*(2.0*(q1.x*q1.z + q1.w*q1.y))); + this.m12 = (float) (s*(2.0*(q1.y*q1.z - q1.w*q1.x))); + this.m22 = (float) (s*(1.0 - 2.0*q1.x*q1.x -2.0*q1.y*q1.y)); + + this.m03 = (float) t1.x; + this.m13 = (float) t1.y; + this.m23 = (float) t1.z; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this matrix from the rotation expressed + * by the quaternion q1, the translation t1, and the scale s. + * @param q1 the rotation expressed as a quaternion + * @param t1 the translation + * @param s the scale value + */ + public final void set(Quat4f q1, Vector3f t1, float s) + { + this.m00 = (s*(1.0f - 2.0f*q1.y*q1.y -2.0f*q1.z*q1.z)); + this.m10 = (s*(2.0f*(q1.x*q1.y + q1.w*q1.z))); + this.m20 = (s*(2.0f*(q1.x*q1.z - q1.w*q1.y))); + + this.m01 = (s*(2.0f*(q1.x*q1.y - q1.w*q1.z))); + this.m11 = (s*(1.0f - 2.0f*q1.x*q1.x -2.0f*q1.z*q1.z)); + this.m21 = (s*(2.0f*(q1.y*q1.z + q1.w*q1.x))); + + this.m02 = (s*(2.0f*(q1.x*q1.z + q1.w*q1.y))); + this.m12 = (s*(2.0f*(q1.y*q1.z - q1.w*q1.x))); + this.m22 = (s*(1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)); + + this.m03 = t1.x; + this.m13 = t1.y; + this.m23 = t1.z; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this matrix to the float value of the + * passed matrix4d m1. + * @param m1 the matrix4d to be converted to float + */ + public final void set(Matrix4d m1) + { + this.m00 = (float) m1.m00; + this.m01 = (float) m1.m01; + this.m02 = (float) m1.m02; + this.m03 = (float) m1.m03; + + this.m10 = (float) m1.m10; + this.m11 = (float) m1.m11; + this.m12 = (float) m1.m12; + this.m13 = (float) m1.m13; + + this.m20 = (float) m1.m20; + this.m21 = (float) m1.m21; + this.m22 = (float) m1.m22; + this.m23 = (float) m1.m23; + + this.m30 = (float) m1.m30; + this.m31 = (float) m1.m31; + this.m32 = (float) m1.m32; + this.m33 = (float) m1.m33; + } + + /** + * Sets the value of this matrix to a copy of the + * passed matrix m1. + * @param m1 the matrix to be copied + */ + public final void set(Matrix4f m1) + { + this.m00 = m1.m00; + this.m01 = m1.m01; + this.m02 = m1.m02; + this.m03 = m1.m03; + + this.m10 = m1.m10; + this.m11 = m1.m11; + this.m12 = m1.m12; + this.m13 = m1.m13; + + this.m20 = m1.m20; + this.m21 = m1.m21; + this.m22 = m1.m22; + this.m23 = m1.m23; + + this.m30 = m1.m30; + this.m31 = m1.m31; + this.m32 = m1.m32; + this.m33 = m1.m33; + } + + /** + * Sets the value of this matrix to the matrix inverse + * of the passed (user declared) matrix m1. + * @param m1 the matrix to be inverted + */ + public final void invert(Matrix4f m1) + { + + invertGeneral( m1); + } + + /** + * Inverts this matrix in place. + */ + public final void invert() + { + invertGeneral( this ); + } + + /** + * General invert routine. Inverts m1 and places the result in "this". + * Note that this routine handles both the "this" version and the + * non-"this" version. + * + * Also note that since this routine is slow anyway, we won't worry + * about allocating a little bit of garbage. + */ + final void invertGeneral(Matrix4f m1) { + double temp[] = new double[16]; + double result[] = new double[16]; + int row_perm[] = new int[4]; + int i, r, c; + + // Use LU decomposition and backsubstitution code specifically + // for floating-point 4x4 matrices. + + // Copy source matrix to t1tmp + temp[0] = m1.m00; + temp[1] = m1.m01; + temp[2] = m1.m02; + temp[3] = m1.m03; + + temp[4] = m1.m10; + temp[5] = m1.m11; + temp[6] = m1.m12; + temp[7] = m1.m13; + + temp[8] = m1.m20; + temp[9] = m1.m21; + temp[10] = m1.m22; + temp[11] = m1.m23; + + temp[12] = m1.m30; + temp[13] = m1.m31; + temp[14] = m1.m32; + temp[15] = m1.m33; + + // Calculate LU decomposition: Is the matrix singular? + if (!luDecomposition(temp, row_perm)) { + // Matrix has no inverse + throw new SingularMatrixException(VecMathI18N.getString("Matrix4f12")); + } + + // Perform back substitution on the identity matrix + for(i=0;i<16;i++) result[i] = 0.0; + result[0] = 1.0; result[5] = 1.0; result[10] = 1.0; result[15] = 1.0; + luBacksubstitution(temp, row_perm, result); + + this.m00 = (float)result[0]; + this.m01 = (float)result[1]; + this.m02 = (float)result[2]; + this.m03 = (float)result[3]; + + this.m10 = (float)result[4]; + this.m11 = (float)result[5]; + this.m12 = (float)result[6]; + this.m13 = (float)result[7]; + + this.m20 = (float)result[8]; + this.m21 = (float)result[9]; + this.m22 = (float)result[10]; + this.m23 = (float)result[11]; + + this.m30 = (float)result[12]; + this.m31 = (float)result[13]; + this.m32 = (float)result[14]; + this.m33 = (float)result[15]; + + } + + /** + * Given a 4x4 array "matrix0", this function replaces it with the + * LU decomposition of a row-wise permutation of itself. The input + * parameters are "matrix0" and "dimen". The array "matrix0" is also + * an output parameter. The vector "row_perm[4]" is an output + * parameter that contains the row permutations resulting from partial + * pivoting. The output parameter "even_row_xchg" is 1 when the + * number of row exchanges is even, or -1 otherwise. Assumes data + * type is always double. + * + * This function is similar to luDecomposition, except that it + * is tuned specifically for 4x4 matrices. + * + * @return true if the matrix is nonsingular, or false otherwise. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 40-45. + // + static boolean luDecomposition(double[] matrix0, + int[] row_perm) { + + double row_scale[] = new double[4]; + + // Determine implicit scaling information by looping over rows + { + int i, j; + int ptr, rs; + double big, temp; + + ptr = 0; + rs = 0; + + // For each row ... + i = 4; + while (i-- != 0) { + big = 0.0; + + // For each column, find the largest element in the row + j = 4; + while (j-- != 0) { + temp = matrix0[ptr++]; + temp = Math.abs(temp); + if (temp > big) { + big = temp; + } + } + + // Is the matrix singular? + if (big == 0.0) { + return false; + } + row_scale[rs++] = 1.0 / big; + } + } + + { + int j; + int mtx; + + mtx = 0; + + // For all columns, execute Crout's method + for (j = 0; j < 4; j++) { + int i, imax, k; + int target, p1, p2; + double sum, big, temp; + + // Determine elements of upper diagonal matrix U + for (i = 0; i < j; i++) { + target = mtx + (4*i) + j; + sum = matrix0[target]; + k = i; + p1 = mtx + (4*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 4; + } + matrix0[target] = sum; + } + + // Search for largest pivot element and calculate + // intermediate elements of lower diagonal matrix L. + big = 0.0; + imax = -1; + for (i = j; i < 4; i++) { + target = mtx + (4*i) + j; + sum = matrix0[target]; + k = j; + p1 = mtx + (4*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 4; + } + matrix0[target] = sum; + + // Is this the best pivot so far? + if ((temp = row_scale[i] * Math.abs(sum)) >= big) { + big = temp; + imax = i; + } + } + + if (imax < 0) { + throw new RuntimeException(VecMathI18N.getString("Matrix4f13")); + } + + // Is a row exchange necessary? + if (j != imax) { + // Yes: exchange rows + k = 4; + p1 = mtx + (4*imax); + p2 = mtx + (4*j); + while (k-- != 0) { + temp = matrix0[p1]; + matrix0[p1++] = matrix0[p2]; + matrix0[p2++] = temp; + } + + // Record change in scale factor + row_scale[imax] = row_scale[j]; + } + + // Record row permutation + row_perm[j] = imax; + + // Is the matrix singular + if (matrix0[(mtx + (4*j) + j)] == 0.0) { + return false; + } + + // Divide elements of lower diagonal matrix L by pivot + if (j != (4-1)) { + temp = 1.0 / (matrix0[(mtx + (4*j) + j)]); + target = mtx + (4*(j+1)) + j; + i = 3 - j; + while (i-- != 0) { + matrix0[target] *= temp; + target += 4; + } + } + } + } + + return true; + } + + /** + * Solves a set of linear equations. The input parameters "matrix1", + * and "row_perm" come from luDecompostionD4x4 and do not change + * here. The parameter "matrix2" is a set of column vectors assembled + * into a 4x4 matrix of floating-point values. The procedure takes each + * column of "matrix2" in turn and treats it as the right-hand side of the + * matrix equation Ax = LUx = b. The solution vector replaces the + * original column of the matrix. + * + * If "matrix2" is the identity matrix, the procedure replaces its contents + * with the inverse of the matrix from which "matrix1" was originally + * derived. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 44-45. + // + static void luBacksubstitution(double[] matrix1, + int[] row_perm, + double[] matrix2) { + + int i, ii, ip, j, k; + int rp; + int cv, rv; + + // rp = row_perm; + rp = 0; + + // For each column vector of matrix2 ... + for (k = 0; k < 4; k++) { + // cv = &(matrix2[0][k]); + cv = k; + ii = -1; + + // Forward substitution + for (i = 0; i < 4; i++) { + double sum; + + ip = row_perm[rp+i]; + sum = matrix2[cv+4*ip]; + matrix2[cv+4*ip] = matrix2[cv+4*i]; + if (ii >= 0) { + // rv = &(matrix1[i][0]); + rv = i*4; + for (j = ii; j <= i-1; j++) { + sum -= matrix1[rv+j] * matrix2[cv+4*j]; + } + } + else if (sum != 0.0) { + ii = i; + } + matrix2[cv+4*i] = sum; + } + + // Backsubstitution + // rv = &(matrix1[3][0]); + rv = 3*4; + matrix2[cv+4*3] /= matrix1[rv+3]; + + rv -= 4; + matrix2[cv+4*2] = (matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+2]; + + rv -= 4; + matrix2[cv+4*1] = (matrix2[cv+4*1] - + matrix1[rv+2] * matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+1]; + + rv -= 4; + matrix2[cv+4*0] = (matrix2[cv+4*0] - + matrix1[rv+1] * matrix2[cv+4*1] - + matrix1[rv+2] * matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+0]; + } + } + + /** + * Computes the determinate of this matrix. + * @return the determinate of the matrix + */ + public final float determinant() + { + float det; + + // cofactor exapainsion along first row + + det = m00*(m11*m22*m33+ m12*m23*m31 + m13*m21*m32 + - m13*m22*m31 -m11*m23*m32 - m12*m21*m33); + det -= m01*(m10*m22*m33+ m12*m23*m30 + m13*m20*m32 + - m13*m22*m30 -m10*m23*m32 - m12*m20*m33); + det += m02*(m10*m21*m33+ m11*m23*m30 + m13*m20*m31 + - m13*m21*m30 -m10*m23*m31 - m11*m20*m33); + det -= m03*(m10*m21*m32+ m11*m22*m30 + m12*m20*m31 + - m12*m21*m30 -m10*m22*m31 - m11*m20*m32); + + return( det ); + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the single precision Matrix3f argument; the other + * elements of this matrix are initialized as if this were an identity + * matrix (i.e., affine matrix with no translational component). + * @param m1 the single-precision 3x3 matrix + */ + public final void set(Matrix3f m1) + { + m00 = m1.m00; m01 = m1.m01; m02 = m1.m02; m03 = 0.0f; + m10 = m1.m10; m11 = m1.m11; m12 = m1.m12; m13 = 0.0f; + m20 = m1.m20; m21 = m1.m21; m22 = m1.m22; m23 = 0.0f; + m30 = 0.0f; m31 = 0.0f ; m32 = 0.0f ; m33 = 1.0f; + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the double precision Matrix3d argument; the other + * elements of this matrix are initialized as if this were an identity + * matrix (i.e., affine matrix with no translational component). + * @param m1 the double-precision 3x3 matrix + */ + public final void set(Matrix3d m1) + { + m00 = (float)m1.m00; m01 = (float)m1.m01; m02 = (float)m1.m02; m03 = 0.0f; + m10 = (float)m1.m10; m11 = (float)m1.m11; m12 = (float)m1.m12; m13 = 0.0f; + m20 = (float)m1.m20; m21 = (float)m1.m21; m22 = (float)m1.m22; m23 = 0.0f; + m30 = 0.0f; m31 = 0.0f ; m32 = 0.0f ; m33 = 1.0f; + } + + /** + * Sets the value of this matrix to a scale matrix with the + * the passed scale amount. + * @param scale the scale factor for the matrix + */ + public final void set(float scale) + { + this.m00 = scale; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + this.m03 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = scale; + this.m12 = (float) 0.0; + this.m13 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = scale; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the values in this Matrix4f equal to the row-major + * array parameter (ie, the first four elements of the + * array will be copied into the first row of this matrix, etc.). + * @param m the single precision array of length 16 + */ + public final void set(float[] m) + { + m00 = m[0]; + m01 = m[1]; + m02 = m[2]; + m03 = m[3]; + m10 = m[4]; + m11 = m[5]; + m12 = m[6]; + m13 = m[7]; + m20 = m[8]; + m21 = m[9]; + m22 = m[10]; + m23 = m[11]; + m30 = m[12]; + m31 = m[13]; + m32 = m[14]; + m33 = m[15]; + } + + /** + * Sets the value of this matrix to a translate matrix with + * the passed translation value. + * @param v1 the translation amount + */ + public final void set(Vector3f v1) + { + this.m00 = (float) 1.0; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + this.m03 = v1.x; + + this.m10 = (float) 0.0; + this.m11 = (float) 1.0; + this.m12 = (float) 0.0; + this.m13 = v1.y; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = (float) 1.0; + this.m23 = v1.z; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this transform to a scale and translation matrix; + * the scale is not applied to the translation and all of the matrix + * values are modified. + * @param scale the scale factor for the matrix + * @param t1 the translation amount + */ + public final void set(float scale, Vector3f t1) + { + this.m00 = scale; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + this.m03 = t1.x; + + this.m10 = (float) 0.0; + this.m11 = scale; + this.m12 = (float) 0.0; + this.m13 = t1.y; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = scale; + this.m23 = t1.z; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this transform to a scale and translation matrix; + * the translation is scaled by the scale factor and all of the matrix + * values are modified. + * @param t1 the translation amount + * @param scale the scale factor for the matrix + */ + public final void set(Vector3f t1, float scale) + { + this.m00 = scale; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + this.m03 = scale*t1.x; + + this.m10 = (float) 0.0; + this.m11 = scale; + this.m12 = (float) 0.0; + this.m13 = scale*t1.y; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = scale; + this.m23 = scale*t1.z; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this matrix from the rotation expressed by + * the rotation matrix m1, the translation t1, and the scale factor. + * The translation is not modified by the scale. + * @param m1 the rotation component + * @param t1 the translation component + * @param scale the scale component + */ + public final void set(Matrix3f m1, Vector3f t1, float scale) + { + this.m00 = m1.m00*scale; + this.m01 = m1.m01*scale; + this.m02 = m1.m02*scale; + this.m03 = t1.x; + + this.m10 = m1.m10*scale; + this.m11 = m1.m11*scale; + this.m12 = m1.m12*scale; + this.m13 = t1.y; + + this.m20 = m1.m20*scale; + this.m21 = m1.m21*scale; + this.m22 = m1.m22*scale; + this.m23 = t1.z; + + this.m30 = 0.0f; + this.m31 = 0.0f; + this.m32 = 0.0f; + this.m33 = 1.0f; + } + + /** + * Sets the value of this matrix from the rotation expressed by + * the rotation matrix m1, the translation t1, and the scale factor. + * The translation is not modified by the scale. + * @param m1 the rotation component + * @param t1 the translation component + * @param scale the scale factor + */ + public final void set(Matrix3d m1, Vector3d t1, double scale) + { + this.m00 = (float)(m1.m00*scale); + this.m01 = (float)(m1.m01*scale); + this.m02 = (float)(m1.m02*scale); + this.m03 = (float)t1.x; + + this.m10 = (float)(m1.m10*scale); + this.m11 = (float)(m1.m11*scale); + this.m12 = (float)(m1.m12*scale); + this.m13 = (float)t1.y; + + this.m20 = (float)(m1.m20*scale); + this.m21 = (float)(m1.m21*scale); + this.m22 = (float)(m1.m22*scale); + this.m23 = (float)t1.z; + + this.m30 = 0.0f; + this.m31 = 0.0f; + this.m32 = 0.0f; + this.m33 = 1.0f; + } + + /** + * Modifies the translational components of this matrix to the values + * of the Vector3f argument; the other values of this matrix are not + * modified. + * @param trans the translational component + */ + public final void setTranslation(Vector3f trans) + { + m03 = trans.x; + m13 = trans.y; + m23 = trans.z; + } + + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the x axis. + * @param angle the angle to rotate about the X axis in radians + */ + public final void rotX(float angle) + { + float sinAngle, cosAngle; + + sinAngle = (float) Math.sin((double) angle); + cosAngle = (float) Math.cos((double) angle); + + this.m00 = (float) 1.0; + this.m01 = (float) 0.0; + this.m02 = (float) 0.0; + this.m03 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = cosAngle; + this.m12 = -sinAngle; + this.m13 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = sinAngle; + this.m22 = cosAngle; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the y axis. + * @param angle the angle to rotate about the Y axis in radians + */ + public final void rotY(float angle) + { + float sinAngle, cosAngle; + + sinAngle = (float) Math.sin((double) angle); + cosAngle = (float) Math.cos((double) angle); + + this.m00 = cosAngle; + this.m01 = (float) 0.0; + this.m02 = sinAngle; + this.m03 = (float) 0.0; + + this.m10 = (float) 0.0; + this.m11 = (float) 1.0; + this.m12 = (float) 0.0; + this.m13 = (float) 0.0; + + this.m20 = -sinAngle; + this.m21 = (float) 0.0; + this.m22 = cosAngle; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Sets the value of this matrix to a counter clockwise rotation + * about the z axis. + * @param angle the angle to rotate about the Z axis in radians + */ + public final void rotZ(float angle) + { + float sinAngle, cosAngle; + + sinAngle = (float) Math.sin((double) angle); + cosAngle = (float) Math.cos((double) angle); + + this.m00 = cosAngle; + this.m01 = -sinAngle; + this.m02 = (float) 0.0; + this.m03 = (float) 0.0; + + this.m10 = sinAngle; + this.m11 = cosAngle; + this.m12 = (float) 0.0; + this.m13 = (float) 0.0; + + this.m20 = (float) 0.0; + this.m21 = (float) 0.0; + this.m22 = (float) 1.0; + this.m23 = (float) 0.0; + + this.m30 = (float) 0.0; + this.m31 = (float) 0.0; + this.m32 = (float) 0.0; + this.m33 = (float) 1.0; + } + + /** + * Multiplies each element of this matrix by a scalar. + * @param scalar the scalar multiplier. + */ + public final void mul(float scalar) + { + m00 *= scalar; + m01 *= scalar; + m02 *= scalar; + m03 *= scalar; + m10 *= scalar; + m11 *= scalar; + m12 *= scalar; + m13 *= scalar; + m20 *= scalar; + m21 *= scalar; + m22 *= scalar; + m23 *= scalar; + m30 *= scalar; + m31 *= scalar; + m32 *= scalar; + m33 *= scalar; + } + + /** + * Multiplies each element of matrix m1 by a scalar and places + * the result into this. Matrix m1 is not modified. + * @param scalar the scalar multiplier. + * @param m1 the original matrix. + */ + public final void mul(float scalar, Matrix4f m1) + { + this.m00 = m1.m00 * scalar; + this.m01 = m1.m01 * scalar; + this.m02 = m1.m02 * scalar; + this.m03 = m1.m03 * scalar; + this.m10 = m1.m10 * scalar; + this.m11 = m1.m11 * scalar; + this.m12 = m1.m12 * scalar; + this.m13 = m1.m13 * scalar; + this.m20 = m1.m20 * scalar; + this.m21 = m1.m21 * scalar; + this.m22 = m1.m22 * scalar; + this.m23 = m1.m23 * scalar; + this.m30 = m1.m30 * scalar; + this.m31 = m1.m31 * scalar; + this.m32 = m1.m32 * scalar; + this.m33 = m1.m33 * scalar; + } + + /** + * Sets the value of this matrix to the result of multiplying itself + * with matrix m1. + * @param m1 the other matrix + */ + public final void mul(Matrix4f m1) + { + float m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33; // vars for temp result matrix + + m00 = this.m00*m1.m00 + this.m01*m1.m10 + + this.m02*m1.m20 + this.m03*m1.m30; + m01 = this.m00*m1.m01 + this.m01*m1.m11 + + this.m02*m1.m21 + this.m03*m1.m31; + m02 = this.m00*m1.m02 + this.m01*m1.m12 + + this.m02*m1.m22 + this.m03*m1.m32; + m03 = this.m00*m1.m03 + this.m01*m1.m13 + + this.m02*m1.m23 + this.m03*m1.m33; + + m10 = this.m10*m1.m00 + this.m11*m1.m10 + + this.m12*m1.m20 + this.m13*m1.m30; + m11 = this.m10*m1.m01 + this.m11*m1.m11 + + this.m12*m1.m21 + this.m13*m1.m31; + m12 = this.m10*m1.m02 + this.m11*m1.m12 + + this.m12*m1.m22 + this.m13*m1.m32; + m13 = this.m10*m1.m03 + this.m11*m1.m13 + + this.m12*m1.m23 + this.m13*m1.m33; + + m20 = this.m20*m1.m00 + this.m21*m1.m10 + + this.m22*m1.m20 + this.m23*m1.m30; + m21 = this.m20*m1.m01 + this.m21*m1.m11 + + this.m22*m1.m21 + this.m23*m1.m31; + m22 = this.m20*m1.m02 + this.m21*m1.m12 + + this.m22*m1.m22 + this.m23*m1.m32; + m23 = this.m20*m1.m03 + this.m21*m1.m13 + + this.m22*m1.m23 + this.m23*m1.m33; + + m30 = this.m30*m1.m00 + this.m31*m1.m10 + + this.m32*m1.m20 + this.m33*m1.m30; + m31 = this.m30*m1.m01 + this.m31*m1.m11 + + this.m32*m1.m21 + this.m33*m1.m31; + m32 = this.m30*m1.m02 + this.m31*m1.m12 + + this.m32*m1.m22 + this.m33*m1.m32; + m33 = this.m30*m1.m03 + this.m31*m1.m13 + + this.m32*m1.m23 + this.m33*m1.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + + /** + * Sets the value of this matrix to the result of multiplying + * the two argument matrices together. + * @param m1 the first matrix + * @param m2 the second matrix + */ + public final void mul(Matrix4f m1, Matrix4f m2) + { + if (this != m1 && this != m2) { + + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + + m1.m02*m2.m20 + m1.m03*m2.m30; + this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + + m1.m02*m2.m21 + m1.m03*m2.m31; + this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + + m1.m02*m2.m22 + m1.m03*m2.m32; + this.m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + + m1.m02*m2.m23 + m1.m03*m2.m33; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + + m1.m12*m2.m20 + m1.m13*m2.m30; + this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + + m1.m12*m2.m21 + m1.m13*m2.m31; + this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + + m1.m12*m2.m22 + m1.m13*m2.m32; + this.m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + + m1.m12*m2.m23 + m1.m13*m2.m33; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + + m1.m22*m2.m20 + m1.m23*m2.m30; + this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + + m1.m22*m2.m21 + m1.m23*m2.m31; + this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + + m1.m22*m2.m22 + m1.m23*m2.m32; + this.m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + + m1.m22*m2.m23 + m1.m23*m2.m33; + + this.m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + + m1.m32*m2.m20 + m1.m33*m2.m30; + this.m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + + m1.m32*m2.m21 + m1.m33*m2.m31; + this.m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + + m1.m32*m2.m22 + m1.m33*m2.m32; + this.m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + + m1.m32*m2.m23 + m1.m33*m2.m33; + } else { + float m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33; // vars for temp result matrix + m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20 + m1.m03*m2.m30; + m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21 + m1.m03*m2.m31; + m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22 + m1.m03*m2.m32; + m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + m1.m02*m2.m23 + m1.m03*m2.m33; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20 + m1.m13*m2.m30; + m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21 + m1.m13*m2.m31; + m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22 + m1.m13*m2.m32; + m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + m1.m12*m2.m23 + m1.m13*m2.m33; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20 + m1.m23*m2.m30; + m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21 + m1.m23*m2.m31; + m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22 + m1.m23*m2.m32; + m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + m1.m22*m2.m23 + m1.m23*m2.m33; + + m30 = m1.m30*m2.m00 + m1.m31*m2.m10 + m1.m32*m2.m20 + m1.m33*m2.m30; + m31 = m1.m30*m2.m01 + m1.m31*m2.m11 + m1.m32*m2.m21 + m1.m33*m2.m31; + m32 = m1.m30*m2.m02 + m1.m31*m2.m12 + m1.m32*m2.m22 + m1.m33*m2.m32; + m33 = m1.m30*m2.m03 + m1.m31*m2.m13 + m1.m32*m2.m23 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + } + + /** + * Multiplies the transpose of matrix m1 times the transpose of matrix + * m2, and places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeBoth(Matrix4f m1, Matrix4f m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03; + this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13; + this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23; + this.m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03; + this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13; + this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23; + this.m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03; + this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13; + this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23; + this.m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33; + + this.m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03; + this.m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13; + this.m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23; + this.m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33; + } else { + float m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, // vars for temp result matrix + m30, m31, m32, m33; + + m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02 + m1.m30*m2.m03; + m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12 + m1.m30*m2.m13; + m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22 + m1.m30*m2.m23; + m03 = m1.m00*m2.m30 + m1.m10*m2.m31 + m1.m20*m2.m32 + m1.m30*m2.m33; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02 + m1.m31*m2.m03; + m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12 + m1.m31*m2.m13; + m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22 + m1.m31*m2.m23; + m13 = m1.m01*m2.m30 + m1.m11*m2.m31 + m1.m21*m2.m32 + m1.m31*m2.m33; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02 + m1.m32*m2.m03; + m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12 + m1.m32*m2.m13; + m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22 + m1.m32*m2.m23; + m23 = m1.m02*m2.m30 + m1.m12*m2.m31 + m1.m22*m2.m32 + m1.m32*m2.m33; + + m30 = m1.m03*m2.m00 + m1.m13*m2.m01 + m1.m23*m2.m02 + m1.m33*m2.m03; + m31 = m1.m03*m2.m10 + m1.m13*m2.m11 + m1.m23*m2.m12 + m1.m33*m2.m13; + m32 = m1.m03*m2.m20 + m1.m13*m2.m21 + m1.m23*m2.m22 + m1.m33*m2.m23; + m33 = m1.m03*m2.m30 + m1.m13*m2.m31 + m1.m23*m2.m32 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + + } + + /** + * Multiplies matrix m1 times the transpose of matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeRight(Matrix4f m1, Matrix4f m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03; + this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13; + this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23; + this.m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33; + + this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03; + this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13; + this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23; + this.m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33; + + this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03; + this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13; + this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23; + this.m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33; + + this.m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03; + this.m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13; + this.m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23; + this.m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33; + } else { + float m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, // vars for temp result matrix + m30, m31, m32, m33; + + m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02 + m1.m03*m2.m03; + m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12 + m1.m03*m2.m13; + m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22 + m1.m03*m2.m23; + m03 = m1.m00*m2.m30 + m1.m01*m2.m31 + m1.m02*m2.m32 + m1.m03*m2.m33; + + m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02 + m1.m13*m2.m03; + m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12 + m1.m13*m2.m13; + m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22 + m1.m13*m2.m23; + m13 = m1.m10*m2.m30 + m1.m11*m2.m31 + m1.m12*m2.m32 + m1.m13*m2.m33; + + m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02 + m1.m23*m2.m03; + m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12 + m1.m23*m2.m13; + m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22 + m1.m23*m2.m23; + m23 = m1.m20*m2.m30 + m1.m21*m2.m31 + m1.m22*m2.m32 + m1.m23*m2.m33; + + m30 = m1.m30*m2.m00 + m1.m31*m2.m01 + m1.m32*m2.m02 + m1.m33*m2.m03; + m31 = m1.m30*m2.m10 + m1.m31*m2.m11 + m1.m32*m2.m12 + m1.m33*m2.m13; + m32 = m1.m30*m2.m20 + m1.m31*m2.m21 + m1.m32*m2.m22 + m1.m33*m2.m23; + m33 = m1.m30*m2.m30 + m1.m31*m2.m31 + m1.m32*m2.m32 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + + } + + + /** + * Multiplies the transpose of matrix m1 times matrix m2, and + * places the result into this. + * @param m1 the matrix on the left hand side of the multiplication + * @param m2 the matrix on the right hand side of the multiplication + */ + public final void mulTransposeLeft(Matrix4f m1, Matrix4f m2) + { + if (this != m1 && this != m2) { + this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30; + this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31; + this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32; + this.m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33; + + this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30; + this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31; + this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32; + this.m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33; + + this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30; + this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31; + this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32; + this.m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33; + + this.m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30; + this.m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31; + this.m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32; + this.m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33; + } else { + float m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, // vars for temp result matrix + m30, m31, m32, m33; + + + + m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20 + m1.m30*m2.m30; + m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21 + m1.m30*m2.m31; + m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22 + m1.m30*m2.m32; + m03 = m1.m00*m2.m03 + m1.m10*m2.m13 + m1.m20*m2.m23 + m1.m30*m2.m33; + + m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20 + m1.m31*m2.m30; + m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21 + m1.m31*m2.m31; + m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22 + m1.m31*m2.m32; + m13 = m1.m01*m2.m03 + m1.m11*m2.m13 + m1.m21*m2.m23 + m1.m31*m2.m33; + + m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20 + m1.m32*m2.m30; + m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21 + m1.m32*m2.m31; + m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22 + m1.m32*m2.m32; + m23 = m1.m02*m2.m03 + m1.m12*m2.m13 + m1.m22*m2.m23 + m1.m32*m2.m33; + + m30 = m1.m03*m2.m00 + m1.m13*m2.m10 + m1.m23*m2.m20 + m1.m33*m2.m30; + m31 = m1.m03*m2.m01 + m1.m13*m2.m11 + m1.m23*m2.m21 + m1.m33*m2.m31; + m32 = m1.m03*m2.m02 + m1.m13*m2.m12 + m1.m23*m2.m22 + m1.m33*m2.m32; + m33 = m1.m03*m2.m03 + m1.m13*m2.m13 + m1.m23*m2.m23 + m1.m33*m2.m33; + + this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; + this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; + this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; + this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; + } + + } + + + /** + * Returns true if all of the data members of Matrix4f m1 are + * equal to the corresponding data members in this Matrix4f. + * @param m1 the matrix with which the comparison is made. + * @return true or false + */ + public boolean equals(Matrix4f m1) + { + try { + return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02 + && this.m03 == m1.m03 && this.m10 == m1.m10 && this.m11 == m1.m11 + && this.m12 == m1.m12 && this.m13 == m1.m13 && this.m20 == m1.m20 + && this.m21 == m1.m21 && this.m22 == m1.m22 && this.m23 == m1.m23 + && this.m30 == m1.m30 && this.m31 == m1.m31 && this.m32 == m1.m32 + && this.m33 == m1.m33); + } + catch (NullPointerException e2) { return false; } + + } + + /** + * Returns true if the Object t1 is of type Matrix4f and all of the + * data members of t1 are equal to the corresponding data members in + * this Matrix4f. + * @param t1 the matrix with which the comparison is made. + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Matrix4f m2 = (Matrix4f) t1; + return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02 + && this.m03 == m2.m03 && this.m10 == m2.m10 && this.m11 == m2.m11 + && this.m12 == m2.m12 && this.m13 == m2.m13 && this.m20 == m2.m20 + && this.m21 == m2.m21 && this.m22 == m2.m22 && this.m23 == m2.m23 + && this.m30 == m2.m30 && this.m31 == m2.m31 && this.m32 == m2.m32 + && this.m33 == m2.m33); + } + catch (ClassCastException e1) { return false; } + catch (NullPointerException e2) { return false; } + } + + /** + * Returns true if the L-infinite distance between this matrix + * and matrix m1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[i=0,1,2,3 ; j=0,1,2,3 ; abs(this.m(i,j) - m1.m(i,j)] + * @param m1 the matrix to be compared to this matrix + * @param epsilon the threshold value + */ + public boolean epsilonEquals(Matrix4f m1, float epsilon) + { + + boolean status = true; + + if( Math.abs( this.m00 - m1.m00) > epsilon) status = false; + if( Math.abs( this.m01 - m1.m01) > epsilon) status = false; + if( Math.abs( this.m02 - m1.m02) > epsilon) status = false; + if( Math.abs( this.m03 - m1.m03) > epsilon) status = false; + + if( Math.abs( this.m10 - m1.m10) > epsilon) status = false; + if( Math.abs( this.m11 - m1.m11) > epsilon) status = false; + if( Math.abs( this.m12 - m1.m12) > epsilon) status = false; + if( Math.abs( this.m13 - m1.m13) > epsilon) status = false; + + if( Math.abs( this.m20 - m1.m20) > epsilon) status = false; + if( Math.abs( this.m21 - m1.m21) > epsilon) status = false; + if( Math.abs( this.m22 - m1.m22) > epsilon) status = false; + if( Math.abs( this.m23 - m1.m23) > epsilon) status = false; + + if( Math.abs( this.m30 - m1.m30) > epsilon) status = false; + if( Math.abs( this.m31 - m1.m31) > epsilon) status = false; + if( Math.abs( this.m32 - m1.m32) > epsilon) status = false; + if( Math.abs( this.m33 - m1.m33) > epsilon) status = false; + + return( status ); + + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Matrix4f objects with identical data values + * (i.e., Matrix4f.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashFloatBits(bits, m00); + bits = VecMathUtil.hashFloatBits(bits, m01); + bits = VecMathUtil.hashFloatBits(bits, m02); + bits = VecMathUtil.hashFloatBits(bits, m03); + bits = VecMathUtil.hashFloatBits(bits, m10); + bits = VecMathUtil.hashFloatBits(bits, m11); + bits = VecMathUtil.hashFloatBits(bits, m12); + bits = VecMathUtil.hashFloatBits(bits, m13); + bits = VecMathUtil.hashFloatBits(bits, m20); + bits = VecMathUtil.hashFloatBits(bits, m21); + bits = VecMathUtil.hashFloatBits(bits, m22); + bits = VecMathUtil.hashFloatBits(bits, m23); + bits = VecMathUtil.hashFloatBits(bits, m30); + bits = VecMathUtil.hashFloatBits(bits, m31); + bits = VecMathUtil.hashFloatBits(bits, m32); + bits = VecMathUtil.hashFloatBits(bits, m33); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Transform the vector vec using this Matrix4f and place the + * result into vecOut. + * @param vec the single precision vector to be transformed + * @param vecOut the vector into which the transformed values are placed + */ + public final void transform(Tuple4f vec, Tuple4f vecOut) + { + float x,y,z; + x = m00*vec.x + m01*vec.y + + m02*vec.z + m03*vec.w; + y = m10*vec.x + m11*vec.y + + m12*vec.z + m13*vec.w; + z = m20*vec.x + m21*vec.y + + m22*vec.z + m23*vec.w; + vecOut.w = m30*vec.x + m31*vec.y + + m32*vec.z + m33*vec.w; + vecOut.x = x; + vecOut.y = y; + vecOut.z = z; + } + + + /** + * Transform the vector vec using this Transform and place the + * result back into vec. + * @param vec the single precision vector to be transformed + */ + public final void transform(Tuple4f vec) + { + float x,y,z; + + x = m00*vec.x + m01*vec.y + + m02*vec.z + m03*vec.w; + y = m10*vec.x + m11*vec.y + + m12*vec.z + m13*vec.w; + z = m20*vec.x + m21*vec.y + + m22*vec.z + m23*vec.w; + vec.w = m30*vec.x + m31*vec.y + + m32*vec.z + m33*vec.w; + vec.x = x; + vec.y = y; + vec.z = z; + } + + /** + * Transforms the point parameter with this Matrix4f and + * places the result into pointOut. The fourth element of the + * point input paramter is assumed to be one. + * @param point the input point to be transformed. + * @param pointOut the transformed point + */ + public final void transform(Point3f point, Point3f pointOut) + { + float x,y; + x = m00*point.x + m01*point.y + m02*point.z + m03; + y = m10*point.x + m11*point.y + m12*point.z + m13; + pointOut.z = m20*point.x + m21*point.y + m22*point.z + m23; + pointOut.x = x; + pointOut.y = y; + } + + + /** + * Transforms the point parameter with this Matrix4f and + * places the result back into point. The fourth element of the + * point input paramter is assumed to be one. + * @param point the input point to be transformed. + */ + public final void transform(Point3f point) + { + float x, y; + x = m00*point.x + m01*point.y + m02*point.z + m03; + y = m10*point.x + m11*point.y + m12*point.z + m13; + point.z = m20*point.x + m21*point.y + m22*point.z + m23; + point.x = x; + point.y = y; + } + + + /** + * Transforms the normal parameter by this Matrix4f and places the value + * into normalOut. The fourth element of the normal is assumed to be zero. + * @param normal the input normal to be transformed. + * @param normalOut the transformed normal + */ + public final void transform(Vector3f normal, Vector3f normalOut) + { + float x,y; + x = m00*normal.x + m01*normal.y + m02*normal.z; + y = m10*normal.x + m11*normal.y + m12*normal.z; + normalOut.z = m20*normal.x + m21*normal.y + m22*normal.z; + normalOut.x = x; + normalOut.y = y; + } + + + /** + * Transforms the normal parameter by this transform and places the value + * back into normal. The fourth element of the normal is assumed to be zero. + * @param normal the input normal to be transformed. + */ + public final void transform(Vector3f normal) + { + float x, y; + + x = m00*normal.x + m01*normal.y + m02*normal.z; + y = m10*normal.x + m11*normal.y + m12*normal.z; + normal.z = m20*normal.x + m21*normal.y + m22*normal.z; + normal.x = x; + normal.y = y; + } + + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the double precision Matrix3d argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the passed rotation components, + * and then the scale is reapplied to the rotational components. + * @param m1 double precision 3x3 matrix + */ + public final void setRotation( Matrix3d m1) + { + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = (float)(m1.m00*tmp_scale[0]); + m01 = (float)(m1.m01*tmp_scale[1]); + m02 = (float)(m1.m02*tmp_scale[2]); + + m10 = (float)(m1.m10*tmp_scale[0]); + m11 = (float)(m1.m11*tmp_scale[1]); + m12 = (float)(m1.m12*tmp_scale[2]); + + m20 = (float)(m1.m20*tmp_scale[0]); + m21 = (float)(m1.m21*tmp_scale[1]); + m22 = (float)(m1.m22*tmp_scale[2]); + + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix values in the single precision Matrix3f argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the passed rotation components, + * and then the scale is reapplied to the rotational components. + * @param m1 single precision 3x3 matrix + */ + public final void setRotation( Matrix3f m1){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = (float)(m1.m00*tmp_scale[0]); + m01 = (float)(m1.m01*tmp_scale[1]); + m02 = (float)(m1.m02*tmp_scale[2]); + + m10 = (float)(m1.m10*tmp_scale[0]); + m11 = (float)(m1.m11*tmp_scale[1]); + m12 = (float)(m1.m12*tmp_scale[2]); + + m20 = (float)(m1.m20*tmp_scale[0]); + m21 = (float)(m1.m21*tmp_scale[1]); + m22 = (float)(m1.m22*tmp_scale[2]); + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix equivalent values of the quaternion argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the matrix equivalent of the quaternion, + * and then the scale is reapplied to the rotational components. + * @param q1 the quaternion that specifies the rotation + */ + public final void setRotation(Quat4f q1){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = (float)((1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0]); + m10 = (float)((2.0f*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0]); + m20 = (float)((2.0f*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0]); + + m01 = (float)((2.0f*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1]); + m11 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1]); + m21 = (float)((2.0f*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1]); + + m02 = (float)((2.0f*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2]); + m12 = (float)((2.0f*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2]); + m22 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2]); + + } + + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix equivalent values of the quaternion argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the matrix equivalent of the quaternion, + * and then the scale is reapplied to the rotational components. + * @param q1 the quaternion that specifies the rotation + */ + public final void setRotation(Quat4d q1){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + m00 = (float)((1.0f - 2.0f*q1.y*q1.y - 2.0f*q1.z*q1.z)*tmp_scale[0]); + m10 = (float)((2.0f*(q1.x*q1.y + q1.w*q1.z))*tmp_scale[0]); + m20 = (float)((2.0f*(q1.x*q1.z - q1.w*q1.y))*tmp_scale[0]); + + m01 = (float)((2.0f*(q1.x*q1.y - q1.w*q1.z))*tmp_scale[1]); + m11 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.z*q1.z)*tmp_scale[1]); + m21 = (float)((2.0f*(q1.y*q1.z + q1.w*q1.x))*tmp_scale[1]); + + m02 = (float)((2.0f*(q1.x*q1.z + q1.w*q1.y))*tmp_scale[2]); + m12 = (float)((2.0f*(q1.y*q1.z - q1.w*q1.x))*tmp_scale[2]); + m22 = (float)((1.0f - 2.0f*q1.x*q1.x - 2.0f*q1.y*q1.y)*tmp_scale[2]); + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the + * matrix equivalent values of the axis-angle argument; the other + * elements of this matrix are unchanged; a singular value + * decomposition is performed on this object's upper 3x3 matrix to + * factor out the scale, then this object's upper 3x3 matrix components + * are replaced by the matrix equivalent of the axis-angle, + * and then the scale is reapplied to the rotational components. + * @param a1 the axis-angle to be converted (x, y, z, angle) + */ + public final void setRotation(AxisAngle4f a1){ + double[] tmp_rot = new double[9]; // scratch matrix + double[] tmp_scale = new double[3]; // scratch matrix + + getScaleRotate( tmp_scale, tmp_rot ); + + double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z); + if( mag < EPS ) { + m00 = 1.0f; + m01 = 0.0f; + m02 = 0.0f; + + m10 = 0.0f; + m11 = 1.0f; + m12 = 0.0f; + + m20 = 0.0f; + m21 = 0.0f; + m22 = 1.0f; + } else { + mag = 1.0/mag; + double ax = a1.x*mag; + double ay = a1.y*mag; + double az = a1.z*mag; + + double sinTheta = Math.sin(a1.angle); + double cosTheta = Math.cos(a1.angle); + double t = 1.0 - cosTheta; + + double xz = a1.x * a1.z; + double xy = a1.x * a1.y; + double yz = a1.y * a1.z; + + m00 = (float)((t * ax * ax + cosTheta)*tmp_scale[0]); + m01 = (float)((t * xy - sinTheta * az)*tmp_scale[1]); + m02 = (float)((t * xz + sinTheta * ay)*tmp_scale[2]); + + m10 = (float)((t * xy + sinTheta * az)*tmp_scale[0]); + m11 = (float)((t * ay * ay + cosTheta)*tmp_scale[1]); + m12 = (float)((t * yz - sinTheta * ax)*tmp_scale[2]); + + m20 = (float)((t * xz - sinTheta * ay)*tmp_scale[0]); + m21 = (float)((t * yz + sinTheta * ax)*tmp_scale[1]); + m22 = (float)((t * az * az + cosTheta)*tmp_scale[2]); + } + + + } + + /** + * Sets this matrix to all zeros. + */ + public final void setZero() + { + m00 = 0.0f; + m01 = 0.0f; + m02 = 0.0f; + m03 = 0.0f; + m10 = 0.0f; + m11 = 0.0f; + m12 = 0.0f; + m13 = 0.0f; + m20 = 0.0f; + m21 = 0.0f; + m22 = 0.0f; + m23 = 0.0f; + m30 = 0.0f; + m31 = 0.0f; + m32 = 0.0f; + m33 = 0.0f; + } + + /** + * Negates the value of this matrix: this = -this. + */ + public final void negate() + { + m00 = -m00; + m01 = -m01; + m02 = -m02; + m03 = -m03; + m10 = -m10; + m11 = -m11; + m12 = -m12; + m13 = -m13; + m20 = -m20; + m21 = -m21; + m22 = -m22; + m23 = -m23; + m30 = -m30; + m31 = -m31; + m32 = -m32; + m33 = -m33; + } + + /** + * Sets the value of this matrix equal to the negation of + * of the Matrix4f parameter. + * @param m1 the source matrix + */ + public final void negate(Matrix4f m1) + { + this.m00 = -m1.m00; + this.m01 = -m1.m01; + this.m02 = -m1.m02; + this.m03 = -m1.m03; + this.m10 = -m1.m10; + this.m11 = -m1.m11; + this.m12 = -m1.m12; + this.m13 = -m1.m13; + this.m20 = -m1.m20; + this.m21 = -m1.m21; + this.m22 = -m1.m22; + this.m23 = -m1.m23; + this.m30 = -m1.m30; + this.m31 = -m1.m31; + this.m32 = -m1.m32; + this.m33 = -m1.m33; + } + private final void getScaleRotate(double scales[], double rots[]) { + + double[] tmp = new double[9]; // scratch matrix + tmp[0] = m00; + tmp[1] = m01; + tmp[2] = m02; + + tmp[3] = m10; + tmp[4] = m11; + tmp[5] = m12; + + tmp[6] = m20; + tmp[7] = m21; + tmp[8] = m22; + + Matrix3d.compute_svd( tmp, scales, rots); + + return; + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + Matrix4f m1 = null; + try { + m1 = (Matrix4f)super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + + return m1; + } + + /** + * Get the first matrix element in the first row. + * + * @return Returns the m00. + * + * @since vecmath 1.5 + */ + public final float getM00() { + return m00; + } + + /** + * Set the first matrix element in the first row. + * + * @param m00 The m00 to set. + * + * @since vecmath 1.5 + */ + public final void setM00(float m00) { + this.m00 = m00; + } + + /** + * Get the second matrix element in the first row. + * + * @return Returns the m01. + * + * @since vecmath 1.5 + */ + public final float getM01() { + return m01; + } + + /** + * Set the second matrix element in the first row. + * + * @param m01 The m01 to set. + * + * @since vecmath 1.5 + */ + public final void setM01(float m01) { + this.m01 = m01; + } + + /** + * Get the third matrix element in the first row. + * + * @return Returns the m02. + * + * @since vecmath 1.5 + */ + public final float getM02() { + return m02; + } + + /** + * Set the third matrix element in the first row. + * + * @param m02 The m02 to set. + * + * @since vecmath 1.5 + */ + public final void setM02(float m02) { + this.m02 = m02; + } + + /** + * Get first matrix element in the second row. + * + * @return Returns the m10. + * + * @since vecmath 1.5 + */ + public final float getM10() { + return m10; + } + + /** + * Set first matrix element in the second row. + * + * @param m10 The m10 to set. + * + * @since vecmath 1.5 + */ + public final void setM10(float m10) { + this.m10 = m10; + } + + /** + * Get second matrix element in the second row. + * + * @return Returns the m11. + * + * @since vecmath 1.5 + */ + public final float getM11() { + return m11; + } + + /** + * Set the second matrix element in the second row. + * + * @param m11 The m11 to set. + * + * @since vecmath 1.5 + */ + public final void setM11(float m11) { + this.m11 = m11; + } + + /** + * Get the third matrix element in the second row. + * + * @return Returns the m12. + * + * @since vecmath 1.5 + */ + public final float getM12() { + return m12; + } + + /** + * Set the third matrix element in the second row. + * + * @param m12 The m12 to set. + * + * @since vecmath 1.5 + */ + public final void setM12(float m12) { + this.m12 = m12; + } + + /** + * Get the first matrix element in the third row. + * + * @return Returns the m20. + * + * @since vecmath 1.5 + */ + public final float getM20() { + return m20; + } + + /** + * Set the first matrix element in the third row. + * + * @param m20 The m20 to set. + * + * @since vecmath 1.5 + */ + public final void setM20(float m20) { + this.m20 = m20; + } + + /** + * Get the second matrix element in the third row. + * + * @return Returns the m21. + * + * @since vecmath 1.5 + */ + public final float getM21() { + return m21; + } + + /** + * Set the second matrix element in the third row. + * + * @param m21 The m21 to set. + * + * @since vecmath 1.5 + */ + public final void setM21(float m21) { + this.m21 = m21; + } + + /** + * Get the third matrix element in the third row. + * + * @return Returns the m22. + * + * @since vecmath 1.5 + */ + public final float getM22() { + return m22; + } + + /** + * Set the third matrix element in the third row. + * + * @param m22 The m22 to set. + * + * @since vecmath 1.5 + */ + public final void setM22(float m22) { + this.m22 = m22; + } + + /** + * Get the fourth element of the first row. + * + * @return Returns the m03. + * + * @since vecmath 1.5 + */ + public final float getM03() { + return m03; + } + + /** + * Set the fourth element of the first row. + * + * @param m03 The m03 to set. + * + * @since vecmath 1.5 + */ + public final void setM03(float m03) { + this.m03 = m03; + } + + /** + * Get the fourth element of the second row. + * + * @return Returns the m13. + * + * @since vecmath 1.5 + */ + public final float getM13() { + return m13; + } + + /** + * Set the fourth element of the second row. + * + * @param m13 The m13 to set. + * + * @since vecmath 1.5 + */ + public final void setM13(float m13) { + this.m13 = m13; + } + + /** + * Get the fourth element of the third row. + * + * @return Returns the m23. + * + * @since vecmath 1.5 + */ + public final float getM23() { + return m23; + } + + /** + * Set the fourth element of the third row. + * + * @param m23 The m23 to set. + * + * @since vecmath 1.5 + */ + public final void setM23(float m23) { + this.m23 = m23; + } + + /** + * Get the first element of the fourth row. + * + * @return Returns the m30. + * + * @since vecmath 1.5 + */ + public final float getM30() { + return m30; + } + + /** + * Set the first element of the fourth row. + * + * @param m30 The m30 to set. + * + * + * @since vecmath 1.5 + */ + public final void setM30(float m30) { + this.m30 = m30; + } + + /** + * Get the second element of the fourth row. + * + * @return Returns the m31. + * + * @since vecmath 1.5 + */ + public final float getM31() { + return m31; + } + + /** + * Set the second element of the fourth row. + * + * @param m31 The m31 to set. + * + * @since vecmath 1.5 + */ + public final void setM31(float m31) { + this.m31 = m31; + } + + /** + * Get the third element of the fourth row. + * + * @return Returns the m32. + * + * @since vecmath 1.5 + */ + public final float getM32() { + return m32; + } + + /** + * Set the third element of the fourth row. + * + * @param m32 The m32 to set. + * + * + * @since vecmath 1.5 + */ + public final void setM32(float m32) { + this.m32 = m32; + } + + /** + * Get the fourth element of the fourth row. + * + * @return Returns the m33. + * + * @since vecmath 1.5 + */ + public final float getM33() { + return m33; + } + + /** + * Set the fourth element of the fourth row. + * + * @param m33 The m33 to set. + * + * @since vecmath 1.5 + */ + public final void setM33(float m33) { + this.m33 = m33; + } +} diff --git a/src/org/jogamp/vecmath/MismatchedSizeException.java b/src/org/jogamp/vecmath/MismatchedSizeException.java new file mode 100644 index 0000000..4a1f791 --- /dev/null +++ b/src/org/jogamp/vecmath/MismatchedSizeException.java @@ -0,0 +1,52 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +/** + * Indicates that an operation cannot be completed properly because + * of a mismatch in the sizes of object attributes. + */ +public class MismatchedSizeException extends RuntimeException{ + + +/** + * Create the exception object with default values. + */ + public MismatchedSizeException(){ + } + +/** + * Create the exception object that outputs a message. + * @param str the message string to be output. + */ + public MismatchedSizeException(String str){ + + super(str); + } + +} + diff --git a/src/org/jogamp/vecmath/Point2d.java b/src/org/jogamp/vecmath/Point2d.java new file mode 100644 index 0000000..625024b --- /dev/null +++ b/src/org/jogamp/vecmath/Point2d.java @@ -0,0 +1,157 @@ +/* + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 2 element point that is represented by double precision floating + * point x,y coordinates. + * + */ +public class Point2d extends Tuple2d implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = 1133748791492571954L; + + /** + * Constructs and initializes a Point2d from the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Point2d(double x, double y) + { + super(x,y); + } + + + /** + * Constructs and initializes a Point2d from the specified array. + * @param p the array of length 2 containing xy in order + */ + public Point2d(double[] p) + { + super(p); + } + + + /** + * Constructs and initializes a Point2d from the specified Point2d. + * @param p1 the Point2d containing the initialization x y data + */ + public Point2d(Point2d p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point2d from the specified Point2f. + * @param p1 the Point2f containing the initialization x y data + */ + public Point2d(Point2f p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point2d from the specified Tuple2d. + * @param t1 the Tuple2d containing the initialization x y data + */ + public Point2d(Tuple2d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point2d from the specified Tuple2f. + * @param t1 the Tuple2f containing the initialization x y data + */ + public Point2d(Tuple2f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point2d to (0,0). + */ + public Point2d() + { + super(); + } + + /** + * Computes the square of the distance between this point and point p1. + * @param p1 the other point + */ + public final double distanceSquared(Point2d p1) + { + double dx, dy; + + dx = this.x-p1.x; + dy = this.y-p1.y; + return dx*dx+dy*dy; + } + + /** + * Computes the distance between this point and point p1. + * @param p1 the other point + */ + public final double distance(Point2d p1) + { + double dx, dy; + + dx = this.x-p1.x; + dy = this.y-p1.y; + return Math.sqrt(dx*dx+dy*dy); + } + + + /** + * Computes the L-1 (Manhattan) distance between this point and + * point p1. The L-1 distance is equal to abs(x1-x2) + abs(y1-y2). + * @param p1 the other point + */ + public final double distanceL1(Point2d p1) + { + return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y)); + } + + /** + * Computes the L-infinite distance between this point and + * point p1. The L-infinite distance is equal to + * MAX[abs(x1-x2), abs(y1-y2)]. + * @param p1 the other point + */ + public final double distanceLinf(Point2d p1) + { + return(Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y))); + } + +} diff --git a/src/org/jogamp/vecmath/Point2f.java b/src/org/jogamp/vecmath/Point2f.java new file mode 100644 index 0000000..21af62a --- /dev/null +++ b/src/org/jogamp/vecmath/Point2f.java @@ -0,0 +1,158 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 2 element point that is represented by single precision floating + * point x,y coordinates. + * + */ +public class Point2f extends Tuple2f implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = -4801347926528714435L; + + /** + * Constructs and initializes a Point2f from the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Point2f(float x, float y) + { + super(x,y); + } + + + /** + * Constructs and initializes a Point2f from the specified array. + * @param p the array of length 2 containing xy in order + */ + public Point2f(float[] p) + { + super(p); + } + + + /** + * Constructs and initializes a Point2f from the specified Point2f. + * @param p1 the Point2f containing the initialization x y data + */ + public Point2f(Point2f p1) + { + super(p1); + } + + /** + * Constructs and initializes a Point2f from the specified Point2d. + * @param p1 the Point2d containing the initialization x y z data + */ + public Point2f(Point2d p1) + { + super(p1); + } + + + + /** + * Constructs and initializes a Point2f from the specified Tuple2d. + * @param t1 the Tuple2d containing the initialization x y z data + */ + public Point2f(Tuple2d t1) + { + super(t1); + } + + + + /** + * Constructs and initializes a Point2f from the specified Tuple2f. + * @param t1 the Tuple2f containing the initialization x y data + */ + public Point2f(Tuple2f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point2f to (0,0). + */ + public Point2f() + { + super(); + } + + /** + * Computes the square of the distance between this point and point p1. + * @param p1 the other point + */ + public final float distanceSquared(Point2f p1) + { + float dx, dy; + + dx = this.x-p1.x; + dy = this.y-p1.y; + return dx*dx+dy*dy; + } + + /** + * Computes the distance between this point and point p1. + * @param p1 the other point + */ + public final float distance(Point2f p1) + { + float dx, dy; + + dx = this.x-p1.x; + dy = this.y-p1.y; + return (float) Math.sqrt(dx*dx+dy*dy); + } + + + /** + * Computes the L-1 (Manhattan) distance between this point and + * point p1. The L-1 distance is equal to abs(x1-x2) + abs(y1-y2). + * @param p1 the other point + */ + public final float distanceL1(Point2f p1) + { + return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y)); + } + + /** + * Computes the L-infinite distance between this point and + * point p1. The L-infinite distance is equal to + * MAX[abs(x1-x2), abs(y1-y2)]. + * @param p1 the other point + */ + public final float distanceLinf(Point2f p1) + { + return(Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y))); + } + +} diff --git a/src/org/jogamp/vecmath/Point2i.java b/src/org/jogamp/vecmath/Point2i.java new file mode 100644 index 0000000..56823c0 --- /dev/null +++ b/src/org/jogamp/vecmath/Point2i.java @@ -0,0 +1,77 @@ +/* + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 2-element point represented by signed integer x,y + * coordinates. + * + * @since vecmath 1.4 + */ +public class Point2i extends Tuple2i implements java.io.Serializable { + + static final long serialVersionUID = 9208072376494084954L; + + /** + * Constructs and initializes a Point2i from the specified + * x and y coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Point2i(int x, int y) { + super(x, y); + } + + + /** + * Constructs and initializes a Point2i from the array of length 2. + * @param t the array of length 2 containing x and y in order. + */ + public Point2i(int[] t) { + super(t); + } + + + /** + * Constructs and initializes a Point2i from the specified Tuple2i. + * @param t1 the Tuple2i containing the initialization x and y + * data. + */ + public Point2i(Tuple2i t1) { + super(t1); + } + + + /** + * Constructs and initializes a Point2i to (0,0). + */ + public Point2i() { + super(); + } + +} diff --git a/src/org/jogamp/vecmath/Point3d.java b/src/org/jogamp/vecmath/Point3d.java new file mode 100644 index 0000000..f43a1d6 --- /dev/null +++ b/src/org/jogamp/vecmath/Point3d.java @@ -0,0 +1,188 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 3 element point that is represented by double precision floating point + * x,y,z coordinates. + * + */ +public class Point3d extends Tuple3d implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = 5718062286069042927L; + + /** + * Constructs and initializes a Point3d from the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Point3d(double x, double y, double z) + { + super(x,y,z); + } + + + /** + * Constructs and initializes a Point3d from the array of length 3. + * @param p the array of length 3 containing xyz in order + */ + public Point3d(double[] p) + { + super(p); + } + + + /** + * Constructs and initializes a Point3d from the specified Point3d. + * @param p1 the Point3d containing the initialization x y z data + */ + public Point3d(Point3d p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point3d from the specified Point3f. + * @param p1 the Point3f containing the initialization x y z data + */ + public Point3d(Point3f p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point3d from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public Point3d(Tuple3f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point3d from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public Point3d(Tuple3d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point3d to (0,0,0). + */ + public Point3d() + { + super(); + } + + + /** + * Returns the square of the distance between this point and point p1. + * @param p1 the other point + * @return the square of the distance + */ + public final double distanceSquared(Point3d p1) + { + double dx, dy, dz; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + return (dx*dx+dy*dy+dz*dz); + } + + + /** + * Returns the distance between this point and point p1. + * @param p1 the other point + * @return the distance + */ + public final double distance(Point3d p1) + { + double dx, dy, dz; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + return Math.sqrt(dx*dx+dy*dy+dz*dz); + } + + + /** + * Computes the L-1 (Manhattan) distance between this point and + * point p1. The L-1 distance is equal to: + * abs(x1-x2) + abs(y1-y2) + abs(z1-z2). + * @param p1 the other point + * @return the L-1 distance + */ + public final double distanceL1(Point3d p1) { + return Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) + + Math.abs(this.z-p1.z); + } + + + /** + * Computes the L-infinite distance between this point and + * point p1. The L-infinite distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)]. + * @param p1 the other point + * @return the L-infinite distance + */ + public final double distanceLinf(Point3d p1) { + double tmp; + tmp = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y)); + + return Math.max(tmp,Math.abs(this.z-p1.z)); + } + + + /** + * Multiplies each of the x,y,z components of the Point4d parameter + * by 1/w and places the projected values into this point. + * @param p1 the source Point4d, which is not modified + */ + public final void project(Point4d p1) + { + double oneOw; + + oneOw = 1/p1.w; + x = p1.x*oneOw; + y = p1.y*oneOw; + z = p1.z*oneOw; + + } + + +} diff --git a/src/org/jogamp/vecmath/Point3f.java b/src/org/jogamp/vecmath/Point3f.java new file mode 100644 index 0000000..2f97b25 --- /dev/null +++ b/src/org/jogamp/vecmath/Point3f.java @@ -0,0 +1,191 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 3 element point that is represented by single precision floating point + * x,y,z coordinates. + * + */ +public class Point3f extends Tuple3f implements java.io.Serializable { + + + // Compatible with 1.1 + static final long serialVersionUID = -8689337816398030143L; + + /** + * Constructs and initializes a Point3f from the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Point3f(float x, float y, float z) + { + super(x,y,z); + } + + + /** + * Constructs and initializes a Point3f from the array of length 3. + * @param p the array of length 3 containing xyz in order + */ + public Point3f(float[] p) + { + super(p); + } + + + /** + * Constructs and initializes a Point3f from the specified Point3f. + * @param p1 the Point3f containing the initialization x y z data + */ + public Point3f(Point3f p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point3f from the specified Point3d. + * @param p1 the Point3d containing the initialization x y z data + */ + public Point3f(Point3d p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point3f from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public Point3f(Tuple3f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point3f from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public Point3f(Tuple3d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point3f to (0,0,0). + */ + public Point3f() + { + super(); + } + + + /** + * Computes the square of the distance between this point and + * point p1. + * @param p1 the other point + * @return the square of the distance + */ + public final float distanceSquared(Point3f p1) + { + float dx, dy, dz; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + return dx*dx+dy*dy+dz*dz; + } + + + /** + * Computes the distance between this point and point p1. + * @param p1 the other point + * @return the distance + */ + public final float distance(Point3f p1) + { + float dx, dy, dz; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + return (float) Math.sqrt(dx*dx+dy*dy+dz*dz); + } + + + /** + * Computes the L-1 (Manhattan) distance between this point and + * point p1. The L-1 distance is equal to: + * abs(x1-x2) + abs(y1-y2) + abs(z1-z2). + * @param p1 the other point + * @return the L-1 distance + */ + public final float distanceL1(Point3f p1) + { + return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) + Math.abs(this.z-p1.z)); + } + + + /** + * Computes the L-infinite distance between this point and + * point p1. The L-infinite distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)]. + * @param p1 the other point + * @return the L-infinite distance + */ + public final float distanceLinf(Point3f p1) + { + float tmp; + tmp = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y)); + return(Math.max(tmp,Math.abs(this.z-p1.z))); + + } + + + /** + * Multiplies each of the x,y,z components of the Point4f parameter + * by 1/w and places the projected values into this point. + * @param p1 the source Point4f, which is not modified + */ + public final void project(Point4f p1) + { + float oneOw; + + oneOw = 1/p1.w; + x = p1.x*oneOw; + y = p1.y*oneOw; + z = p1.z*oneOw; + + } + + +} diff --git a/src/org/jogamp/vecmath/Point3i.java b/src/org/jogamp/vecmath/Point3i.java new file mode 100644 index 0000000..42e60ae --- /dev/null +++ b/src/org/jogamp/vecmath/Point3i.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 3 element point represented by signed integer x,y,z + * coordinates. + * + * @since vecmath 1.2 + */ +public class Point3i extends Tuple3i implements java.io.Serializable { + + // Compatible with 1.2 + static final long serialVersionUID = 6149289077348153921L; + + /** + * Constructs and initializes a Point3i from the specified + * x, y, and z coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Point3i(int x, int y, int z) { + super(x, y, z); + } + + + /** + * Constructs and initializes a Point3i from the array of length 3. + * @param t the array of length 3 containing x, y, and z in order. + */ + public Point3i(int[] t) { + super(t); + } + + + /** + * Constructs and initializes a Point3i from the specified Tuple3i. + * @param t1 the Tuple3i containing the initialization x, y, and z + * data. + */ + public Point3i(Tuple3i t1) { + super(t1); + } + + + /** + * Constructs and initializes a Point3i to (0,0,0). + */ + public Point3i() { + super(); + } + +} diff --git a/src/org/jogamp/vecmath/Point4d.java b/src/org/jogamp/vecmath/Point4d.java new file mode 100644 index 0000000..8cc9d87 --- /dev/null +++ b/src/org/jogamp/vecmath/Point4d.java @@ -0,0 +1,223 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4 element vector represented by double precision floating point + * x,y,z,w coordinates. + * + */ +public class Point4d extends Tuple4d implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = 1733471895962736949L; + + + /** + * Constructs and initializes a Point4d from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Point4d(double x, double y, double z, double w) + { + super(x,y,z,w); + } + + /** + * Constructs and initializes a Point4d from the coordinates contained + * in the array. + * @param p the array of length 4 containing xyzw in order + */ + public Point4d(double[] p) + { + super(p); + } + + + /** + * Constructs and initializes a Point4d from the specified Point4d. + * @param p1 the Point4d containing the initialization x y z w data + */ + public Point4d(Point4d p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point4d from the specified Point4f. + * @param p1 the Point4f containing the initialization x y z w data + */ + public Point4d(Point4f p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point4d from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Point4d(Tuple4f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point4d from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Point4d(Tuple4d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point4d from the specified Tuple3d. + * The x,y,z components of this point are set to the corresponding + * components of tuple t1. The w component of this point + * is set to 1. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public Point4d(Tuple3d t1) { + super(t1.x, t1.y, t1.z, 1.0); + } + + + /** + * Constructs and initializes a Point4d to (0,0,0,0). + */ + public Point4d() + { + super(); + } + + + /** + * Sets the x,y,z components of this point to the corresponding + * components of tuple t1. The w component of this point + * is set to 1. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public final void set(Tuple3d t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = 1.0; + } + + + /** + * Returns the square of the distance between this point and point p1. + * @param p1 the first point + * @return the square of distance between this point and point p1 + */ + public final double distanceSquared(Point4d p1) + { + double dx, dy, dz, dw; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + dw = this.w-p1.w; + return (dx*dx+dy*dy+dz*dz+dw*dw); + } + + + /** + * Returns the distance between this point and point p1. + * @param p1 the first point + * @return the distance between these this point and point p1. + */ + public final double distance(Point4d p1) + { + double dx, dy, dz, dw; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + dw = this.w-p1.w; + return Math.sqrt(dx*dx+dy*dy+dz*dz+dw*dw); + } + + + /** + * Computes the L-1 (Manhattan) distance between this point and + * point p1. The L-1 distance is equal to: + * abs(x1-x2) + abs(y1-y2) + abs(z1-z2) + abs(w1-w2). + * @param p1 the other point + * @return the L-1 distance + */ + public final double distanceL1(Point4d p1) { + return Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) + + Math.abs(this.z-p1.z) + Math.abs(this.w-p1.w); + } + + /** + * Computes the L-infinite distance between this point and + * point p1. The L-infinite distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)]. + * @param p1 the other point + * @return the L-infinite distance + */ + public final double distanceLinf(Point4d p1) { + double t1, t2; + t1 = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y)); + t2 = Math.max( Math.abs(this.z-p1.z), Math.abs(this.w-p1.w)); + + return Math.max(t1,t2); + } + + /** + * Multiplies each of the x,y,z components of the Point4d parameter + * by 1/w, places the projected values into this point, and places + * a 1 as the w parameter of this point. + * @param p1 the source Point4d, which is not modified + */ + public final void project(Point4d p1) + { + double oneOw; + + oneOw = 1/p1.w; + x = p1.x*oneOw; + y = p1.y*oneOw; + z = p1.z*oneOw; + w = 1.0; + + } + + +} diff --git a/src/org/jogamp/vecmath/Point4f.java b/src/org/jogamp/vecmath/Point4f.java new file mode 100644 index 0000000..612875b --- /dev/null +++ b/src/org/jogamp/vecmath/Point4f.java @@ -0,0 +1,225 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4 element point represented by single precision floating point x,y,z,w + * coordinates. + * + */ +public class Point4f extends Tuple4f implements java.io.Serializable { + + + // Compatible with 1.1 + static final long serialVersionUID = 4643134103185764459L; + + /** + * Constructs and initializes a Point4f from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Point4f(float x, float y, float z, float w) + { + super(x,y,z,w); + } + + + /** + * Constructs and initializes a Point4f from the array of length 4. + * @param p the array of length 4 containing xyzw in order + */ + public Point4f(float[] p) + { + super(p); + } + + + /** + * Constructs and initializes a Point4f from the specified Point4f. + * @param p1 the Point4f containing the initialization x y z w data + */ + public Point4f(Point4f p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point4f from the specified Point4d. + * @param p1 the Point4d containing the initialization x y z w data + */ + public Point4f(Point4d p1) + { + super(p1); + } + + + /** + * Constructs and initializes a Point4f from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Point4f(Tuple4f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point4f from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Point4f(Tuple4d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Point4f from the specified Tuple3f. + * The x,y,z components of this point are set to the corresponding + * components of tuple t1. The w component of this point + * is set to 1. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public Point4f(Tuple3f t1) { + super(t1.x, t1.y, t1.z, 1.0f); + } + + + /** + * Constructs and initializes a Point4f to (0,0,0,0). + */ + public Point4f() + { + super(); + } + + + /** + * Sets the x,y,z components of this point to the corresponding + * components of tuple t1. The w component of this point + * is set to 1. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public final void set(Tuple3f t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = 1.0f; + } + + + /** + * Computes the square of the distance between this point and point p1. + * @param p1 the other point + * @return the square of distance between these two points as a float + */ + public final float distanceSquared(Point4f p1) + { + float dx, dy, dz, dw; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + dw = this.w-p1.w; + return (dx*dx+dy*dy+dz*dz+dw*dw); + } + + + /** + * Computes the distance between this point and point p1. + * @param p1 the other point + * @return the distance between the two points + */ + public final float distance(Point4f p1) + { + float dx, dy, dz, dw; + + dx = this.x-p1.x; + dy = this.y-p1.y; + dz = this.z-p1.z; + dw = this.w-p1.w; + return (float) Math.sqrt(dx*dx+dy*dy+dz*dz+dw*dw); + } + + + /** + * Computes the L-1 (Manhattan) distance between this point and + * point p1. The L-1 distance is equal to: + * abs(x1-x2) + abs(y1-y2) + abs(z1-z2) + abs(w1-w2). + * @param p1 the other point + * @return the L-1 distance + */ + public final float distanceL1(Point4f p1) + { + return( Math.abs(this.x-p1.x) + Math.abs(this.y-p1.y) + Math.abs(this.z-p1.z) + Math.abs(this.w-p1.w)); + } + + + /** + * Computes the L-infinite distance between this point and + * point p1. The L-infinite distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)]. + * @param p1 the other point + * @return the L-infinite distance + */ + public final float distanceLinf(Point4f p1) + { + float t1, t2; + t1 = Math.max( Math.abs(this.x-p1.x), Math.abs(this.y-p1.y)); + t2 = Math.max( Math.abs(this.z-p1.z), Math.abs(this.w-p1.w)); + + return(Math.max(t1,t2)); + + } + + /** + * Multiplies each of the x,y,z components of the Point4f parameter + * by 1/w, places the projected values into this point, and places + * a 1 as the w parameter of this point. + * @param p1 the source Point4f, which is not modified + */ + public final void project(Point4f p1) + { + float oneOw; + + oneOw = 1/p1.w; + x = p1.x*oneOw; + y = p1.y*oneOw; + z = p1.z*oneOw; + w = 1.0f; + + } + +} diff --git a/src/org/jogamp/vecmath/Point4i.java b/src/org/jogamp/vecmath/Point4i.java new file mode 100644 index 0000000..ae0c5f7 --- /dev/null +++ b/src/org/jogamp/vecmath/Point4i.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4 element point represented by signed integer x,y,z,w + * coordinates. + * + * @since vecmath 1.2 + */ +public class Point4i extends Tuple4i implements java.io.Serializable { + + // Combatible with 1.2 + static final long serialVersionUID = 620124780244617983L; + + /** + * Constructs and initializes a Point4i from the specified + * x, y, z, and w coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Point4i(int x, int y, int z, int w) { + super(x, y, z, w); + } + + + /** + * Constructs and initializes a Point4i from the array of length 4. + * @param t the array of length 4 containing x, y, z, and w in order. + */ + public Point4i(int[] t) { + super(t); + } + + + /** + * Constructs and initializes a Point4i from the specified Tuple4i. + * @param t1 the Tuple4i containing the initialization x, y, z, + * and w data. + */ + public Point4i(Tuple4i t1) { + super(t1); + } + + + /** + * Constructs and initializes a Point4i to (0,0,0,0). + */ + public Point4i() { + super(); + } + +} diff --git a/src/org/jogamp/vecmath/Quat4d.java b/src/org/jogamp/vecmath/Quat4d.java new file mode 100644 index 0000000..ac48323 --- /dev/null +++ b/src/org/jogamp/vecmath/Quat4d.java @@ -0,0 +1,677 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +/** + * A 4-element quaternion represented by double precision floating + * point x,y,z,w coordinates. The quaternion is always normalized. + * + */ +public class Quat4d extends Tuple4d implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = 7577479888820201099L; + + // Fixed to issue 538 + final static double EPS = 1.0e-12; + final static double EPS2 = 1.0e-30; + final static double PIO2 = 1.57079632679; + + /** + * Constructs and initializes a Quat4d from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w scalar component + */ + public Quat4d(double x, double y, double z, double w) + { + double mag; + mag = 1.0/Math.sqrt( x*x + y*y + z*z + w*w ); + this.x = x*mag; + this.y = y*mag; + this.z = z*mag; + this.w = w*mag; + + } + + /** + * Constructs and initializes a Quat4d from the array of length 4. + * @param q the array of length 4 containing xyzw in order + */ + public Quat4d(double[] q) + { + double mag; + mag = 1.0/Math.sqrt( q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3] ); + x = q[0]*mag; + y = q[1]*mag; + z = q[2]*mag; + w = q[3]*mag; + + } + + /** + * Constructs and initializes a Quat4d from the specified Quat4d. + * @param q1 the Quat4d containing the initialization x y z w data + */ + public Quat4d(Quat4d q1) + { + super(q1); + } + + /** + * Constructs and initializes a Quat4d from the specified Quat4f. + * @param q1 the Quat4f containing the initialization x y z w data + */ + public Quat4d(Quat4f q1) + { + super(q1); + } + + + /** + * Constructs and initializes a Quat4d from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Quat4d(Tuple4f t1) + { + double mag; + mag = 1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w ); + x = t1.x*mag; + y = t1.y*mag; + z = t1.z*mag; + w = t1.w*mag; + + } + + + /** + * Constructs and initializes a Quat4d from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Quat4d(Tuple4d t1) + { + double mag; + mag = 1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w ); + x = t1.x*mag; + y = t1.y*mag; + z = t1.z*mag; + w = t1.w*mag; + } + + + /** + * Constructs and initializes a Quat4d to (0,0,0,0). + */ + public Quat4d() + { + super(); + } + + + /** + * Sets the value of this quaternion to the conjugate of quaternion q1. + * @param q1 the source vector + */ + public final void conjugate(Quat4d q1) + { + this.x = -q1.x; + this.y = -q1.y; + this.z = -q1.z; + this.w = q1.w; + } + + + /** + * Negate the value of of each of this quaternion's x,y,z coordinates + * in place. + */ + public final void conjugate() + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + } + + + /** + * Sets the value of this quaternion to the quaternion product of + * quaternions q1 and q2 (this = q1 * q2). + * Note that this is safe for aliasing (e.g. this can be q1 or q2). + * @param q1 the first quaternion + * @param q2 the second quaternion + */ + public final void mul(Quat4d q1, Quat4d q2) + { + if (this != q1 && this != q2) { + this.w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; + this.x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y; + this.y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x; + this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x; + } else { + double x, y, w; + + w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; + x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y; + y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x; + this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x; + this.w = w; + this.x = x; + this.y = y; + } + } + + + /** + * Sets the value of this quaternion to the quaternion product of + * itself and q1 (this = this * q1). + * @param q1 the other quaternion + */ + public final void mul(Quat4d q1) + { + double x, y, w; + + w = this.w*q1.w - this.x*q1.x - this.y*q1.y - this.z*q1.z; + x = this.w*q1.x + q1.w*this.x + this.y*q1.z - this.z*q1.y; + y = this.w*q1.y + q1.w*this.y - this.x*q1.z + this.z*q1.x; + this.z = this.w*q1.z + q1.w*this.z + this.x*q1.y - this.y*q1.x; + this.w = w; + this.x = x; + this.y = y; + } + + + /** + * Multiplies quaternion q1 by the inverse of quaternion q2 and places + * the value into this quaternion. The value of both argument quaternions + * is preservered (this = q1 * q2^-1). + * @param q1 the first quaternion + * @param q2 the second quaternion + */ + public final void mulInverse(Quat4d q1, Quat4d q2) + { + Quat4d tempQuat = new Quat4d(q2); + + tempQuat.inverse(); + this.mul(q1, tempQuat); + } + + + + /** + * Multiplies this quaternion by the inverse of quaternion q1 and places + * the value into this quaternion. The value of the argument quaternion + * is preserved (this = this * q^-1). + * @param q1 the other quaternion + */ + public final void mulInverse(Quat4d q1) + { + Quat4d tempQuat = new Quat4d(q1); + + tempQuat.inverse(); + this.mul(tempQuat); + } + + + /** + * Sets the value of this quaternion to quaternion inverse of quaternion q1. + * @param q1 the quaternion to be inverted + */ + public final void inverse(Quat4d q1) + { + double norm; + + norm = 1.0/(q1.w*q1.w + q1.x*q1.x + q1.y*q1.y + q1.z*q1.z); + this.w = norm*q1.w; + this.x = -norm*q1.x; + this.y = -norm*q1.y; + this.z = -norm*q1.z; + } + + + /** + * Sets the value of this quaternion to the quaternion inverse of itself. + */ + public final void inverse() + { + double norm; + + norm = 1.0/(this.w*this.w + this.x*this.x + this.y*this.y + this.z*this.z); + this.w *= norm; + this.x *= -norm; + this.y *= -norm; + this.z *= -norm; + } + + + /** + * Sets the value of this quaternion to the normalized value + * of quaternion q1. + * @param q1 the quaternion to be normalized. + */ + public final void normalize(Quat4d q1) + { + double norm; + + norm = (q1.x*q1.x + q1.y*q1.y + q1.z*q1.z + q1.w*q1.w); + + if (norm > 0.0) { + norm = 1.0/Math.sqrt(norm); + this.x = norm*q1.x; + this.y = norm*q1.y; + this.z = norm*q1.z; + this.w = norm*q1.w; + } else { + this.x = 0.0; + this.y = 0.0; + this.z = 0.0; + this.w = 0.0; + } + } + + + /** + * Normalizes the value of this quaternion in place. + */ + public final void normalize() + { + double norm; + + norm = (this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w); + + if (norm > 0.0) { + norm = 1.0 / Math.sqrt(norm); + this.x *= norm; + this.y *= norm; + this.z *= norm; + this.w *= norm; + } else { + this.x = 0.0; + this.y = 0.0; + this.z = 0.0; + this.w = 0.0; + } + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the matrix4f + */ + public final void set(Matrix4f m1) + { + double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + m1.m33); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = Math.sqrt(ww); + ww = 0.25/this.w; + this.x = ((m1.m21 - m1.m12)*ww); + this.y = ((m1.m02 - m1.m20)*ww); + this.z = ((m1.m10 - m1.m01)*ww); + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5*(m1.m11 + m1.m22); + if (ww >= 0) { + if (ww >= EPS2) { + this.x = Math.sqrt(ww); + ww = 1.0/(2.0*this.x); + this.y = (m1.m10*ww); + this.z = (m1.m20*ww); + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0; + ww = 0.5*(1.0 - m1.m22); + if (ww >= EPS2) { + this.y = Math.sqrt(ww); + this.z = (m1.m21)/(2.0*this.y); + return; + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the matrix4d + */ + public final void set(Matrix4d m1) + { + double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + m1.m33); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = Math.sqrt(ww); + ww = 0.25/this.w; + this.x = (m1.m21 - m1.m12)*ww; + this.y = (m1.m02 - m1.m20)*ww; + this.z = (m1.m10 - m1.m01)*ww; + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5*(m1.m11 + m1.m22); + if (ww >= 0) { + if (ww >= EPS2){ + this.x = Math.sqrt(ww); + ww = 0.5/this.x; + this.y = m1.m10*ww; + this.z = m1.m20*ww; + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0.0; + ww = 0.5*(1.0 - m1.m22); + if (ww >= EPS2) { + this.y = Math.sqrt(ww); + this.z = m1.m21/(2.0*this.y); + return; + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the matrix3f + */ + public final void set(Matrix3f m1) + { + double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + 1.0); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = Math.sqrt(ww); + ww = 0.25/this.w; + this.x = ((m1.m21 - m1.m12)*ww); + this.y = ((m1.m02 - m1.m20)*ww); + this.z = ((m1.m10 - m1.m01)*ww); + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5*(m1.m11 + m1.m22); + if (ww >= 0) { + if (ww >= EPS2) { + this.x = Math.sqrt(ww); + ww = 0.5/this.x; + this.y = (m1.m10*ww); + this.z = (m1.m20*ww); + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0; + ww = 0.5*(1.0 - m1.m22); + if (ww >= EPS2) { + this.y = Math.sqrt(ww); + this.z = (m1.m21/(2.0*this.y)); + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the matrix3d + */ + public final void set(Matrix3d m1) + { + double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + 1.0); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = Math.sqrt(ww); + ww = 0.25/this.w; + this.x = (m1.m21 - m1.m12)*ww; + this.y = (m1.m02 - m1.m20)*ww; + this.z = (m1.m10 - m1.m01)*ww; + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5*(m1.m11 + m1.m22); + if (ww >= 0) { + if (ww >= EPS2) { + this.x = Math.sqrt(ww); + ww = 0.5/this.x; + this.y = m1.m10*ww; + this.z = m1.m20*ww; + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0; + ww = 0.5*(1.0 - m1.m22); + if (ww >= EPS2) { + this.y = Math.sqrt(ww); + this.z = m1.m21/(2.0*this.y); + return; + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the equivalent rotation + * of the AxisAngle argument. + * @param a the AxisAngle to be emulated + */ + public final void set(AxisAngle4f a) + { + double mag,amag; + // Quat = cos(theta/2) + sin(theta/2)(roation_axis) + + amag = Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z); + if( amag < EPS ) { + w = 0.0; + x = 0.0; + y = 0.0; + z = 0.0; + } else { + mag = Math.sin(a.angle/2.0); + amag = 1.0/amag; + w = Math.cos(a.angle/2.0); + x = a.x*amag*mag; + y = a.y*amag*mag; + z = a.z*amag*mag; + } + + } + + /** + * Sets the value of this quaternion to the equivalent rotation + * of the AxisAngle argument. + * @param a the AxisAngle to be emulated + */ + public final void set(AxisAngle4d a) + { + double mag,amag; + // Quat = cos(theta/2) + sin(theta/2)(roation_axis) + + amag = Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z); + if( amag < EPS ) { + w = 0.0; + x = 0.0; + y = 0.0; + z = 0.0; + } else { + amag = 1.0/amag; + mag = Math.sin(a.angle/2.0); + w = Math.cos(a.angle/2.0); + x = a.x*amag*mag; + y = a.y*amag*mag; + z = a.z*amag*mag; + } + + } + + /** + * Performs a great circle interpolation between this quaternion + * and the quaternion parameter and places the result into this + * quaternion. + * @param q1 the other quaternion + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Quat4d q1, double alpha) { + // From "Advanced Animation and Rendering Techniques" + // by Watt and Watt pg. 364, function as implemented appeared to be + // incorrect. Fails to choose the same quaternion for the double + // covering. Resulting in change of direction for rotations. + // Fixed function to negate the first quaternion in the case that the + // dot product of q1 and this is negative. Second case was not needed. + double dot,s1,s2,om,sinom; + + dot = x*q1.x + y*q1.y + z*q1.z + w*q1.w; + + if ( dot < 0 ) { + // negate quaternion + q1.x = -q1.x; q1.y = -q1.y; q1.z = -q1.z; q1.w = -q1.w; + dot = -dot; + } + + if ( (1.0 - dot) > EPS ) { + om = Math.acos(dot); + sinom = Math.sin(om); + s1 = Math.sin((1.0-alpha)*om)/sinom; + s2 = Math.sin( alpha*om)/sinom; + } else{ + s1 = 1.0 - alpha; + s2 = alpha; + } + + w = s1*w + s2*q1.w; + x = s1*x + s2*q1.x; + y = s1*y + s2*q1.y; + z = s1*z + s2*q1.z; + } + +/** + * Performs a great circle interpolation between quaternion q1 + * and quaternion q2 and places the result into this quaternion. + * @param q1 the first quaternion + * @param q2 the second quaternion + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Quat4d q1, Quat4d q2, double alpha) { + // From "Advanced Animation and Rendering Techniques" + // by Watt and Watt pg. 364, function as implemented appeared to be + // incorrect. Fails to choose the same quaternion for the double + // covering. Resulting in change of direction for rotations. + // Fixed function to negate the first quaternion in the case that the + // dot product of q1 and this is negative. Second case was not needed. + double dot,s1,s2,om,sinom; + + dot = q2.x*q1.x + q2.y*q1.y + q2.z*q1.z + q2.w*q1.w; + + if ( dot < 0 ) { + // negate quaternion + q1.x = -q1.x; q1.y = -q1.y; q1.z = -q1.z; q1.w = -q1.w; + dot = -dot; + } + + if ( (1.0 - dot) > EPS ) { + om = Math.acos(dot); + sinom = Math.sin(om); + s1 = Math.sin((1.0-alpha)*om)/sinom; + s2 = Math.sin( alpha*om)/sinom; + } else{ + s1 = 1.0 - alpha; + s2 = alpha; + } + w = s1*q1.w + s2*q2.w; + x = s1*q1.x + s2*q2.x; + y = s1*q1.y + s2*q2.y; + z = s1*q1.z + s2*q2.z; + } + +} diff --git a/src/org/jogamp/vecmath/Quat4f.java b/src/org/jogamp/vecmath/Quat4f.java new file mode 100644 index 0000000..0aa33a5 --- /dev/null +++ b/src/org/jogamp/vecmath/Quat4f.java @@ -0,0 +1,689 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4 element unit quaternion represented by single precision floating + * point x,y,z,w coordinates. The quaternion is always normalized. + * + */ +public class Quat4f extends Tuple4f implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = 2675933778405442383L; + + final static double EPS = 0.000001; + final static double EPS2 = 1.0e-30; + final static double PIO2 = 1.57079632679; + + /** + * Constructs and initializes a Quat4f from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w scalar component + */ + public Quat4f(float x, float y, float z, float w) + { + float mag; + mag = (float)(1.0/Math.sqrt( x*x + y*y + z*z + w*w )); + this.x = x*mag; + this.y = y*mag; + this.z = z*mag; + this.w = w*mag; + + } + + /** + * Constructs and initializes a Quat4f from the array of length 4. + * @param q the array of length 4 containing xyzw in order + */ + public Quat4f(float[] q) + { + float mag; + mag = (float)(1.0/Math.sqrt( q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3] )); + x = q[0]*mag; + y = q[1]*mag; + z = q[2]*mag; + w = q[3]*mag; + + } + + + /** + * Constructs and initializes a Quat4f from the specified Quat4f. + * @param q1 the Quat4f containing the initialization x y z w data + */ + public Quat4f(Quat4f q1) + { + super(q1); + } + + /** + * Constructs and initializes a Quat4f from the specified Quat4d. + * @param q1 the Quat4d containing the initialization x y z w data + */ + public Quat4f(Quat4d q1) + { + super(q1); + } + + + /** + * Constructs and initializes a Quat4f from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Quat4f(Tuple4f t1) + { + float mag; + mag = (float)(1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w )); + x = t1.x*mag; + y = t1.y*mag; + z = t1.z*mag; + w = t1.w*mag; + + } + + + /** + * Constructs and initializes a Quat4f from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Quat4f(Tuple4d t1) + { + double mag; + mag = 1.0/Math.sqrt( t1.x*t1.x + t1.y*t1.y + t1.z*t1.z + t1.w*t1.w ); + x = (float)(t1.x*mag); + y = (float)(t1.y*mag); + z = (float)(t1.z*mag); + w = (float)(t1.w*mag); + } + + + /** + * Constructs and initializes a Quat4f to (0.0,0.0,0.0,0.0). + */ + public Quat4f() + { + super(); + } + + + /** + * Sets the value of this quaternion to the conjugate of quaternion q1. + * @param q1 the source vector + */ + public final void conjugate(Quat4f q1) + { + this.x = -q1.x; + this.y = -q1.y; + this.z = -q1.z; + this.w = q1.w; + } + + /** + * Sets the value of this quaternion to the conjugate of itself. + */ + public final void conjugate() + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + } + + + /** + * Sets the value of this quaternion to the quaternion product of + * quaternions q1 and q2 (this = q1 * q2). + * Note that this is safe for aliasing (e.g. this can be q1 or q2). + * @param q1 the first quaternion + * @param q2 the second quaternion + */ + public final void mul(Quat4f q1, Quat4f q2) + { + if (this != q1 && this != q2) { + this.w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; + this.x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y; + this.y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x; + this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x; + } else { + float x, y, w; + + w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; + x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y; + y = q1.w*q2.y + q2.w*q1.y - q1.x*q2.z + q1.z*q2.x; + this.z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x; + this.w = w; + this.x = x; + this.y = y; + } + } + + + /** + * Sets the value of this quaternion to the quaternion product of + * itself and q1 (this = this * q1). + * @param q1 the other quaternion + */ + public final void mul(Quat4f q1) + { + float x, y, w; + + w = this.w*q1.w - this.x*q1.x - this.y*q1.y - this.z*q1.z; + x = this.w*q1.x + q1.w*this.x + this.y*q1.z - this.z*q1.y; + y = this.w*q1.y + q1.w*this.y - this.x*q1.z + this.z*q1.x; + this.z = this.w*q1.z + q1.w*this.z + this.x*q1.y - this.y*q1.x; + this.w = w; + this.x = x; + this.y = y; + } + + + /** + * Multiplies quaternion q1 by the inverse of quaternion q2 and places + * the value into this quaternion. The value of both argument quaternions + * is preservered (this = q1 * q2^-1). + * @param q1 the first quaternion + * @param q2 the second quaternion + */ + public final void mulInverse(Quat4f q1, Quat4f q2) + { + Quat4f tempQuat = new Quat4f(q2); + + tempQuat.inverse(); + this.mul(q1, tempQuat); + } + + + + /** + * Multiplies this quaternion by the inverse of quaternion q1 and places + * the value into this quaternion. The value of the argument quaternion + * is preserved (this = this * q^-1). + * @param q1 the other quaternion + */ + public final void mulInverse(Quat4f q1) + { + Quat4f tempQuat = new Quat4f(q1); + + tempQuat.inverse(); + this.mul(tempQuat); + } + + + + /** + * Sets the value of this quaternion to quaternion inverse of quaternion q1. + * @param q1 the quaternion to be inverted + */ + public final void inverse(Quat4f q1) + { + float norm; + + norm = 1.0f/(q1.w*q1.w + q1.x*q1.x + q1.y*q1.y + q1.z*q1.z); + this.w = norm*q1.w; + this.x = -norm*q1.x; + this.y = -norm*q1.y; + this.z = -norm*q1.z; + } + + + /** + * Sets the value of this quaternion to the quaternion inverse of itself. + */ + public final void inverse() + { + float norm; + + norm = 1.0f/(this.w*this.w + this.x*this.x + this.y*this.y + this.z*this.z); + this.w *= norm; + this.x *= -norm; + this.y *= -norm; + this.z *= -norm; + } + + + /** + * Sets the value of this quaternion to the normalized value + * of quaternion q1. + * @param q1 the quaternion to be normalized. + */ + public final void normalize(Quat4f q1) + { + float norm; + + norm = (q1.x*q1.x + q1.y*q1.y + q1.z*q1.z + q1.w*q1.w); + + if (norm > 0.0f) { + norm = 1.0f/(float)Math.sqrt(norm); + this.x = norm*q1.x; + this.y = norm*q1.y; + this.z = norm*q1.z; + this.w = norm*q1.w; + } else { + this.x = (float) 0.0; + this.y = (float) 0.0; + this.z = (float) 0.0; + this.w = (float) 0.0; + } + } + + + /** + * Normalizes the value of this quaternion in place. + */ + public final void normalize() + { + float norm; + + norm = (this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w); + + if (norm > 0.0f) { + norm = 1.0f / (float)Math.sqrt(norm); + this.x *= norm; + this.y *= norm; + this.z *= norm; + this.w *= norm; + } else { + this.x = (float) 0.0; + this.y = (float) 0.0; + this.z = (float) 0.0; + this.w = (float) 0.0; + } + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the Matrix4f + */ + public final void set(Matrix4f m1) + { + float ww = 0.25f*(m1.m00 + m1.m11 + m1.m22 + m1.m33); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = (float) Math.sqrt((double)ww); + ww = 0.25f/this.w; + this.x = (m1.m21 - m1.m12)*ww; + this.y = (m1.m02 - m1.m20)*ww; + this.z = (m1.m10 - m1.m01)*ww; + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5f*(m1.m11 + m1.m22); + + if (ww >= 0) { + if (ww >= EPS2) { + this.x = (float) Math.sqrt((double) ww); + ww = 1.0f/(2.0f*this.x); + this.y = m1.m10*ww; + this.z = m1.m20*ww; + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0; + ww = 0.5f*(1.0f - m1.m22); + + if (ww >= EPS2) { + this.y = (float) Math.sqrt((double) ww); + this.z = m1.m21/(2.0f*this.y); + return; + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the Matrix4d + */ + public final void set(Matrix4d m1) + { + double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + m1.m33); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = (float) Math.sqrt(ww); + ww = 0.25/this.w; + this.x = (float) ((m1.m21 - m1.m12)*ww); + this.y = (float) ((m1.m02 - m1.m20)*ww); + this.z = (float) ((m1.m10 - m1.m01)*ww); + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5*(m1.m11 + m1.m22); + if (ww >= 0) { + if (ww >= EPS2) { + this.x = (float) Math.sqrt(ww); + ww = 0.5/this.x; + this.y = (float)(m1.m10*ww); + this.z = (float)(m1.m20*ww); + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0; + ww = 0.5*(1.0 - m1.m22); + if (ww >= EPS2) { + this.y = (float) Math.sqrt(ww); + this.z = (float) (m1.m21/(2.0*(double)(this.y))); + return; + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the Matrix3f + */ + public final void set(Matrix3f m1) + { + float ww = 0.25f*(m1.m00 + m1.m11 + m1.m22 + 1.0f); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = (float) Math.sqrt((double) ww); + ww = 0.25f/this.w; + this.x = (m1.m21 - m1.m12)*ww; + this.y = (m1.m02 - m1.m20)*ww; + this.z = (m1.m10 - m1.m01)*ww; + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5f*(m1.m11 + m1.m22); + if (ww >= 0) { + if (ww >= EPS2) { + this.x = (float) Math.sqrt((double) ww); + ww = 0.5f/this.x; + this.y = m1.m10*ww; + this.z = m1.m20*ww; + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0; + ww = 0.5f*(1.0f - m1.m22); + if (ww >= EPS2) { + this.y = (float) Math.sqrt((double) ww); + this.z = m1.m21/(2.0f*this.y); + return; + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the rotational component of + * the passed matrix. + * @param m1 the Matrix3d + */ + public final void set(Matrix3d m1) + { + double ww = 0.25*(m1.m00 + m1.m11 + m1.m22 + 1.0f); + + if (ww >= 0) { + if (ww >= EPS2) { + this.w = (float) Math.sqrt(ww); + ww = 0.25/this.w; + this.x = (float) ((m1.m21 - m1.m12)*ww); + this.y = (float) ((m1.m02 - m1.m20)*ww); + this.z = (float) ((m1.m10 - m1.m01)*ww); + return; + } + } else { + this.w = 0; + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.w = 0; + ww = -0.5*(m1.m11 + m1.m22); + if (ww >= 0) { + if (ww >= EPS2) { + this.x = (float) Math.sqrt(ww); + ww = 0.5/this.x; + this.y = (float) (m1.m10*ww); + this.z = (float) (m1.m20*ww); + return; + } + } else { + this.x = 0; + this.y = 0; + this.z = 1; + return; + } + + this.x = 0; + ww = 0.5*(1.0 - m1.m22); + if (ww >= EPS2) { + this.y = (float) Math.sqrt(ww); + this.z = (float) (m1.m21/(2.0*(double)(this.y))); + return; + } + + this.y = 0; + this.z = 1; + } + + + /** + * Sets the value of this quaternion to the equivalent rotation + * of the AxisAngle argument. + * @param a the AxisAngle to be emulated + */ + public final void set(AxisAngle4f a) + { + float mag,amag; + // Quat = cos(theta/2) + sin(theta/2)(roation_axis) + amag = (float)Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z); + if (amag < EPS ) { + w = 0.0f; + x = 0.0f; + y = 0.0f; + z = 0.0f; + } else { + amag = 1.0f/amag; + mag = (float)Math.sin(a.angle/2.0); + w = (float)Math.cos(a.angle/2.0); + x = a.x*amag*mag; + y = a.y*amag*mag; + z = a.z*amag*mag; + } + } + + + /** + * Sets the value of this quaternion to the equivalent rotation + * of the AxisAngle argument. + * @param a the AxisAngle to be emulated + */ + public final void set(AxisAngle4d a) + { + float mag,amag; + // Quat = cos(theta/2) + sin(theta/2)(roation_axis) + + amag = (float)(1.0/Math.sqrt( a.x*a.x + a.y*a.y + a.z*a.z)); + + if (amag < EPS ) { + w = 0.0f; + x = 0.0f; + y = 0.0f; + z = 0.0f; + } else { + amag = 1.0f/amag; + mag = (float)Math.sin(a.angle/2.0); + w = (float)Math.cos(a.angle/2.0); + x = (float)a.x*amag*mag; + y = (float)a.y*amag*mag; + z = (float)a.z*amag*mag; + } + + } + + + /** + * Performs a great circle interpolation between this quaternion + * and the quaternion parameter and places the result into this + * quaternion. + * @param q1 the other quaternion + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Quat4f q1, float alpha) { + // From "Advanced Animation and Rendering Techniques" + // by Watt and Watt pg. 364, function as implemented appeared to be + // incorrect. Fails to choose the same quaternion for the double + // covering. Resulting in change of direction for rotations. + // Fixed function to negate the first quaternion in the case that the + // dot product of q1 and this is negative. Second case was not needed. + + double dot,s1,s2,om,sinom; + + dot = x*q1.x + y*q1.y + z*q1.z + w*q1.w; + + if ( dot < 0 ) { + // negate quaternion + q1.x = -q1.x; q1.y = -q1.y; q1.z = -q1.z; q1.w = -q1.w; + dot = -dot; + } + + if ( (1.0 - dot) > EPS ) { + om = Math.acos(dot); + sinom = Math.sin(om); + s1 = Math.sin((1.0-alpha)*om)/sinom; + s2 = Math.sin( alpha*om)/sinom; + } else{ + s1 = 1.0 - alpha; + s2 = alpha; + } + + w = (float)(s1*w + s2*q1.w); + x = (float)(s1*x + s2*q1.x); + y = (float)(s1*y + s2*q1.y); + z = (float)(s1*z + s2*q1.z); + } + + + + /** + * Performs a great circle interpolation between quaternion q1 + * and quaternion q2 and places the result into this quaternion. + * @param q1 the first quaternion + * @param q2 the second quaternion + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Quat4f q1, Quat4f q2, float alpha) { + // From "Advanced Animation and Rendering Techniques" + // by Watt and Watt pg. 364, function as implemented appeared to be + // incorrect. Fails to choose the same quaternion for the double + // covering. Resulting in change of direction for rotations. + // Fixed function to negate the first quaternion in the case that the + // dot product of q1 and this is negative. Second case was not needed. + + double dot,s1,s2,om,sinom; + + dot = q2.x*q1.x + q2.y*q1.y + q2.z*q1.z + q2.w*q1.w; + + if ( dot < 0 ) { + // negate quaternion + q1.x = -q1.x; q1.y = -q1.y; q1.z = -q1.z; q1.w = -q1.w; + dot = -dot; + } + + if ( (1.0 - dot) > EPS ) { + om = Math.acos(dot); + sinom = Math.sin(om); + s1 = Math.sin((1.0-alpha)*om)/sinom; + s2 = Math.sin( alpha*om)/sinom; + } else{ + s1 = 1.0 - alpha; + s2 = alpha; + } + w = (float)(s1*q1.w + s2*q2.w); + x = (float)(s1*q1.x + s2*q2.x); + y = (float)(s1*q1.y + s2*q2.y); + z = (float)(s1*q1.z + s2*q2.z); + } + +} + + + + diff --git a/src/org/jogamp/vecmath/SingularMatrixException.java b/src/org/jogamp/vecmath/SingularMatrixException.java new file mode 100644 index 0000000..806eda6 --- /dev/null +++ b/src/org/jogamp/vecmath/SingularMatrixException.java @@ -0,0 +1,49 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +/** + * Indicates that inverse of a matrix can not be computed. + */ +public class SingularMatrixException extends RuntimeException{ + +/** + * Create the exception object with default values. + */ + public SingularMatrixException(){ + } + +/** + * Create the exception object that outputs message. + * @param str the message string to be output. + */ + public SingularMatrixException(String str){ + + super(str); + } + +} diff --git a/src/org/jogamp/vecmath/TexCoord2f.java b/src/org/jogamp/vecmath/TexCoord2f.java new file mode 100644 index 0000000..589a15e --- /dev/null +++ b/src/org/jogamp/vecmath/TexCoord2f.java @@ -0,0 +1,90 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 2-element vector that is represented by single-precision floating + * point x,y coordinates. + * + */ +public class TexCoord2f extends Tuple2f implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = 7998248474800032487L; + + /** + * Constructs and initializes a TexCoord2f from the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public TexCoord2f(float x, float y) + { + super(x,y); + } + + + /** + * Constructs and initializes a TexCoord2f from the specified array. + * @param v the array of length 2 containing xy in order + */ + public TexCoord2f(float[] v) + { + super(v); + } + + + /** + * Constructs and initializes a TexCoord2f from the specified TexCoord2f. + * @param v1 the TexCoord2f containing the initialization x y data + */ + public TexCoord2f(TexCoord2f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a TexCoord2f from the specified Tuple2f. + * @param t1 the Tuple2f containing the initialization x y data + */ + public TexCoord2f(Tuple2f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a TexCoord2f to (0,0). + */ + public TexCoord2f() + { + super(); + } + + +} diff --git a/src/org/jogamp/vecmath/TexCoord3f.java b/src/org/jogamp/vecmath/TexCoord3f.java new file mode 100644 index 0000000..d0e74c0 --- /dev/null +++ b/src/org/jogamp/vecmath/TexCoord3f.java @@ -0,0 +1,101 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 3 element texture coordinate that is represented by single precision + * floating point x,y,z coordinates. + * + */ +public class TexCoord3f extends Tuple3f implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = -3517736544731446513L; + + /** + * Constructs and initializes a TexCoord3f from the specified xyz + * coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public TexCoord3f(float x, float y, float z) + { + super(x,y,z); + } + + + /** + * Constructs and initializes a TexCoord3f from the array of length 3. + * @param v the array of length 3 containing xyz in order + */ + public TexCoord3f(float[] v) + { + super(v); + } + + + /** + * Constructs and initializes a TexCoord3f from the specified TexCoord3f. + * @param v1 the TexCoord3f containing the initialization x y z data + */ + public TexCoord3f(TexCoord3f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a TexCoord3f from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public TexCoord3f(Tuple3f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a TexCoord3f from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public TexCoord3f(Tuple3d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a TexCoord3f to (0,0,0). + */ + public TexCoord3f() + { + super(); + } + +} diff --git a/src/org/jogamp/vecmath/TexCoord4f.java b/src/org/jogamp/vecmath/TexCoord4f.java new file mode 100644 index 0000000..b151c4a --- /dev/null +++ b/src/org/jogamp/vecmath/TexCoord4f.java @@ -0,0 +1,103 @@ +/* + * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4 element texture coordinate that is represented by single precision + * floating point x,y,z,w coordinates. + * + * @since vecmath 1.3 + */ +public class TexCoord4f extends Tuple4f implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = -3517736544731446513L; + + /** + * Constructs and initializes a TexCoord4f from the specified xyzw + * coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public TexCoord4f(float x, float y, float z, float w) + { + super(x,y,z,w); + } + + + /** + * Constructs and initializes a TexCoord4f from the array of length 4. + * @param v the array of length w containing xyzw in order + */ + public TexCoord4f(float[] v) + { + super(v); + } + + + /** + * Constructs and initializes a TexCoord4f from the specified TexCoord4f. + * @param v1 the TexCoord4f containing the initialization x y z w data + */ + public TexCoord4f(TexCoord4f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a TexCoord4f from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public TexCoord4f(Tuple4f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a TexCoord4f from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public TexCoord4f(Tuple4d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a TexCoord4f to (0,0,0,0). + */ + public TexCoord4f() + { + super(); + } + +} diff --git a/src/org/jogamp/vecmath/Tuple2d.java b/src/org/jogamp/vecmath/Tuple2d.java new file mode 100644 index 0000000..bba9d26 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple2d.java @@ -0,0 +1,604 @@ +/* + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A generic 2-element tuple that is represented by double-precision + * floating point x,y coordinates. + * + */ +public abstract class Tuple2d implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = 6205762482756093838L; + + /** + * The x coordinate. + */ + public double x; + + /** + * The y coordinate. + */ + public double y; + + + /** + * Constructs and initializes a Tuple2d from the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Tuple2d(double x, double y) + { + this.x = x; + this.y = y; + } + + + /** + * Constructs and initializes a Tuple2d from the specified array. + * @param t the array of length 2 containing xy in order + */ + public Tuple2d(double[] t) + { + this.x = t[0]; + this.y = t[1]; + } + + + /** + * Constructs and initializes a Tuple2d from the specified Tuple2d. + * @param t1 the Tuple2d containing the initialization x y data + */ + public Tuple2d(Tuple2d t1) + { + this.x = t1.x; + this.y = t1.y; + } + + + /** + * Constructs and initializes a Tuple2d from the specified Tuple2f. + * @param t1 the Tuple2f containing the initialization x y data + */ + public Tuple2d(Tuple2f t1) + { + this.x = (double) t1.x; + this.y = (double) t1.y; + } + + /** + * Constructs and initializes a Tuple2d to (0,0). + */ + public Tuple2d() + { + this.x = 0.0; + this.y = 0.0; + } + + + /** + * Sets the value of this tuple to the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public final void set(double x, double y) + { + this.x = x; + this.y = y; + } + + + /** + * Sets the value of this tuple from the 2 values specified in + * the array. + * @param t the array of length 2 containing xy in order + */ + public final void set(double[] t) + { + this.x = t[0]; + this.y = t[1]; + } + + + /** + * Sets the value of this tuple to the value of the Tuple2d argument. + * @param t1 the tuple to be copied + */ + public final void set(Tuple2d t1) + { + this.x = t1.x; + this.y = t1.y; + } + + + /** + * Sets the value of this tuple to the value of Tuple2f t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple2f t1) + { + this.x = (double) t1.x; + this.y = (double) t1.y; + } + + /** + * Copies the value of the elements of this tuple into the array t. + * @param t the array that will contain the values of the vector + */ + public final void get(double[] t) + { + t[0] = this.x; + t[1] = this.y; + } + + + /** + * Sets the value of this tuple to the vector sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple2d t1, Tuple2d t2) + { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + } + + + /** + * Sets the value of this tuple to the vector sum of itself and tuple t1. + * @param t1 the other tuple + */ + public final void add(Tuple2d t1) + { + this.x += t1.x; + this.y += t1.y; + } + + + /** + * Sets the value of this tuple to the vector difference of + * tuple t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple2d t1, Tuple2d t2) + { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + } + + + /** + * Sets the value of this tuple to the vector difference of + * itself and tuple t1 (this = this - t1). + * @param t1 the other vector + */ + public final void sub(Tuple2d t1) + { + this.x -= t1.x; + this.y -= t1.y; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source vector + */ + public final void negate(Tuple2d t1) + { + this.x = -t1.x; + this.y = -t1.y; + } + + + /** + * Negates the value of this vector in place. + */ + public final void negate() + { + this.x = -this.x; + this.y = -this.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(double s, Tuple2d t1) + { + this.x = s*t1.x; + this.y = s*t1.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself. + * @param s the scalar value + */ + public final void scale(double s) + { + this.x *= s; + this.y *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 and then adds tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(double s, Tuple2d t1, Tuple2d t2) + { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(double s, Tuple2d t1) + { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + } + + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple2d objects with identical data values + * (i.e., Tuple2d.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashDoubleBits(bits, x); + bits = VecMathUtil.hashDoubleBits(bits, y); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Returns true if all of the data members of Tuple2d t1 are + * equal to the corresponding data members in this Tuple2d. + * @param t1 the vector with which the comparison is made + * @return true or false + */ + public boolean equals(Tuple2d t1) + { + try { + return(this.x == t1.x && this.y == t1.y); + } + catch (NullPointerException e2) {return false;} + + } + + /** + * Returns true if the Object t1 is of type Tuple2d and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple2d. + * @param t1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Tuple2d t2 = (Tuple2d) t1; + return(this.x == t2.x && this.y == t2.y); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + + } + + /** + * Returns true if the L-infinite distance between this tuple + * and tuple t1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to MAX[abs(x1-x2), abs(y1-y2)]. + * @param t1 the tuple to be compared to this tuple + * @param epsilon the threshold value + * @return true or false + */ + public boolean epsilonEquals(Tuple2d t1, double epsilon) + { + double diff; + + diff = x - t1.x; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - t1.y; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + } + + /** + * Returns a string that contains the values of this Tuple2d. + * The form is (x,y). + * @return the String representation + */ + @Override + public String toString() + { + return("(" + this.x + ", " + this.y + ")"); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(double min, double max, Tuple2d t) + { + if( t.x > max ) { + x = max; + } else if( t.x < min ){ + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ){ + y = min; + } else { + y = t.y; + } + + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(double min, Tuple2d t) + { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(double max, Tuple2d t) + { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple2d t) + { + x = Math.abs(t.x); + y = Math.abs(t.y); + } + + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(double min, double max) + { + if( x > max ) { + x = max; + } else if( x < min ){ + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ){ + y = min; + } + + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(double min) + { + if( x < min ) x=min; + if( y < min ) y=min; + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(double max) + { + if( x > max ) x=max; + if( y > max ) y=max; + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() + { + x = Math.abs(x); + y = Math.abs(y); + } + + + /** + * Linearly interpolates between tuples t1 and t2 and places the + * result into this tuple: this = (1-alpha)*t1 + alpha*t2. + * @param t1 the first tuple + * @param t2 the second tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple2d t1, Tuple2d t2, double alpha) + { + this.x = (1-alpha)*t1.x + alpha*t2.x; + this.y = (1-alpha)*t1.y + alpha*t2.y; + } + + + /** + * Linearly interpolates between this tuple and tuple t1 and + * places the result into this tuple: this = (1-alpha)*this + alpha*t1. + * @param t1 the first tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple2d t1, double alpha) + { + this.x = (1-alpha)*this.x + alpha*t1.x; + this.y = (1-alpha)*this.y + alpha*t1.y; + + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get the <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(double x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(double y) { + this.y = y; + } + +} diff --git a/src/org/jogamp/vecmath/Tuple2f.java b/src/org/jogamp/vecmath/Tuple2f.java new file mode 100644 index 0000000..f929f1b --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple2f.java @@ -0,0 +1,607 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A generic 2-element tuple that is represented by single-precision + * floating point x,y coordinates. + * + */ +public abstract class Tuple2f implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = 9011180388985266884L; + + /** + * The x coordinate. + */ + public float x; + + /** + * The y coordinate. + */ + public float y; + + + /** + * Constructs and initializes a Tuple2f from the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Tuple2f(float x, float y) + { + this.x = x; + this.y = y; + } + + + /** + * Constructs and initializes a Tuple2f from the specified array. + * @param t the array of length 2 containing xy in order + */ + public Tuple2f(float[] t) + { + this.x = t[0]; + this.y = t[1]; + } + + + /** + * Constructs and initializes a Tuple2f from the specified Tuple2f. + * @param t1 the Tuple2f containing the initialization x y data + */ + public Tuple2f(Tuple2f t1) + { + this.x = t1.x; + this.y = t1.y; + } + + + /** + * Constructs and initializes a Tuple2f from the specified Tuple2d. + * @param t1 the Tuple2d containing the initialization x y data + */ + public Tuple2f(Tuple2d t1) + { + this.x = (float) t1.x; + this.y = (float) t1.y; + } + + + /** + * Constructs and initializes a Tuple2f to (0,0). + */ + public Tuple2f() + { + this.x = (float) 0.0; + this.y = (float) 0.0; + } + + + /** + * Sets the value of this tuple to the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public final void set(float x, float y) + { + this.x = x; + this.y = y; + } + + + /** + * Sets the value of this tuple from the 2 values specified in + * the array. + * @param t the array of length 2 containing xy in order + */ + public final void set(float[] t) + { + this.x = t[0]; + this.y = t[1]; + } + + + /** + * Sets the value of this tuple to the value of the Tuple2f argument. + * @param t1 the tuple to be copied + */ + public final void set(Tuple2f t1) + { + this.x = t1.x; + this.y = t1.y; + } + + + /** + * Sets the value of this tuple to the value of the Tuple2d argument. + * @param t1 the tuple to be copied + */ + public final void set(Tuple2d t1) + { + this.x = (float) t1.x; + this.y = (float) t1.y; + } + + + /** + * Copies the value of the elements of this tuple into the array t. + * @param t the array that will contain the values of the vector + */ + public final void get(float[] t) + { + t[0] = this.x; + t[1] = this.y; + } + + + /** + * Sets the value of this tuple to the vector sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple2f t1, Tuple2f t2) + { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + } + + + /** + * Sets the value of this tuple to the vector sum of itself and tuple t1. + * @param t1 the other tuple + */ + public final void add(Tuple2f t1) + { + this.x += t1.x; + this.y += t1.y; + } + + + /** + * Sets the value of this tuple to the vector difference of + * tuple t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple2f t1, Tuple2f t2) + { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + } + + + /** + * Sets the value of this tuple to the vector difference of + * itself and tuple t1 (this = this - t1). + * @param t1 the other tuple + */ + public final void sub(Tuple2f t1) + { + this.x -= t1.x; + this.y -= t1.y; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple2f t1) + { + this.x = -t1.x; + this.y = -t1.y; + } + + + /** + * Negates the value of this vector in place. + */ + public final void negate() + { + this.x = -this.x; + this.y = -this.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(float s, Tuple2f t1) + { + this.x = s*t1.x; + this.y = s*t1.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself. + * @param s the scalar value + */ + public final void scale(float s) + { + this.x *= s; + this.y *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 and then adds tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(float s, Tuple2f t1, Tuple2f t2) + { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(float s, Tuple2f t1) + { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + } + + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple2f objects with identical data values + * (i.e., Tuple2f.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashFloatBits(bits, x); + bits = VecMathUtil.hashFloatBits(bits, y); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Returns true if all of the data members of Tuple2f t1 are + * equal to the corresponding data members in this Tuple2f. + * @param t1 the vector with which the comparison is made + * @return true or false + */ + public boolean equals(Tuple2f t1) + { + try { + return(this.x == t1.x && this.y == t1.y); + } + catch (NullPointerException e2) {return false;} + + } + + /** + * Returns true if the Object t1 is of type Tuple2f and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple2f. + * @param t1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Tuple2f t2 = (Tuple2f) t1; + return(this.x == t2.x && this.y == t2.y); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + + } + + /** + * Returns true if the L-infinite distance between this tuple + * and tuple t1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to MAX[abs(x1-x2), abs(y1-y2)]. + * @param t1 the tuple to be compared to this tuple + * @param epsilon the threshold value + * @return true or false + */ + public boolean epsilonEquals(Tuple2f t1, float epsilon) + { + float diff; + + diff = x - t1.x; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - t1.y; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + } + + /** + * Returns a string that contains the values of this Tuple2f. + * The form is (x,y). + * @return the String representation + */ + @Override + public String toString() + { + return("(" + this.x + ", " + this.y + ")"); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(float min, float max, Tuple2f t) + { + if( t.x > max ) { + x = max; + } else if( t.x < min ){ + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ){ + y = min; + } else { + y = t.y; + } + + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(float min, Tuple2f t) + { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(float max, Tuple2f t) + { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple2f t) + { + x = Math.abs(t.x); + y = Math.abs(t.y); + } + + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(float min, float max) + { + if( x > max ) { + x = max; + } else if( x < min ){ + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ){ + y = min; + } + + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(float min) + { + if( x < min ) x=min; + if( y < min ) y=min; + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(float max) + { + if( x > max ) x=max; + if( y > max ) y=max; + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() + { + x = Math.abs(x); + y = Math.abs(y); + } + + + /** + * Linearly interpolates between tuples t1 and t2 and places the + * result into this tuple: this = (1-alpha)*t1 + alpha*t2. + * @param t1 the first tuple + * @param t2 the second tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple2f t1, Tuple2f t2, float alpha) + { + this.x = (1-alpha)*t1.x + alpha*t2.x; + this.y = (1-alpha)*t1.y + alpha*t2.y; + + } + + + /** + * Linearly interpolates between this tuple and tuple t1 and + * places the result into this tuple: this = (1-alpha)*this + alpha*t1. + * @param t1 the first tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple2f t1, float alpha) + { + + this.x = (1-alpha)*this.x + alpha*t1.x; + this.y = (1-alpha)*this.y + alpha*t1.y; + + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get the <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(float x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(float y) { + this.y = y; + } +} diff --git a/src/org/jogamp/vecmath/Tuple2i.java b/src/org/jogamp/vecmath/Tuple2i.java new file mode 100644 index 0000000..ed3dce1 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple2i.java @@ -0,0 +1,504 @@ +/* + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 2-element tuple represented by signed integer x,y + * coordinates. + * + * @since vecmath 1.4 + */ +public abstract class Tuple2i implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = -3555701650170169638L; + + /** + * The x coordinate. + */ + public int x; + + /** + * The y coordinate. + */ + public int y; + + + /** + * Constructs and initializes a Tuple2i from the specified + * x and y coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Tuple2i(int x, int y) { + this.x = x; + this.y = y; + } + + + /** + * Constructs and initializes a Tuple2i from the array of length 2. + * @param t the array of length 2 containing x and y in order. + */ + public Tuple2i(int[] t) { + this.x = t[0]; + this.y = t[1]; + } + + + /** + * Constructs and initializes a Tuple2i from the specified Tuple2i. + * @param t1 the Tuple2i containing the initialization x and y + * data. + */ + public Tuple2i(Tuple2i t1) { + this.x = t1.x; + this.y = t1.y; + } + + + /** + * Constructs and initializes a Tuple2i to (0,0). + */ + public Tuple2i() { + this.x = 0; + this.y = 0; + } + + + /** + * Sets the value of this tuple to the specified x and y + * coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public final void set(int x, int y) { + this.x = x; + this.y = y; + } + + + /** + * Sets the value of this tuple to the specified coordinates in the + * array of length 2. + * @param t the array of length 2 containing x and y in order. + */ + public final void set(int[] t) { + this.x = t[0]; + this.y = t[1]; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple2i t1) { + this.x = t1.x; + this.y = t1.y; + } + + + /** + * Copies the values of this tuple into the array t. + * @param t is the array + */ + public final void get(int[] t) { + t[0] = this.x; + t[1] = this.y; + } + + + /** + * Copies the values of this tuple into the tuple t. + * @param t is the target tuple + */ + public final void get(Tuple2i t) { + t.x = this.x; + t.y = this.y; + } + + + /** + * Sets the value of this tuple to the sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple2i t1, Tuple2i t2) { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + } + + + /** + * Sets the value of this tuple to the sum of itself and t1. + * @param t1 the other tuple + */ + public final void add(Tuple2i t1) { + this.x += t1.x; + this.y += t1.y; + } + + + /** + * Sets the value of this tuple to the difference + * of tuples t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple2i t1, Tuple2i t2) { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + } + + + /** + * Sets the value of this tuple to the difference + * of itself and t1 (this = this - t1). + * @param t1 the other tuple + */ + public final void sub(Tuple2i t1) { + this.x -= t1.x; + this.y -= t1.y; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple2i t1) { + this.x = -t1.x; + this.y = -t1.y; + } + + + /** + * Negates the value of this tuple in place. + */ + public final void negate() { + this.x = -this.x; + this.y = -this.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(int s, Tuple2i t1) { + this.x = s*t1.x; + this.y = s*t1.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of the scale factor with this. + * @param s the scalar value + */ + public final void scale(int s) { + this.x *= s; + this.y *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 plus tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(int s, Tuple2i t1, Tuple2i t2) { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(int s, Tuple2i t1) { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + } + + + /** + * Returns a string that contains the values of this Tuple2i. + * The form is (x,y). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ")"; + } + + + /** + * Returns true if the Object t1 is of type Tuple2i and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple2i. + * @param t1 the object with which the comparison is made + */ + @Override + public boolean equals(Object t1) { + try { + Tuple2i t2 = (Tuple2i) t1; + return(this.x == t2.x && this.y == t2.y); + } + catch (NullPointerException e2) { + return false; + } + catch (ClassCastException e1) { + return false; + } + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple2i objects with identical data values + * (i.e., Tuple2i.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = 31L * bits + (long)x; + bits = 31L * bits + (long)y; + return (int) (bits ^ (bits >> 32)); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(int min, int max, Tuple2i t) { + if( t.x > max ) { + x = max; + } else if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ) { + y = min; + } else { + y = t.y; + } + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(int min, Tuple2i t) { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(int max, Tuple2i t) { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple2i t) { + x = Math.abs(t.x); + y = Math.abs(t.y); + } + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(int min, int max) { + if( x > max ) { + x = max; + } else if( x < min ) { + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ) { + y = min; + } + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(int min) { + if (x < min) + x=min; + + if (y < min) + y = min; + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(int max) { + if (x > max) + x = max; + + if (y > max) + y = max; + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() { + x = Math.abs(x); + y = Math.abs(y); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get the <i>x</i> coordinate. + * + * @return the x coordinate. + * + * @since vecmath 1.5 + */ + public final int getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(int x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final int getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(int y) { + this.y = y; + } +} diff --git a/src/org/jogamp/vecmath/Tuple3b.java b/src/org/jogamp/vecmath/Tuple3b.java new file mode 100644 index 0000000..c692280 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple3b.java @@ -0,0 +1,317 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A three byte tuple. Note that Java defines a byte as a signed integer + * in the range [-128, 127]. However, colors are more typically + * represented by values in the range [0, 255]. Java 3D recognizes this + * and, in those cases where Tuple3b is used to represent color, treats + * the bytes as if the range were [0, 255]---in other words, as if the + * bytes were unsigned. + * Values greater than 127 can be assigned to a byte variable using a + * type cast. For example: + * <ul>byteVariable = (byte) intValue; // intValue can be > 127</ul> + * If intValue is greater than 127, then byteVariable will be negative. The + * correct value will be extracted when it is used (by masking off the upper + * bits). + */ +public abstract class Tuple3b implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = -483782685323607044L; + + /** + * The first value. + */ + public byte x; + + /** + * The second value. + */ + public byte y; + + /** + * The third value. + */ + public byte z; + + + /** + * Constructs and initializes a Tuple3b from the specified three values. + * @param b1 the first value + * @param b2 the second value + * @param b3 the third value + */ + public Tuple3b(byte b1, byte b2, byte b3) + { + this.x = b1; + this.y = b2; + this.z = b3; + } + + + /** + * Constructs and initializes a Tuple3b from input array of length 3. + * @param t the array of length 3 containing b1 b2 b3 in order + */ + public Tuple3b(byte[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + + /** + * Constructs and initializes a Tuple3b from the specified Tuple3b. + * @param t1 the Tuple3b containing the initialization x y z data + */ + public Tuple3b(Tuple3b t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + + /** + * Constructs and initializes a Tuple3b to (0,0,0). + */ + public Tuple3b() + { + this.x = (byte) 0; + this.y = (byte) 0; + this.z = (byte) 0; + } + + + /** + * Returns a string that contains the values of this Tuple3b. + * @return a String with the values + */ + @Override + public String toString() + { + return("(" + ((int)this.x & 0xff) + + ", " + ((int)this.y & 0xff) + + ", " + ((int)this.z & 0xff) + ")"); + } + + + /** + * Places the value of the x,y,z components of this Tuple3b + * into the array of length 3. + * @param t array of length 3 into which the component values are copied + */ + public final void get(byte[] t) + { + + t[0] = this.x; + t[1] = this.y; + t[2] = this.z; + } + + + /** + * Places the value of the x,y,z components of this tuple into + * the tuple t1. + * @param t1 the tuple into which the values are placed + */ + public final void get(Tuple3b t1) + { + t1.x = this.x; + t1.y = this.y; + t1.z = this.z; + } + + + /** + * Sets the value of the data members of this tuple to the value + * of the argument tuple t1. + * @param t1 the source tuple for the memberwise copy + */ + public final void set(Tuple3b t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + + /** + * Sets the value of the x,y,z, data members of this tuple to the + * values in the array t of length 3. + * @param t array of length 3 which is the source for the memberwise copy + */ + public final void set(byte[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + + /** + * Returns true if all of the data members of tuple t1 are equal to + * the corresponding data members in this tuple. + * @param t1 the tuple with which the comparison is made + * @return true or false + */ + public boolean equals(Tuple3b t1) + { + try { + return(this.x == t1.x && this.y == t1.y && this.z == t1.z); + } + catch (NullPointerException e2) {return false;} + + } + + /** + * Returns true if the Object t1 is of type Tuple3b and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple3b. + * @param t1 the object with which the comparison is made + */ + @Override + public boolean equals(Object t1) + { + try { + Tuple3b t2 = (Tuple3b) t1; + return(this.x == t2.x && this.y == t2.y && this.z == t2.z); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + + } + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple3b objects with identical data values + * (i.e., Tuple3b.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + return ((((int)x & 0xff) << 0) | + (((int)y & 0xff) << 8) | + (((int)z & 0xff) << 16)); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get <i>x</i>, the first value. + * + * @return the first value. + * + * @since vecmath 1.5 + */ + public final byte getX() { + return x; + } + + + /** + * Set <i>x</i>, the first value. + * + * @param x the first value to set. + * + * @since vecmath 1.5 + */ + public final void setX(byte x) { + this.x = x; + } + + + /** + * Get <i>y</i>, the second value. + * + * @return the second value. + * + * @since vecmath 1.5 + */ + public final byte getY() { + return y; + } + + + /** + * Set <i>y</i>, the second value. + * + * @param y the second value to set. + * + * @since vecmath 1.5 + */ + public final void setY(byte y) { + this.y = y; + } + + /** + * Get <i>z</i>, the third value. + * + * @return the third value. + * + * @since vecmath 1.5 + */ + public final byte getZ() { + return z; + } + + + /** + * Set <i>z</i>, the third value. + * + * @param z the third value to set. + * + * @since vecmath 1.5 + */ + public final void setZ(byte z) { + this.z = z; + } + +} diff --git a/src/org/jogamp/vecmath/Tuple3d.java b/src/org/jogamp/vecmath/Tuple3d.java new file mode 100644 index 0000000..a34511c --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple3d.java @@ -0,0 +1,756 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A generic 3-element tuple that is represented by double-precision + * floating point x,y,z coordinates. + * + */ +public abstract class Tuple3d implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = 5542096614926168415L; + + /** + * The x coordinate. + */ + public double x; + + /** + * The y coordinate. + */ + public double y; + + /** + * The z coordinate. + */ + public double z; + + + /** + * Constructs and initializes a Tuple3d from the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Tuple3d(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Constructs and initializes a Tuple3d from the array of length 3. + * @param t the array of length 3 containing xyz in order + */ + public Tuple3d(double[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + /** + * Constructs and initializes a Tuple3d from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public Tuple3d(Tuple3d t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + /** + * Constructs and initializes a Tuple3d from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public Tuple3d(Tuple3f t1) + { + this.x = (double) t1.x; + this.y = (double) t1.y; + this.z = (double) t1.z; + } + + /** + * Constructs and initializes a Tuple3d to (0,0,0). + */ + public Tuple3d() + { + this.x = (double) 0.0; + this.y = (double) 0.0; + this.z = (double) 0.0; + } + + /** + * Sets the value of this tuple to the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public final void set(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Sets the value of this tuple to the value of the xyz coordinates + * located in the array of length 3. + * @param t the array of length 3 containing xyz in order + */ + public final void set(double[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple3d t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple3f t1) + { + this.x = (double) t1.x; + this.y = (double) t1.y; + this.z = (double) t1.z; + } + + /** + * Copies the x,y,z coordinates of this tuple into the array t + * of length 3. + * @param t the target array + */ + public final void get(double[] t) + { + t[0] = this.x; + t[1] = this.y; + t[2] = this.z; + } + + + /** + * Copies the x,y,z coordinates of this tuple into the tuple t. + * @param t the Tuple3d object into which the values of this object are copied + */ + public final void get(Tuple3d t) + { + t.x = this.x; + t.y = this.y; + t.z = this.z; + } + + + /** + * Sets the value of this tuple to the sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple3d t1, Tuple3d t2) + { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + this.z = t1.z + t2.z; + } + + + /** + * Sets the value of this tuple to the sum of itself and t1. + * @param t1 the other tuple + */ + public final void add(Tuple3d t1) + { + this.x += t1.x; + this.y += t1.y; + this.z += t1.z; + } + + /** + * Sets the value of this tuple to the difference of tuples + * t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple3d t1, Tuple3d t2) + { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + this.z = t1.z - t2.z; + } + + /** + * Sets the value of this tuple to the difference + * of itself and t1 (this = this - t1). + * @param t1 the other tuple + */ + public final void sub(Tuple3d t1) + { + this.x -= t1.x; + this.y -= t1.y; + this.z -= t1.z; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple3d t1) + { + this.x = -t1.x; + this.y = -t1.y; + this.z = -t1.z; + } + + + /** + * Negates the value of this tuple in place. + */ + public final void negate() + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(double s, Tuple3d t1) + { + this.x = s*t1.x; + this.y = s*t1.y; + this.z = s*t1.z; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself. + * @param s the scalar value + */ + public final void scale(double s) + { + this.x *= s; + this.y *= s; + this.z *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 and then adds tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(double s, Tuple3d t1, Tuple3d t2) + { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + this.z = s*t1.z + t2.z; + } + + + /** + * @deprecated Use scaleAdd(double,Tuple3d) instead + */ + public final void scaleAdd(double s, Tuple3f t1) { + scaleAdd(s, new Point3d(t1)); + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(double s, Tuple3d t1) { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + this.z = s*this.z + t1.z; + } + + + + /** + * Returns a string that contains the values of this Tuple3d. + * The form is (x,y,z). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ")"; + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple3d objects with identical data values + * (i.e., Tuple3d.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashDoubleBits(bits, x); + bits = VecMathUtil.hashDoubleBits(bits, y); + bits = VecMathUtil.hashDoubleBits(bits, z); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Returns true if all of the data members of Tuple3d t1 are + * equal to the corresponding data members in this Tuple3d. + * @param t1 the tuple with which the comparison is made + * @return true or false + */ + public boolean equals(Tuple3d t1) + { + try { + return(this.x == t1.x && this.y == t1.y && this.z == t1.z); + } + catch (NullPointerException e2) {return false;} + } + + /** + * Returns true if the Object t1 is of type Tuple3d and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple3d. + * @param t1 the Object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Tuple3d t2 = (Tuple3d) t1; + return(this.x == t2.x && this.y == t2.y && this.z == t2.z); + } + catch (ClassCastException e1) {return false;} + catch (NullPointerException e2) {return false;} + + } + + /** + * Returns true if the L-infinite distance between this tuple + * and tuple t1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)]. + * @param t1 the tuple to be compared to this tuple + * @param epsilon the threshold value + * @return true or false + */ + public boolean epsilonEquals(Tuple3d t1, double epsilon) + { + double diff; + + diff = x - t1.x; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - t1.y; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = z - t1.z; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + + } + + + /** + * @deprecated Use clamp(double,double,Tuple3d) instead + */ + public final void clamp(float min, float max, Tuple3d t) { + clamp((double)min, (double)max, t); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(double min, double max, Tuple3d t) { + if( t.x > max ) { + x = max; + } else if( t.x < min ){ + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ){ + y = min; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else if( t.z < min ){ + z = min; + } else { + z = t.z; + } + + } + + + /** + * @deprecated Use clampMin(double,Tuple3d) instead + */ + public final void clampMin(float min, Tuple3d t) { + clampMin((double)min, t); + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(double min, Tuple3d t) { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z < min ) { + z = min; + } else { + z = t.z; + } + + } + + + /** + * @deprecated Use clampMax(double,Tuple3d) instead + */ + public final void clampMax(float max, Tuple3d t) { + clampMax((double)max, t); + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(double max, Tuple3d t) { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else { + z = t.z; + } + + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple3d t) + { + x = Math.abs(t.x); + y = Math.abs(t.y); + z = Math.abs(t.z); + + } + + + /** + * @deprecated Use clamp(double,double) instead + */ + public final void clamp(float min, float max) { + clamp((double)min, (double)max); + } + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(double min, double max) { + if( x > max ) { + x = max; + } else if( x < min ){ + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ){ + y = min; + } + + if( z > max ) { + z = max; + } else if( z < min ){ + z = min; + } + + } + + + /** + * @deprecated Use clampMin(double) instead + */ + public final void clampMin(float min) { + clampMin((double)min); + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(double min) { + if( x < min ) x=min; + if( y < min ) y=min; + if( z < min ) z=min; + + } + + + /** + * @deprecated Use clampMax(double) instead + */ + public final void clampMax(float max) { + clampMax((double)max); + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(double max) { + if( x > max ) x=max; + if( y > max ) y=max; + if( z > max ) z=max; + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() + { + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + } + + + /** + * @deprecated Use interpolate(Tuple3d,Tuple3d,double) instead + */ + public final void interpolate(Tuple3d t1, Tuple3d t2, float alpha) { + interpolate(t1, t2, (double)alpha); + } + + + /** + * Linearly interpolates between tuples t1 and t2 and places the + * result into this tuple: this = (1-alpha)*t1 + alpha*t2. + * @param t1 the first tuple + * @param t2 the second tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple3d t1, Tuple3d t2, double alpha) { + this.x = (1-alpha)*t1.x + alpha*t2.x; + this.y = (1-alpha)*t1.y + alpha*t2.y; + this.z = (1-alpha)*t1.z + alpha*t2.z; + } + + + /** + * @deprecated Use interpolate(Tuple3d,double) instead + */ + public final void interpolate(Tuple3d t1, float alpha) { + interpolate(t1, (double)alpha); + } + + + /** + * Linearly interpolates between this tuple and tuple t1 and + * places the result into this tuple: this = (1-alpha)*this + alpha*t1. + * @param t1 the first tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple3d t1, double alpha) { + this.x = (1-alpha)*this.x + alpha*t1.x; + this.y = (1-alpha)*this.y + alpha*t1.y; + this.z = (1-alpha)*this.z + alpha*t1.z; + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + /** + * Get the <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(double x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(double y) { + this.y = y; + } + + /** + * Get the <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getZ() { + return z; + } + + + /** + * Set the <i>z</i> coordinate. + * + * @param z value to <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(double z) { + this.z = z; + } +} diff --git a/src/org/jogamp/vecmath/Tuple3f.java b/src/org/jogamp/vecmath/Tuple3f.java new file mode 100644 index 0000000..cd5ec18 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple3f.java @@ -0,0 +1,711 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A generic 3-element tuple that is represented by single precision-floating + * point x,y,z coordinates. + * + */ +public abstract class Tuple3f implements java.io.Serializable, Cloneable { + + static final long serialVersionUID=5019834619484343712L; + + /** + * The x coordinate. + */ + public float x; + + /** + * The y coordinate. + */ + public float y; + + /** + * The z coordinate. + */ + public float z; + + + /** + * Constructs and initializes a Tuple3f from the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Tuple3f(float x, float y, float z) + { + this.x = x; + this.y = y; + this.z = z; + } + + + /** + * Constructs and initializes a Tuple3f from the array of length 3. + * @param t the array of length 3 containing xyz in order + */ + public Tuple3f(float[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + + /** + * Constructs and initializes a Tuple3f from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public Tuple3f(Tuple3f t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + + /** + * Constructs and initializes a Tuple3f from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public Tuple3f(Tuple3d t1) + { + this.x = (float) t1.x; + this.y = (float) t1.y; + this.z = (float) t1.z; + } + + + /** + * Constructs and initializes a Tuple3f to (0,0,0). + */ + public Tuple3f() + { + this.x = 0.0f; + this.y = 0.0f; + this.z = 0.0f; + } + + + /** + * Returns a string that contains the values of this Tuple3f. + * The form is (x,y,z). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ")"; + } + + + /** + * Sets the value of this tuple to the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public final void set(float x, float y, float z) + { + this.x = x; + this.y = y; + this.z = z; + } + + + /** + * Sets the value of this tuple to the xyz coordinates specified in + * the array of length 3. + * @param t the array of length 3 containing xyz in order + */ + public final void set(float[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple3f t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple3d t1) + { + this.x = (float) t1.x; + this.y = (float) t1.y; + this.z = (float) t1.z; + } + + + /** + * Gets the value of this tuple and copies the values into t. + * @param t the array of length 3 into which the values are copied + */ + public final void get(float[] t) + { + t[0] = this.x; + t[1] = this.y; + t[2] = this.z; + } + + + /** + * Gets the value of this tuple and copies the values into t. + * @param t the Tuple3f object into which the values of this object are copied + */ + public final void get(Tuple3f t) + { + t.x = this.x; + t.y = this.y; + t.z = this.z; + } + + + /** + * Sets the value of this tuple to the vector sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple3f t1, Tuple3f t2) + { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + this.z = t1.z + t2.z; + } + + + /** + * Sets the value of this tuple to the vector sum of itself and tuple t1. + * @param t1 the other tuple + */ + public final void add(Tuple3f t1) + { + this.x += t1.x; + this.y += t1.y; + this.z += t1.z; + } + + + /** + * Sets the value of this tuple to the vector difference + * of tuples t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple3f t1, Tuple3f t2) + { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + this.z = t1.z - t2.z; + } + + + /** + * Sets the value of this tuple to the vector difference of + * itself and tuple t1 (this = this - t1) . + * @param t1 the other tuple + */ + public final void sub(Tuple3f t1) + { + this.x -= t1.x; + this.y -= t1.y; + this.z -= t1.z; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple3f t1) + { + this.x = -t1.x; + this.y = -t1.y; + this.z = -t1.z; + } + + + /** + * Negates the value of this tuple in place. + */ + public final void negate() + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + } + + + /** + * Sets the value of this vector to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(float s, Tuple3f t1) + { + this.x = s*t1.x; + this.y = s*t1.y; + this.z = s*t1.z; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of the scale factor with this. + * @param s the scalar value + */ + public final void scale(float s) + { + this.x *= s; + this.y *= s; + this.z *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 and then adds tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be scaled and added + * @param t2 the tuple to be added without a scale + */ + public final void scaleAdd(float s, Tuple3f t1, Tuple3f t2) + { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + this.z = s*t1.z + t2.z; + } + + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(float s, Tuple3f t1) + { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + this.z = s*this.z + t1.z; + } + + + /** + * Returns true if the Object t1 is of type Tuple3f and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple3f. + * @param t1 the vector with which the comparison is made + * @return true or false + */ + public boolean equals(Tuple3f t1) + { + try { + return(this.x == t1.x && this.y == t1.y && this.z == t1.z); + } + catch (NullPointerException e2) {return false;} + } + /** + * Returns true if the Object t1 is of type Tuple3f and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple3f. + * @param t1 the Object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Tuple3f t2 = (Tuple3f) t1; + return(this.x == t2.x && this.y == t2.y && this.z == t2.z); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + } + + + /** + * Returns true if the L-infinite distance between this tuple + * and tuple t1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)]. + * @param t1 the tuple to be compared to this tuple + * @param epsilon the threshold value + * @return true or false + */ + public boolean epsilonEquals(Tuple3f t1, float epsilon) + { + float diff; + + diff = x - t1.x; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - t1.y; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = z - t1.z; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple3f objects with identical data values + * (i.e., Tuple3f.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashFloatBits(bits, x); + bits = VecMathUtil.hashFloatBits(bits, y); + bits = VecMathUtil.hashFloatBits(bits, z); + return VecMathUtil.hashFinish(bits); + } + + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(float min, float max, Tuple3f t) + { + if( t.x > max ) { + x = max; + } else if( t.x < min ){ + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ){ + y = min; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else if( t.z < min ){ + z = min; + } else { + z = t.z; + } + + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(float min, Tuple3f t) + { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z < min ) { + z = min; + } else { + z = t.z; + } + + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(float max, Tuple3f t) + { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else { + z = t.z; + } + + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple3f t) + { + x = Math.abs(t.x); + y = Math.abs(t.y); + z = Math.abs(t.z); + } + + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(float min, float max) + { + if( x > max ) { + x = max; + } else if( x < min ){ + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ){ + y = min; + } + + if( z > max ) { + z = max; + } else if( z < min ){ + z = min; + } + + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(float min) + { + if( x < min ) x=min; + if( y < min ) y=min; + if( z < min ) z=min; + + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(float max) + { + if( x > max ) x=max; + if( y > max ) y=max; + if( z > max ) z=max; + + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() + { + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + + } + + + /** + * Linearly interpolates between tuples t1 and t2 and places the + * result into this tuple: this = (1-alpha)*t1 + alpha*t2. + * @param t1 the first tuple + * @param t2 the second tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple3f t1, Tuple3f t2, float alpha) + { + this.x = (1-alpha)*t1.x + alpha*t2.x; + this.y = (1-alpha)*t1.y + alpha*t2.y; + this.z = (1-alpha)*t1.z + alpha*t2.z; + + + } + + + /** + * Linearly interpolates between this tuple and tuple t1 and + * places the result into this tuple: this = (1-alpha)*this + alpha*t1. + * @param t1 the first tuple + * @param alpha the alpha interpolation parameter + */ + public final void interpolate(Tuple3f t1, float alpha) + { + this.x = (1-alpha)*this.x + alpha*t1.x; + this.y = (1-alpha)*this.y + alpha*t1.y; + this.z = (1-alpha)*this.z + alpha*t1.z; + + + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get the <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(float x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(float y) { + this.y = y; + } + + /** + * Get the <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate + * + * @since vecmath 1.5 + */ + public final float getZ() { + return z; + } + + + /** + * Set the <i>Z</i> coordinate. + * + * @param z value to <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(float z) { + this.z = z; + } +} diff --git a/src/org/jogamp/vecmath/Tuple3i.java b/src/org/jogamp/vecmath/Tuple3i.java new file mode 100644 index 0000000..2da4ec3 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple3i.java @@ -0,0 +1,588 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 3-element tuple represented by signed integer x,y,z + * coordinates. + * + * @since vecmath 1.2 + */ +public abstract class Tuple3i implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = -732740491767276200L; + + /** + * The x coordinate. + */ + public int x; + + /** + * The y coordinate. + */ + public int y; + + /** + * The z coordinate. + */ + public int z; + + + /** + * Constructs and initializes a Tuple3i from the specified + * x, y, and z coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Tuple3i(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + + /** + * Constructs and initializes a Tuple3i from the array of length 3. + * @param t the array of length 3 containing x, y, and z in order. + */ + public Tuple3i(int[] t) { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + + /** + * Constructs and initializes a Tuple3i from the specified Tuple3i. + * @param t1 the Tuple3i containing the initialization x, y, and z + * data. + */ + public Tuple3i(Tuple3i t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + + /** + * Constructs and initializes a Tuple3i to (0,0,0). + */ + public Tuple3i() { + this.x = 0; + this.y = 0; + this.z = 0; + } + + + /** + * Sets the value of this tuple to the specified x, y, and z + * coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public final void set(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + + /** + * Sets the value of this tuple to the specified coordinates in the + * array of length 3. + * @param t the array of length 3 containing x, y, and z in order. + */ + public final void set(int[] t) { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple3i t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + } + + + /** + * Copies the values of this tuple into the array t. + * @param t is the array + */ + public final void get(int[] t) { + t[0] = this.x; + t[1] = this.y; + t[2] = this.z; + } + + + /** + * Copies the values of this tuple into the tuple t. + * @param t is the target tuple + */ + public final void get(Tuple3i t) { + t.x = this.x; + t.y = this.y; + t.z = this.z; + } + + + /** + * Sets the value of this tuple to the sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple3i t1, Tuple3i t2) { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + this.z = t1.z + t2.z; + } + + + /** + * Sets the value of this tuple to the sum of itself and t1. + * @param t1 the other tuple + */ + public final void add(Tuple3i t1) { + this.x += t1.x; + this.y += t1.y; + this.z += t1.z; + } + + + /** + * Sets the value of this tuple to the difference + * of tuples t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple3i t1, Tuple3i t2) { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + this.z = t1.z - t2.z; + } + + + /** + * Sets the value of this tuple to the difference + * of itself and t1 (this = this - t1). + * @param t1 the other tuple + */ + public final void sub(Tuple3i t1) { + this.x -= t1.x; + this.y -= t1.y; + this.z -= t1.z; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple3i t1) { + this.x = -t1.x; + this.y = -t1.y; + this.z = -t1.z; + } + + + /** + * Negates the value of this tuple in place. + */ + public final void negate() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(int s, Tuple3i t1) { + this.x = s*t1.x; + this.y = s*t1.y; + this.z = s*t1.z; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of the scale factor with this. + * @param s the scalar value + */ + public final void scale(int s) { + this.x *= s; + this.y *= s; + this.z *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 plus tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(int s, Tuple3i t1, Tuple3i t2) { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + this.z = s*t1.z + t2.z; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(int s, Tuple3i t1) { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + this.z = s*this.z + t1.z; + } + + + /** + * Returns a string that contains the values of this Tuple3i. + * The form is (x,y,z). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ")"; + } + + + /** + * Returns true if the Object t1 is of type Tuple3i and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple3i. + * @param t1 the object with which the comparison is made + */ + @Override + public boolean equals(Object t1) { + try { + Tuple3i t2 = (Tuple3i) t1; + return(this.x == t2.x && this.y == t2.y && this.z == t2.z); + } + catch (NullPointerException e2) { + return false; + } + catch (ClassCastException e1) { + return false; + } + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple3i objects with identical data values + * (i.e., Tuple3i.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = 31L * bits + (long)x; + bits = 31L * bits + (long)y; + bits = 31L * bits + (long)z; + return (int) (bits ^ (bits >> 32)); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(int min, int max, Tuple3i t) { + if( t.x > max ) { + x = max; + } else if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else if( t.z < min ) { + z = min; + } else { + z = t.z; + } + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(int min, Tuple3i t) { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z < min ) { + z = min; + } else { + z = t.z; + } + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(int max, Tuple3i t) { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else { + z = t.z; + } + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple3i t) { + x = Math.abs(t.x); + y = Math.abs(t.y); + z = Math.abs(t.z); + } + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(int min, int max) { + if( x > max ) { + x = max; + } else if( x < min ) { + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ) { + y = min; + } + + if( z > max ) { + z = max; + } else if( z < min ) { + z = min; + } + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(int min) { + if (x < min) + x=min; + + if (y < min) + y = min; + + if (z < min) + z = min; + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(int max) { + if (x > max) + x = max; + + if (y > max) + y = max; + + if (z > max) + z = max; + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() { + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get the <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final int getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(int x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final int getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(int y) { + this.y = y; + } + + /** + * Get the <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate. + * @since vecmath 1.5 + */ + public final int getZ() { + return z; + } + + + /** + * Set the <i>z</i> coordinate. + * + * @param z value to <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(int z) { + this.z = z; + } +} diff --git a/src/org/jogamp/vecmath/Tuple4b.java b/src/org/jogamp/vecmath/Tuple4b.java new file mode 100644 index 0000000..9bc28b2 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple4b.java @@ -0,0 +1,357 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A four byte tuple. Note that Java defines a byte as a signed integer + * in the range [-128, 127]. However, colors are more typically + * represented by values in the range [0, 255]. Java 3D recognizes this + * and, in those cases where Tuple4b is used to represent color, treats + * the bytes as if the range were [0, 255]---in other words, as if the + * bytes were unsigned. + * Values greater than 127 can be assigned to a byte variable using a + * type cast. For example: + * <ul>byteVariable = (byte) intValue; // intValue can be > 127</ul> + * If intValue is greater than 127, then byteVariable will be negative. The + * correct value will be extracted when it is used (by masking off the upper + * bits). + */ +public abstract class Tuple4b implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = -8226727741811898211L; + + /** + * The first value. + */ + public byte x; + + /** + * The second value. + */ + public byte y; + + /** + * The third value. + */ + public byte z; + + /** + * The fourth value. + */ + public byte w; + + + /** + * Constructs and initializes a Tuple4b from the specified four values. + * @param b1 the first value + * @param b2 the second value + * @param b3 the third value + * @param b4 the fourth value + */ + public Tuple4b(byte b1, byte b2, byte b3, byte b4) + { + this.x = b1; + this.y = b2; + this.z = b3; + this.w = b4; + } + + + /** + * Constructs and initializes a Tuple4b from the array of length 4. + * @param t the array of length 4 containing b1 b2 b3 b4 in order + */ + public Tuple4b(byte[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + this.w = t[3]; + } + + + /** + * Constructs and initializes a Tuple4b from the specified Tuple4b. + * @param t1 the Tuple4b containing the initialization x y z w data + */ + public Tuple4b(Tuple4b t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Constructs and initializes a Tuple4b to (0,0,0,0). + */ + public Tuple4b() + { + this.x = (byte) 0; + this.y = (byte) 0; + this.z = (byte) 0; + this.w = (byte) 0; + } + + + /** + * Returns a string that contains the values of this Tuple4b. + * @return the String representation + */ + @Override + public String toString() + { + return("(" + ((int)this.x & 0xff) + + ", " + ((int)this.y & 0xff) + + ", " + ((int)this.z & 0xff) + + ", " + ((int)this.w & 0xff) + ")"); + } + + + /** + * Places the value of the x,y,z,w components of this Tuple4b + * into the array of length 4. + * @param b array of length 4 into which the values are placed + */ + public final void get(byte[] b) + { + b[0] = this.x; + b[1] = this.y; + b[2] = this.z; + b[3] = this.w; + } + + + /** + * Places the value of the x,y,z,w components of this + * Tuple4b into the tuple t1. + * @param t1 tuple into which the values are placed + */ + public final void get(Tuple4b t1) + { + t1.x = this.x; + t1.y = this.y; + t1.z = this.z; + t1.w = this.w; + } + + + /** + * Sets the value of the data members of this tuple to the value + * of the argument tuple t1. + * @param t1 the source tuple + */ + public final void set(Tuple4b t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Sets the value of the data members of this tuple to the value + * of the array b of length 4. + * @param b the source array of length 4 + */ + public final void set(byte[] b) + { + this.x = b[0]; + this.y = b[1]; + this.z = b[2]; + this.w = b[3]; + } + + + /** + * Returns true if all of the data members of tuple t1 are equal to + * the corresponding data members in this tuple. + * @param t1 the tuple with which the comparison is made + */ + public boolean equals(Tuple4b t1) + { + try { + return(this.x == t1.x && this.y == t1.y && + this.z == t1.z && this.w == t1.w); + } + catch (NullPointerException e2) {return false;} + + } + + /** + * Returns true if the Object t1 is of type Tuple4b and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple4b. + * @param t1 the object with which the comparison is made + */ + @Override + public boolean equals(Object t1) + { + try { + Tuple4b t2 = (Tuple4b) t1; + return(this.x == t2.x && this.y == t2.y && + this.z == t2.z && this.w == t2.w); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple4b objects with identical data values + * (i.e., Tuple4b.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + return ((((int)x & 0xff) << 0) | + (((int)y & 0xff) << 8) | + (((int)z & 0xff) << 16) | + (((int)w & 0xff) << 24)); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + /** + * Get <i>x</i>, the first value. + * + * @return Returns <i>x</i>, the first value. + * + * @since vecmath 1.5 + */ + public final byte getX() { + return x; + } + + + /** + * Set <i>x</i>, the first value. + * + * @param x the first value. + * + * @since vecmath 1.5 + */ + public final void setX(byte x) { + this.x = x; + } + + + /** + * Get <i>y</i>, the second value. + * + * @return Returns <i>y</i>, the second value. + * + * @since vecmath 1.5 + */ + public final byte getY() { + return y; + } + + + /** + * Set <i>y</i>, the second value. + * + * @param y the second value. + * + * @since vecmath 1.5 + */ + public final void setY(byte y) { + this.y = y; + } + + /** + * Get <i>z</i>, the third value. + * + * @return Returns <i>z</i>, the third value. + * + * @since vecmath 1.5 + */ + public final byte getZ() { + return z; + } + + + /** + * Set <i>z</i>, the third value. + * + * @param z the third value. + * + * @since vecmath 1.5 + */ + public final void setZ(byte z) { + this.z = z; + } + + + /** + * Get <i>w</i>, the fourth value. + * + * @return Returns <i>w</i> - the fourth value. + * + * @since vecmath 1.5 + */ + public final byte getW() { + return w; + } + + + /** + * Set <i>w</i>, the fourth value. + * + * @param w the fourth value. + * + * @since vecmath 1.5 + */ + public final void setW(byte w) { + this.w = w; + } +} diff --git a/src/org/jogamp/vecmath/Tuple4d.java b/src/org/jogamp/vecmath/Tuple4d.java new file mode 100644 index 0000000..618fef1 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple4d.java @@ -0,0 +1,865 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4 element tuple represented by double precision floating point + * x,y,z,w coordinates. + * + */ +public abstract class Tuple4d implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = -4748953690425311052L; + + /** + * The x coordinate. + */ + public double x; + + /** + * The y coordinate. + */ + public double y; + + /** + * The z coordinate. + */ + public double z; + + /** + * The w coordinate. + */ + public double w; + + + /** + * Constructs and initializes a Tuple4d from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Tuple4d(double x, double y, double z, double w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + + /** + * Constructs and initializes a Tuple4d from the coordinates contained + * in the array. + * @param t the array of length 4 containing xyzw in order + */ + public Tuple4d(double[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + this.w = t[3]; + } + + + /** + * Constructs and initializes a Tuple4d from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Tuple4d(Tuple4d t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Constructs and initializes a Tuple4d from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Tuple4d(Tuple4f t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Constructs and initializes a Tuple4d to (0,0,0,0). + */ + public Tuple4d() + { + this.x = 0.0; + this.y = 0.0; + this.z = 0.0; + this.w = 0.0; + } + + + /** + * Sets the value of this tuple to the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public final void set(double x, double y, double z, double w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + + /** + * Sets the value of this tuple to the specified xyzw coordinates. + * @param t the array of length 4 containing xyzw in order + */ + public final void set(double[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + this.w = t[3]; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple4d t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple4f t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Gets the value of this tuple and places it into the array t of + * length four in x,y,z,w order. + * @param t the array of length four + */ + public final void get(double[] t) + { + t[0] = this.x; + t[1] = this.y; + t[2] = this.z; + t[3] = this.w; + } + + + /** + * Gets the value of this tuple and places it into the Tuple4d + * argument of + * length four in x,y,z,w order. + * @param t the Tuple into which the values will be copied + */ + public final void get(Tuple4d t) + { + t.x = this.x; + t.y = this.y; + t.z = this.z; + t.w = this.w; + } + + + /** + * Sets the value of this tuple to the tuple sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple4d t1, Tuple4d t2) + { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + this.z = t1.z + t2.z; + this.w = t1.w + t2.w; + } + + + /** + * Sets the value of this tuple to the sum of itself and tuple t1. + * @param t1 the other tuple + */ + public final void add(Tuple4d t1) + { + this.x += t1.x; + this.y += t1.y; + this.z += t1.z; + this.w += t1.w; + } + + + /** + * Sets the value of this tuple to the difference + * of tuples t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple4d t1, Tuple4d t2) + { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + this.z = t1.z - t2.z; + this.w = t1.w - t2.w; + } + + + /** + * Sets the value of this tuple to the difference of itself + * and tuple t1 (this = this - t1). + * @param t1 the other tuple + */ + public final void sub(Tuple4d t1) + { + this.x -= t1.x; + this.y -= t1.y; + this.z -= t1.z; + this.w -= t1.w; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple4d t1) + { + this.x = -t1.x; + this.y = -t1.y; + this.z = -t1.z; + this.w = -t1.w; + } + + + /** + * Negates the value of this tuple in place. + */ + public final void negate() + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + this.w = -this.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of the scale factor with the tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(double s, Tuple4d t1) + { + this.x = s*t1.x; + this.y = s*t1.y; + this.z = s*t1.z; + this.w = s*t1.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of the scale factor with this. + * @param s the scalar value + */ + public final void scale(double s) + { + this.x *= s; + this.y *= s; + this.z *= s; + this.w *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication by s + * of tuple t1 plus tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(double s, Tuple4d t1, Tuple4d t2) + { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + this.z = s*t1.z + t2.z; + this.w = s*t1.w + t2.w; + } + + + + /** + * @deprecated Use scaleAdd(double,Tuple4d) instead + */ + public final void scaleAdd(float s, Tuple4d t1) { + scaleAdd((double)s, t1); + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(double s, Tuple4d t1) { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + this.z = s*this.z + t1.z; + this.w = s*this.w + t1.w; + } + + + + /** + * Returns a string that contains the values of this Tuple4d. + * The form is (x,y,z,w). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")"; + } + + + /** + * Returns true if all of the data members of Tuple4d t1 are + * equal to the corresponding data members in this Tuple4d. + * @param t1 the tuple with which the comparison is made + * @return true or false + */ + public boolean equals(Tuple4d t1) + { + try { + return(this.x == t1.x && this.y == t1.y && this.z == t1.z + && this.w == t1.w); + } + catch (NullPointerException e2) {return false;} + } + + /** + * Returns true if the Object t1 is of type Tuple4d and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple4d. + * @param t1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + + Tuple4d t2 = (Tuple4d) t1; + return(this.x == t2.x && this.y == t2.y && + this.z == t2.z && this.w == t2.w); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + } + + + /** + * Returns true if the L-infinite distance between this tuple + * and tuple t1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)]. + * @param t1 the tuple to be compared to this tuple + * @param epsilon the threshold value + * @return true or false + */ + public boolean epsilonEquals(Tuple4d t1, double epsilon) + { + double diff; + + diff = x - t1.x; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - t1.y; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = z - t1.z; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = w - t1.w; + if(Double.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple4d objects with identical data values + * (i.e., Tuple4d.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashDoubleBits(bits, x); + bits = VecMathUtil.hashDoubleBits(bits, y); + bits = VecMathUtil.hashDoubleBits(bits, z); + bits = VecMathUtil.hashDoubleBits(bits, w); + return VecMathUtil.hashFinish(bits); + } + + + /** + * @deprecated Use clamp(double,double,Tuple4d) instead + */ + public final void clamp(float min, float max, Tuple4d t) { + clamp((double)min, (double)max, t); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(double min, double max, Tuple4d t) { + if( t.x > max ) { + x = max; + } else if( t.x < min ){ + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ){ + y = min; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else if( t.z < min ){ + z = min; + } else { + z = t.z; + } + + if( t.w > max ) { + w = max; + } else if( t.w < min ){ + w = min; + } else { + w = t.w; + } + + } + + + /** + * @deprecated Use clampMin(double,Tuple4d) instead + */ + public final void clampMin(float min, Tuple4d t) { + clampMin((double)min, t); + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(double min, Tuple4d t) { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z < min ) { + z = min; + } else { + z = t.z; + } + + if( t.w < min ) { + w = min; + } else { + w = t.w; + } + + } + + + /** + * @deprecated Use clampMax(double,Tuple4d) instead + */ + public final void clampMax(float max, Tuple4d t) { + clampMax((double)max, t); + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(double max, Tuple4d t) { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else { + z = t.z; + } + + if( t.w > max ) { + w = max; + } else { + w = t.z; + } + + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple4d t) + { + x = Math.abs(t.x); + y = Math.abs(t.y); + z = Math.abs(t.z); + w = Math.abs(t.w); + + } + + + + /** + * @deprecated Use clamp(double,double) instead + */ + public final void clamp(float min, float max) { + clamp((double)min, (double)max); + } + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(double min, double max) { + if( x > max ) { + x = max; + } else if( x < min ){ + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ){ + y = min; + } + + if( z > max ) { + z = max; + } else if( z < min ){ + z = min; + } + + if( w > max ) { + w = max; + } else if( w < min ){ + w = min; + } + + } + + + /** + * @deprecated Use clampMin(double) instead + */ + public final void clampMin(float min) { + clampMin((double)min); + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(double min) { + if( x < min ) x=min; + if( y < min ) y=min; + if( z < min ) z=min; + if( w < min ) w=min; + } + + + /** + * @deprecated Use clampMax(double) instead + */ + public final void clampMax(float max) { + clampMax((double)max); + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(double max) { + if( x > max ) x=max; + if( y > max ) y=max; + if( z > max ) z=max; + if( w > max ) w=max; + + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() + { + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + w = Math.abs(w); + + } + + + /** + * @deprecated Use interpolate(Tuple4d,Tuple4d,double) instead + */ + public void interpolate(Tuple4d t1, Tuple4d t2, float alpha) { + interpolate(t1, t2, (double)alpha); + } + + + /** + * Linearly interpolates between tuples t1 and t2 and places the + * result into this tuple: this = (1-alpha)*t1 + alpha*t2. + * @param t1 the first tuple + * @param t2 the second tuple + * @param alpha the alpha interpolation parameter + */ + public void interpolate(Tuple4d t1, Tuple4d t2, double alpha) { + this.x = (1-alpha)*t1.x + alpha*t2.x; + this.y = (1-alpha)*t1.y + alpha*t2.y; + this.z = (1-alpha)*t1.z + alpha*t2.z; + this.w = (1-alpha)*t1.w + alpha*t2.w; + } + + + /** + * @deprecated Use interpolate(Tuple4d,double) instead + */ + public void interpolate(Tuple4d t1, float alpha) { + interpolate(t1, (double)alpha); + } + + + /** + * Linearly interpolates between this tuple and tuple t1 and + * places the result into this tuple: this = (1-alpha)*this + alpha*t1. + * @param t1 the first tuple + * @param alpha the alpha interpolation parameter + */ + public void interpolate(Tuple4d t1, double alpha) { + this.x = (1-alpha)*this.x + alpha*t1.x; + this.y = (1-alpha)*this.y + alpha*t1.y; + this.z = (1-alpha)*this.z + alpha*t1.z; + this.w = (1-alpha)*this.w + alpha*t1.w; + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + /** + * Get the <i>x</i> coordinate. + * + * @return the x coordinate. + * + * @since vecmath 1.5 + */ + public final double getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(double x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(double y) { + this.y = y; + } + + /** + * Get the <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getZ() { + return z; + } + + + /** + * Set the <i>z</i> coordinate. + * + * @param z value to <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(double z) { + this.z = z; + } + + + /** + * Get the <i>w</i> coordinate. + * + * @return the <i>w</i> coordinate. + * + * @since vecmath 1.5 + */ + public final double getW() { + return w; + } + + + /** + * Set the <i>w</i> coordinate. + * + * @param w value to <i>w</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setW(double w) { + this.w = w; + } +} diff --git a/src/org/jogamp/vecmath/Tuple4f.java b/src/org/jogamp/vecmath/Tuple4f.java new file mode 100644 index 0000000..e227979 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple4f.java @@ -0,0 +1,796 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4-element tuple represented by single-precision floating point x,y,z,w + * coordinates. + * + */ +public abstract class Tuple4f implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = 7068460319248845763L; + + /** + * The x coordinate. + */ + public float x; + + /** + * The y coordinate. + */ + public float y; + + /** + * The z coordinate. + */ + public float z; + + /** + * The w coordinate. + */ + public float w; + + + /** + * Constructs and initializes a Tuple4f from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Tuple4f(float x, float y, float z, float w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + + /** + * Constructs and initializes a Tuple4f from the array of length 4. + * @param t the array of length 4 containing xyzw in order + */ + public Tuple4f(float[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + this.w = t[3]; + } + + + /** + * Constructs and initializes a Tuple4f from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Tuple4f(Tuple4f t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Constructs and initializes a Tuple4f from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Tuple4f(Tuple4d t1) + { + this.x = (float) t1.x; + this.y = (float) t1.y; + this.z = (float) t1.z; + this.w = (float) t1.w; + } + + + /** + * Constructs and initializes a Tuple4f to (0,0,0,0). + */ + public Tuple4f() + { + this.x = 0.0f; + this.y = 0.0f; + this.z = 0.0f; + this.w = 0.0f; + } + + + /** + * Sets the value of this tuple to the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public final void set(float x, float y, float z, float w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + + /** + * Sets the value of this tuple to the specified coordinates in the + * array of length 4. + * @param t the array of length 4 containing xyzw in order + */ + public final void set(float[] t) + { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + this.w = t[3]; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple4f t1) + { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple4d t1) + { + this.x = (float) t1.x; + this.y = (float) t1.y; + this.z = (float) t1.z; + this.w = (float) t1.w; + } + + + /** + * Copies the values of this tuple into the array t. + * @param t the array + */ + public final void get(float[] t) + { + t[0] = this.x; + t[1] = this.y; + t[2] = this.z; + t[3] = this.w; + } + + + /** + * Copies the values of this tuple into the tuple t. + * @param t the target tuple + */ + public final void get(Tuple4f t) + { + t.x = this.x; + t.y = this.y; + t.z = this.z; + t.w = this.w; + } + + + /** + * Sets the value of this tuple to the sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple4f t1, Tuple4f t2) + { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + this.z = t1.z + t2.z; + this.w = t1.w + t2.w; + } + + + /** + * Sets the value of this tuple to the sum of itself and t1. + * @param t1 the other tuple + */ + public final void add(Tuple4f t1) + { + this.x += t1.x; + this.y += t1.y; + this.z += t1.z; + this.w += t1.w; + } + + + /** + * Sets the value of this tuple to the difference + * of tuples t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple4f t1, Tuple4f t2) + { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + this.z = t1.z - t2.z; + this.w = t1.w - t2.w; + } + + + /** + * Sets the value of this tuple to the difference + * of itself and t1 (this = this - t1). + * @param t1 the other tuple + */ + public final void sub(Tuple4f t1) + { + this.x -= t1.x; + this.y -= t1.y; + this.z -= t1.z; + this.w -= t1.w; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple4f t1) + { + this.x = -t1.x; + this.y = -t1.y; + this.z = -t1.z; + this.w = -t1.w; + } + + + /** + * Negates the value of this tuple in place. + */ + public final void negate() + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + this.w = -this.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(float s, Tuple4f t1) + { + this.x = s*t1.x; + this.y = s*t1.y; + this.z = s*t1.z; + this.w = s*t1.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of the scale factor with this. + * @param s the scalar value + */ + public final void scale(float s) + { + this.x *= s; + this.y *= s; + this.z *= s; + this.w *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 plus tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(float s, Tuple4f t1, Tuple4f t2) + { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + this.z = s*t1.z + t2.z; + this.w = s*t1.w + t2.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(float s, Tuple4f t1) + { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + this.z = s*this.z + t1.z; + this.w = s*this.w + t1.w; + } + + + + /** + * Returns a string that contains the values of this Tuple4f. + * The form is (x,y,z,w). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")"; + } + + /** + * Returns true if all of the data members of Tuple4f t1 are + * equal to the corresponding data members in this Tuple4f. + * @param t1 the vector with which the comparison is made + * @return true or false + */ + public boolean equals(Tuple4f t1) + { + try { + return(this.x == t1.x && this.y == t1.y && this.z == t1.z + && this.w == t1.w); + } + catch (NullPointerException e2) {return false;} + } + + /** + * Returns true if the Object t1 is of type Tuple4f and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple4f. + * @param t1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) + { + try { + Tuple4f t2 = (Tuple4f) t1; + return(this.x == t2.x && this.y == t2.y && + this.z == t2.z && this.w == t2.w); + } + catch (NullPointerException e2) {return false;} + catch (ClassCastException e1) {return false;} + } + + + /** + * Returns true if the L-infinite distance between this tuple + * and tuple t1 is less than or equal to the epsilon parameter, + * otherwise returns false. The L-infinite + * distance is equal to + * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2), abs(w1-w2)]. + * @param t1 the tuple to be compared to this tuple + * @param epsilon the threshold value + * @return true or false + */ + public boolean epsilonEquals(Tuple4f t1, float epsilon) + { + float diff; + + diff = x - t1.x; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = y - t1.y; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = z - t1.z; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + diff = w - t1.w; + if(Float.isNaN(diff)) return false; + if((diff<0?-diff:diff) > epsilon) return false; + + return true; + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple4f objects with identical data values + * (i.e., Tuple4f.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = VecMathUtil.hashFloatBits(bits, x); + bits = VecMathUtil.hashFloatBits(bits, y); + bits = VecMathUtil.hashFloatBits(bits, z); + bits = VecMathUtil.hashFloatBits(bits, w); + return VecMathUtil.hashFinish(bits); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(float min, float max, Tuple4f t) + { + if( t.x > max ) { + x = max; + } else if( t.x < min ){ + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ){ + y = min; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else if( t.z < min ){ + z = min; + } else { + z = t.z; + } + + if( t.w > max ) { + w = max; + } else if( t.w < min ){ + w = min; + } else { + w = t.w; + } + + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(float min, Tuple4f t) + { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z < min ) { + z = min; + } else { + z = t.z; + } + + if( t.w < min ) { + w = min; + } else { + w = t.w; + } + + + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(float max, Tuple4f t) + { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else { + z = t.z; + } + + if( t.w > max ) { + w = max; + } else { + w = t.z; + } + + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple4f t) + { + x = Math.abs(t.x); + y = Math.abs(t.y); + z = Math.abs(t.z); + w = Math.abs(t.w); + } + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(float min, float max) + { + if( x > max ) { + x = max; + } else if( x < min ){ + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ){ + y = min; + } + + if( z > max ) { + z = max; + } else if( z < min ){ + z = min; + } + + if( w > max ) { + w = max; + } else if( w < min ){ + w = min; + } + + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(float min) + { + if( x < min ) x=min; + if( y < min ) y=min; + if( z < min ) z=min; + if( w < min ) w=min; + + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(float max) + { + if( x > max ) x=max; + if( y > max ) y=max; + if( z > max ) z=max; + if( w > max ) w=max; + + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() + { + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + w = Math.abs(w); + } + + + /** + * Linearly interpolates between tuples t1 and t2 and places the + * result into this tuple: this = (1-alpha)*t1 + alpha*t2. + * @param t1 the first tuple + * @param t2 the second tuple + * @param alpha the alpha interpolation parameter + */ + public void interpolate(Tuple4f t1, Tuple4f t2, float alpha) + { + this.x = (1-alpha)*t1.x + alpha*t2.x; + this.y = (1-alpha)*t1.y + alpha*t2.y; + this.z = (1-alpha)*t1.z + alpha*t2.z; + this.w = (1-alpha)*t1.w + alpha*t2.w; + + } + + + /** + * Linearly interpolates between this tuple and tuple t1 and + * places the result into this tuple: this = (1-alpha)*this + alpha*t1. + * @param t1 the first tuple + * @param alpha the alpha interpolation parameter + */ + public void interpolate(Tuple4f t1, float alpha) + { + this.x = (1-alpha)*this.x + alpha*t1.x; + this.y = (1-alpha)*this.y + alpha*t1.y; + this.z = (1-alpha)*this.z + alpha*t1.z; + this.w = (1-alpha)*this.w + alpha*t1.w; + + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + /** + * Get the <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(float x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(float y) { + this.y = y; + } + + /** + * Get the <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getZ() { + return z; + } + + + /** + * Set the <i>z</i> coordinate. + * + * @param z value to <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(float z) { + this.z = z; + } + + + /** + * Get the <i>w</i> coordinate. + * + * @return the <i>w</i> coordinate. + * + * @since vecmath 1.5 + */ + public final float getW() { + return w; + } + + + /** + * Set the <i>w</i> coordinate. + * + * @param w value to <i>w</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setW(float w) { + this.w = w; + } +} diff --git a/src/org/jogamp/vecmath/Tuple4i.java b/src/org/jogamp/vecmath/Tuple4i.java new file mode 100644 index 0000000..6dbd848 --- /dev/null +++ b/src/org/jogamp/vecmath/Tuple4i.java @@ -0,0 +1,678 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4-element tuple represented by signed integer x,y,z,w + * coordinates. + * + * @since vecmath 1.2 + */ +public abstract class Tuple4i implements java.io.Serializable, Cloneable { + + static final long serialVersionUID = 8064614250942616720L; + + /** + * The x coordinate. + */ + public int x; + + /** + * The y coordinate. + */ + public int y; + + /** + * The z coordinate. + */ + public int z; + + /** + * The w coordinate. + */ + public int w; + + + /** + * Constructs and initializes a Tuple4i from the specified + * x, y, z, and w coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Tuple4i(int x, int y, int z, int w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + + /** + * Constructs and initializes a Tuple4i from the array of length 4. + * @param t the array of length 4 containing x, y, z, and w in order. + */ + public Tuple4i(int[] t) { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + this.w = t[3]; + } + + + /** + * Constructs and initializes a Tuple4i from the specified Tuple4i. + * @param t1 the Tuple4i containing the initialization x, y, z, + * and w data. + */ + public Tuple4i(Tuple4i t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Constructs and initializes a Tuple4i to (0,0,0,0). + */ + public Tuple4i() { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + } + + + /** + * Sets the value of this tuple to the specified x, y, z, and w + * coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public final void set(int x, int y, int z, int w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + + /** + * Sets the value of this tuple to the specified coordinates in the + * array of length 4. + * @param t the array of length 4 containing x, y, z, and w in order. + */ + public final void set(int[] t) { + this.x = t[0]; + this.y = t[1]; + this.z = t[2]; + this.w = t[3]; + } + + + /** + * Sets the value of this tuple to the value of tuple t1. + * @param t1 the tuple to be copied + */ + public final void set(Tuple4i t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = t1.w; + } + + + /** + * Copies the values of this tuple into the array t. + * @param t the array + */ + public final void get(int[] t) { + t[0] = this.x; + t[1] = this.y; + t[2] = this.z; + t[3] = this.w; + } + + + /** + * Copies the values of this tuple into the tuple t. + * @param t the target tuple + */ + public final void get(Tuple4i t) { + t.x = this.x; + t.y = this.y; + t.z = this.z; + t.w = this.w; + } + + + /** + * Sets the value of this tuple to the sum of tuples t1 and t2. + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void add(Tuple4i t1, Tuple4i t2) { + this.x = t1.x + t2.x; + this.y = t1.y + t2.y; + this.z = t1.z + t2.z; + this.w = t1.w + t2.w; + } + + + /** + * Sets the value of this tuple to the sum of itself and t1. + * @param t1 the other tuple + */ + public final void add(Tuple4i t1) { + this.x += t1.x; + this.y += t1.y; + this.z += t1.z; + this.w += t1.w; + } + + + /** + * Sets the value of this tuple to the difference + * of tuples t1 and t2 (this = t1 - t2). + * @param t1 the first tuple + * @param t2 the second tuple + */ + public final void sub(Tuple4i t1, Tuple4i t2) { + this.x = t1.x - t2.x; + this.y = t1.y - t2.y; + this.z = t1.z - t2.z; + this.w = t1.w - t2.w; + } + + + /** + * Sets the value of this tuple to the difference + * of itself and t1 (this = this - t1). + * @param t1 the other tuple + */ + public final void sub(Tuple4i t1) { + this.x -= t1.x; + this.y -= t1.y; + this.z -= t1.z; + this.w -= t1.w; + } + + + /** + * Sets the value of this tuple to the negation of tuple t1. + * @param t1 the source tuple + */ + public final void negate(Tuple4i t1) { + this.x = -t1.x; + this.y = -t1.y; + this.z = -t1.z; + this.w = -t1.w; + } + + + /** + * Negates the value of this tuple in place. + */ + public final void negate() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + this.w = -this.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1. + * @param s the scalar value + * @param t1 the source tuple + */ + public final void scale(int s, Tuple4i t1) { + this.x = s*t1.x; + this.y = s*t1.y; + this.z = s*t1.z; + this.w = s*t1.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of the scale factor with this. + * @param s the scalar value + */ + public final void scale(int s) { + this.x *= s; + this.y *= s; + this.z *= s; + this.w *= s; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of tuple t1 plus tuple t2 (this = s*t1 + t2). + * @param s the scalar value + * @param t1 the tuple to be multipled + * @param t2 the tuple to be added + */ + public final void scaleAdd(int s, Tuple4i t1, Tuple4i t2) { + this.x = s*t1.x + t2.x; + this.y = s*t1.y + t2.y; + this.z = s*t1.z + t2.z; + this.w = s*t1.w + t2.w; + } + + + /** + * Sets the value of this tuple to the scalar multiplication + * of itself and then adds tuple t1 (this = s*this + t1). + * @param s the scalar value + * @param t1 the tuple to be added + */ + public final void scaleAdd(int s, Tuple4i t1) { + this.x = s*this.x + t1.x; + this.y = s*this.y + t1.y; + this.z = s*this.z + t1.z; + this.w = s*this.w + t1.w; + } + + + /** + * Returns a string that contains the values of this Tuple4i. + * The form is (x,y,z,w). + * @return the String representation + */ + @Override + public String toString() { + return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")"; + } + + + /** + * Returns true if the Object t1 is of type Tuple4i and all of the + * data members of t1 are equal to the corresponding data members in + * this Tuple4i. + * @param t1 the object with which the comparison is made + * @return true or false + */ + @Override + public boolean equals(Object t1) { + try { + Tuple4i t2 = (Tuple4i) t1; + return(this.x == t2.x && this.y == t2.y && + this.z == t2.z && this.w == t2.w); + } + catch (NullPointerException e2) { + return false; + } + catch (ClassCastException e1) { + return false; + } + } + + + /** + * Returns a hash code value based on the data values in this + * object. Two different Tuple4i objects with identical data values + * (i.e., Tuple4i.equals returns true) will return the same hash + * code value. Two objects with different data members may return the + * same hash value, although this is not likely. + * @return the integer hash code value + */ + @Override + public int hashCode() { + long bits = 1L; + bits = 31L * bits + (long)x; + bits = 31L * bits + (long)y; + bits = 31L * bits + (long)z; + bits = 31L * bits + (long)w; + return (int) (bits ^ (bits >> 32)); + } + + + /** + * Clamps the tuple parameter to the range [low, high] and + * places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clamp(int min, int max, Tuple4i t) { + if( t.x > max ) { + x = max; + } else if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else if( t.z < min ) { + z = min; + } else { + z = t.z; + } + + if( t.w > max ) { + w = max; + } else if( t.w < min ) { + w = min; + } else { + w = t.w; + } + } + + + /** + * Clamps the minimum value of the tuple parameter to the min + * parameter and places the values into this tuple. + * @param min the lowest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMin(int min, Tuple4i t) { + if( t.x < min ) { + x = min; + } else { + x = t.x; + } + + if( t.y < min ) { + y = min; + } else { + y = t.y; + } + + if( t.z < min ) { + z = min; + } else { + z = t.z; + } + + if( t.w < min ) { + w = min; + } else { + w = t.w; + } + + + } + + + /** + * Clamps the maximum value of the tuple parameter to the max + * parameter and places the values into this tuple. + * @param max the highest value in the tuple after clamping + * @param t the source tuple, which will not be modified + */ + public final void clampMax(int max, Tuple4i t) { + if( t.x > max ) { + x = max; + } else { + x = t.x; + } + + if( t.y > max ) { + y = max; + } else { + y = t.y; + } + + if( t.z > max ) { + z = max; + } else { + z = t.z; + } + + if( t.w > max ) { + w = max; + } else { + w = t.z; + } + } + + + /** + * Sets each component of the tuple parameter to its absolute + * value and places the modified values into this tuple. + * @param t the source tuple, which will not be modified + */ + public final void absolute(Tuple4i t) { + x = Math.abs(t.x); + y = Math.abs(t.y); + z = Math.abs(t.z); + w = Math.abs(t.w); + } + + + /** + * Clamps this tuple to the range [low, high]. + * @param min the lowest value in this tuple after clamping + * @param max the highest value in this tuple after clamping + */ + public final void clamp(int min, int max) { + if( x > max ) { + x = max; + } else if( x < min ) { + x = min; + } + + if( y > max ) { + y = max; + } else if( y < min ) { + y = min; + } + + if( z > max ) { + z = max; + } else if( z < min ) { + z = min; + } + + if( w > max ) { + w = max; + } else if( w < min ) { + w = min; + } + } + + + /** + * Clamps the minimum value of this tuple to the min parameter. + * @param min the lowest value in this tuple after clamping + */ + public final void clampMin(int min) { + if (x < min) + x=min; + + if (y < min) + y = min; + + if (z < min) + z = min; + + if (w < min) + w = min; + } + + + /** + * Clamps the maximum value of this tuple to the max parameter. + * @param max the highest value in the tuple after clamping + */ + public final void clampMax(int max) { + if (x > max) + x = max; + + if (y > max) + y = max; + + if (z > max) + z = max; + + if (w > max) + w = max; + } + + + /** + * Sets each component of this tuple to its absolute value. + */ + public final void absolute() { + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + w = Math.abs(w); + } + + /** + * Creates a new object of the same class as this object. + * + * @return a clone of this instance. + * @exception OutOfMemoryError if there is not enough memory. + * @see java.lang.Cloneable + * @since vecmath 1.3 + */ + @Override + public Object clone() { + // Since there are no arrays we can just use Object.clone() + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + + + /** + * Get the <i>x</i> coordinate. + * + * @return the <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final int getX() { + return x; + } + + + /** + * Set the <i>x</i> coordinate. + * + * @param x value to <i>x</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setX(int x) { + this.x = x; + } + + + /** + * Get the <i>y</i> coordinate. + * + * @return the <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final int getY() { + return y; + } + + + /** + * Set the <i>y</i> coordinate. + * + * @param y value to <i>y</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setY(int y) { + this.y = y; + } + + /** + * Get the <i>z</i> coordinate. + * + * @return the <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final int getZ() { + return z; + } + + + /** + * Set the <i>z</i> coordinate. + * + * @param z value to <i>z</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setZ(int z) { + this.z = z; + } + + + /** + * Get the <i>w</i> coordinate. + * @return the <i>w</i> coordinate. + * @since vecmath 1.5 + */ + public final int getW() { + return w; + } + + + /** + * Set the <i>w</i> coordinate. + * + * @param w value to <i>w</i> coordinate. + * + * @since vecmath 1.5 + */ + public final void setW(int w) { + this.w = w; + } + +} diff --git a/src/org/jogamp/vecmath/VecMathI18N.java b/src/org/jogamp/vecmath/VecMathI18N.java new file mode 100644 index 0000000..48f0ce4 --- /dev/null +++ b/src/org/jogamp/vecmath/VecMathI18N.java @@ -0,0 +1,45 @@ +/* + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + + +class VecMathI18N { + static String getString(String key) { + String s; + try { + s = (String) ResourceBundle.getBundle("org.jogamp.vecmath.ExceptionStrings").getString(key); + } + catch (MissingResourceException e) { + System.err.println("VecMathI18N: Error looking up: " + key); + s = key; + } + return s; + } +} diff --git a/src/org/jogamp/vecmath/VecMathUtil.java b/src/org/jogamp/vecmath/VecMathUtil.java new file mode 100644 index 0000000..49b125a --- /dev/null +++ b/src/org/jogamp/vecmath/VecMathUtil.java @@ -0,0 +1,68 @@ +/* + * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + +/** + * Utility vecmath class used when computing the hash code for vecmath + * objects containing float or double values. This fixes Issue 36. + */ +class VecMathUtil { +/** + * Do not construct an instance of this class. + */ +private VecMathUtil() {} + + static final long hashLongBits(long hash, long l) { + hash *= 31L; + return hash + l; + } + + static final long hashFloatBits(long hash, float f) { + hash *= 31L; + // Treat 0.0d and -0.0d the same (all zero bits) + if (f == 0.0f) + return hash; + + return hash + Float.floatToIntBits(f); + } + + static final long hashDoubleBits(long hash, double d) { + hash *= 31L; + // Treat 0.0d and -0.0d the same (all zero bits) + if (d == 0.0d) + return hash; + + return hash + Double.doubleToLongBits(d); + } + + /** + * Return an integer hash from a long by mixing it with itself. + */ + static final int hashFinish(long hash) { + return (int)(hash ^ (hash >> 32)); + } +} diff --git a/src/org/jogamp/vecmath/Vector2d.java b/src/org/jogamp/vecmath/Vector2d.java new file mode 100644 index 0000000..86230be --- /dev/null +++ b/src/org/jogamp/vecmath/Vector2d.java @@ -0,0 +1,181 @@ +/* + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 2-element vector that is represented by double-precision floating + * point x,y coordinates. + * + */ +public class Vector2d extends Tuple2d implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = 8572646365302599857L; + + /** + * Constructs and initializes a Vector2d from the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Vector2d(double x, double y) + { + super(x,y); + } + + + /** + * Constructs and initializes a Vector2d from the specified array. + * @param v the array of length 2 containing xy in order + */ + public Vector2d(double[] v) + { + super(v); + } + + + /** + * Constructs and initializes a Vector2d from the specified Vector2d. + * @param v1 the Vector2d containing the initialization x y data + */ + public Vector2d(Vector2d v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector2d from the specified Vector2f. + * @param v1 the Vector2f containing the initialization x y data + */ + public Vector2d(Vector2f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector2d from the specified Tuple2d. + * @param t1 the Tuple2d containing the initialization x y data + */ + public Vector2d(Tuple2d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector2d from the specified Tuple2f. + * @param t1 the Tuple2f containing the initialization x y data + */ + public Vector2d(Tuple2f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector2d to (0,0). + */ + public Vector2d() + { + super(); + } + + + /** + * Computes the dot product of the this vector and vector v1. + * @param v1 the other vector + */ + public final double dot(Vector2d v1) + { + return (this.x*v1.x + this.y*v1.y); + } + + + /** + * Returns the length of this vector. + * @return the length of this vector + */ + public final double length() + { + return (double) Math.sqrt(this.x*this.x + this.y*this.y); + } + + /** + * Returns the squared length of this vector. + * @return the squared length of this vector + */ + public final double lengthSquared() + { + return (this.x*this.x + this.y*this.y); + } + + /** + * Sets the value of this vector to the normalization of vector v1. + * @param v1 the un-normalized vector + */ + public final void normalize(Vector2d v1) + { + double norm; + + norm = (double) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y)); + this.x = v1.x*norm; + this.y = v1.y*norm; + } + + /** + * Normalizes this vector in place. + */ + public final void normalize() + { + double norm; + + norm = (double) + (1.0/Math.sqrt(this.x*this.x + this.y*this.y)); + this.x *= norm; + this.y *= norm; + } + + + /** + * Returns the angle in radians between this vector and the vector + * parameter; the return value is constrained to the range [0,PI]. + * @param v1 the other vector + * @return the angle in radians in the range [0,PI] + */ + public final double angle(Vector2d v1) + { + double vDot = this.dot(v1) / ( this.length()*v1.length() ); + if( vDot < -1.0) vDot = -1.0; + if( vDot > 1.0) vDot = 1.0; + return((double) (Math.acos( vDot ))); + + } + + +} diff --git a/src/org/jogamp/vecmath/Vector2f.java b/src/org/jogamp/vecmath/Vector2f.java new file mode 100644 index 0000000..d01ad92 --- /dev/null +++ b/src/org/jogamp/vecmath/Vector2f.java @@ -0,0 +1,181 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 2-element vector that is represented by single-precision floating + * point x,y coordinates. + * + */ +public class Vector2f extends Tuple2f implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = -2168194326883512320L; + + /** + * Constructs and initializes a Vector2f from the specified xy coordinates. + * @param x the x coordinate + * @param y the y coordinate + */ + public Vector2f(float x, float y) + { + super(x,y); + } + + + /** + * Constructs and initializes a Vector2f from the specified array. + * @param v the array of length 2 containing xy in order + */ + public Vector2f(float[] v) + { + super(v); + } + + + /** + * Constructs and initializes a Vector2f from the specified Vector2f. + * @param v1 the Vector2f containing the initialization x y data + */ + public Vector2f(Vector2f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector2f from the specified Vector2d. + * @param v1 the Vector2d containing the initialization x y data + */ + public Vector2f(Vector2d v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector2f from the specified Tuple2f. + * @param t1 the Tuple2f containing the initialization x y data + */ + public Vector2f(Tuple2f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector2f from the specified Tuple2d. + * @param t1 the Tuple2d containing the initialization x y data + */ + public Vector2f(Tuple2d t1) + { + super(t1); + } + + + + /** + * Constructs and initializes a Vector2f to (0,0). + */ + public Vector2f() + { + super(); + } + + + /** + * Computes the dot product of the this vector and vector v1. + * @param v1 the other vector + */ + public final float dot(Vector2f v1) + { + return (this.x*v1.x + this.y*v1.y); + } + + + /** + * Returns the length of this vector. + * @return the length of this vector + */ + public final float length() + { + return (float) Math.sqrt(this.x*this.x + this.y*this.y); + } + + /** + * Returns the squared length of this vector. + * @return the squared length of this vector + */ + public final float lengthSquared() + { + return (this.x*this.x + this.y*this.y); + } + + /** + * Sets the value of this vector to the normalization of vector v1. + * @param v1 the un-normalized vector + */ + public final void normalize(Vector2f v1) + { + float norm; + + norm = (float) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y)); + this.x = v1.x*norm; + this.y = v1.y*norm; + } + + /** + * Normalizes this vector in place. + */ + public final void normalize() + { + float norm; + + norm = (float) + (1.0/Math.sqrt(this.x*this.x + this.y*this.y)); + this.x *= norm; + this.y *= norm; + } + + + /** + * Returns the angle in radians between this vector and the vector + * parameter; the return value is constrained to the range [0,PI]. + * @param v1 the other vector + * @return the angle in radians in the range [0,PI] + */ + public final float angle(Vector2f v1) + { + double vDot = this.dot(v1) / ( this.length()*v1.length() ); + if( vDot < -1.0) vDot = -1.0; + if( vDot > 1.0) vDot = 1.0; + return((float) (Math.acos( vDot ))); + } + + +} diff --git a/src/org/jogamp/vecmath/Vector3d.java b/src/org/jogamp/vecmath/Vector3d.java new file mode 100644 index 0000000..75918fd --- /dev/null +++ b/src/org/jogamp/vecmath/Vector3d.java @@ -0,0 +1,204 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 3-element vector that is represented by double-precision floating point + * x,y,z coordinates. If this value represents a normal, then it should + * be normalized. + * + */ +public class Vector3d extends Tuple3d implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = 3761969948420550442L; + + /** + * Constructs and initializes a Vector3d from the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Vector3d(double x, double y, double z) + { + super(x,y,z); + } + + + /** + * Constructs and initializes a Vector3d from the array of length 3. + * @param v the array of length 3 containing xyz in order + */ + public Vector3d(double[] v) + { + super(v); + } + + + /** + * Constructs and initializes a Vector3d from the specified Vector3d. + * @param v1 the Vector3d containing the initialization x y z data + */ + public Vector3d(Vector3d v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector3d from the specified Vector3f. + * @param v1 the Vector3f containing the initialization x y z data + */ + public Vector3d(Vector3f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector3d from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public Vector3d(Tuple3f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector3d from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public Vector3d(Tuple3d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector3d to (0,0,0). + */ + public Vector3d() + { + super(); + } + + + /** + * Sets this vector to the vector cross product of vectors v1 and v2. + * @param v1 the first vector + * @param v2 the second vector + */ + public final void cross(Vector3d v1, Vector3d v2) + { + double x,y; + + x = v1.y*v2.z - v1.z*v2.y; + y = v2.x*v1.z - v2.z*v1.x; + this.z = v1.x*v2.y - v1.y*v2.x; + this.x = x; + this.y = y; + } + + + /** + * Sets the value of this vector to the normalization of vector v1. + * @param v1 the un-normalized vector + */ + public final void normalize(Vector3d v1) + { + double norm; + + norm = 1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z); + this.x = v1.x*norm; + this.y = v1.y*norm; + this.z = v1.z*norm; + } + + + /** + * Normalizes this vector in place. + */ + public final void normalize() + { + double norm; + + norm = 1.0/Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); + this.x *= norm; + this.y *= norm; + this.z *= norm; + } + + + /** + * Returns the dot product of this vector and vector v1. + * @param v1 the other vector + * @return the dot product of this and v1 + */ + public final double dot(Vector3d v1) + { + return (this.x*v1.x + this.y*v1.y + this.z*v1.z); + } + + + /** + * Returns the squared length of this vector. + * @return the squared length of this vector + */ + public final double lengthSquared() + { + return (this.x*this.x + this.y*this.y + this.z*this.z); + } + + + /** + * Returns the length of this vector. + * @return the length of this vector + */ + public final double length() + { + return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); + } + + + /** + * Returns the angle in radians between this vector and the vector + * parameter; the return value is constrained to the range [0,PI]. + * @param v1 the other vector + * @return the angle in radians in the range [0,PI] + */ + public final double angle(Vector3d v1) + { + double vDot = this.dot(v1) / ( this.length()*v1.length() ); + if( vDot < -1.0) vDot = -1.0; + if( vDot > 1.0) vDot = 1.0; + return((double) (Math.acos( vDot ))); + } + + +} diff --git a/src/org/jogamp/vecmath/Vector3f.java b/src/org/jogamp/vecmath/Vector3f.java new file mode 100644 index 0000000..3f88ab7 --- /dev/null +++ b/src/org/jogamp/vecmath/Vector3f.java @@ -0,0 +1,199 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 3-element vector that is represented by single-precision floating point + * x,y,z coordinates. If this value represents a normal, then it should + * be normalized. + * + */ +public class Vector3f extends Tuple3f implements java.io.Serializable { + + // Combatible with 1.1 + static final long serialVersionUID = -7031930069184524614L; + + /** + * Constructs and initializes a Vector3f from the specified xyz coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + */ + public Vector3f(float x, float y, float z) + { + super(x,y,z); + } + + + /** + * Constructs and initializes a Vector3f from the array of length 3. + * @param v the array of length 3 containing xyz in order + */ + public Vector3f(float[] v) + { + super(v); + } + + + /** + * Constructs and initializes a Vector3f from the specified Vector3f. + * @param v1 the Vector3f containing the initialization x y z data + */ + public Vector3f(Vector3f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector3f from the specified Vector3d. + * @param v1 the Vector3d containing the initialization x y z data + */ + public Vector3f(Vector3d v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector3f from the specified Tuple3f. + * @param t1 the Tuple3f containing the initialization x y z data + */ + public Vector3f(Tuple3f t1) { + super(t1); + } + + + /** + * Constructs and initializes a Vector3f from the specified Tuple3d. + * @param t1 the Tuple3d containing the initialization x y z data + */ + public Vector3f(Tuple3d t1) { + super(t1); + } + + + /** + * Constructs and initializes a Vector3f to (0,0,0). + */ + public Vector3f() + { + super(); + } + + + /** + * Returns the squared length of this vector. + * @return the squared length of this vector + */ + public final float lengthSquared() + { + return (this.x*this.x + this.y*this.y + this.z*this.z); + } + + /** + * Returns the length of this vector. + * @return the length of this vector + */ + public final float length() + { + return (float) + Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); + } + + + /** + * Sets this vector to be the vector cross product of vectors v1 and v2. + * @param v1 the first vector + * @param v2 the second vector + */ + public final void cross(Vector3f v1, Vector3f v2) + { + float x,y; + + x = v1.y*v2.z - v1.z*v2.y; + y = v2.x*v1.z - v2.z*v1.x; + this.z = v1.x*v2.y - v1.y*v2.x; + this.x = x; + this.y = y; + } + + /** + * Computes the dot product of this vector and vector v1. + * @param v1 the other vector + * @return the dot product of this vector and v1 + */ + public final float dot(Vector3f v1) + { + return (this.x*v1.x + this.y*v1.y + this.z*v1.z); + } + + /** + * Sets the value of this vector to the normalization of vector v1. + * @param v1 the un-normalized vector + */ + public final void normalize(Vector3f v1) + { + float norm; + + norm = (float) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z)); + this.x = v1.x*norm; + this.y = v1.y*norm; + this.z = v1.z*norm; + } + + /** + * Normalizes this vector in place. + */ + public final void normalize() + { + float norm; + + norm = (float) + (1.0/Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z)); + this.x *= norm; + this.y *= norm; + this.z *= norm; + } + + + /** + * Returns the angle in radians between this vector and the vector + * parameter; the return value is constrained to the range [0,PI]. + * @param v1 the other vector + * @return the angle in radians in the range [0,PI] + */ + public final float angle(Vector3f v1) + { + double vDot = this.dot(v1) / ( this.length()*v1.length() ); + if( vDot < -1.0) vDot = -1.0; + if( vDot > 1.0) vDot = 1.0; + return((float) (Math.acos( vDot ))); + } + +} diff --git a/src/org/jogamp/vecmath/Vector4d.java b/src/org/jogamp/vecmath/Vector4d.java new file mode 100644 index 0000000..b5a847c --- /dev/null +++ b/src/org/jogamp/vecmath/Vector4d.java @@ -0,0 +1,218 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4-element vector represented by double-precision floating point + * x,y,z,w coordinates. + * + */ +public class Vector4d extends Tuple4d implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = 3938123424117448700L; + + /** + * Constructs and initializes a Vector4d from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Vector4d(double x, double y, double z, double w) + { + super(x,y,z,w); + } + + /** + * Constructs and initializes a Vector4d from the coordinates contained + * in the array. + * @param v the array of length 4 containing xyzw in order + */ + public Vector4d(double[] v) + { + super(v); + } + + /** + * Constructs and initializes a Vector4d from the specified Vector4d. + * @param v1 the Vector4d containing the initialization x y z w data + */ + public Vector4d(Vector4d v1) + { + super(v1); + } + + /** + * Constructs and initializes a Vector4d from the specified Vector4f. + * @param v1 the Vector4f containing the initialization x y z w data + */ + public Vector4d(Vector4f v1) + { + super(v1); + } + + /** + * Constructs and initializes a Vector4d from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Vector4d(Tuple4f t1) + { + super(t1); + } + + /** + * Constructs and initializes a Vector4d from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Vector4d(Tuple4d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector4d from the specified Tuple3d. + * The x,y,z components of this vector are set to the corresponding + * components of tuple t1. The w component of this vector + * is set to 0. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public Vector4d(Tuple3d t1) { + super(t1.x, t1.y, t1.z, 0.0); + } + + + /** + * Constructs and initializes a Vector4d to (0,0,0,0). + */ + public Vector4d() + { + super(); + } + + + /** + * Sets the x,y,z components of this vector to the corresponding + * components of tuple t1. The w component of this vector + * is set to 0. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public final void set(Tuple3d t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = 0.0; + } + + + /** + * Returns the length of this vector. + * @return the length of this vector + */ + public final double length() + { + return Math.sqrt(this.x*this.x + this.y*this.y + + this.z*this.z + this.w*this.w); + } + + + /** + * Returns the squared length of this vector. + * @return the squared length of this vector + */ + public final double lengthSquared() + { + return (this.x*this.x + this.y*this.y + + this.z*this.z + this.w*this.w); + } + + + /** + * Returns the dot product of this vector and vector v1. + * @param v1 the other vector + * @return the dot product of this vector and vector v1 + */ + public final double dot(Vector4d v1) + { + return (this.x*v1.x + this.y*v1.y + this.z*v1.z + this.w*v1.w); + } + + + /** + * Sets the value of this vector to the normalization of vector v1. + * @param v1 the un-normalized vector + */ + public final void normalize(Vector4d v1) + { + double norm; + + norm = 1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z + v1.w*v1.w); + this.x = v1.x*norm; + this.y = v1.y*norm; + this.z = v1.z*norm; + this.w = v1.w*norm; + } + + + /** + * Normalizes this vector in place. + */ + public final void normalize() + { + double norm; + + norm = 1.0/Math.sqrt(this.x*this.x + this.y*this.y + + this.z*this.z + this.w*this.w); + this.x *= norm; + this.y *= norm; + this.z *= norm; + this.w *= norm; + } + + + /** + * Returns the (4-space) angle in radians between this vector and + * the vector parameter; the return value is constrained to the + * range [0,PI]. + * @param v1 the other vector + * @return the angle in radians in the range [0,PI] + */ + public final double angle(Vector4d v1) + { + double vDot = this.dot(v1) / ( this.length()*v1.length() ); + if( vDot < -1.0) vDot = -1.0; + if( vDot > 1.0) vDot = 1.0; + return((double) (Math.acos( vDot ))); + } + +} diff --git a/src/org/jogamp/vecmath/Vector4f.java b/src/org/jogamp/vecmath/Vector4f.java new file mode 100644 index 0000000..680c210 --- /dev/null +++ b/src/org/jogamp/vecmath/Vector4f.java @@ -0,0 +1,222 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package org.jogamp.vecmath; + + +/** + * A 4-element vector represented by single-precision floating point x,y,z,w + * coordinates. + * + */ +public class Vector4f extends Tuple4f implements java.io.Serializable { + + // Compatible with 1.1 + static final long serialVersionUID = 8749319902347760659L; + + /** + * Constructs and initializes a Vector4f from the specified xyzw coordinates. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param w the w coordinate + */ + public Vector4f(float x, float y, float z, float w) + { + super(x,y,z,w); + } + + + /** + * Constructs and initializes a Vector4f from the array of length 4. + * @param v the array of length 4 containing xyzw in order + */ + public Vector4f(float[] v) + { + super(v); + } + + + /** + * Constructs and initializes a Vector4f from the specified Vector4f. + * @param v1 the Vector4f containing the initialization x y z w data + */ + public Vector4f(Vector4f v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector4f from the specified Vector4d. + * @param v1 the Vector4d containing the initialization x y z w data + */ + public Vector4f(Vector4d v1) + { + super(v1); + } + + + /** + * Constructs and initializes a Vector4f from the specified Tuple4f. + * @param t1 the Tuple4f containing the initialization x y z w data + */ + public Vector4f(Tuple4f t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector4f from the specified Tuple4d. + * @param t1 the Tuple4d containing the initialization x y z w data + */ + public Vector4f(Tuple4d t1) + { + super(t1); + } + + + /** + * Constructs and initializes a Vector4f from the specified Tuple3f. + * The x,y,z components of this vector are set to the corresponding + * components of tuple t1. The w component of this vector + * is set to 0. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public Vector4f(Tuple3f t1) { + super(t1.x, t1.y, t1.z, 0.0f); + } + + + /** + * Constructs and initializes a Vector4f to (0,0,0,0). + */ + public Vector4f() + { + super(); + } + + + /** + * Sets the x,y,z components of this vector to the corresponding + * components of tuple t1. The w component of this vector + * is set to 0. + * @param t1 the tuple to be copied + * + * @since vecmath 1.2 + */ + public final void set(Tuple3f t1) { + this.x = t1.x; + this.y = t1.y; + this.z = t1.z; + this.w = 0.0f; + } + + + /** + * Returns the length of this vector. + * @return the length of this vector as a float + */ + public final float length() + { + return + (float) Math.sqrt(this.x*this.x + this.y*this.y + + this.z*this.z + this.w*this.w); + } + + /** + * Returns the squared length of this vector + * @return the squared length of this vector as a float + */ + public final float lengthSquared() + { + return (this.x*this.x + this.y*this.y + + this.z*this.z + this.w*this.w); + } + + /** + * returns the dot product of this vector and v1 + * @param v1 the other vector + * @return the dot product of this vector and v1 + */ + public final float dot(Vector4f v1) + { + return (this.x*v1.x + this.y*v1.y + this.z*v1.z + this.w*v1.w); + } + + + /** + * Sets the value of this vector to the normalization of vector v1. + * @param v1 the un-normalized vector + */ + public final void normalize(Vector4f v1) + { + float norm; + + norm = (float) (1.0/Math.sqrt(v1.x*v1.x + v1.y*v1.y + + v1.z*v1.z + v1.w*v1.w)); + this.x = v1.x*norm; + this.y = v1.y*norm; + this.z = v1.z*norm; + this.w = v1.w*norm; + } + + + /** + * Normalizes this vector in place. + */ + public final void normalize() + { + float norm; + + norm = (float) (1.0/Math.sqrt(this.x*this.x + this.y*this.y + + this.z*this.z + this.w*this.w)); + this.x *= norm; + this.y *= norm; + this.z *= norm; + this.w *= norm; + } + + + /** + * Returns the (4-space) angle in radians between this vector and + * the vector parameter; the return value is constrained to the + * range [0,PI]. + * @param v1 the other vector + * @return the angle in radians in the range [0,PI] + */ + public final float angle(Vector4f v1) + { + double vDot = this.dot(v1) / ( this.length()*v1.length() ); + if( vDot < -1.0) vDot = -1.0; + if( vDot > 1.0) vDot = 1.0; + return((float) (Math.acos( vDot ))); + } + +} diff --git a/src/org/jogamp/vecmath/package-info.java b/src/org/jogamp/vecmath/package-info.java new file mode 100644 index 0000000..a54d21e --- /dev/null +++ b/src/org/jogamp/vecmath/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides 3D vector mathematics classes. + */ +package org.jogamp.vecmath; |