aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-03-15 10:21:36 +0100
committerSven Gothel <[email protected]>2014-03-15 10:21:36 +0100
commit7e2512c8f63cee63ab2f74407fb94859fe20043a (patch)
tree9589bc7aabc5f69c9215d056edf1f929852e81c2 /src
parent0b61e9a2641e38475a330303e49f6becf99158e1 (diff)
Quaternion: User EPSILON for all tests against zero and one (identity .. ) and document the same. ; Minor edits ..
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java2
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/Outline.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Quaternion.java171
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java4
-rw-r--r--src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java8
6 files changed, 146 insertions, 45 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
index 63183bf68..160e171e4 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
@@ -685,7 +685,7 @@ public class OutlineShape implements Comparable<OutlineShape> {
public final int compareTo(final OutlineShape other) {
final float thisSize = getBounds().getSize();
final float otherSize = other.getBounds().getSize();
- if( FloatUtil.equals(thisSize, otherSize, FloatUtil.EPSILON) ) {
+ if( FloatUtil.isEqual(thisSize, otherSize, FloatUtil.EPSILON) ) {
return 0;
} else if( thisSize < otherSize ){
return -1;
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Outline.java b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
index 5f6dd028f..9d4d1f26d 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Outline.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
@@ -222,7 +222,7 @@ public class Outline implements Cloneable, Comparable<Outline> {
public final int compareTo(final Outline other) {
final float thisSize = getBounds().getSize();
final float otherSize = other.getBounds().getSize();
- if( FloatUtil.equals(thisSize, otherSize, FloatUtil.EPSILON) ) {
+ if( FloatUtil.isEqual(thisSize, otherSize, FloatUtil.EPSILON) ) {
return 0;
} else if(thisSize < otherSize){
return -1;
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
index 6177a6b2d..ee57fc7e8 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
@@ -707,7 +707,7 @@ public class FloatUtil {
* boolean isNotEqual = abs(bfloat - afloat) >= EPSILON;
* </pre>
* </p>
- * @see #equals(float, float, float)
+ * @see #isEqual(float, float, float)
* @see #isZero(float, float)
*/
public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d
@@ -716,7 +716,7 @@ public class FloatUtil {
* Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>.
* @see #EPSILON
*/
- public static boolean equals(final float a, final float b, final float epsilon) {
+ public static boolean isEqual(final float a, final float b, final float epsilon) {
return Math.abs(a - b) < epsilon;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
index 56d270380..6e567fc1d 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
@@ -68,6 +68,8 @@ public class Quaternion {
}
/**
+ * See {@link #magnitude()} for special handling of {@link FloatUtil#EPSILON epsilon},
+ * which is not applied here.
* @return the squared magnitude of this quaternion.
*/
public final float magnitudeSquared() {
@@ -75,11 +77,25 @@ public class Quaternion {
}
/**
- * @return the magnitude of this quaternion, i.e. sqrt({@link #magnitude()})
+ * Return the magnitude of this quaternion, i.e. sqrt({@link #magnitude()})
+ * <p>
+ * A magnitude of zero shall equal {@link #isIdentity() identity},
+ * as performed by {@link #normalize()}.
+ * </p>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> returns 0f if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * <li> returns 1f if {@link #magnitudeSquared()} is {@link FloatUtil#isEqual(float, float, float) equals 1f} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
*/
public final float magnitude() {
final float magnitudeSQ = magnitudeSquared();
- if (magnitudeSQ == 1f) {
+ if ( FloatUtil.isZero(magnitudeSQ, FloatUtil.EPSILON) ) {
+ return 0f;
+ }
+ if ( FloatUtil.isEqual(1f, magnitudeSQ, FloatUtil.EPSILON) ) {
return 1f;
}
return FloatUtil.sqrt(magnitudeSQ);
@@ -132,13 +148,17 @@ public class Quaternion {
}
/**
- * Check if this quaternion represents an identity matrix for rotation,
- * , ie (0,0,0,1).
- *
- * @return true if it is an identity rep., false otherwise
+ * Returns <code>true</code> if this quaternion has identity.
+ * <p>
+ * Implementation uses {@link FloatUtil#EPSILON epsilon} to compare
+ * {@link #getW() W} {@link FloatUtil#isEqual(float, float, float) against 1f} and
+ * {@link #getX() X}, {@link #getY() Y} and {@link #getZ() Z}
+ * {@link FloatUtil#isZero(float, float) against zero}.
+ * </p>
*/
public final boolean isIdentity() {
- return w == 1 && x == 0 && y == 0 && z == 0;
+ return FloatUtil.isEqual(1f, w, FloatUtil.EPSILON) && VectorUtil.isZero(x, y, z, FloatUtil.EPSILON);
+ // return w == 1f && x == 0f && y == 0f && z == 0f;
}
/***
@@ -146,17 +166,23 @@ public class Quaternion {
* @return this quaternion for chaining.
*/
public final Quaternion setIdentity() {
- x = y = z = 0; w = 1;
+ x = y = z = 0f; w = 1f;
return this;
}
/**
- * Normalize a quaternion required if to be used as a rotational quaternion
+ * Normalize a quaternion required if to be used as a rotational quaternion.
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if {@link #magnitude()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
* @return this quaternion for chaining.
*/
public final Quaternion normalize() {
final float norm = magnitude();
- if (norm == 0.0f) {
+ if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) {
setIdentity();
} else {
w /= norm;
@@ -181,12 +207,18 @@ public class Quaternion {
/**
* Invert the quaternion If rotational, will produce a the inverse rotation
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #conjugate() conjugates} if {@link #magnitudeSquared()} is is {@link FloatUtil#isEqual(float, float, float) equals 1f} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
* @return this quaternion for chaining.
* @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q50">Matrix-FAQ Q50</a>
*/
public final Quaternion invert() {
final float magnitudeSQ = magnitudeSquared();
- if ( FloatUtil.equals(1.0f, magnitudeSQ, FloatUtil.EPSILON) ) {
+ if ( FloatUtil.isEqual(1.0f, magnitudeSQ, FloatUtil.EPSILON) ) {
conjugate();
} else {
w /= magnitudeSQ;
@@ -543,6 +575,12 @@ public class Quaternion {
* angle = angle(v1, v2) = v1•v2
* axis = normal(v1 x v2)
* </pre>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if square vector-length is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
* @param v1 not normalized
* @param v2 not normalized
* @param tmpPivotVec float[3] temp storage for cross product
@@ -593,6 +631,12 @@ public class Quaternion {
* angle = angle(v1, v2) = v1•v2
* axis = v1 x v2
* </pre>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if square vector-length is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
* @param v1 normalized
* @param v2 normalized
* @param tmpPivotVec float[3] temp storage for cross product
@@ -638,7 +682,10 @@ public class Quaternion {
/***
* Initialize this quaternion with given non-normalized axis vector and rotation angle
* <p>
- * If axis == 0,0,0 the quaternion is set to identity.
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if axis is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
* </p>
* @param angle rotation angle (rads)
* @param vector axis vector not normalized
@@ -656,7 +703,10 @@ public class Quaternion {
/***
* Initialize this quaternion with given normalized axis vector and rotation angle
* <p>
- * If axis == 0,0,0 the quaternion is set to identity.
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if axis is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
* </p>
* @param angle rotation angle (rads)
* @param vector axis vector normalized
@@ -722,7 +772,12 @@ public class Quaternion {
* <li>x - bank</li>
* </ul>
* </p>
- *
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if all angles are {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
* @param angradXYZ euler angel array in radians
* @return this quaternion for chaining.
* @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60">Matrix-FAQ Q60</a>
@@ -745,6 +800,12 @@ public class Quaternion {
* <li>x - bank</li>
* </ul>
* </p>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if all angles are {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
* @param bankX the Euler pitch angle in radians. (rotation about the X axis)
* @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
* @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
@@ -756,27 +817,31 @@ public class Quaternion {
* @see #toEuler(float[])
*/
public final Quaternion setFromEuler(final float bankX, final float headingY, float attitudeZ) {
- float angle = headingY * 0.5f;
- final float sinHeadingY = FloatUtil.sin(angle);
- final float cosHeadingY = FloatUtil.cos(angle);
- angle = attitudeZ * 0.5f;
- final float sinAttitudeZ = FloatUtil.sin(angle);
- final float cosAttitudeZ = FloatUtil.cos(angle);
- angle = bankX * 0.5f;
- final float sinBankX = FloatUtil.sin(angle);
- final float cosBankX = FloatUtil.cos(angle);
-
- // variables used to reduce multiplication calls.
- final float cosHeadingXcosAttitude = cosHeadingY * cosAttitudeZ;
- final float sinHeadingXsinAttitude = sinHeadingY * sinAttitudeZ;
- final float cosHeadingXsinAttitude = cosHeadingY * sinAttitudeZ;
- final float sinHeadingXcosAttitude = sinHeadingY * cosAttitudeZ;
-
- w = cosHeadingXcosAttitude * cosBankX - sinHeadingXsinAttitude * sinBankX;
- x = cosHeadingXcosAttitude * sinBankX + sinHeadingXsinAttitude * cosBankX;
- y = sinHeadingXcosAttitude * cosBankX + cosHeadingXsinAttitude * sinBankX;
- z = cosHeadingXsinAttitude * cosBankX - sinHeadingXcosAttitude * sinBankX;
- return normalize();
+ if ( VectorUtil.isZero(bankX, headingY, attitudeZ, FloatUtil.EPSILON) ) {
+ return setIdentity();
+ } else {
+ float angle = headingY * 0.5f;
+ final float sinHeadingY = FloatUtil.sin(angle);
+ final float cosHeadingY = FloatUtil.cos(angle);
+ angle = attitudeZ * 0.5f;
+ final float sinAttitudeZ = FloatUtil.sin(angle);
+ final float cosAttitudeZ = FloatUtil.cos(angle);
+ angle = bankX * 0.5f;
+ final float sinBankX = FloatUtil.sin(angle);
+ final float cosBankX = FloatUtil.cos(angle);
+
+ // variables used to reduce multiplication calls.
+ final float cosHeadingXcosAttitude = cosHeadingY * cosAttitudeZ;
+ final float sinHeadingXsinAttitude = sinHeadingY * sinAttitudeZ;
+ final float cosHeadingXsinAttitude = cosHeadingY * sinAttitudeZ;
+ final float sinHeadingXcosAttitude = sinHeadingY * cosAttitudeZ;
+
+ w = cosHeadingXcosAttitude * cosBankX - sinHeadingXsinAttitude * sinBankX;
+ x = cosHeadingXcosAttitude * sinBankX + sinHeadingXsinAttitude * cosBankX;
+ y = sinHeadingXcosAttitude * cosBankX + cosHeadingXsinAttitude * sinBankX;
+ z = cosHeadingXsinAttitude * cosBankX - sinHeadingXcosAttitude * sinBankX;
+ return normalize();
+ }
}
/**
@@ -910,6 +975,12 @@ public class Quaternion {
/**
* Transform this quaternion to a normalized 4x4 column matrix representing the rotation.
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
*
* @param matrix float[16] store for the resulting normalized column matrix 4x4
* @param mat_offset
@@ -920,7 +991,17 @@ public class Quaternion {
public final float[] toMatrix(final float[] matrix, final int mat_offset) {
// pre-multiply scaled-reciprocal-magnitude to reduce multiplications
final float norm = magnitudeSquared();
- final float srecip = norm == 1.0f ? 2.0f : norm > 0.0f ? 2.0f / norm : 0f;
+ if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) {
+ // identity matrix -> srecip = 0f
+ FloatUtil.makeIdentityf(matrix, mat_offset);
+ return matrix;
+ }
+ final float srecip;
+ if ( FloatUtil.isEqual(1f, norm, FloatUtil.EPSILON) ) {
+ srecip = 2f;
+ } else {
+ srecip = 2.0f / norm;
+ }
final float xs = srecip * x;
final float ys = srecip * y;
@@ -960,6 +1041,12 @@ public class Quaternion {
/**
* Transform this quaternion to a normalized 4x4 column matrix representing the rotation.
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
*
* @param matrix FloatBuffer store for the resulting normalized column matrix 4x4
* @param mat_offset
@@ -972,7 +1059,17 @@ public class Quaternion {
// pre-multipliy scaled-reciprocal-magnitude to reduce multiplications
final float norm = magnitudeSquared();
- final float srecip = norm == 1.0f ? 2.0f : norm > 0.0f ? 2.0f / norm : 0f;
+ if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) {
+ // identity matrix -> srecip = 0f
+ FloatUtil.makeIdentityf(matrix);
+ return matrix;
+ }
+ final float srecip;
+ if ( FloatUtil.isEqual(1f, norm, FloatUtil.EPSILON) ) {
+ srecip = 2f;
+ } else {
+ srecip = 2.0f / norm;
+ }
final float xs = srecip * x;
final float ys = srecip * y;
diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
index ff16fba79..4aa1baf78 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
@@ -77,7 +77,7 @@ public class VectorUtil {
/**
* Return true if both vectors are equal, no {@link FloatUtil#EPSILON} is taken into consideration.
*/
- public static boolean equals(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset) {
+ public static boolean isEqual(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset) {
return vec1[0+vec1Offset] == vec2[0+vec2Offset] &&
vec1[1+vec1Offset] == vec2[1+vec2Offset] &&
vec1[2+vec1Offset] == vec2[2+vec2Offset];
@@ -87,7 +87,7 @@ public class VectorUtil {
* Return true if both vectors are equal, i.e. their absolute delta < <code>epsilon</code>.
* @see FloatUtil#EPSILON
*/
- public static boolean equals(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset, final float epsilon) {
+ public static boolean isEqual(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset, final float epsilon) {
return Math.abs(vec1[0+vec1Offset] - vec2[0+vec2Offset]) < epsilon &&
Math.abs(vec1[1+vec1Offset] - vec2[1+vec2Offset]) < epsilon &&
Math.abs(vec1[2+vec1Offset] - vec2[2+vec2Offset]) < epsilon ;
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
index fdf317f68..c6efae883 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
@@ -365,8 +365,9 @@ public class AffineTransform implements Cloneable {
* </pre>
* </p>
* @param tR the right-argument of the matrix multiplication
+ * @return this transform for chaining
*/
- public final void concatenate(AffineTransform tR) {
+ public final AffineTransform concatenate(AffineTransform tR) {
// setTransform(multiply(this, tR));
type = TYPE_UNKNOWN;
setTransform(
@@ -376,6 +377,7 @@ public class AffineTransform implements Cloneable {
tR.m01 * m10 + tR.m11 * m11, // m11
tR.m02 * m00 + tR.m12 * m01 + m02, // m02
tR.m02 * m10 + tR.m12 * m11 + m12);// m12
+ return this;
}
/**
@@ -387,8 +389,9 @@ public class AffineTransform implements Cloneable {
* </pre>
* </p>
* @param tL the left-argument of the matrix multiplication
+ * @return this transform for chaining
*/
- public final void preConcatenate(AffineTransform tL) {
+ public final AffineTransform preConcatenate(AffineTransform tL) {
// setTransform(multiply(tL, this));
type = TYPE_UNKNOWN;
setTransform(
@@ -398,6 +401,7 @@ public class AffineTransform implements Cloneable {
m01 * tL.m10 + m11 * tL.m11, // m11
m02 * tL.m00 + m12 * tL.m01 + tL.m02, // m02
m02 * tL.m10 + m12 * tL.m11 + tL.m12);// m12
+ return this;
}
public final AffineTransform createInverse() throws NoninvertibleTransformException {