diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/math/Quaternion.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/math/Quaternion.java | 358 |
1 files changed, 160 insertions, 198 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java index 849477f54..2bb0f96c6 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java +++ b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2010-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -99,7 +99,7 @@ public class Quaternion { return FloatUtil.sqrt(magnitudeSQ); } - public final float getW() { + public final float w() { return w; } @@ -107,7 +107,7 @@ public class Quaternion { this.w = w; } - public final float getX() { + public final float x() { return x; } @@ -115,7 +115,7 @@ public class Quaternion { this.x = x; } - public final float getY() { + public final float y() { return y; } @@ -123,7 +123,7 @@ public class Quaternion { this.y = y; } - public final float getZ() { + public final float z() { return z; } @@ -142,15 +142,15 @@ public class Quaternion { * Returns the dot product of this quaternion with the given quaternion */ public final float dot(final Quaternion quat) { - return dot(quat.getX(), quat.getY(), quat.getZ(), quat.getW()); + return dot(quat.x(), quat.y(), quat.z(), quat.w()); } /** * 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 #w() W} {@link FloatUtil#isEqual(float, float, float) against 1f} and + * {@link #x() X}, {@link #y() Y} and {@link #z() Z} * {@link FloatUtil#isZero(float, float) against zero}. * </p> */ @@ -404,12 +404,12 @@ public class Quaternion { * </ul> * </p> * For details see {@link #rotateByEuler(float, float, float)}. - * @param angradXYZ euler angel array in radians + * @param angradXYZ euler angle array in radians * @return this quaternion for chaining. * @see #rotateByEuler(float, float, float) */ - public final Quaternion rotateByEuler(final float[] angradXYZ) { - return rotateByEuler(angradXYZ[0], angradXYZ[1], angradXYZ[2]); + public final Quaternion rotateByEuler(final Vec3f angradXYZ) { + return rotateByEuler(angradXYZ.x(), angradXYZ.y(), angradXYZ.z()); } /** @@ -450,48 +450,42 @@ public class Quaternion { /*** * Rotate the given vector by this quaternion + * @param vecIn vector to be rotated + * @param vecOut result storage for rotated vector, maybe equal to vecIn for in-place rotation * - * @param vecOut result float[3] storage for rotated vector, maybe equal to vecIn for in-place rotation - * @param vecOutOffset offset in result storage - * @param vecIn float[3] vector to be rotated - * @param vecInOffset offset in vecIn * @return the given vecOut store for chaining * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q63">Matrix-FAQ Q63</a> */ - public final float[] rotateVector(final float[] vecOut, final int vecOutOffset, final float[] vecIn, final int vecInOffset) { - if ( VectorUtil.isVec3Zero(vecIn, vecInOffset, FloatUtil.EPSILON) ) { - vecOut[0+vecOutOffset] = 0f; - vecOut[1+vecOutOffset] = 0f; - vecOut[2+vecOutOffset] = 0f; + public final Vec3f rotateVector(final Vec3f vecIn, final Vec3f vecOut) { + if( vecIn.isZero() ) { + vecOut.set(0, 0, 0); } else { - final float vecX = vecIn[0+vecInOffset]; - final float vecY = vecIn[1+vecInOffset]; - final float vecZ = vecIn[2+vecInOffset]; + final float vecX = vecIn.x(); + final float vecY = vecIn.y(); + final float vecZ = vecIn.z(); final float x_x = x*x; final float y_y = y*y; final float z_z = z*z; final float w_w = w*w; - vecOut[0+vecOutOffset] = w_w * vecX - + x_x * vecX - - z_z * vecX - - y_y * vecX - + 2f * ( y*w*vecZ - z*w*vecY + y*x*vecY + z*x*vecZ ); + vecOut.setX( w_w * vecX + + x_x * vecX + - z_z * vecX + - y_y * vecX + + 2f * ( y*w*vecZ - z*w*vecY + y*x*vecY + z*x*vecZ ) ); ; - vecOut[1+vecOutOffset] = y_y * vecY - - z_z * vecY - + w_w * vecY - - x_x * vecY - + 2f * ( x*y*vecX + z*y*vecZ + w*z*vecX - x*w*vecZ ); - ; - - vecOut[2+vecOutOffset] = z_z * vecZ - - y_y * vecZ - - x_x * vecZ - + w_w * vecZ - + 2f * ( x*z*vecX + y*z*vecY - w*y*vecX + w*x*vecY ); - ; + vecOut.setY( y_y * vecY + - z_z * vecY + + w_w * vecY + - x_x * vecY + + 2f * ( x*y*vecX + z*y*vecZ + w*z*vecX - x*w*vecZ ) );; + + vecOut.setZ( z_z * vecZ + - y_y * vecZ + - x_x * vecZ + + w_w * vecZ + + 2f * ( x*z*vecX + y*z*vecY - w*y*vecX + w*x*vecY ) ); } return vecOut; } @@ -593,21 +587,19 @@ public class Quaternion { * @return this quaternion for chaining. * @see <a href="http://www.euclideanspace.com/maths/algebra/vectors/lookat/index.htm">euclideanspace.com-LookUp</a> */ - public Quaternion setLookAt(final float[] directionIn, final float[] upIn, - final float[] xAxisOut, final float[] yAxisOut, final float[] zAxisOut) { + public Quaternion setLookAt(final Vec3f directionIn, final Vec3f upIn, + final Vec3f xAxisOut, final Vec3f yAxisOut, final Vec3f zAxisOut) { // Z = norm(dir) - VectorUtil.normalizeVec3(zAxisOut, directionIn); + zAxisOut.set(directionIn).normalize(); // X = upIn x Z // (borrow yAxisOut for upNorm) - VectorUtil.normalizeVec3(yAxisOut, upIn); - VectorUtil.crossVec3(xAxisOut, yAxisOut, zAxisOut); - VectorUtil.normalizeVec3(xAxisOut); + yAxisOut.set(upIn).normalize(); + xAxisOut.cross(yAxisOut, zAxisOut).normalize(); // Y = Z x X // - VectorUtil.crossVec3(yAxisOut, zAxisOut, xAxisOut); - VectorUtil.normalizeVec3(yAxisOut); + yAxisOut.cross(zAxisOut, xAxisOut).normalize(); /** final float m00 = xAxisOut[0]; @@ -642,42 +634,42 @@ public class Quaternion { * </p> * @param v1 not normalized * @param v2 not normalized - * @param tmpPivotVec float[3] temp storage for cross product - * @param tmpNormalVec float[3] temp storage to normalize vector + * @param tmpPivotVec temp storage for cross product + * @param tmpNormalVec temp storage to normalize vector * @return this quaternion for chaining. */ - public final Quaternion setFromVectors(final float[] v1, final float[] v2, final float[] tmpPivotVec, final float[] tmpNormalVec) { - final float factor = VectorUtil.normVec3(v1) * VectorUtil.normVec3(v2); + public final Quaternion setFromVectors(final Vec3f v1, final Vec3f v2, final Vec3f tmpPivotVec, final Vec3f tmpNormalVec) { + final float factor = v1.length() * v2.length(); if ( FloatUtil.isZero(factor, FloatUtil.EPSILON ) ) { return setIdentity(); } else { - final float dot = VectorUtil.dotVec3(v1, v2) / factor; // normalize + final float dot = v1.dot(v2) / factor; // normalize final float theta = FloatUtil.acos(Math.max(-1.0f, Math.min(dot, 1.0f))); // clipping [-1..1] - VectorUtil.crossVec3(tmpPivotVec, v1, v2); + tmpPivotVec.cross(v1, v2); - if ( dot < 0.0f && FloatUtil.isZero( VectorUtil.normVec3(tmpPivotVec), FloatUtil.EPSILON ) ) { + if ( dot < 0.0f && FloatUtil.isZero( tmpPivotVec.length(), FloatUtil.EPSILON ) ) { // Vectors parallel and opposite direction, therefore a rotation of 180 degrees about any vector // perpendicular to this vector will rotate vector a onto vector b. // // The following guarantees the dot-product will be 0.0. int dominantIndex; - if (Math.abs(v1[0]) > Math.abs(v1[1])) { - if (Math.abs(v1[0]) > Math.abs(v1[2])) { + if (Math.abs(v1.x()) > Math.abs(v1.y())) { + if (Math.abs(v1.x()) > Math.abs(v1.z())) { dominantIndex = 0; } else { dominantIndex = 2; } } else { - if (Math.abs(v1[1]) > Math.abs(v1[2])) { + if (Math.abs(v1.y()) > Math.abs(v1.z())) { dominantIndex = 1; } else { dominantIndex = 2; } } - tmpPivotVec[dominantIndex] = -v1[(dominantIndex + 1) % 3]; - tmpPivotVec[(dominantIndex + 1) % 3] = v1[dominantIndex]; - tmpPivotVec[(dominantIndex + 2) % 3] = 0f; + tmpPivotVec.set( dominantIndex, -v1.get( (dominantIndex + 1) % 3 ) ); + tmpPivotVec.set( (dominantIndex + 1) % 3, v1.get( dominantIndex ) ); + tmpPivotVec.set( (dominantIndex + 2) % 3, 0f ); } return setFromAngleAxis(theta, tmpPivotVec, tmpNormalVec); } @@ -698,41 +690,41 @@ public class Quaternion { * </p> * @param v1 normalized * @param v2 normalized - * @param tmpPivotVec float[3] temp storage for cross product + * @param tmpPivotVec temp storage for cross product * @return this quaternion for chaining. */ - public final Quaternion setFromNormalVectors(final float[] v1, final float[] v2, final float[] tmpPivotVec) { - final float factor = VectorUtil.normVec3(v1) * VectorUtil.normVec3(v2); + public final Quaternion setFromNormalVectors(final Vec3f v1, final Vec3f v2, final Vec3f tmpPivotVec) { + final float factor = v1.length() * v2.length(); if ( FloatUtil.isZero(factor, FloatUtil.EPSILON ) ) { return setIdentity(); } else { - final float dot = VectorUtil.dotVec3(v1, v2) / factor; // normalize + final float dot = v1.dot(v2) / factor; // normalize final float theta = FloatUtil.acos(Math.max(-1.0f, Math.min(dot, 1.0f))); // clipping [-1..1] - VectorUtil.crossVec3(tmpPivotVec, v1, v2); + tmpPivotVec.cross(v1, v2); - if ( dot < 0.0f && FloatUtil.isZero( VectorUtil.normVec3(tmpPivotVec), FloatUtil.EPSILON ) ) { + if ( dot < 0.0f && FloatUtil.isZero( tmpPivotVec.length(), FloatUtil.EPSILON ) ) { // Vectors parallel and opposite direction, therefore a rotation of 180 degrees about any vector // perpendicular to this vector will rotate vector a onto vector b. // // The following guarantees the dot-product will be 0.0. int dominantIndex; - if (Math.abs(v1[0]) > Math.abs(v1[1])) { - if (Math.abs(v1[0]) > Math.abs(v1[2])) { + if (Math.abs(v1.x()) > Math.abs(v1.y())) { + if (Math.abs(v1.x()) > Math.abs(v1.z())) { dominantIndex = 0; } else { dominantIndex = 2; } } else { - if (Math.abs(v1[1]) > Math.abs(v1[2])) { + if (Math.abs(v1.y()) > Math.abs(v1.z())) { dominantIndex = 1; } else { dominantIndex = 2; } } - tmpPivotVec[dominantIndex] = -v1[(dominantIndex + 1) % 3]; - tmpPivotVec[(dominantIndex + 1) % 3] = v1[dominantIndex]; - tmpPivotVec[(dominantIndex + 2) % 3] = 0f; + tmpPivotVec.set( dominantIndex, -v1.get( (dominantIndex + 1) % 3 ) ); + tmpPivotVec.set( (dominantIndex + 1) % 3, v1.get( dominantIndex ) ); + tmpPivotVec.set( (dominantIndex + 2) % 3, 0f ); } return setFromAngleNormalAxis(theta, tmpPivotVec); } @@ -748,14 +740,14 @@ public class Quaternion { * </p> * @param angle rotation angle (rads) * @param vector axis vector not normalized - * @param tmpV3f float[3] temp storage to normalize vector + * @param tmpV3f temp storage to normalize vector * @return this quaternion for chaining. * * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56">Matrix-FAQ Q56</a> - * @see #toAngleAxis(float[]) + * @see #toAngleAxis(Vec3f) */ - public final Quaternion setFromAngleAxis(final float angle, final float[] vector, final float[] tmpV3f) { - VectorUtil.normalizeVec3(tmpV3f, vector); + public final Quaternion setFromAngleAxis(final float angle, final Vec3f vector, final Vec3f tmpV3f) { + tmpV3f.set(vector).normalize(); return setFromAngleNormalAxis(angle, tmpV3f); } @@ -772,17 +764,17 @@ public class Quaternion { * @return this quaternion for chaining. * * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56">Matrix-FAQ Q56</a> - * @see #toAngleAxis(float[]) + * @see #toAngleAxis(Vec3f) */ - public final Quaternion setFromAngleNormalAxis(final float angle, final float[] vector) { - if ( VectorUtil.isVec3Zero(vector, 0, FloatUtil.EPSILON) ) { + public final Quaternion setFromAngleNormalAxis(final float angle, final Vec3f vector) { + if( vector.isZero() ) { setIdentity(); } else { final float halfangle = angle * 0.5f; final float sin = FloatUtil.sin(halfangle); - x = vector[0] * sin; - y = vector[1] * sin; - z = vector[2] * sin; + x = vector.x() * sin; + y = vector.y() * sin; + z = vector.z() * sin; w = FloatUtil.cos(halfangle); } return this; @@ -791,24 +783,22 @@ public class Quaternion { /** * Transform the rotational quaternion to axis based rotation angles * - * @param axis float[3] storage for computed axis + * @param axis storage for computed axis * @return the rotation angle in radians - * @see #setFromAngleAxis(float, float[], float[]) + * @see #setFromAngleAxis(float, Vec3f, Vec3f) */ - public final float toAngleAxis(final float[] axis) { + public final float toAngleAxis(final Vec3f axis) { final float sqrLength = x*x + y*y + z*z; float angle; if ( FloatUtil.isZero(sqrLength, FloatUtil.EPSILON) ) { // length is ~0 angle = 0.0f; - axis[0] = 1.0f; - axis[1] = 0.0f; - axis[2] = 0.0f; + axis.set( 1.0f, 0.0f, 0.0f ); } else { angle = FloatUtil.acos(w) * 2.0f; final float invLength = 1.0f / FloatUtil.sqrt(sqrLength); - axis[0] = x * invLength; - axis[1] = y * invLength; - axis[2] = z * invLength; + axis.set( x * invLength, + y * invLength, + z * invLength ); } return angle; } @@ -816,7 +806,7 @@ public class Quaternion { /** * Initializes this quaternion from the given Euler rotation array <code>angradXYZ</code> in radians. * <p> - * The <code>angradXYZ</code> array is laid out in natural order: + * The <code>angradXYZ</code> vector is laid out in natural order: * <ul> * <li>x - bank</li> * <li>y - heading</li> @@ -824,12 +814,12 @@ public class Quaternion { * </ul> * </p> * For details see {@link #setFromEuler(float, float, float)}. - * @param angradXYZ euler angel array in radians + * @param angradXYZ euler angle vector in radians holding x-bank, y-heading and z-attitude * @return this quaternion for chaining. * @see #setFromEuler(float, float, float) */ - public final Quaternion setFromEuler(final float[] angradXYZ) { - return setFromEuler(angradXYZ[0], angradXYZ[1], angradXYZ[2]); + public final Quaternion setFromEuler(final Vec3f angradXYZ) { + return setFromEuler(angradXYZ.x(), angradXYZ.y(), angradXYZ.z()); } /** @@ -857,7 +847,7 @@ public class Quaternion { * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60">Matrix-FAQ Q60</a> * @see <a href="http://vered.rose.utoronto.ca/people/david_dir/GEMS/GEMS.html">Gems</a> * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm">euclideanspace.com-eulerToQuaternion</a> - * @see #toEuler(float[]) + * @see #toEuler(Vec3f) */ public final Quaternion setFromEuler(final float bankX, final float headingY, final float attitudeZ) { if ( VectorUtil.isZero(bankX, headingY, attitudeZ, FloatUtil.EPSILON) ) { @@ -889,58 +879,45 @@ public class Quaternion { /** * Transform this quaternion to Euler rotation angles in radians (pitchX, yawY and rollZ). + * <p> + * The <code>result</code> array is laid out in natural order: + * <ul> + * <li>x - bank</li> + * <li>y - heading</li> + * <li>z - attitude</li> + * </ul> + * </p> * - * @param result the float[] array storing the computed angles. - * @return the double[] array, filled with heading, attitude and bank in that order.. + * @param result euler angle result vector for radians x-bank, y-heading and z-attitude + * @return the Vec3f `result` filled with x-bank, y-heading and z-attitude * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm">euclideanspace.com-quaternionToEuler</a> * @see #setFromEuler(float, float, float) */ - public float[] toEuler(final float[] result) { + public Vec3f toEuler(final Vec3f result) { final float sqw = w*w; final float sqx = x*x; final float sqy = y*y; final float sqz = z*z; - final float unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise - // is correction factor + final float unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise, is correction factor final float test = x*y + z*w; if (test > 0.499f * unit) { // singularity at north pole - result[0] = 0f; - result[1] = 2f * FloatUtil.atan2(x, w); - result[2] = FloatUtil.HALF_PI; + result.set( 0f, // x-bank + 2f * FloatUtil.atan2(x, w), // y-heading + FloatUtil.HALF_PI ); // z-attitude } else if (test < -0.499f * unit) { // singularity at south pole - result[0] = 0f; - result[1] = -2 * FloatUtil.atan2(x, w); - result[2] = -FloatUtil.HALF_PI; + result.set( 0f, // x-bank + -2 * FloatUtil.atan2(x, w), // y-heading + -FloatUtil.HALF_PI ); // z-attitude } else { - result[0] = FloatUtil.atan2(2f * x * w - 2 * y * z, -sqx + sqy - sqz + sqw); - result[1] = FloatUtil.atan2(2f * y * w - 2 * x * z, sqx - sqy - sqz + sqw); - result[2] = FloatUtil.asin( 2f * test / unit); + result.set( FloatUtil.atan2(2f * x * w - 2 * y * z, -sqx + sqy - sqz + sqw), // x-bank + FloatUtil.atan2(2f * y * w - 2 * x * z, sqx - sqy - sqz + sqw), // y-heading + FloatUtil.asin( 2f * test / unit) ); // z-attitude } return result; } /** - * Initializes this quaternion from a 4x4 column rotation matrix - * <p> - * See <a href="ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z">Graphics Gems Code</a>,<br/> - * <a href="http://mathworld.wolfram.com/MatrixTrace.html">MatrixTrace</a>. - * </p> - * <p> - * Buggy <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q55">Matrix-FAQ Q55</a> - * </p> - * - * @param m 4x4 column matrix - * @return this quaternion for chaining. - * @see #toMatrix(float[], int) - */ - public final Quaternion setFromMatrix(final float[] m, final int m_off) { - return setFromMatrix(m[0+0*4+m_off], m[0+1*4+m_off], m[0+2*4+m_off], - m[1+0*4+m_off], m[1+1*4+m_off], m[1+2*4+m_off], - m[2+0*4+m_off], m[2+1*4+m_off], m[2+2*4+m_off]); - } - - /** * Compute the quaternion from a 3x3 column rotation matrix * <p> * See <a href="ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z">Graphics Gems Code</a>,<br/> @@ -951,7 +928,7 @@ public class Quaternion { * </p> * * @return this quaternion for chaining. - * @see #toMatrix(float[], int) + * @see #setFromMatrix(Matrix4f) */ public Quaternion setFromMatrix(final float m00, final float m01, final float m02, final float m10, final float m11, final float m12, @@ -996,6 +973,24 @@ public class Quaternion { } /** + * Compute the quaternion from a 3x3 column rotation matrix + * <p> + * See <a href="ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z">Graphics Gems Code</a>,<br/> + * <a href="http://mathworld.wolfram.com/MatrixTrace.html">MatrixTrace</a>. + * </p> + * <p> + * Buggy <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q55">Matrix-FAQ Q55</a> + * </p> + * + * @return this quaternion for chaining. + * @see Matrix4f#getRotation(Quaternion) + * @see #setFromMatrix(float, float, float, float, float, float, float, float, float) + */ + public Quaternion setFromMatrix(final Matrix4f m) { + return m.getRotation(this); + } + + /** * Transform this quaternion to a normalized 4x4 column matrix representing the rotation. * <p> * Implementation Details: @@ -1008,7 +1003,8 @@ public class Quaternion { * @param mat_offset * @return the given matrix store * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a> - * @see #setFromMatrix(float[], int) + * @see #setFromMatrix(Matrix4f) + * @see #setFromMatrix(float, float, float, float, float, float, float, float, float) */ public final float[] toMatrix(final float[] matrix, final int mat_offset) { // pre-multiply scaled-reciprocal-magnitude to reduce multiplications @@ -1061,58 +1057,22 @@ public class Quaternion { } /** - * @param index the 3x3 rotation matrix column to retrieve from this quaternion (normalized). Must be between 0 and 2. - * @param result the vector object to store the result in. - * @return the result column-vector for chaining. + * 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 store for the resulting normalized column matrix 4x4 + * @return the given matrix store + * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a> + * @see #setFromMatrix(float, float, float, float, float, float, float, float, float) + * @see Matrix4f#setToRotation(Quaternion) */ - public float[] copyMatrixColumn(final int index, final float[] result, final int resultOffset) { - // pre-multipliy scaled-reciprocal-magnitude to reduce multiplications - final float norm = magnitudeSquared(); - final float srecip; - if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) { - srecip= 0f; - } else if ( FloatUtil.isEqual(1f, norm, FloatUtil.EPSILON) ) { - srecip= 2f; - } else { - srecip= 2.0f / norm; - } - - // compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs - // will be used 2-4 times each. - final float xs = x * srecip; - final float ys = y * srecip; - final float zs = z * srecip; - final float xx = x * xs; - final float xy = x * ys; - final float xz = x * zs; - final float xw = w * xs; - final float yy = y * ys; - final float yz = y * zs; - final float yw = w * ys; - final float zz = z * zs; - final float zw = w * zs; - - // using s=2/norm (instead of 1/norm) saves 3 multiplications by 2 here - switch (index) { - case 0: - result[0+resultOffset] = 1.0f - (yy + zz); - result[1+resultOffset] = xy + zw; - result[2+resultOffset] = xz - yw; - break; - case 1: - result[0+resultOffset] = xy - zw; - result[1+resultOffset] = 1.0f - (xx + zz); - result[2+resultOffset] = yz + xw; - break; - case 2: - result[0+resultOffset] = xz + yw; - result[1+resultOffset] = yz - xw; - result[2+resultOffset] = 1.0f - (xx + yy); - break; - default: - throw new IllegalArgumentException("Invalid column index. " + index); - } - return result; + public final Matrix4f toMatrix(final Matrix4f matrix) { + return matrix.setToRotation(this); } /** @@ -1126,10 +1086,10 @@ public class Quaternion { * @param zAxis vector representing the <i>orthogonal</i> z-axis of the coordinate system. * @return this quaternion for chaining. */ - public final Quaternion setFromAxes(final float[] xAxis, final float[] yAxis, final float[] zAxis) { - return setFromMatrix(xAxis[0], yAxis[0], zAxis[0], - xAxis[1], yAxis[1], zAxis[1], - xAxis[2], yAxis[2], zAxis[2]); + public final Quaternion setFromAxes(final Vec3f xAxis, final Vec3f yAxis, final Vec3f zAxis) { + return setFromMatrix(xAxis.x(), yAxis.x(), zAxis.x(), + xAxis.y(), yAxis.y(), zAxis.y(), + xAxis.z(), yAxis.z(), zAxis.z()); } /** @@ -1140,11 +1100,11 @@ public class Quaternion { * @param zAxis vector representing the <i>orthogonal</i> z-axis of the coordinate system. * @param tmpMat4 temporary float[4] matrix, used to transform this quaternion to a matrix. */ - public void toAxes(final float[] xAxis, final float[] yAxis, final float[] zAxis, final float[] tmpMat4) { - toMatrix(tmpMat4, 0); - FloatUtil.copyMatrixColumn(tmpMat4, 0, 2, zAxis, 0); - FloatUtil.copyMatrixColumn(tmpMat4, 0, 1, yAxis, 0); - FloatUtil.copyMatrixColumn(tmpMat4, 0, 0, xAxis, 0); + public void toAxes(final Vec3f xAxis, final Vec3f yAxis, final Vec3f zAxis, final Matrix4f tmpMat4) { + tmpMat4.setToRotation(this); + tmpMat4.getColumn(2, zAxis); + tmpMat4.getColumn(1, yAxis); + tmpMat4.getColumn(0, xAxis); } /** @@ -1154,6 +1114,7 @@ public class Quaternion { * @param m 3x3 column matrix * @return true if representing a rotational matrix, false otherwise */ + @Deprecated public final boolean isRotationMatrix3f(final float[] m) { final float epsilon = 0.01f; // margin to allow for rounding errors if (FloatUtil.abs(m[0] * m[3] + m[3] * m[4] + m[6] * m[7]) > epsilon) @@ -1171,6 +1132,7 @@ public class Quaternion { return (FloatUtil.abs(determinant3f(m) - 1) < epsilon); } + @Deprecated private final float determinant3f(final float[] m) { return m[0] * m[4] * m[8] + m[3] * m[7] * m[2] + m[6] * m[1] * m[5] - m[0] * m[7] * m[5] - m[3] * m[1] * m[8] - m[6] * m[4] * m[2]; @@ -1193,10 +1155,10 @@ public class Quaternion { return false; } final Quaternion comp = (Quaternion) o; - return Math.abs(x - comp.getX()) <= ALLOWED_DEVIANCE && - Math.abs(y - comp.getY()) <= ALLOWED_DEVIANCE && - Math.abs(z - comp.getZ()) <= ALLOWED_DEVIANCE && - Math.abs(w - comp.getW()) <= ALLOWED_DEVIANCE; + return Math.abs(x - comp.x()) <= ALLOWED_DEVIANCE && + Math.abs(y - comp.y()) <= ALLOWED_DEVIANCE && + Math.abs(z - comp.z()) <= ALLOWED_DEVIANCE && + Math.abs(w - comp.w()) <= ALLOWED_DEVIANCE; } @Override public final int hashCode() { |