From 2179980ed660ef66a9c064d153c5de7994d431ab Mon Sep 17 00:00:00 2001 From: Kenneth Russel Date: Wed, 25 Jun 2003 09:05:29 +0000 Subject: Split up net.java.games.util; moved GLUT and BufferUtils into net.java.games.jogl.util, and moved demo-specific utility classes into jogl-demos project under demos.util. Added nearly all JavaOne demos into jogl-demos project; rewrote where necessary to use ClassLoader.getResourceAsStream() instead of flat files, put into packages and added to Makefile. Added gleem to jogl-demos project. Added jogl.jar build rule. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@3 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4 --- src/gleem/linalg/DimensionMismatchException.java | 53 ++++ src/gleem/linalg/IntersectionPoint.java | 63 +++++ src/gleem/linalg/Line.java | 152 +++++++++++ src/gleem/linalg/Mat2f.java | 169 +++++++++++++ src/gleem/linalg/Mat3f.java | 194 ++++++++++++++ src/gleem/linalg/Mat4f.java | 265 +++++++++++++++++++ src/gleem/linalg/Matf.java | 168 ++++++++++++ src/gleem/linalg/MathUtil.java | 90 +++++++ src/gleem/linalg/NonSquareMatrixException.java | 53 ++++ src/gleem/linalg/Plane.java | 121 +++++++++ src/gleem/linalg/PlaneUV.java | 203 +++++++++++++++ src/gleem/linalg/Rotf.java | 309 +++++++++++++++++++++++ src/gleem/linalg/SingularMatrixException.java | 53 ++++ src/gleem/linalg/Vec2f.java | 182 +++++++++++++ src/gleem/linalg/Vec3d.java | 175 +++++++++++++ src/gleem/linalg/Vec3f.java | 232 +++++++++++++++++ src/gleem/linalg/Vec4f.java | 216 ++++++++++++++++ src/gleem/linalg/Vecf.java | 96 +++++++ src/gleem/linalg/Veci.java | 96 +++++++ src/gleem/linalg/package.html | 13 + 20 files changed, 2903 insertions(+) create mode 100644 src/gleem/linalg/DimensionMismatchException.java create mode 100644 src/gleem/linalg/IntersectionPoint.java create mode 100644 src/gleem/linalg/Line.java create mode 100644 src/gleem/linalg/Mat2f.java create mode 100644 src/gleem/linalg/Mat3f.java create mode 100644 src/gleem/linalg/Mat4f.java create mode 100644 src/gleem/linalg/Matf.java create mode 100644 src/gleem/linalg/MathUtil.java create mode 100644 src/gleem/linalg/NonSquareMatrixException.java create mode 100644 src/gleem/linalg/Plane.java create mode 100644 src/gleem/linalg/PlaneUV.java create mode 100644 src/gleem/linalg/Rotf.java create mode 100644 src/gleem/linalg/SingularMatrixException.java create mode 100644 src/gleem/linalg/Vec2f.java create mode 100644 src/gleem/linalg/Vec3d.java create mode 100644 src/gleem/linalg/Vec3f.java create mode 100644 src/gleem/linalg/Vec4f.java create mode 100644 src/gleem/linalg/Vecf.java create mode 100644 src/gleem/linalg/Veci.java create mode 100644 src/gleem/linalg/package.html (limited to 'src/gleem/linalg') diff --git a/src/gleem/linalg/DimensionMismatchException.java b/src/gleem/linalg/DimensionMismatchException.java new file mode 100644 index 0000000..612d49d --- /dev/null +++ b/src/gleem/linalg/DimensionMismatchException.java @@ -0,0 +1,53 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Thrown to indicate a mismatch of dimensionality of a matrix or + vector. */ + +public class DimensionMismatchException extends RuntimeException { + public DimensionMismatchException() { + super(); + } + + public DimensionMismatchException(String msg) { + super(msg); + } +} diff --git a/src/gleem/linalg/IntersectionPoint.java b/src/gleem/linalg/IntersectionPoint.java new file mode 100644 index 0000000..486be06 --- /dev/null +++ b/src/gleem/linalg/IntersectionPoint.java @@ -0,0 +1,63 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Wraps a 3D point and parametric time value. */ + +public class IntersectionPoint { + private Vec3f intPt = new Vec3f(); + private float t; + + public Vec3f getIntersectionPoint() { + return intPt; + } + + public void setIntersectionPoint(Vec3f newPt) { + intPt.set(newPt); + } + + public float getT() { + return t; + } + + public void setT(float t) { + this.t = t; + } +} diff --git a/src/gleem/linalg/Line.java b/src/gleem/linalg/Line.java new file mode 100644 index 0000000..cbf8efd --- /dev/null +++ b/src/gleem/linalg/Line.java @@ -0,0 +1,152 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Represents a line in 3D space. */ + +public class Line { + private Vec3f point; + /** Normalized */ + private Vec3f direction; + /** For computing projections along line */ + private Vec3f alongVec; + + /** Default constructor initializes line to point (0, 0, 0) and + direction (1, 0, 0) */ + public Line() { + point = new Vec3f(0, 0, 0); + direction = new Vec3f(1, 0, 0); + alongVec = new Vec3f(); + recalc(); + } + + /** Line goes in direction direction through the point + point. direction does not need to be normalized but must + not be the zero vector. */ + public Line(Vec3f direction, Vec3f point) { + direction = new Vec3f(direction); + direction.normalize(); + point = new Vec3f(point); + alongVec = new Vec3f(); + recalc(); + } + + /** Setter does some work to maintain internal caches. + direction does not need to be normalized but must not be + the zero vector. */ + public void setDirection(Vec3f direction) { + this.direction.set(direction); + this.direction.normalize(); + recalc(); + } + + /** Direction is normalized internally, so direction is not + necessarily equal to plane.setDirection(direction); + plane.getDirection(); */ + public Vec3f getDirection() { + return direction; + } + + /** Setter does some work to maintain internal caches. */ + public void setPoint(Vec3f point) { + this.point.set(point); + recalc(); + } + + public Vec3f getPoint() { + return point; + } + + /** Project a point onto the line */ + public void projectPoint(Vec3f pt, + Vec3f projPt) { + float dotp = direction.dot(pt); + projPt.set(direction); + projPt.scale(dotp); + projPt.add(alongVec); + } + + /** Find closest point on this line to the given ray, specified by + start point and direction. If ray is parallel to this line, + returns false and closestPoint is not modified. */ + public boolean closestPointToRay(Vec3f rayStart, + Vec3f rayDirection, + Vec3f closestPoint) { + // Line 1 is this one. Line 2 is the incoming one. + Mat2f A = new Mat2f(); + A.set(0, 0, -direction.lengthSquared()); + A.set(1, 1, -rayDirection.lengthSquared()); + A.set(0, 1, direction.dot(rayDirection)); + A.set(1, 0, A.get(0, 1)); + if (Math.abs(A.determinant()) == 0.0f) { + return false; + } + if (!A.invert()) { + return false; + } + Vec2f b = new Vec2f(); + b.setX(point.dot(direction) - rayStart.dot(direction)); + b.setY(rayStart.dot(rayDirection) - point.dot(rayDirection)); + Vec2f x = new Vec2f(); + A.xformVec(b, x); + if (x.y() < 0) { + // Means that ray start is closest point to this line + closestPoint.set(rayStart); + } else { + closestPoint.set(direction); + closestPoint.scale(x.x()); + closestPoint.add(point); + } + return true; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void recalc() { + float denom = direction.lengthSquared(); + if (denom == 0.0f) { + throw new RuntimeException("Line.recalc: ERROR: direction was the zero vector " + + "(not allowed)"); + } + alongVec.set(point.minus(direction.times(point.dot(direction)))); + } +} diff --git a/src/gleem/linalg/Mat2f.java b/src/gleem/linalg/Mat2f.java new file mode 100644 index 0000000..6852dbc --- /dev/null +++ b/src/gleem/linalg/Mat2f.java @@ -0,0 +1,169 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** 2x2 matrix class useful for simple linear algebra. Representation + is (as Mat4f) in row major order and assumes multiplication by + column vectors on the right. */ + +public class Mat2f { + private float[] data; + + /** Creates new matrix initialized to the zero matrix */ + public Mat2f() { + data = new float[4]; + } + + /** Initialize to the identity matrix. */ + public void makeIdent() { + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + if (i == j) { + set(i, j, 1.0f); + } else { + set(i, j, 0.0f); + } + } + } + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[2 * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[2 * i + j] = val; + } + + /** Set column i (i=[0..1]) to vector v. */ + public void setCol(int i, Vec2f v) { + set(0, i, v.x()); + set(1, i, v.y()); + } + + /** Set row i (i=[0..1]) to vector v. */ + public void setRow(int i, Vec2f v) { + set(i, 0, v.x()); + set(i, 1, v.y()); + } + + /** Transpose this matrix in place. */ + public void transpose() { + float t = get(0, 1); + set(0, 1, get(1, 0)); + set(1, 0, t); + } + + /** Return the determinant. */ + public float determinant() { + return (get(0, 0) * get(1, 1) - get(1, 0) * get(0, 1)); + } + + /** Full matrix inversion in place. If matrix is singular, returns + false and matrix contents are untouched. If you know the matrix + is orthonormal, you can call transpose() instead. */ + public boolean invert() { + float det = determinant(); + if (det == 0.0f) + return false; + + // Create transpose of cofactor matrix in place + float t = get(0, 0); + set(0, 0, get(1, 1)); + set(1, 1, t); + set(0, 1, -get(0, 1)); + set(1, 0, -get(1, 0)); + + // Now divide by determinant + for (int i = 0; i < 4; i++) { + data[i] /= det; + } + return true; + } + + /** Multiply a 2D vector by this matrix. NOTE: src and dest must be + different vectors. */ + public void xformVec(Vec2f src, Vec2f dest) { + dest.set(get(0, 0) * src.x() + + get(0, 1) * src.y(), + + get(1, 0) * src.x() + + get(1, 1) * src.y()); + } + + /** Returns this * b; creates new matrix */ + public Mat2f mul(Mat2f b) { + Mat2f tmp = new Mat2f(); + tmp.mul(this, b); + return tmp; + } + + /** this = a * b */ + public void mul(Mat2f a, Mat2f b) { + for (int rc = 0; rc < 2; rc++) + for (int cc = 0; cc < 2; cc++) { + float tmp = 0.0f; + for (int i = 0; i < 2; i++) + tmp += a.get(rc, i) * b.get(i, cc); + set(rc, cc, tmp); + } + } + + public Matf toMatf() { + Matf out = new Matf(2, 2); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + out.set(i, j, get(i, j)); + } + } + return out; + } + + public String toString() { + String endl = System.getProperty("line.separator"); + return "(" + + get(0, 0) + ", " + get(0, 1) + endl + + get(1, 0) + ", " + get(1, 1) + ")"; + } +} diff --git a/src/gleem/linalg/Mat3f.java b/src/gleem/linalg/Mat3f.java new file mode 100644 index 0000000..024df82 --- /dev/null +++ b/src/gleem/linalg/Mat3f.java @@ -0,0 +1,194 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** 3x3 matrix class useful for simple linear algebra. Representation + is (as Mat4f) in row major order and assumes multiplication by + column vectors on the right. */ + +public class Mat3f { + private float[] data; + + /** Creates new matrix initialized to the zero matrix */ + public Mat3f() { + data = new float[9]; + } + + /** Initialize to the identity matrix. */ + public void makeIdent() { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (i == j) { + set(i, j, 1.0f); + } else { + set(i, j, 0.0f); + } + } + } + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[3 * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[3 * i + j] = val; + } + + /** Set column i (i=[0..2]) to vector v. */ + public void setCol(int i, Vec3f v) { + set(0, i, v.x()); + set(1, i, v.y()); + set(2, i, v.z()); + } + + /** Set row i (i=[0..2]) to vector v. */ + public void setRow(int i, Vec3f v) { + set(i, 0, v.x()); + set(i, 1, v.y()); + set(i, 2, v.z()); + } + + /** Transpose this matrix in place. */ + public void transpose() { + float t; + t = get(0, 1); + set(0, 1, get(1, 0)); + set(1, 0, t); + + t = get(0, 2); + set(0, 2, get(2, 0)); + set(2, 0, t); + + t = get(1, 2); + set(1, 2, get(2, 1)); + set(2, 1, t); + } + + /** Return the determinant. Computed across the zeroth row. */ + public float determinant() { + return (get(0, 0) * (get(1, 1) * get(2, 2) - get(2, 1) * get(1, 2)) + + get(0, 1) * (get(2, 0) * get(1, 2) - get(1, 0) * get(2, 2)) + + get(0, 2) * (get(1, 0) * get(2, 1) - get(2, 0) * get(1, 1))); + } + + /** Full matrix inversion in place. If matrix is singular, returns + false and matrix contents are untouched. If you know the matrix + is orthonormal, you can call transpose() instead. */ + public boolean invert() { + float det = determinant(); + if (det == 0.0f) + return false; + + // Form cofactor matrix + Mat3f cf = new Mat3f(); + cf.set(0, 0, get(1, 1) * get(2, 2) - get(2, 1) * get(1, 2)); + cf.set(0, 1, get(2, 0) * get(1, 2) - get(1, 0) * get(2, 2)); + cf.set(0, 2, get(1, 0) * get(2, 1) - get(2, 0) * get(1, 1)); + cf.set(1, 0, get(2, 1) * get(0, 2) - get(0, 1) * get(2, 2)); + cf.set(1, 1, get(0, 0) * get(2, 2) - get(2, 0) * get(0, 2)); + cf.set(1, 2, get(2, 0) * get(0, 1) - get(0, 0) * get(2, 1)); + cf.set(2, 0, get(0, 1) * get(1, 2) - get(1, 1) * get(0, 2)); + cf.set(2, 1, get(1, 0) * get(0, 2) - get(0, 0) * get(1, 2)); + cf.set(2, 2, get(0, 0) * get(1, 1) - get(1, 0) * get(0, 1)); + + // Now copy back transposed + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + set(i, j, cf.get(j, i) / det); + return true; + } + + /** Multiply a 3D vector by this matrix. NOTE: src and dest must be + different vectors. */ + public void xformVec(Vec3f src, Vec3f dest) { + dest.set(get(0, 0) * src.x() + + get(0, 1) * src.y() + + get(0, 2) * src.z(), + + get(1, 0) * src.x() + + get(1, 1) * src.y() + + get(1, 2) * src.z(), + + get(2, 0) * src.x() + + get(2, 1) * src.y() + + get(2, 2) * src.z()); + } + + /** Returns this * b; creates new matrix */ + public Mat3f mul(Mat3f b) { + Mat3f tmp = new Mat3f(); + tmp.mul(this, b); + return tmp; + } + + /** this = a * b */ + public void mul(Mat3f a, Mat3f b) { + for (int rc = 0; rc < 3; rc++) + for (int cc = 0; cc < 3; cc++) { + float tmp = 0.0f; + for (int i = 0; i < 3; i++) + tmp += a.get(rc, i) * b.get(i, cc); + set(rc, cc, tmp); + } + } + + public Matf toMatf() { + Matf out = new Matf(3, 3); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + out.set(i, j, get(i, j)); + } + } + return out; + } + + public String toString() { + String endl = System.getProperty("line.separator"); + return "(" + + get(0, 0) + ", " + get(0, 1) + ", " + get(0, 2) + endl + + get(1, 0) + ", " + get(1, 1) + ", " + get(1, 2) + endl + + get(2, 0) + ", " + get(2, 1) + ", " + get(2, 2) + ")"; + } +} diff --git a/src/gleem/linalg/Mat4f.java b/src/gleem/linalg/Mat4f.java new file mode 100644 index 0000000..ed16cc6 --- /dev/null +++ b/src/gleem/linalg/Mat4f.java @@ -0,0 +1,265 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** A (very incomplete) 4x4 matrix class. Representation assumes + multiplication by column vectors on the right. */ + +public class Mat4f { + private float[] data; + + /** Creates new matrix initialized to the zero matrix */ + public Mat4f() { + data = new float[16]; + } + + /** Creates new matrix initialized to argument's contents */ + public Mat4f(Mat4f arg) { + this(); + set(arg); + } + + /** Sets this matrix to the identity matrix */ + public void makeIdent() { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (i == j) { + set(i, j, 1.0f); + } else { + set(i, j, 0.0f); + } + } + } + } + + /** Sets this matrix to be equivalent to the given one */ + public void set(Mat4f arg) { + float[] mine = data; + float[] yours = arg.data; + for (int i = 0; i < mine.length; i++) { + mine[i] = yours[i]; + } + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[4 * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[4 * i + j] = val; + } + + /** Sets the translation component of this matrix (i.e., the three + top elements of the third column) without touching any of the + other parts of the matrix */ + public void setTranslation(Vec3f trans) { + set(0, 3, trans.x()); + set(1, 3, trans.y()); + set(2, 3, trans.z()); + } + + /** Sets the rotation component of this matrix (i.e., the upper left + 3x3) without touching any of the other parts of the matrix */ + public void setRotation(Rotf rot) { + rot.toMatrix(this); + } + + /** Sets the upper-left 3x3 of this matrix assuming that the given + x, y, and z vectors form an orthonormal basis */ + public void setRotation(Vec3f x, Vec3f y, Vec3f z) { + set(0, 0, x.x()); + set(1, 0, x.y()); + set(2, 0, x.z()); + + set(0, 1, y.x()); + set(1, 1, y.y()); + set(2, 1, y.z()); + + set(0, 2, z.x()); + set(1, 2, z.y()); + set(2, 2, z.z()); + } + + /** Gets the upper left 3x3 of this matrix as a rotation. Currently + does not work if there are scales. Ignores translation + component. */ + public void getRotation(Rotf rot) { + rot.fromMatrix(this); + } + + /** Sets the elements (0, 0), (1, 1), and (2, 2) with the + appropriate elements of the given three-dimensional scale + vector. Does not perform a full multiplication of the upper-left + 3x3; use this with an identity matrix in conjunction with + mul for that. */ + public void setScale(Vec3f scale) { + set(0, 0, scale.x()); + set(1, 1, scale.y()); + set(2, 2, scale.z()); + } + + /** Inverts this matrix assuming that it represents a rigid + transform (i.e., some combination of rotations and + translations). Assumes column vectors. Algorithm: transposes + upper left 3x3; negates translation in rightmost column and + transforms by inverted rotation. */ + public void invertRigid() { + float t; + // Transpose upper left 3x3 + t = get(0, 1); + set(0, 1, get(1, 0)); + set(1, 0, t); + t = get(0, 2); + set(0, 2, get(2, 0)); + set(2, 0, t); + t = get(1, 2); + set(1, 2, get(2, 1)); + set(2, 1, t); + // Transform negative translation by this + Vec3f negTrans = new Vec3f(-get(0, 3), -get(1, 3), -get(2, 3)); + Vec3f trans = new Vec3f(); + xformDir(negTrans, trans); + set(0, 3, trans.x()); + set(1, 3, trans.y()); + set(2, 3, trans.z()); + } + + /** Returns this * b; creates new matrix */ + public Mat4f mul(Mat4f b) { + Mat4f tmp = new Mat4f(); + tmp.mul(this, b); + return tmp; + } + + /** this = a * b */ + public void mul(Mat4f a, Mat4f b) { + for (int rc = 0; rc < 4; rc++) + for (int cc = 0; cc < 4; cc++) { + float tmp = 0.0f; + for (int i = 0; i < 4; i++) + tmp += a.get(rc, i) * b.get(i, cc); + set(rc, cc, tmp); + } + } + + /** Transpose this matrix in place. */ + public void transpose() { + float t; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < i; j++) { + t = get(i, j); + set(i, j, get(j, i)); + set(j, i, t); + } + } + } + + /** Multiply a 4D vector by this matrix. NOTE: src and dest must be + different vectors. */ + public void xformVec(Vec4f src, Vec4f dest) { + for (int rc = 0; rc < 4; rc++) { + float tmp = 0.0f; + for (int cc = 0; cc < 4; cc++) { + tmp += get(rc, cc) * src.get(cc); + } + dest.set(rc, tmp); + } + } + + /** Transforms a 3D vector as though it had a homogeneous coordinate + and assuming that this matrix represents only rigid + transformations; i.e., is not a full transformation. NOTE: src + and dest must be different vectors. */ + public void xformPt(Vec3f src, Vec3f dest) { + for (int rc = 0; rc < 3; rc++) { + float tmp = 0.0f; + for (int cc = 0; cc < 3; cc++) { + tmp += get(rc, cc) * src.get(cc); + } + tmp += get(rc, 3); + dest.set(rc, tmp); + } + } + + /** Transforms src using only the upper left 3x3. NOTE: src and dest + must be different vectors. */ + public void xformDir(Vec3f src, Vec3f dest) { + for (int rc = 0; rc < 3; rc++) { + float tmp = 0.0f; + for (int cc = 0; cc < 3; cc++) { + tmp += get(rc, cc) * src.get(cc); + } + dest.set(rc, tmp); + } + } + + /** Copies data in column-major (OpenGL format) order into passed + float array, which must have length 16 or greater. */ + public void getColumnMajorData(float[] out) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + out[4 * j + i] = get(i, j); + } + } + } + + public Matf toMatf() { + Matf out = new Matf(4, 4); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + out.set(i, j, get(i, j)); + } + } + return out; + } + + public String toString() { + String endl = System.getProperty("line.separator"); + return "(" + + get(0, 0) + ", " + get(0, 1) + ", " + get(0, 2) + ", " + get(0, 3) + endl + + get(1, 0) + ", " + get(1, 1) + ", " + get(1, 2) + ", " + get(1, 3) + endl + + get(2, 0) + ", " + get(2, 1) + ", " + get(2, 2) + ", " + get(2, 3) + endl + + get(3, 0) + ", " + get(3, 1) + ", " + get(3, 2) + ", " + get(3, 3) + ")"; + } +} diff --git a/src/gleem/linalg/Matf.java b/src/gleem/linalg/Matf.java new file mode 100644 index 0000000..ae4ef92 --- /dev/null +++ b/src/gleem/linalg/Matf.java @@ -0,0 +1,168 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Arbitrary-size single-precision matrix class. Currently very + simple and only supports a few needed operations. */ + +public class Matf { + private float[] data; + private int nCol; // number of columns + private int nRow; // number of columns + + public Matf(int nRow, int nCol) { + data = new float[nRow * nCol]; + this.nCol = nCol; + this.nRow = nRow; + } + + public Matf(Matf arg) { + nRow = arg.nRow; + nCol = arg.nCol; + data = new float[nRow * nCol]; + System.arraycopy(arg.data, 0, data, 0, data.length); + } + + public int nRow() { + return nRow; + } + + public int nCol() { + return nCol; + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[nCol * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[nCol * i + j] = val; + } + + /** Returns transpose of this matrix; creates new matrix */ + public Matf transpose() { + Matf tmp = new Matf(nCol, nRow); + for (int i = 0; i < nRow; i++) { + for (int j = 0; j < nCol; j++) { + tmp.set(j, i, get(i, j)); + } + } + return tmp; + } + + /** Returns this * b; creates new matrix */ + public Matf mul(Matf b) throws DimensionMismatchException { + if (nCol() != b.nRow()) + throw new DimensionMismatchException(); + Matf tmp = new Matf(nRow(), b.nCol()); + for (int i = 0; i < nRow(); i++) { + for (int j = 0; j < b.nCol(); j++) { + float val = 0; + for (int t = 0; t < nCol(); t++) { + val += get(i, t) * b.get(t, j); + } + tmp.set(i, j, val); + } + } + return tmp; + } + + /** Returns this * v, assuming v is a column vector. */ + public Vecf mul(Vecf v) throws DimensionMismatchException { + if (nCol() != v.length()) { + throw new DimensionMismatchException(); + } + Vecf out = new Vecf(nRow()); + for (int i = 0; i < nRow(); i++) { + float tmp = 0; + for (int j = 0; j < nCol(); j++) { + tmp += get(i, j) * v.get(j); + } + out.set(i, tmp); + } + return out; + } + + /** If this is a 2x2 matrix, returns it as a Mat2f. */ + public Mat2f toMat2f() throws DimensionMismatchException { + if (nRow() != 2 || nCol() != 2) { + throw new DimensionMismatchException(); + } + Mat2f tmp = new Mat2f(); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + tmp.set(i, j, get(i, j)); + } + } + return tmp; + } + + /** If this is a 3x3 matrix, returns it as a Mat3f. */ + public Mat3f toMat3f() throws DimensionMismatchException { + if (nRow() != 3 || nCol() != 3) { + throw new DimensionMismatchException(); + } + Mat3f tmp = new Mat3f(); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + tmp.set(i, j, get(i, j)); + } + } + return tmp; + } + + /** If this is a 4x4 matrix, returns it as a Mat4f. */ + public Mat4f toMat4f() throws DimensionMismatchException { + if (nRow() != 4 || nCol() != 4) { + throw new DimensionMismatchException(); + } + Mat4f tmp = new Mat4f(); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + tmp.set(i, j, get(i, j)); + } + } + return tmp; + } +} diff --git a/src/gleem/linalg/MathUtil.java b/src/gleem/linalg/MathUtil.java new file mode 100644 index 0000000..7415953 --- /dev/null +++ b/src/gleem/linalg/MathUtil.java @@ -0,0 +1,90 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Utility math routines. */ + +public class MathUtil { + /** Makes an arbitrary vector perpendicular to src and + inserts it into dest. Returns false if the source vector + was equal to (0, 0, 0). */ + public static boolean makePerpendicular(Vec3f src, + Vec3f dest) { + if ((src.x() == 0.0f) && (src.y() == 0.0f) && (src.z() == 0.0f)) { + return false; + } + + if (src.x() != 0.0f) { + if (src.y() != 0.0f) { + dest.set(-src.y(), src.x(), 0.0f); + } else { + dest.set(-src.z(), 0.0f, src.x()); + } + } else { + dest.set(1.0f, 0.0f, 0.0f); + } + return true; + } + + /** Returns 1 if the sign of the given argument is positive; -1 if + negative; 0 if 0. */ + public static int sgn(float f) { + if (f > 0) { + return 1; + } else if (f < 0) { + return -1; + } + return 0; + } + + /** Clamps argument between min and max values. */ + public static float clamp(float val, float min, float max) { + if (val < min) return min; + if (val > max) return max; + return val; + } + + /** Clamps argument between min and max values. */ + public static int clamp(int val, int min, int max) { + if (val < min) return min; + if (val > max) return max; + return val; + } +} diff --git a/src/gleem/linalg/NonSquareMatrixException.java b/src/gleem/linalg/NonSquareMatrixException.java new file mode 100644 index 0000000..efc0c6a --- /dev/null +++ b/src/gleem/linalg/NonSquareMatrixException.java @@ -0,0 +1,53 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Thrown to indicate a non-square matrix during an operation + requiring one. */ + +public class NonSquareMatrixException extends RuntimeException { + public NonSquareMatrixException() { + super(); + } + + public NonSquareMatrixException(String msg) { + super(msg); + } +} diff --git a/src/gleem/linalg/Plane.java b/src/gleem/linalg/Plane.java new file mode 100644 index 0000000..fa58259 --- /dev/null +++ b/src/gleem/linalg/Plane.java @@ -0,0 +1,121 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Represents a plane in 3D space. */ + +public class Plane { + /** Normalized */ + private Vec3f normal; + private Vec3f point; + /** Constant for faster projection and intersection */ + float c; + + /** Default constructor initializes normal to (0, 1, 0) and point to + (0, 0, 0) */ + public Plane() { + normal = new Vec3f(0, 1, 0); + point = new Vec3f(0, 0, 0); + recalc(); + } + + /** Sets all parameters of plane. Plane has normal normal and + goes through the point point. Normal does not need to be + unit length but must not be the zero vector. */ + public Plane(Vec3f normal, Vec3f point) { + this.normal.set(normal); + this.normal.normalize(); + this.point.set(point); + recalc(); + } + + /** Setter does some work to maintain internal caches. Normal does + not need to be unit length but must not be the zero vector. */ + public void setNormal(Vec3f normal) { + this.normal.set(normal); + this.normal.normalize(); + recalc(); + } + + /** Normal is normalized internally, so normal is not + necessarily equal to plane.setNormal(normal); + plane.getNormal(); */ + public Vec3f getNormal() { + return normal; + } + + /** Setter does some work to maintain internal caches */ + public void setPoint(Vec3f point) { + this.point.set(point); + recalc(); + } + + public Vec3f getPoint() { + return point; + } + + /** Project a point onto the plane */ + public void projectPoint(Vec3f pt, + Vec3f projPt) { + float scale = normal.dot(pt) - c; + projPt.set(pt.minus(normal.times(normal.dot(point) - c))); + } + + /** Intersect a ray with the plane. Returns true if intersection occurred, false + otherwise. This is a two-sided ray cast. */ + public boolean intersectRay(Vec3f rayStart, + Vec3f rayDirection, + IntersectionPoint intPt) { + float denom = normal.dot(rayDirection); + if (denom == 0) + return false; + intPt.setT((c - normal.dot(rayStart)) / denom); + intPt.setIntersectionPoint(rayStart.plus(rayDirection.times(intPt.getT()))); + return true; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void recalc() { + c = normal.dot(point); + } +} diff --git a/src/gleem/linalg/PlaneUV.java b/src/gleem/linalg/PlaneUV.java new file mode 100644 index 0000000..ff1baad --- /dev/null +++ b/src/gleem/linalg/PlaneUV.java @@ -0,0 +1,203 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** This differs from the Plane class in that it maintains an origin + and orthonormal U, V axes in the plane so that it can project a 3D + point to a 2D one. U cross V = normal. U and V coordinates are + computed with respect to the origin. */ + +public class PlaneUV { + private Vec3f origin = new Vec3f(); + /** Normalized */ + private Vec3f normal = new Vec3f(); + private Vec3f uAxis = new Vec3f(); + private Vec3f vAxis = new Vec3f(); + + /** Default constructor initializes normal to (0, 1, 0), origin to + (0, 0, 0), U axis to (1, 0, 0) and V axis to (0, 0, -1). */ + public PlaneUV() { + setEverything(new Vec3f(0, 1, 0), + new Vec3f(0, 0, 0), + new Vec3f(1, 0, 0), + new Vec3f(0, 0, -1)); + } + + /** Takes normal vector and a point which the plane goes through + (which becomes the plane's "origin"). Normal does NOT have to be + normalized, but may not be zero vector. U and V axes are + initialized to arbitrary values. */ + public PlaneUV(Vec3f normal, Vec3f origin) { + setOrigin(origin); + setNormal(normal); + } + + /** Takes normal vector, point which plane goes through, and the "u" + axis in the plane. Computes the "v" axis by taking the cross + product of the normal and the u axis. Axis must be perpendicular + to normal. Normal and uAxis do NOT have to be normalized, but + neither may be the zero vector. */ + public PlaneUV(Vec3f normal, + Vec3f origin, + Vec3f uAxis) { + setOrigin(origin); + setNormalAndU(normal, uAxis); + } + + /** Takes normal vector, point which plane goes through, and both + the u and v axes. u axis cross v axis = normal. Normal, uAxis, and + vAxis do NOT have to be normalized, but none may be the zero + vector. */ + public PlaneUV(Vec3f normal, + Vec3f origin, + Vec3f uAxis, + Vec3f vAxis) { + setEverything(normal, origin, uAxis, vAxis); + } + + /** Set the origin, through which this plane goes and with respect + to which U and V coordinates are computed */ + public void setOrigin(Vec3f origin) { + this.origin.set(origin); + } + + public Vec3f getOrigin() { + return new Vec3f(origin); + } + + /** Normal, U and V axes must be orthogonal and satisfy U cross V = + normal, do not need to be unit length but must not be the zero + vector. */ + public void setNormalAndUV(Vec3f normal, + Vec3f uAxis, + Vec3f vAxis) { + setEverything(normal, origin, uAxis, vAxis); + } + + /** This version sets the normal vector and generates new U and V + axes. */ + public void setNormal(Vec3f normal) { + Vec3f uAxis = new Vec3f(); + MathUtil.makePerpendicular(normal, uAxis); + Vec3f vAxis = normal.cross(uAxis); + setEverything(normal, origin, uAxis, vAxis); + } + + /** This version computes the V axis from (normal cross U). */ + public void setNormalAndU(Vec3f normal, + Vec3f uAxis) { + Vec3f vAxis = normal.cross(uAxis); + setEverything(normal, origin, uAxis, vAxis); + } + + /** Normal, U and V axes are normalized internally, so, for example, + normal is not necessarily equal to + plane.setNormal(normal); plane.getNormal(); */ + public Vec3f getNormal() { + return normal; + } + + public Vec3f getUAxis() { + return uAxis; + } + + public Vec3f getVAxis() { + return vAxis; + } + + /** Project a point onto the plane */ + public void projectPoint(Vec3f point, + Vec3f projPt, + Vec2f uvCoords) { + // Using projPt as a temporary + projPt.sub(point, origin); + float dotp = normal.dot(projPt); + // Component perpendicular to plane + Vec3f tmpDir = new Vec3f(); + tmpDir.set(normal); + tmpDir.scale(dotp); + projPt.sub(projPt, tmpDir); + // Take dot products with basis vectors + uvCoords.set(projPt.dot(uAxis), + projPt.dot(vAxis)); + // Add on center to intersection point + projPt.add(origin); + } + + /** Intersect a ray with this plane, outputting not only the 3D + intersection point but also the U, V coordinates of the + intersection. Returns true if intersection occurred, false + otherwise. This is a two-sided ray cast. */ + public boolean intersectRay(Vec3f rayStart, + Vec3f rayDirection, + IntersectionPoint intPt, + Vec2f uvCoords) { + float denom = rayDirection.dot(normal); + if (denom == 0.0f) + return false; + Vec3f tmpDir = new Vec3f(); + tmpDir.sub(origin, rayStart); + float t = tmpDir.dot(normal) / denom; + // Find intersection point + Vec3f tmpPt = new Vec3f(); + tmpPt.set(rayDirection); + tmpPt.scale(t); + tmpPt.add(rayStart); + intPt.setIntersectionPoint(tmpPt); + intPt.setT(t); + // Find UV coords + tmpDir.sub(intPt.getIntersectionPoint(), origin); + uvCoords.set(tmpDir.dot(uAxis), tmpDir.dot(vAxis)); + return true; + } + + private void setEverything(Vec3f normal, + Vec3f origin, + Vec3f uAxis, + Vec3f vAxis) { + this.normal.set(normal); + this.origin.set(origin); + this.uAxis.set(uAxis); + this.vAxis.set(vAxis); + this.normal.normalize(); + this.uAxis.normalize(); + this.vAxis.normalize(); + } +} diff --git a/src/gleem/linalg/Rotf.java b/src/gleem/linalg/Rotf.java new file mode 100644 index 0000000..4e39c21 --- /dev/null +++ b/src/gleem/linalg/Rotf.java @@ -0,0 +1,309 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Represents a rotation with single-precision components */ + +public class Rotf { + private static float EPSILON = 1.0e-7f; + + // Representation is a quaternion. Element 0 is the scalar part (= + // cos(theta/2)), elements 1..3 the imaginary/"vector" part (= + // sin(theta/2) * axis). + private float q0; + private float q1; + private float q2; + private float q3; + + /** Default constructor initializes to the identity quaternion */ + public Rotf() { + init(); + } + + public Rotf(Rotf arg) { + set(arg); + } + + /** Axis does not need to be normalized but must not be the zero + vector. Angle is in radians. */ + public Rotf(Vec3f axis, float angle) { + set(axis, angle); + } + + /** Creates a rotation which will rotate vector "from" into vector + "to". */ + public Rotf(Vec3f from, Vec3f to) { + set(from, to); + } + + /** Re-initialize this quaternion to be the identity quaternion "e" + (i.e., no rotation) */ + public void init() { + q0 = 1; + q1 = q2 = q3 = 0; + } + + /** Test for "approximate equality" -- performs componentwise test + to see whether difference between all components is less than + epsilon. */ + public boolean withinEpsilon(Rotf arg, float epsilon) { + return ((Math.abs(q0 - arg.q0) < epsilon) && + (Math.abs(q1 - arg.q1) < epsilon) && + (Math.abs(q2 - arg.q2) < epsilon) && + (Math.abs(q3 - arg.q3) < epsilon)); + } + + /** Axis does not need to be normalized but must not be the zero + vector. Angle is in radians. */ + public void set(Vec3f axis, float angle) { + float halfTheta = angle / 2.0f; + q0 = (float) Math.cos(halfTheta); + float sinHalfTheta = (float) Math.sin(halfTheta); + Vec3f realAxis = new Vec3f(axis); + realAxis.normalize(); + q1 = realAxis.x() * sinHalfTheta; + q2 = realAxis.y() * sinHalfTheta; + q3 = realAxis.z() * sinHalfTheta; + } + + public void set(Rotf arg) { + q0 = arg.q0; + q1 = arg.q1; + q2 = arg.q2; + q3 = arg.q3; + } + + /** Sets this rotation to that which will rotate vector "from" into + vector "to". from and to do not have to be the same length. */ + public void set(Vec3f from, Vec3f to) { + Vec3f axis = from.cross(to); + if (axis.lengthSquared() < EPSILON) { + init(); + return; + } + float dotp = from.dot(to); + float denom = from.length() * to.length(); + if (denom < EPSILON) { + init(); + return; + } + dotp /= denom; + set(axis, (float) Math.acos(dotp)); + } + + /** Returns angle (in radians) and mutates the given vector to be + the axis. */ + public float get(Vec3f axis) { + // FIXME: Is this numerically stable? Is there a better way to + // extract the angle from a quaternion? + // NOTE: remove (float) to illustrate compiler bug + float retval = (float) (2.0f * Math.acos(q0)); + axis.set(q1, q2, q3); + float len = axis.length(); + if (len == 0.0f) { + axis.set(0, 0, 1); + } else { + axis.scale(1.0f / len); + } + return retval; + } + + /** Returns inverse of this rotation; creates new rotation */ + public Rotf inverse() { + Rotf tmp = new Rotf(this); + tmp.invert(); + return tmp; + } + + /** Mutate this quaternion to be its inverse. This is equivalent to + the conjugate of the quaternion. */ + public void invert() { + q1 = -q1; + q2 = -q2; + q3 = -q3; + } + + /** Length of this quaternion in four-space */ + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + /** This dotted with this */ + public float lengthSquared() { + return (q0 * q0 + + q1 * q1 + + q2 * q2 + + q3 * q3); + } + + /** Make this quaternion a unit quaternion again. If you are + composing dozens of quaternions you probably should call this + periodically to ensure that you have a valid rotation. */ + public void normalize() { + float len = length(); + q0 /= len; + q1 /= len; + q2 /= len; + q3 /= len; + } + + /** Returns this * b, in that order; creates new rotation */ + public Rotf times(Rotf b) { + Rotf tmp = new Rotf(); + tmp.mul(this, b); + return tmp; + } + + /** Compose two rotations: this = A * B in that order. NOTE that + because we assume a column vector representation that this + implies that a vector rotated by the cumulative rotation will be + rotated first by B, then A. NOTE: "this" must be different than + both a and b. */ + public void mul(Rotf a, Rotf b) { + q0 = (a.q0 * b.q0 - a.q1 * b.q1 - + a.q2 * b.q2 - a.q3 * b.q3); + q1 = (a.q0 * b.q1 + a.q1 * b.q0 + + a.q2 * b.q3 - a.q3 * b.q2); + q2 = (a.q0 * b.q2 + a.q2 * b.q0 - + a.q1 * b.q3 + a.q3 * b.q1); + q3 = (a.q0 * b.q3 + a.q3 * b.q0 + + a.q1 * b.q2 - a.q2 * b.q1); + } + + /** Turns this rotation into a 3x3 rotation matrix. NOTE: only + mutates the upper-left 3x3 of the passed Mat4f. Implementation + from B. K. P. Horn's Robot Vision textbook. */ + public void toMatrix(Mat4f mat) { + float q00 = q0 * q0; + float q11 = q1 * q1; + float q22 = q2 * q2; + float q33 = q3 * q3; + // Diagonal elements + mat.set(0, 0, q00 + q11 - q22 - q33); + mat.set(1, 1, q00 - q11 + q22 - q33); + mat.set(2, 2, q00 - q11 - q22 + q33); + // 0,1 and 1,0 elements + float q03 = q0 * q3; + float q12 = q1 * q2; + mat.set(0, 1, 2.0f * (q12 - q03)); + mat.set(1, 0, 2.0f * (q03 + q12)); + // 0,2 and 2,0 elements + float q02 = q0 * q2; + float q13 = q1 * q3; + mat.set(0, 2, 2.0f * (q02 + q13)); + mat.set(2, 0, 2.0f * (q13 - q02)); + // 1,2 and 2,1 elements + float q01 = q0 * q1; + float q23 = q2 * q3; + mat.set(1, 2, 2.0f * (q23 - q01)); + mat.set(2, 1, 2.0f * (q01 + q23)); + } + + /** Turns the upper left 3x3 of the passed matrix into a rotation. + Implementation from Watt and Watt, Advanced Animation and + Rendering Techniques. + @see gleem.linalg.Mat4f#getRotation */ + public void fromMatrix(Mat4f mat) { + // FIXME: Should reimplement to follow Horn's advice of using + // eigenvector decomposition to handle roundoff error in given + // matrix. + + float tr, s; + int i, j, k; + + tr = mat.get(0, 0) + mat.get(1, 1) + mat.get(2, 2); + if (tr > 0.0) { + s = (float) Math.sqrt(tr + 1.0f); + q0 = s * 0.5f; + s = 0.5f / s; + q1 = (mat.get(2, 1) - mat.get(1, 2)) * s; + q2 = (mat.get(0, 2) - mat.get(2, 0)) * s; + q3 = (mat.get(1, 0) - mat.get(0, 1)) * s; + } else { + i = 0; + if (mat.get(1, 1) > mat.get(0, 0)) + i = 1; + if (mat.get(2, 2) > mat.get(i, i)) + i = 2; + j = (i+1)%3; + k = (j+1)%3; + s = (float) Math.sqrt( (mat.get(i, i) - (mat.get(j, j) + mat.get(k, k))) + 1.0f); + setQ(i+1, s * 0.5f); + s = 0.5f / s; + q0 = (mat.get(k, j) - mat.get(j, k)) * s; + setQ(j+1, (mat.get(j, i) + mat.get(i, j)) * s); + setQ(k+1, (mat.get(k, i) + mat.get(i, k)) * s); + } + } + + /** Rotate a vector by this quaternion. Implementation is from + Horn's Robot Vision. NOTE: src and dest must be different + vectors. */ + public void rotateVector(Vec3f src, Vec3f dest) { + Vec3f qVec = new Vec3f(q1, q2, q3); + Vec3f qCrossX = qVec.cross(src); + Vec3f qCrossXCrossQ = qCrossX.cross(qVec); + qCrossX.scale(2.0f * q0); + qCrossXCrossQ.scale(-2.0f); + dest.add(src, qCrossX); + dest.add(dest, qCrossXCrossQ); + } + + /** Rotate a vector by this quaternion, returning newly-allocated result. */ + public Vec3f rotateVector(Vec3f src) { + Vec3f tmp = new Vec3f(); + rotateVector(src, tmp); + return tmp; + } + + public String toString() { + return "(" + q0 + ", " + q1 + ", " + q2 + ", " + q3 + ")"; + } + + private void setQ(int i, float val) { + switch (i) { + case 0: q0 = val; break; + case 1: q1 = val; break; + case 2: q2 = val; break; + case 3: q3 = val; break; + default: throw new IndexOutOfBoundsException(); + } + } +} diff --git a/src/gleem/linalg/SingularMatrixException.java b/src/gleem/linalg/SingularMatrixException.java new file mode 100644 index 0000000..fa6ef32 --- /dev/null +++ b/src/gleem/linalg/SingularMatrixException.java @@ -0,0 +1,53 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Thrown to indicate a singular matrix during an inversion or + related operation. */ + +public class SingularMatrixException extends RuntimeException { + public SingularMatrixException() { + super(); + } + + public SingularMatrixException(String msg) { + super(msg); + } +} diff --git a/src/gleem/linalg/Vec2f.java b/src/gleem/linalg/Vec2f.java new file mode 100644 index 0000000..2e02701 --- /dev/null +++ b/src/gleem/linalg/Vec2f.java @@ -0,0 +1,182 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** 2-element single-precision vector */ + +public class Vec2f { + private float x; + private float y; + + public Vec2f() {} + + public Vec2f(Vec2f arg) { + this(arg.x, arg.y); + } + + public Vec2f(float x, float y) { + set(x, y); + } + + public Vec2f copy() { + return new Vec2f(this); + } + + public void set(float x, float y) { + this.x = x; + this.y = y; + } + + /** Sets the ith component, 0 <= i < 2 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 2 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + + public float dot(Vec2f arg) { + return x * arg.x + y * arg.y; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec2f times(float val) { + Vec2f tmp = new Vec2f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec2f plus(Vec2f arg) { + Vec2f tmp = new Vec2f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec2f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec2f a, Vec2f b) { + x = a.x + b.x; + y = a.y + b.y; + } + + /** Returns this + s * arg; creates new vector */ + public Vec2f addScaled(float s, Vec2f arg) { + Vec2f tmp = new Vec2f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec2f a, float s, Vec2f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + } + + /** Returns this - arg; creates new vector */ + public Vec2f minus(Vec2f arg) { + Vec2f tmp = new Vec2f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec2f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec2f a, Vec2f b) { + x = a.x - b.x; + y = a.y - b.y; + } + + public Vecf toVecf() { + Vecf out = new Vecf(2); + for (int i = 0; i < 2; i++) { + out.set(i, get(i)); + } + return out; + } + + public String toString() { + return "(" + x + ", " + y + ")"; + } +} diff --git a/src/gleem/linalg/Vec3d.java b/src/gleem/linalg/Vec3d.java new file mode 100644 index 0000000..7a7a907 --- /dev/null +++ b/src/gleem/linalg/Vec3d.java @@ -0,0 +1,175 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * See the file GLEEM-LICENSE.txt in the doc/ directory for licensing terms. + */ + +package gleem.linalg; + +/** 3-element double-precision vector */ + +public class Vec3d { + private double x; + private double y; + private double z; + + public Vec3d() {} + + public Vec3d(Vec3d arg) { + set(arg); + } + + public Vec3d(double x, double y, double z) { + set(x, y, z); + } + + public Vec3d copy() { + return new Vec3d(this); + } + + /** Convert to single-precision */ + public Vec3f toFloat() { + return new Vec3f((float) x, (float) y, (float) z); + } + + public void set(Vec3d arg) { + set(arg.x, arg.y, arg.z); + } + + public void set(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** Sets the ith component, 0 <= i < 3 */ + public void set(int i, double val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 3 */ + public double get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new IndexOutOfBoundsException(); + } + } + + public double x() { return x; } + public double y() { return y; } + public double z() { return z; } + + public void setX(double x) { this.x = x; } + public void setY(double y) { this.y = y; } + public void setZ(double z) { this.z = z; } + + public double dot(Vec3d arg) { + return x * arg.x + y * arg.y + z * arg.z; + } + + public double length() { + return Math.sqrt(lengthSquared()); + } + + public double lengthSquared() { + return this.dot(this); + } + + public void normalize() { + double len = length(); + if (len == 0.0) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec3d times(double val) { + Vec3d tmp = new Vec3d(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(double val) { + x *= val; + y *= val; + z *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec3d plus(Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec3d b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec3d a, Vec3d b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + } + + /** Returns this + s * arg; creates new vector */ + public Vec3d addScaled(double s, Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec3d a, double s, Vec3d b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + } + + /** Returns this - arg; creates new vector */ + public Vec3d minus(Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec3d b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec3d a, Vec3d b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + } + + /** Returns this cross arg; creates new vector */ + public Vec3d cross(Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.cross(this, arg); + return tmp; + } + + /** this = a cross b. NOTE: "this" must be a different vector than + both a and b. */ + public void cross(Vec3d a, Vec3d b) { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/gleem/linalg/Vec3f.java b/src/gleem/linalg/Vec3f.java new file mode 100644 index 0000000..5468f3e --- /dev/null +++ b/src/gleem/linalg/Vec3f.java @@ -0,0 +1,232 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** 3-element single-precision vector */ + +public class Vec3f { + public static final Vec3f X_AXIS = new Vec3f( 1, 0, 0); + public static final Vec3f Y_AXIS = new Vec3f( 0, 1, 0); + public static final Vec3f Z_AXIS = new Vec3f( 0, 0, 1); + public static final Vec3f NEG_X_AXIS = new Vec3f(-1, 0, 0); + public static final Vec3f NEG_Y_AXIS = new Vec3f( 0, -1, 0); + public static final Vec3f NEG_Z_AXIS = new Vec3f( 0, 0, -1); + + private float x; + private float y; + private float z; + + public Vec3f() {} + + public Vec3f(Vec3f arg) { + set(arg); + } + + public Vec3f(float x, float y, float z) { + set(x, y, z); + } + + public Vec3f copy() { + return new Vec3f(this); + } + + /** Convert to double-precision */ + public Vec3d toDouble() { + return new Vec3d(x, y, z); + } + + public void set(Vec3f arg) { + set(arg.x, arg.y, arg.z); + } + + public void set(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** Sets the ith component, 0 <= i < 3 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 3 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + public float z() { return z; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + public void setZ(float z) { this.z = z; } + + public float dot(Vec3f arg) { + return x * arg.x + y * arg.y + z * arg.z; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec3f times(float val) { + Vec3f tmp = new Vec3f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + z *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec3f plus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec3f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec3f a, Vec3f b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + } + + /** Returns this + s * arg; creates new vector */ + public Vec3f addScaled(float s, Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec3f a, float s, Vec3f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + } + + /** Returns this - arg; creates new vector */ + public Vec3f minus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec3f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec3f a, Vec3f b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + } + + /** Returns this cross arg; creates new vector */ + public Vec3f cross(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.cross(this, arg); + return tmp; + } + + /** this = a cross b. NOTE: "this" must be a different vector than + both a and b. */ + public void cross(Vec3f a, Vec3f b) { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + } + + /** Sets each component of this vector to the product of the + component with the corresponding component of the argument + vector. */ + public void componentMul(Vec3f arg) { + x *= arg.x; + y *= arg.y; + z *= arg.z; + } + + public Vecf toVecf() { + Vecf out = new Vecf(3); + for (int i = 0; i < 3; i++) { + out.set(i, get(i)); + } + return out; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/gleem/linalg/Vec4f.java b/src/gleem/linalg/Vec4f.java new file mode 100644 index 0000000..bfb53ab --- /dev/null +++ b/src/gleem/linalg/Vec4f.java @@ -0,0 +1,216 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** 4-element single-precision vector */ + +public class Vec4f { + private float x; + private float y; + private float z; + private float w; + + public Vec4f() {} + + public Vec4f(Vec4f arg) { + set(arg); + } + + public Vec4f(float x, float y, float z, float w) { + set(x, y, z, w); + } + + public Vec4f copy() { + return new Vec4f(this); + } + + public void set(Vec4f arg) { + set(arg.x, arg.y, arg.z, arg.w); + } + + public void set(float x, float y, float z, float w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /** Sets the ith component, 0 <= i < 4 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + case 3: w = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 4 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + public float z() { return z; } + public float w() { return w; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + public void setZ(float z) { this.z = z; } + public void setW(float w) { this.w = w; } + + public float dot(Vec4f arg) { + return x * arg.x + y * arg.y + z * arg.z + w * arg.w; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec4f times(float val) { + Vec4f tmp = new Vec4f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + z *= val; + w *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec4f plus(Vec4f arg) { + Vec4f tmp = new Vec4f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec4f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec4f a, Vec4f b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + w = a.w + b.w; + } + + /** Returns this + s * arg; creates new vector */ + public Vec4f addScaled(float s, Vec4f arg) { + Vec4f tmp = new Vec4f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec4f a, float s, Vec4f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + w = a.w + s * b.w; + } + + /** Returns this - arg; creates new vector */ + public Vec4f minus(Vec4f arg) { + Vec4f tmp = new Vec4f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec4f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec4f a, Vec4f b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + w = a.w - b.w; + } + + /** Sets each component of this vector to the product of the + component with the corresponding component of the argument + vector. */ + public void componentMul(Vec4f arg) { + x *= arg.x; + y *= arg.y; + z *= arg.z; + w *= arg.w; + } + + public Vecf toVecf() { + Vecf out = new Vecf(4); + for (int i = 0; i < 4; i++) { + out.set(i, get(i)); + } + return out; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/gleem/linalg/Vecf.java b/src/gleem/linalg/Vecf.java new file mode 100644 index 0000000..1249695 --- /dev/null +++ b/src/gleem/linalg/Vecf.java @@ -0,0 +1,96 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Arbitrary-length single-precision vector class. Currently very + simple and only supports a few needed operations. */ + +public class Vecf { + private float[] data; + + public Vecf(int n) { + data = new float[n]; + } + + public Vecf(Vecf arg) { + data = new float[arg.data.length]; + System.arraycopy(arg.data, 0, data, 0, data.length); + } + + public int length() { + return data.length; + } + + public float get(int i) { + return data[i]; + } + + public void set(int i, float val) { + data[i] = val; + } + + public Vec2f toVec2f() throws DimensionMismatchException { + if (length() != 2) + throw new DimensionMismatchException(); + Vec2f out = new Vec2f(); + for (int i = 0; i < 2; i++) { + out.set(i, get(i)); + } + return out; + } + + public Vec3f toVec3f() throws DimensionMismatchException { + if (length() != 3) + throw new DimensionMismatchException(); + Vec3f out = new Vec3f(); + for (int i = 0; i < 3; i++) { + out.set(i, get(i)); + } + return out; + } + + public Veci toInt() { + Veci out = new Veci(length()); + for (int i = 0; i < length(); i++) { + out.set(i, (int) get(i)); + } + return out; + } +} diff --git a/src/gleem/linalg/Veci.java b/src/gleem/linalg/Veci.java new file mode 100644 index 0000000..d7705e7 --- /dev/null +++ b/src/gleem/linalg/Veci.java @@ -0,0 +1,96 @@ +/* + * gleem -- OpenGL Extremely Easy-To-Use Manipulators. + * Copyright (C) 1998-2003 Kenneth B. Russell (kbrussel@alum.mit.edu) + * + * Copying, distribution and use of this software in source and binary + * forms, with or without modification, is permitted provided that the + * following conditions are met: + * + * Distributions of source code must reproduce the copyright notice, + * this list of conditions and the following disclaimer in the source + * code header files; and Distributions of binary code must reproduce + * the copyright notice, this list of conditions and the following + * disclaimer in the documentation, Read me file, license file and/or + * other materials provided with the software distribution. + * + * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright + * holder may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY + * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF + * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE + * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE + * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, + * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND + * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR + * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT + * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, + * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT + * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED + * WARRANTY OF FITNESS FOR SUCH USES. + */ + +package gleem.linalg; + +/** Arbitrary-length integer vector class. Currently very simple and + only supports a few needed operations. */ + +public class Veci { + private int[] data; + + public Veci(int n) { + data = new int[n]; + } + + public Veci(Veci arg) { + data = new int[arg.data.length]; + System.arraycopy(arg.data, 0, data, 0, data.length); + } + + public int length() { + return data.length; + } + + public int get(int i) { + return data[i]; + } + + public void set(int i, int val) { + data[i] = val; + } + + public Vec2f toVec2f() throws DimensionMismatchException { + if (length() != 2) + throw new DimensionMismatchException(); + Vec2f out = new Vec2f(); + for (int i = 0; i < 2; i++) { + out.set(i, get(i)); + } + return out; + } + + public Vec3f toVec3f() throws DimensionMismatchException { + if (length() != 3) + throw new DimensionMismatchException(); + Vec3f out = new Vec3f(); + for (int i = 0; i < 3; i++) { + out.set(i, get(i)); + } + return out; + } + + public Vecf toVecf() { + Vecf out = new Vecf(length()); + for (int i = 0; i < length(); i++) { + out.set(i, get(i)); + } + return out; + } +} diff --git a/src/gleem/linalg/package.html b/src/gleem/linalg/package.html new file mode 100644 index 0000000..bc1e60f --- /dev/null +++ b/src/gleem/linalg/package.html @@ -0,0 +1,13 @@ + + + + +Linear algebra and classes implementing basic 3D operations. + +

+ +See the gleem +home page for more information. + + + -- cgit v1.2.3