/*
* (C) Copyright 2015-2017 JOML
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package org.joml;
//#ifdef __HAS_NIO__
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
//#endif
/**
* Interface to an immutable quaternion of single-precision floats.
*
* @author Kai Burjack
*/
public interface Quaternionfc {
/**
* @return the first component of the vector part
*/
float x();
/**
* @return the second component of the vector part
*/
float y();
/**
* @return the third component of the vector part
*/
float z();
/**
* @return the real/scalar part of the quaternion
*/
float w();
/**
* Normalize this quaternion and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Quaternionf normalize(Quaternionf dest);
/**
* Add the quaternion <tt>(x, y, z, w)</tt> to this quaternion and store the result in <code>dest</code>.
*
* @param x
* the x component of the vector part
* @param y
* the y component of the vector part
* @param z
* the z component of the vector part
* @param w
* the real/scalar component
* @param dest
* will hold the result
* @return dest
*/
Quaternionf add(float x, float y, float z, float w, Quaternionf dest);
/**
* Add <code>q2</code> to this quaternion and store the result in <code>dest</code>.
*
* @param q2
* the quaternion to add to this
* @param dest
* will hold the result
* @return dest
*/
Quaternionf add(Quaternionfc q2, Quaternionf dest);
/**
* Return the angle in radians represented by this quaternion rotation.
*
* @return the angle in radians
*/
float angle();
/**
* Set the given destination matrix to the rotation represented by <code>this</code>.
*
* @see Matrix3f#set(Quaternionfc)
*
* @param dest
* the matrix to write the rotation into
* @return the passed in destination
*/
Matrix3f get(Matrix3f dest);
/**
* Set the given destination matrix to the rotation represented by <code>this</code>.
*
* @see Matrix3d#set(Quaternionfc)
*
* @param dest
* the matrix to write the rotation into
* @return the passed in destination
*/
Matrix3d get(Matrix3d dest);
/**
* Set the given destination matrix to the rotation represented by <code>this</code>.
*
* @see Matrix4f#set(Quaternionfc)
*
* @param dest
* the matrix to write the rotation into
* @return the passed in destination
*/
Matrix4f get(Matrix4f dest);
/**
* Set the given destination matrix to the rotation represented by <code>this</code>.
*
* @see Matrix4d#set(Quaternionfc)
*
* @param dest
* the matrix to write the rotation into
* @return the passed in destination
*/
Matrix4d get(Matrix4d dest);
/**
* Set the given destination matrix to the rotation represented by <code>this</code>.
*
* @see Matrix4x3f#set(Quaternionfc)
*
* @param dest
* the matrix to write the rotation into
* @return the passed in destination
*/
Matrix4x3f get(Matrix4x3f dest);
/**
* Set the given destination matrix to the rotation represented by <code>this</code>.
*
* @see Matrix4x3d#set(Quaternionfc)
*
* @param dest
* the matrix to write the rotation into
* @return the passed in destination
*/
Matrix4x3d get(Matrix4x3d dest);
/**
* Set the given {@link AxisAngle4f} to represent the rotation of
* <code>this</code> quaternion.
*
* @param dest
* the {@link AxisAngle4f} to set
* @return the passed in destination
*/
AxisAngle4f get(AxisAngle4f dest);
/**
* Set the given {@link Quaterniond} to the values of <code>this</code>.
*
* @see Quaterniond#set(Quaternionfc)
*
* @param dest
* the {@link Quaterniond} to set
* @return the passed in destination
*/
Quaterniond get(Quaterniond dest);
/**
* Set the given {@link Quaternionf} to the values of <code>this</code>.
*
* @param dest
* the {@link Quaternionf} to set
* @return the passed in destination
*/
Quaternionf get(Quaternionf dest);
//#ifdef __HAS_NIO__
/**
* Store the 3x3 float matrix representation of <code>this</code> quaternion in column-major order into the given {@link ByteBuffer}.
* <p>
* This is equivalent to calling: <code>this.get(new Matrix3f()).get(dest)</code>
*
* @param dest
* the destination buffer
* @return dest
*/
ByteBuffer getAsMatrix3f(ByteBuffer dest);
/**
* Store the 3x3 float matrix representation of <code>this</code> quaternion in column-major order into the given {@link FloatBuffer}.
* <p>
* This is equivalent to calling: <code>this.get(new Matrix3f()).get(dest)</code>
*
* @param dest
* the destination buffer
* @return dest
*/
FloatBuffer getAsMatrix3f(FloatBuffer dest);
/**
* Store the 4x4 float matrix representation of <code>this</code> quaternion in column-major order into the given {@link ByteBuffer}.
* <p>
* This is equivalent to calling: <code>this.get(new Matrix4f()).get(dest)</code>
*
* @param dest
* the destination buffer
* @return dest
*/
ByteBuffer getAsMatrix4f(ByteBuffer dest);
/**
* Store the 4x4 float matrix representation of <code>this</code> quaternion in column-major order into the given {@link FloatBuffer}.
* <p>
* This is equivalent to calling: <code>this.get(new Matrix4f()).get(dest)</code>
*
* @param dest
* the destination buffer
* @return dest
*/
FloatBuffer getAsMatrix4f(FloatBuffer dest);
/**
* Store the 4x3 float matrix representation of <code>this</code> quaternion in column-major order into the given {@link ByteBuffer}.
* <p>
* This is equivalent to calling: <code>this.get(new Matrix4x3f()).get(dest)</code>
*
* @param dest
* the destination buffer
* @return dest
*/
ByteBuffer getAsMatrix4x3f(ByteBuffer dest);
/**
* Store the 4x3 float matrix representation of <code>this</code> quaternion in column-major order into the given {@link FloatBuffer}.
* <p>
* This is equivalent to calling: <code>this.get(new Matrix4x3f()).get(dest)</code>
*
* @param dest
* the destination buffer
* @return dest
*/
FloatBuffer getAsMatrix4x3f(FloatBuffer dest);
//#endif
/**
* Multiply this quaternion by <code>q</code> and store the result in <code>dest</code>.
* <p>
* If <tt>T</tt> is <code>this</code> and <tt>Q</tt> is the given
* quaternion, then the resulting quaternion <tt>R</tt> is:
* <p>
* <tt>R = T * Q</tt>
* <p>
* So, this method uses post-multiplication like the matrix classes, resulting in a
* vector to be transformed by <tt>Q</tt> first, and then by <tt>T</tt>.
*
* @param q
* the quaternion to multiply <code>this</code> by
* @param dest
* will hold the result
* @return dest
*/
Quaternionf mul(Quaternionfc q, Quaternionf dest);
/**
* Multiply this quaternion by the quaternion represented via <tt>(qx, qy, qz, qw)</tt> and store the result in <code>dest</code>.
* <p>
* If <tt>T</tt> is <code>this</code> and <tt>Q</tt> is the given
* quaternion, then the resulting quaternion <tt>R</tt> is:
* <p>
* <tt>R = T * Q</tt>
* <p>
* So, this method uses post-multiplication like the matrix classes, resulting in a
* vector to be transformed by <tt>Q</tt> first, and then by <tt>T</tt>.
*
* @param qx
* the x component of the quaternion to multiply <code>this</code> by
* @param qy
* the y component of the quaternion to multiply <code>this</code> by
* @param qz
* the z component of the quaternion to multiply <code>this</code> by
* @param qw
* the w component of the quaternion to multiply <code>this</code> by
* @param dest
* will hold the result
* @return dest
*/
Quaternionf mul(float qx, float qy, float qz, float qw, Quaternionf dest);
/**
* Pre-multiply this quaternion by <code>q</code> and store the result in <code>dest</code>.
* <p>
* If <tt>T</tt> is <code>this</code> and <tt>Q</tt> is the given quaternion, then the resulting quaternion <tt>R</tt> is:
* <p>
* <tt>R = Q * T</tt>
* <p>
* So, this method uses pre-multiplication, resulting in a vector to be transformed by <tt>T</tt> first, and then by <tt>Q</tt>.
*
* @param q
* the quaternion to pre-multiply <code>this</code> by
* @param dest
* will hold the result
* @return dest
*/
Quaternionf premul(Quaternionfc q, Quaternionf dest);
/**
* Pre-multiply this quaternion by the quaternion represented via <tt>(qx, qy, qz, qw)</tt> and store the result in <code>dest</code>.
* <p>
* If <tt>T</tt> is <code>this</code> and <tt>Q</tt> is the given quaternion, then the resulting quaternion <tt>R</tt> is:
* <p>
* <tt>R = Q * T</tt>
* <p>
* So, this method uses pre-multiplication, resulting in a vector to be transformed by <tt>T</tt> first, and then by <tt>Q</tt>.
*
* @param qx
* the x component of the quaternion to multiply <code>this</code> by
* @param qy
* the y component of the quaternion to multiply <code>this</code> by
* @param qz
* the z component of the quaternion to multiply <code>this</code> by
* @param qw
* the w component of the quaternion to multiply <code>this</code> by
* @param dest
* will hold the result
* @return dest
*/
Quaternionf premul(float qx, float qy, float qz, float qw, Quaternionf dest);
/**
* Transform the given vector by this quaternion.
* This will apply the rotation described by this quaternion to the given vector.
*
* @param vec
* the vector to transform
* @return vec
*/
Vector3f transform(Vector3f vec);
/**
* Transform the given vector by this quaternion.
* This will apply the rotation described by this quaternion to the given vector.
* <p>
* Only the first three components of the given 4D vector are being used and modified.
*
* @param vec
* the vector to transform
* @return vec
*/
Vector4f transform(Vector4f vec);
/**
* Transform the given vector by this quaternion and store the result in <code>dest</code>.
* This will apply the rotation described by this quaternion to the given vector.
*
* @param vec
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector3f transform(Vector3fc vec, Vector3f dest);
/**
* Transform the given vector <tt>(x, y, z)</tt> by this quaternion and store the result in <code>dest</code>.
* This will apply the rotation described by this quaternion to the given vector.
*
* @param x
* the x coordinate of the vector to transform
* @param y
* the y coordinate of the vector to transform
* @param z
* the z coordinate of the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector3f transform(float x, float y, float z, Vector3f dest);
/**
* Transform the given vector by this quaternion and store the result in <code>dest</code>.
* This will apply the rotation described by this quaternion to the given vector.
* <p>
* Only the first three components of the given 4D vector are being used and set on the destination.
*
* @param vec
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector4f transform(Vector4fc vec, Vector4f dest);
/**
* Transform the given vector <tt>(x, y, z)</tt> by this quaternion and store the result in <code>dest</code>.
* This will apply the rotation described by this quaternion to the given vector.
*
* @param x
* the x coordinate of the vector to transform
* @param y
* the y coordinate of the vector to transform
* @param z
* the z coordinate of the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector4f transform(float x, float y, float z, Vector4f dest);
/**
* Invert this quaternion and store the {@link #normalize(Quaternionf) normalized} result in <code>dest</code>.
* <p>
* If this quaternion is already normalized, then {@link #conjugate(Quaternionf)} should be used instead.
*
* @see #conjugate(Quaternionf)
*
* @param dest
* will hold the result
* @return dest
*/
Quaternionf invert(Quaternionf dest);
/**
* Divide <code>this</code> quaternion by <code>b</code> and store the result in <code>dest</code>.
* <p>
* The division expressed using the inverse is performed in the following way:
* <p>
* <tt>dest = this * b^-1</tt>, where <tt>b^-1</tt> is the inverse of <code>b</code>.
*
* @param b
* the {@link Quaternionfc} to divide this by
* @param dest
* will hold the result
* @return dest
*/
Quaternionf div(Quaternionfc b, Quaternionf dest);
/**
* Conjugate this quaternion and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Quaternionf conjugate(Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the cartesian base unit axes,
* called the euler angles using rotation sequence <tt>XYZ</tt> and store the result in <code>dest</code>.
* <p>
* This method is equivalent to calling: <tt>rotateX(angleX, dest).rotateY(angleY).rotateZ(angleZ)</tt>
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @param angleX
* the angle in radians to rotate about the x axis
* @param angleY
* the angle in radians to rotate about the y axis
* @param angleZ
* the angle in radians to rotate about the z axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateXYZ(float angleX, float angleY, float angleZ, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the cartesian base unit axes,
* called the euler angles, using the rotation sequence <tt>ZYX</tt> and store the result in <code>dest</code>.
* <p>
* This method is equivalent to calling: <tt>rotateZ(angleZ, dest).rotateY(angleY).rotateX(angleX)</tt>
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @param angleZ
* the angle in radians to rotate about the z axis
* @param angleY
* the angle in radians to rotate about the y axis
* @param angleX
* the angle in radians to rotate about the x axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateZYX(float angleZ, float angleY, float angleX, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the cartesian base unit axes,
* called the euler angles, using the rotation sequence <tt>YXZ</tt> and store the result in <code>dest</code>.
* <p>
* This method is equivalent to calling: <tt>rotateY(angleY, dest).rotateX(angleX).rotateZ(angleZ)</tt>
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @param angleY
* the angle in radians to rotate about the y axis
* @param angleX
* the angle in radians to rotate about the x axis
* @param angleZ
* the angle in radians to rotate about the z axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateYXZ(float angleY, float angleX, float angleZ, Quaternionf dest);
/**
* Get the euler angles in radians in rotation sequence <tt>XYZ</tt> of this quaternion and store them in the
* provided parameter <code>eulerAngles</code>.
*
* @param eulerAngles
* will hold the euler angles in radians
* @return the passed in vector
*/
Vector3f getEulerAnglesXYZ(Vector3f eulerAngles);
/**
* Return the square of the length of this quaternion.
*
* @return the length
*/
float lengthSquared();
/**
* Interpolate between <code>this</code> {@link #normalize(Quaternionf) unit} quaternion and the specified
* <code>target</code> {@link #normalize(Quaternionf) unit} quaternion using spherical linear interpolation using the specified interpolation factor <code>alpha</code>,
* and store the result in <code>dest</code>.
* <p>
* This method resorts to non-spherical linear interpolation when the absolute dot product of <code>this</code> and <code>target</code> is
* below <tt>1E-6f</tt>.
* <p>
* Reference: <a href="http://fabiensanglard.net/doom3_documentation/37725-293747_293747.pdf">http://fabiensanglard.net</a>
*
* @param target
* the target of the interpolation, which should be reached with <tt>alpha = 1.0</tt>
* @param alpha
* the interpolation factor, within <tt>[0..1]</tt>
* @param dest
* will hold the result
* @return dest
*/
Quaternionf slerp(Quaternionfc target, float alpha, Quaternionf dest);
/**
* Apply scaling to this quaternion, which results in any vector transformed by the quaternion to change
* its length by the given <code>factor</code>, and store the result in <code>dest</code>.
*
* @param factor
* the scaling factor
* @param dest
* will hold the result
* @return dest
*/
Quaternionf scale(float factor, Quaternionf dest);
/**
* Integrate the rotation given by the angular velocity <code>(vx, vy, vz)</code> around the x, y and z axis, respectively,
* with respect to the given elapsed time delta <code>dt</code> and add the differentiate rotation to the rotation represented by this quaternion
* and store the result into <code>dest</code>.
* <p>
* This method pre-multiplies the rotation given by <code>dt</code> and <code>(vx, vy, vz)</code> by <code>this</code>, so
* the angular velocities are always relative to the local coordinate system of the rotation represented by <code>this</code> quaternion.
* <p>
* This method is equivalent to calling: <code>rotateLocal(dt * vx, dt * vy, dt * vz, dest)</code>
* <p>
* Reference: <a href="http://physicsforgames.blogspot.de/2010/02/quaternions.html">http://physicsforgames.blogspot.de/</a>
*
* @see #rotateLocal(float, float, float, Quaternionf)
*
* @param dt
* the delta time
* @param vx
* the angular velocity around the x axis
* @param vy
* the angular velocity around the y axis
* @param vz
* the angular velocity around the z axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf integrate(float dt, float vx, float vy, float vz, Quaternionf dest);
/**
* Compute a linear (non-spherical) interpolation of <code>this</code> and the given quaternion <code>q</code>
* and store the result in <code>dest</code>.
* <p>
* Reference: <a href="http://fabiensanglard.net/doom3_documentation/37725-293747_293747.pdf">http://fabiensanglard.net</a>
*
* @param q
* the other quaternion
* @param factor
* the interpolation factor. It is between 0.0 and 1.0
* @param dest
* will hold the result
* @return dest
*/
Quaternionf nlerp(Quaternionfc q, float factor, Quaternionf dest);
/**
* Compute linear (non-spherical) interpolations of <code>this</code> and the given quaternion <code>q</code>
* iteratively and store the result in <code>dest</code>.
* <p>
* This method performs a series of small-step nlerp interpolations to avoid doing a costly spherical linear interpolation, like
* {@link #slerp(Quaternionfc, float, Quaternionf) slerp},
* by subdividing the rotation arc between <code>this</code> and <code>q</code> via non-spherical linear interpolations as long as
* the absolute dot product of <code>this</code> and <code>q</code> is greater than the given <code>dotThreshold</code> parameter.
* <p>
* Thanks to <tt>@theagentd</tt> at <a href="http://www.java-gaming.org/">http://www.java-gaming.org/</a> for providing the code.
*
* @param q
* the other quaternion
* @param alpha
* the interpolation factor, between 0.0 and 1.0
* @param dotThreshold
* the threshold for the dot product of <code>this</code> and <code>q</code> above which this method performs another iteration
* of a small-step linear interpolation
* @param dest
* will hold the result
* @return dest
*/
Quaternionf nlerpIterative(Quaternionfc q, float alpha, float dotThreshold, Quaternionf dest);
/**
* Apply a rotation to this quaternion that maps the given direction to the positive Z axis, and store the result in <code>dest</code>.
* <p>
* Because there are multiple possibilities for such a rotation, this method will choose the one that ensures the given up direction to remain
* parallel to the plane spanned by the <code>up</code> and <code>dir</code> vectors.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
* <p>
* Reference: <a href="http://answers.unity3d.com/questions/467614/what-is-the-source-code-of-quaternionlookrotation.html">http://answers.unity3d.com</a>
*
* @see #lookAlong(float, float, float, float, float, float, Quaternionf)
*
* @param dir
* the direction to map to the positive Z axis
* @param up
* the vector which will be mapped to a vector parallel to the plane
* spanned by the given <code>dir</code> and <code>up</code>
* @param dest
* will hold the result
* @return dest
*/
Quaternionf lookAlong(Vector3fc dir, Vector3fc up, Quaternionf dest);
/**
* Apply a rotation to this quaternion that maps the given direction to the positive Z axis, and store the result in <code>dest</code>.
* <p>
* Because there are multiple possibilities for such a rotation, this method will choose the one that ensures the given up direction to remain
* parallel to the plane spanned by the <tt>up</tt> and <tt>dir</tt> vectors.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
* <p>
* Reference: <a href="http://answers.unity3d.com/questions/467614/what-is-the-source-code-of-quaternionlookrotation.html">http://answers.unity3d.com</a>
*
* @param dirX
* the x-coordinate of the direction to look along
* @param dirY
* the y-coordinate of the direction to look along
* @param dirZ
* the z-coordinate of the direction to look along
* @param upX
* the x-coordinate of the up vector
* @param upY
* the y-coordinate of the up vector
* @param upZ
* the z-coordinate of the up vector
* @param dest
* will hold the result
* @return dest
*/
Quaternionf lookAlong(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> that rotates the <tt>fromDir</tt> vector to point along <tt>toDir</tt> and
* store the result in <code>dest</code>.
* <p>
* Since there can be multiple possible rotations, this method chooses the one with the shortest arc.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
* <p>
* Reference: <a href="http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another#answer-1171995">stackoverflow.com</a>
*
* @param fromDirX
* the x-coordinate of the direction to rotate into the destination direction
* @param fromDirY
* the y-coordinate of the direction to rotate into the destination direction
* @param fromDirZ
* the z-coordinate of the direction to rotate into the destination direction
* @param toDirX
* the x-coordinate of the direction to rotate to
* @param toDirY
* the y-coordinate of the direction to rotate to
* @param toDirZ
* the z-coordinate of the direction to rotate to
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateTo(float fromDirX, float fromDirY, float fromDirZ, float toDirX, float toDirY, float toDirZ, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> that rotates the <code>fromDir</code> vector to point along <code>toDir</code> and
* store the result in <code>dest</code>.
* <p>
* Because there can be multiple possible rotations, this method chooses the one with the shortest arc.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @see #rotateTo(float, float, float, float, float, float, Quaternionf)
*
* @param fromDir
* the starting direction
* @param toDir
* the destination direction
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateTo(Vector3fc fromDir, Vector3fc toDir, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the basis unit axes of the
* cartesian space and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @param angleX
* the angle in radians to rotate about the x axis
* @param angleY
* the angle in radians to rotate about the y axis
* @param angleZ
* the angle in radians to rotate about the z axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotate(float angleX, float angleY, float angleZ, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the basis unit axes of the
* local coordinate system represented by this quaternion and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>R * Q</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>R * Q * v</code>, the
* rotation represented by <code>this</code> will be applied first!
*
* @param angleX
* the angle in radians to rotate about the local x axis
* @param angleY
* the angle in radians to rotate about the local y axis
* @param angleZ
* the angle in radians to rotate about the local z axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateLocal(float angleX, float angleY, float angleZ, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the x axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @see #rotate(float, float, float, Quaternionf)
*
* @param angle
* the angle in radians to rotate about the x axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateX(float angle, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the y axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @see #rotate(float, float, float, Quaternionf)
*
* @param angle
* the angle in radians to rotate about the y axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateY(float angle, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the z axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @see #rotate(float, float, float, Quaternionf)
*
* @param angle
* the angle in radians to rotate about the z axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateZ(float angle, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the local x axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>R * Q</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>R * Q * v</code>, the
* rotation represented by <code>this</code> will be applied first!
*
* @param angle
* the angle in radians to rotate about the local x axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateLocalX(float angle, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the local y axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>R * Q</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>R * Q * v</code>, the
* rotation represented by <code>this</code> will be applied first!
*
* @param angle
* the angle in radians to rotate about the local y axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateLocalY(float angle, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the local z axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>R * Q</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>R * Q * v</code>, the
* rotation represented by <code>this</code> will be applied first!
*
* @param angle
* the angle in radians to rotate about the local z axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateLocalZ(float angle, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the specified axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @param angle
* the angle in radians to rotate about the specified axis
* @param axisX
* the x coordinate of the rotation axis
* @param axisY
* the y coordinate of the rotation axis
* @param axisZ
* the z coordinate of the rotation axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateAxis(float angle, float axisX, float axisY, float axisZ, Quaternionf dest);
/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the specified axis
* and store the result in <code>dest</code>.
* <p>
* If <code>Q</code> is <code>this</code> quaternion and <code>R</code> the quaternion representing the
* specified rotation, then the new quaternion will be <code>Q * R</code>. So when transforming a
* vector <code>v</code> with the new quaternion by using <code>Q * R * v</code>, the
* rotation added by this method will be applied first!
*
* @see #rotateAxis(float, float, float, float, Quaternionf)
*
* @param angle
* the angle in radians to rotate about the specified axis
* @param axis
* the rotation axis
* @param dest
* will hold the result
* @return dest
*/
Quaternionf rotateAxis(float angle, Vector3fc axis, Quaternionf dest);
/**
* Compute the difference between <code>this</code> and the <code>other</code> quaternion
* and store the result in <code>dest</code>.
* <p>
* The difference is the rotation that has to be applied to get from
* <code>this</code> rotation to <code>other</code>. If <tt>T</tt> is <code>this</code>, <tt>Q</tt>
* is <code>other</code> and <tt>D</tt> is the computed difference, then the following equation holds:
* <p>
* <tt>T * D = Q</tt>
* <p>
* It is defined as: <tt>D = T^-1 * Q</tt>, where <tt>T^-1</tt> denotes the {@link #invert(Quaternionf) inverse} of <tt>T</tt>.
*
* @param other
* the other quaternion
* @param dest
* will hold the result
* @return dest
*/
Quaternionf difference(Quaternionf other, Quaternionf dest);
/**
* Obtain the direction of <tt>+X</tt> before the rotation transformation represented by <code>this</code> quaternion is applied.
* <p>
* This method is equivalent to the following code:
* <pre>
* Quaternionf inv = new Quaternionf(this).invert();
* inv.transform(dir.set(1, 0, 0));
* </pre>
*
* @param dir
* will hold the direction of <tt>+X</tt>
* @return dir
*/
Vector3f positiveX(Vector3f dir);
/**
* Obtain the direction of <tt>+X</tt> before the rotation transformation represented by <code>this</code> <i>normalized</i> quaternion is applied.
* The quaternion <i>must</i> be {@link #normalize(Quaternionf) normalized} for this method to work.
* <p>
* This method is equivalent to the following code:
* <pre>
* Quaternionf inv = new Quaternionf(this).conjugate();
* inv.transform(dir.set(1, 0, 0));
* </pre>
*
* @param dir
* will hold the direction of <tt>+X</tt>
* @return dir
*/
Vector3f normalizedPositiveX(Vector3f dir);
/**
* Obtain the direction of <tt>+Y</tt> before the rotation transformation represented by <code>this</code> quaternion is applied.
* <p>
* This method is equivalent to the following code:
* <pre>
* Quaternionf inv = new Quaternionf(this).invert();
* inv.transform(dir.set(0, 1, 0));
* </pre>
*
* @param dir
* will hold the direction of <tt>+Y</tt>
* @return dir
*/
Vector3f positiveY(Vector3f dir);
/**
* Obtain the direction of <tt>+Y</tt> before the rotation transformation represented by <code>this</code> <i>normalized</i> quaternion is applied.
* The quaternion <i>must</i> be {@link #normalize(Quaternionf) normalized} for this method to work.
* <p>
* This method is equivalent to the following code:
* <pre>
* Quaternionf inv = new Quaternionf(this).conjugate();
* inv.transform(dir.set(0, 1, 0));
* </pre>
*
* @param dir
* will hold the direction of <tt>+Y</tt>
* @return dir
*/
Vector3f normalizedPositiveY(Vector3f dir);
/**
* Obtain the direction of <tt>+Z</tt> before the rotation transformation represented by <code>this</code> quaternion is applied.
* <p>
* This method is equivalent to the following code:
* <pre>
* Quaternionf inv = new Quaternionf(this).invert();
* inv.transform(dir.set(0, 0, 1));
* </pre>
*
* @param dir
* will hold the direction of <tt>+Z</tt>
* @return dir
*/
Vector3f positiveZ(Vector3f dir);
/**
* Obtain the direction of <tt>+Z</tt> before the rotation transformation represented by <code>this</code> <i>normalized</i> quaternion is applied.
* The quaternion <i>must</i> be {@link #normalize(Quaternionf) normalized} for this method to work.
* <p>
* This method is equivalent to the following code:
* <pre>
* Quaternionf inv = new Quaternionf(this).conjugate();
* inv.transform(dir.set(0, 0, 1));
* </pre>
*
* @param dir
* will hold the direction of <tt>+Z</tt>
* @return dir
*/
Vector3f normalizedPositiveZ(Vector3f dir);
}