/*
* (C) Copyright 2015-2017 Richard Greenlees
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;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
//#ifdef __HAS_NIO__
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
//#endif
import java.text.DecimalFormat;
import java.text.NumberFormat;
/**
* Contains the definition of a 3x3 matrix of doubles, and associated functions to transform
* it. The matrix is column-major to match OpenGL's interpretation, and it looks like this:
* <p>
* m00 m10 m20<br>
* m01 m11 m21<br>
* m02 m12 m22<br>
*
* @author Richard Greenlees
* @author Kai Burjack
*/
public class Matrix3d implements Externalizable, Matrix3dc {
private final class Proxy implements Matrix3dc {
private final Matrix3dc delegate;
Proxy(Matrix3dc delegate) {
this.delegate = delegate;
}
public double m00() {
return delegate.m00();
}
public double m01() {
return delegate.m01();
}
public double m02() {
return delegate.m02();
}
public double m10() {
return delegate.m10();
}
public double m11() {
return delegate.m11();
}
public double m12() {
return delegate.m12();
}
public double m20() {
return delegate.m20();
}
public double m21() {
return delegate.m21();
}
public double m22() {
return delegate.m22();
}
public Matrix3d mul(Matrix3dc right, Matrix3d dest) {
return delegate.mul(right, dest);
}
public Matrix3d mulLocal(Matrix3dc left, Matrix3d dest) {
return delegate.mulLocal(left, dest);
}
public Matrix3d mul(Matrix3fc right, Matrix3d dest) {
return delegate.mul(right, dest);
}
public double determinant() {
return delegate.determinant();
}
public Matrix3d invert(Matrix3d dest) {
return delegate.invert(dest);
}
public Matrix3d transpose(Matrix3d dest) {
return delegate.transpose(dest);
}
public Matrix3d get(Matrix3d dest) {
return delegate.get(dest);
}
public AxisAngle4f getRotation(AxisAngle4f dest) {
return delegate.getRotation(dest);
}
public Quaternionf getUnnormalizedRotation(Quaternionf dest) {
return delegate.getUnnormalizedRotation(dest);
}
public Quaternionf getNormalizedRotation(Quaternionf dest) {
return delegate.getNormalizedRotation(dest);
}
public Quaterniond getUnnormalizedRotation(Quaterniond dest) {
return delegate.getUnnormalizedRotation(dest);
}
public Quaterniond getNormalizedRotation(Quaterniond dest) {
return delegate.getNormalizedRotation(dest);
}
//#ifdef __HAS_NIO__
public DoubleBuffer get(DoubleBuffer buffer) {
return delegate.get(buffer);
}
public DoubleBuffer get(int index, DoubleBuffer buffer) {
return delegate.get(index, buffer);
}
public FloatBuffer get(FloatBuffer buffer) {
return delegate.get(buffer);
}
public FloatBuffer get(int index, FloatBuffer buffer) {
return delegate.get(index, buffer);
}
public ByteBuffer get(ByteBuffer buffer) {
return delegate.get(buffer);
}
public ByteBuffer get(int index, ByteBuffer buffer) {
return delegate.get(index, buffer);
}
public ByteBuffer getFloats(ByteBuffer buffer) {
return delegate.getFloats(buffer);
}
public ByteBuffer getFloats(int index, ByteBuffer buffer) {
return delegate.getFloats(index, buffer);
}
//#endif
public double[] get(double[] arr, int offset) {
return delegate.get(arr, offset);
}
public double[] get(double[] arr) {
return delegate.get(arr);
}
public float[] get(float[] arr, int offset) {
return delegate.get(arr, offset);
}
public float[] get(float[] arr) {
return delegate.get(arr);
}
public Matrix3d scale(Vector3dc xyz, Matrix3d dest) {
return delegate.scale(xyz, dest);
}
public Matrix3d scale(double x, double y, double z, Matrix3d dest) {
return delegate.scale(x, y, z, dest);
}
public Matrix3d scale(double xyz, Matrix3d dest) {
return delegate.scale(xyz, dest);
}
public Matrix3d scaleLocal(double x, double y, double z, Matrix3d dest) {
return delegate.scaleLocal(x, y, z, dest);
}
public Vector3d transform(Vector3d v) {
return delegate.transform(v);
}
public Vector3d transform(Vector3dc v, Vector3d dest) {
return delegate.transform(v, dest);
}
public Vector3f transform(Vector3f v) {
return delegate.transform(v);
}
public Vector3f transform(Vector3fc v, Vector3f dest) {
return delegate.transform(v, dest);
}
public Vector3d transform(double x, double y, double z, Vector3d dest) {
return delegate.transform(x, y, z, dest);
}
public Matrix3d rotateX(double ang, Matrix3d dest) {
return delegate.rotateX(ang, dest);
}
public Matrix3d rotateY(double ang, Matrix3d dest) {
return delegate.rotateY(ang, dest);
}
public Matrix3d rotateZ(double ang, Matrix3d dest) {
return delegate.rotateZ(ang, dest);
}
public Matrix3d rotateXYZ(double angleX, double angleY, double angleZ, Matrix3d dest) {
return delegate.rotateXYZ(angleX, angleY, angleZ, dest);
}
public Matrix3d rotateZYX(double angleZ, double angleY, double angleX, Matrix3d dest) {
return delegate.rotateZYX(angleZ, angleY, angleX, dest);
}
public Matrix3d rotateYXZ(double angleY, double angleX, double angleZ, Matrix3d dest) {
return delegate.rotateYXZ(angleY, angleX, angleZ, dest);
}
public Matrix3d rotate(double ang, double x, double y, double z, Matrix3d dest) {
return delegate.rotate(ang, x, y, z, dest);
}
public Matrix3d rotateLocal(double ang, double x, double y, double z, Matrix3d dest) {
return delegate.rotateLocal(ang, x, y, z, dest);
}
public Matrix3d rotateLocal(Quaterniondc quat, Matrix3d dest) {
return delegate.rotateLocal(quat, dest);
}
public Matrix3d rotateLocalX(double ang, Matrix3d dest) {
return delegate.rotateLocalX(ang, dest);
}
public Matrix3d rotateLocalY(double ang, Matrix3d dest) {
return delegate.rotateLocalY(ang, dest);
}
public Matrix3d rotateLocalZ(double ang, Matrix3d dest) {
return delegate.rotateLocalZ(ang, dest);
}
public Matrix3d rotateLocal(Quaternionfc quat, Matrix3d dest) {
return delegate.rotateLocal(quat, dest);
}
public Matrix3d rotate(Quaterniondc quat, Matrix3d dest) {
return delegate.rotate(quat, dest);
}
public Matrix3d rotate(Quaternionfc quat, Matrix3d dest) {
return delegate.rotate(quat, dest);
}
public Matrix3d rotate(AxisAngle4f axisAngle, Matrix3d dest) {
return delegate.rotate(axisAngle, dest);
}
public Matrix3d rotate(AxisAngle4d axisAngle, Matrix3d dest) {
return delegate.rotate(axisAngle, dest);
}
public Matrix3d rotate(double angle, Vector3dc axis, Matrix3d dest) {
return delegate.rotate(angle, axis, dest);
}
public Matrix3d rotate(double angle, Vector3fc axis, Matrix3d dest) {
return delegate.rotate(angle, axis, dest);
}
public Vector3d getRow(int row, Vector3d dest) throws IndexOutOfBoundsException {
return delegate.getRow(row, dest);
}
public Vector3d getColumn(int column, Vector3d dest) throws IndexOutOfBoundsException {
return delegate.getColumn(column, dest);
}
public double get(int column, int row) {
return delegate.get(column, row);
}
public Matrix3d normal(Matrix3d dest) {
return delegate.normal(dest);
}
public Matrix3d lookAlong(Vector3dc dir, Vector3dc up, Matrix3d dest) {
return delegate.lookAlong(dir, up, dest);
}
public Matrix3d lookAlong(double dirX, double dirY, double dirZ, double upX, double upY, double upZ, Matrix3d dest) {
return delegate.lookAlong(dirX, dirY, dirZ, upX, upY, upZ, dest);
}
public Vector3d getScale(Vector3d dest) {
return delegate.getScale(dest);
}
public Vector3d positiveZ(Vector3d dir) {
return delegate.positiveZ(dir);
}
public Vector3d normalizedPositiveZ(Vector3d dir) {
return delegate.normalizedPositiveZ(dir);
}
public Vector3d positiveX(Vector3d dir) {
return delegate.positiveX(dir);
}
public Vector3d normalizedPositiveX(Vector3d dir) {
return delegate.normalizedPositiveX(dir);
}
public Vector3d positiveY(Vector3d dir) {
return delegate.positiveY(dir);
}
public Vector3d normalizedPositiveY(Vector3d dir) {
return delegate.normalizedPositiveY(dir);
}
public Matrix3d add(Matrix3dc other, Matrix3d dest) {
return delegate.add(other, dest);
}
public Matrix3d sub(Matrix3dc subtrahend, Matrix3d dest) {
return delegate.sub(subtrahend, dest);
}
public Matrix3d mulComponentWise(Matrix3dc other, Matrix3d dest) {
return delegate.mulComponentWise(other, dest);
}
public Matrix3d lerp(Matrix3dc other, double t, Matrix3d dest) {
return delegate.lerp(other, t, dest);
}
public Matrix3d rotateTowards(Vector3dc direction, Vector3dc up, Matrix3d dest) {
return delegate.rotateTowards(direction, up, dest);
}
public Matrix3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ, Matrix3d dest) {
return delegate.rotateTowards(dirX, dirY, dirZ, upX, upY, upZ, dest);
}
public Vector3d getEulerAnglesZYX(Vector3d dest) {
return delegate.getEulerAnglesZYX(dest);
}
}
private static final long serialVersionUID = 1L;
public double m00, m01, m02;
public double m10, m11, m12;
public double m20, m21, m22;
/**
* Create a new {@link Matrix3d} and initialize it to {@link #identity() identity}.
*/
public Matrix3d() {
m00 = 1.0;
m11 = 1.0;
m22 = 1.0;
}
/**
* Create a new {@link Matrix3d} and initialize it with the values from the given matrix.
*
* @param mat
* the matrix to initialize this matrix with
*/
public Matrix3d(Matrix3dc mat) {
m00 = mat.m00();
m01 = mat.m01();
m02 = mat.m02();
m10 = mat.m10();
m11 = mat.m11();
m12 = mat.m12();
m20 = mat.m20();
m21 = mat.m21();
m22 = mat.m22();
}
/**
* Create a new {@link Matrix3d} and initialize it with the values from the given matrix.
*
* @param mat
* the matrix to initialize this matrix with
*/
public Matrix3d(Matrix3fc mat) {
m00 = mat.m00();
m01 = mat.m01();
m02 = mat.m02();
m10 = mat.m10();
m11 = mat.m11();
m12 = mat.m12();
m20 = mat.m20();
m21 = mat.m21();
m22 = mat.m22();
}
/**
* Create a new {@link Matrix3d} and make it a copy of the upper left 3x3 of the given {@link Matrix4fc}.
*
* @param mat
* the {@link Matrix4fc} to copy the values from
*/
public Matrix3d(Matrix4fc mat) {
m00 = mat.m00();
m01 = mat.m01();
m02 = mat.m02();
m10 = mat.m10();
m11 = mat.m11();
m12 = mat.m12();
m20 = mat.m20();
m21 = mat.m21();
m22 = mat.m22();
}
/**
* Create a new {@link Matrix3d} and make it a copy of the upper left 3x3 of the given {@link Matrix4dc}.
*
* @param mat
* the {@link Matrix4dc} to copy the values from
*/
public Matrix3d(Matrix4dc mat) {
m00 = mat.m00();
m01 = mat.m01();
m02 = mat.m02();
m10 = mat.m10();
m11 = mat.m11();
m12 = mat.m12();
m20 = mat.m20();
m21 = mat.m21();
m22 = mat.m22();
}
/**
* Create a new {@link Matrix3d} and initialize its elements with the given values.
*
* @param m00
* the value of m00
* @param m01
* the value of m01
* @param m02
* the value of m02
* @param m10
* the value of m10
* @param m11
* the value of m11
* @param m12
* the value of m12
* @param m20
* the value of m20
* @param m21
* the value of m21
* @param m22
* the value of m22
*/
public Matrix3d(double m00, double m01, double m02,
double m10, double m11, double m12,
double m20, double m21, double m22) {
this.m00 = m00;
this.m01 = m01;
this.m02 = m02;
this.m10 = m10;
this.m11 = m11;
this.m12 = m12;
this.m20 = m20;
this.m21 = m21;
this.m22 = m22;
}
//#ifdef __HAS_NIO__
/**
* Create a new {@link Matrix3d} by reading its 9 double components from the given {@link DoubleBuffer}
* at the buffer's current position.
* <p>
* That DoubleBuffer is expected to hold the values in column-major order.
* <p>
* The buffer's position will not be changed by this method.
*
* @param buffer
* the {@link DoubleBuffer} to read the matrix values from
*/
public Matrix3d(DoubleBuffer buffer) {
MemUtil.INSTANCE.get(this, buffer.position(), buffer);
}
//#endif
/**
* Create a new {@link Matrix3d} and initialize its three columns using the supplied vectors.
*
* @param col0
* the first column
* @param col1
* the second column
* @param col2
* the third column
*/
public Matrix3d(Vector3dc col0, Vector3dc col1, Vector3dc col2) {
this.m00 = col0.x();
this.m01 = col0.y();
this.m02 = col0.z();
this.m10 = col1.x();
this.m11 = col1.y();
this.m12 = col1.z();
this.m20 = col2.x();
this.m21 = col2.y();
this.m22 = col2.z();
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m00()
*/
public double m00() {
return m00;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m01()
*/
public double m01() {
return m01;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m02()
*/
public double m02() {
return m02;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m10()
*/
public double m10() {
return m10;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m11()
*/
public double m11() {
return m11;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m12()
*/
public double m12() {
return m12;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m20()
*/
public double m20() {
return m20;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m21()
*/
public double m21() {
return m21;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#m22()
*/
public double m22() {
return m22;
}
/**
* Set the value of the matrix element at column 0 and row 0
*
* @param m00
* the new value
* @return the value of the matrix element
*/
public Matrix3d m00(double m00) {
this.m00 = m00;
return this;
}
/**
* Set the value of the matrix element at column 0 and row 1
*
* @param m01
* the new value
* @return the value of the matrix element
*/
public Matrix3d m01(double m01) {
this.m01 = m01;
return this;
}
/**
* Set the value of the matrix element at column 0 and row 2
*
* @param m02
* the new value
* @return the value of the matrix element
*/
public Matrix3d m02(double m02) {
this.m02 = m02;
return this;
}
/**
* Set the value of the matrix element at column 1 and row 0
*
* @param m10
* the new value
* @return the value of the matrix element
*/
public Matrix3d m10(double m10) {
this.m10 = m10;
return this;
}
/**
* Set the value of the matrix element at column 1 and row 1
*
* @param m11
* the new value
* @return the value of the matrix element
*/
public Matrix3d m11(double m11) {
this.m11 = m11;
return this;
}
/**
* Set the value of the matrix element at column 1 and row 2
*
* @param m12
* the new value
* @return the value of the matrix element
*/
public Matrix3d m12(double m12) {
this.m12 = m12;
return this;
}
/**
* Set the value of the matrix element at column 2 and row 0
*
* @param m20
* the new value
* @return the value of the matrix element
*/
public Matrix3d m20(double m20) {
this.m20 = m20;
return this;
}
/**
* Set the value of the matrix element at column 2 and row 1
*
* @param m21
* the new value
* @return the value of the matrix element
*/
public Matrix3d m21(double m21) {
this.m21 = m21;
return this;
}
/**
* Set the value of the matrix element at column 2 and row 2
*
* @param m22
* the new value
* @return the value of the matrix element
*/
public Matrix3d m22(double m22) {
this.m22 = m22;
return this;
}
/**
* Set the values in this matrix to the ones in m.
*
* @param m
* the matrix whose values will be copied
* @return this
*/
public Matrix3d set(Matrix3dc m) {
m00 = m.m00();
m01 = m.m01();
m02 = m.m02();
m10 = m.m10();
m11 = m.m11();
m12 = m.m12();
m20 = m.m20();
m21 = m.m21();
m22 = m.m22();
return this;
}
/**
* Set the values in this matrix to the ones in m.
*
* @param m
* the matrix whose values will be copied
* @return this
*/
public Matrix3d set(Matrix3fc m) {
m00 = m.m00();
m01 = m.m01();
m02 = m.m02();
m10 = m.m10();
m11 = m.m11();
m12 = m.m12();
m20 = m.m20();
m21 = m.m21();
m22 = m.m22();
return this;
}
/**
* Set the elements of this matrix to the upper left 3x3 of the given {@link Matrix4fc}.
*
* @param mat
* the {@link Matrix4fc} to copy the values from
* @return this
*/
public Matrix3d set(Matrix4fc mat) {
m00 = mat.m00();
m01 = mat.m01();
m02 = mat.m02();
m10 = mat.m10();
m11 = mat.m11();
m12 = mat.m12();
m20 = mat.m20();
m21 = mat.m21();
m22 = mat.m22();
return this;
}
/**
* Set the elements of this matrix to the upper left 3x3 of the given {@link Matrix4dc}.
*
* @param mat
* the {@link Matrix4dc} to copy the values from
* @return this
*/
public Matrix3d set(Matrix4dc mat) {
m00 = mat.m00();
m01 = mat.m01();
m02 = mat.m02();
m10 = mat.m10();
m11 = mat.m11();
m12 = mat.m12();
m20 = mat.m20();
m21 = mat.m21();
m22 = mat.m22();
return this;
}
/**
* Set this matrix to be equivalent to the rotation specified by the given {@link AxisAngle4f}.
*
* @param axisAngle
* the {@link AxisAngle4f}
* @return this
*/
public Matrix3d set(AxisAngle4f axisAngle) {
double x = axisAngle.x;
double y = axisAngle.y;
double z = axisAngle.z;
double angle = axisAngle.angle;
double invLength = 1.0 / Math.sqrt(x*x + y*y + z*z);
x *= invLength;
y *= invLength;
z *= invLength;
double s = Math.sin(angle);
double c = Math.cosFromSin(s, angle);
double omc = 1.0 - c;
m00 = c + x*x*omc;
m11 = c + y*y*omc;
m22 = c + z*z*omc;
double tmp1 = x*y*omc;
double tmp2 = z*s;
m10 = tmp1 - tmp2;
m01 = tmp1 + tmp2;
tmp1 = x*z*omc;
tmp2 = y*s;
m20 = tmp1 + tmp2;
m02 = tmp1 - tmp2;
tmp1 = y*z*omc;
tmp2 = x*s;
m21 = tmp1 - tmp2;
m12 = tmp1 + tmp2;
return this;
}
/**
* Set this matrix to be equivalent to the rotation specified by the given {@link AxisAngle4d}.
*
* @param axisAngle
* the {@link AxisAngle4d}
* @return this
*/
public Matrix3d set(AxisAngle4d axisAngle) {
double x = axisAngle.x;
double y = axisAngle.y;
double z = axisAngle.z;
double angle = axisAngle.angle;
double invLength = 1.0 / Math.sqrt(x*x + y*y + z*z);
x *= invLength;
y *= invLength;
z *= invLength;
double s = Math.sin(angle);
double c = Math.cosFromSin(s, angle);
double omc = 1.0 - c;
m00 = c + x*x*omc;
m11 = c + y*y*omc;
m22 = c + z*z*omc;
double tmp1 = x*y*omc;
double tmp2 = z*s;
m10 = tmp1 - tmp2;
m01 = tmp1 + tmp2;
tmp1 = x*z*omc;
tmp2 = y*s;
m20 = tmp1 + tmp2;
m02 = tmp1 - tmp2;
tmp1 = y*z*omc;
tmp2 = x*s;
m21 = tmp1 - tmp2;
m12 = tmp1 + tmp2;
return this;
}
/**
* Set this matrix to a rotation - and possibly scaling - equivalent to the given quaternion.
* <p>
* This method is equivalent to calling: <tt>rotation(q)</tt>
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/">http://www.euclideanspace.com/</a>
*
* @see #rotation(Quaternionfc)
*
* @param q
* the quaternion
* @return this
*/
public Matrix3d set(Quaternionfc q) {
return rotation(q);
}
/**
* Set this matrix to a rotation - and possibly scaling - equivalent to the given quaternion.
* <p>
* This method is equivalent to calling: <tt>rotation(q)</tt>
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/">http://www.euclideanspace.com/</a>
*
* @see #rotation(Quaterniondc)
*
* @param q
* the quaternion
* @return this
*/
public Matrix3d set(Quaterniondc q) {
return rotation(q);
}
/**
* Multiply this matrix by the supplied matrix.
* This matrix will be the left one.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* transformation of the right matrix will be applied first!
*
* @param right
* the right operand
* @return this
*/
public Matrix3d mul(Matrix3dc right) {
return mul(right, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#mul(org.joml.Matrix3dc, org.joml.Matrix3d)
*/
public Matrix3d mul(Matrix3dc right, Matrix3d dest) {
double nm00 = m00 * right.m00() + m10 * right.m01() + m20 * right.m02();
double nm01 = m01 * right.m00() + m11 * right.m01() + m21 * right.m02();
double nm02 = m02 * right.m00() + m12 * right.m01() + m22 * right.m02();
double nm10 = m00 * right.m10() + m10 * right.m11() + m20 * right.m12();
double nm11 = m01 * right.m10() + m11 * right.m11() + m21 * right.m12();
double nm12 = m02 * right.m10() + m12 * right.m11() + m22 * right.m12();
double nm20 = m00 * right.m20() + m10 * right.m21() + m20 * right.m22();
double nm21 = m01 * right.m20() + m11 * right.m21() + m21 * right.m22();
double nm22 = m02 * right.m20() + m12 * right.m21() + m22 * right.m22();
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Pre-multiply this matrix by the supplied <code>left</code> matrix and store the result in <code>this</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the <code>left</code> matrix,
* then the new matrix will be <code>L * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>L * M * v</code>, the
* transformation of <code>this</code> matrix will be applied first!
*
* @param left
* the left operand of the matrix multiplication
* @return this
*/
public Matrix3d mulLocal(Matrix3dc left) {
return mulLocal(left, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#mulLocal(org.joml.Matrix3dc, org.joml.Matrix3d)
*/
public Matrix3d mulLocal(Matrix3dc left, Matrix3d dest) {
double nm00 = left.m00() * m00 + left.m10() * m01 + left.m20() * m02;
double nm01 = left.m01() * m00 + left.m11() * m01 + left.m20() * m02;
double nm10 = left.m00() * m10 + left.m10() * m11 + left.m20() * m12;
double nm11 = left.m01() * m10 + left.m11() * m11 + left.m20() * m12;
double nm20 = left.m00() * m20 + left.m10() * m21 + left.m20() * m22;
double nm21 = left.m01() * m20 + left.m11() * m21 + left.m21() * m22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m20 = nm20;
dest.m21 = nm21;
return dest;
}
/**
* Multiply this matrix by the supplied matrix.
* This matrix will be the left one.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* transformation of the right matrix will be applied first!
*
* @param right
* the right operand
* @return this
*/
public Matrix3d mul(Matrix3fc right) {
return mul(right, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#mul(org.joml.Matrix3fc, org.joml.Matrix3d)
*/
public Matrix3d mul(Matrix3fc right, Matrix3d dest) {
double nm00 = m00 * right.m00() + m10 * right.m01() + m20 * right.m02();
double nm01 = m01 * right.m00() + m11 * right.m01() + m21 * right.m02();
double nm02 = m02 * right.m00() + m12 * right.m01() + m22 * right.m02();
double nm10 = m00 * right.m10() + m10 * right.m11() + m20 * right.m12();
double nm11 = m01 * right.m10() + m11 * right.m11() + m21 * right.m12();
double nm12 = m02 * right.m10() + m12 * right.m11() + m22 * right.m12();
double nm20 = m00 * right.m20() + m10 * right.m21() + m20 * right.m22();
double nm21 = m01 * right.m20() + m11 * right.m21() + m21 * right.m22();
double nm22 = m02 * right.m20() + m12 * right.m21() + m22 * right.m22();
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Set the values within this matrix to the supplied double values. The result looks like this:
* <p>
* m00, m10, m20<br>
* m01, m11, m21<br>
* m02, m12, m22<br>
*
* @param m00
* the new value of m00
* @param m01
* the new value of m01
* @param m02
* the new value of m02
* @param m10
* the new value of m10
* @param m11
* the new value of m11
* @param m12
* the new value of m12
* @param m20
* the new value of m20
* @param m21
* the new value of m21
* @param m22
* the new value of m22
* @return this
*/
public Matrix3d set(double m00, double m01, double m02,
double m10, double m11, double m12,
double m20, double m21, double m22) {
this.m00 = m00;
this.m01 = m01;
this.m02 = m02;
this.m10 = m10;
this.m11 = m11;
this.m12 = m12;
this.m20 = m20;
this.m21 = m21;
this.m22 = m22;
return this;
}
/**
* Set the values in this matrix based on the supplied double array. The result looks like this:
* <p>
* 0, 3, 6<br>
* 1, 4, 7<br>
* 2, 5, 8<br>
* <p>
* Only uses the first 9 values, all others are ignored.
*
* @param m
* the array to read the matrix values from
* @return this
*/
public Matrix3d set(double m[]) {
m00 = m[0];
m01 = m[1];
m02 = m[2];
m10 = m[3];
m11 = m[4];
m12 = m[5];
m20 = m[6];
m21 = m[7];
m22 = m[8];
return this;
}
/**
* Set the values in this matrix based on the supplied double array. The result looks like this:
* <p>
* 0, 3, 6<br>
* 1, 4, 7<br>
* 2, 5, 8<br>
* <p>
* Only uses the first 9 values, all others are ignored
*
* @param m
* the array to read the matrix values from
* @return this
*/
public Matrix3d set(float m[]) {
m00 = m[0];
m01 = m[1];
m02 = m[2];
m10 = m[3];
m11 = m[4];
m12 = m[5];
m20 = m[6];
m21 = m[7];
m22 = m[8];
return this;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#determinant()
*/
public double determinant() {
return (m00 * m11 - m01 * m10) * m22
+ (m02 * m10 - m00 * m12) * m21
+ (m01 * m12 - m02 * m11) * m20;
}
/**
* Invert this matrix.
*
* @return this
*/
public Matrix3d invert() {
return invert(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#invert(org.joml.Matrix3d)
*/
public Matrix3d invert(Matrix3d dest) {
double s = determinant();
// client must make sure that matrix is invertible
s = 1.0 / s;
double nm00 = (m11 * m22 - m21 * m12) * s;
double nm01 = (m21 * m02 - m01 * m22) * s;
double nm02 = (m01 * m12 - m11 * m02) * s;
double nm10 = (m20 * m12 - m10 * m22) * s;
double nm11 = (m00 * m22 - m20 * m02) * s;
double nm12 = (m10 * m02 - m00 * m12) * s;
double nm20 = (m10 * m21 - m20 * m11) * s;
double nm21 = (m20 * m01 - m00 * m21) * s;
double nm22 = (m00 * m11 - m10 * m01) * s;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Transpose this matrix.
*
* @return this
*/
public Matrix3d transpose() {
return transpose(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#transpose(org.joml.Matrix3d)
*/
public Matrix3d transpose(Matrix3d dest) {
dest.set(m00, m10, m20,
m01, m11, m21,
m02, m12, m22);
return dest;
}
/**
* Return a string representation of this matrix.
* <p>
* This method creates a new {@link DecimalFormat} on every invocation with the format string "<tt>0.000E0;-</tt>".
*
* @return the string representation
*/
public String toString() {
DecimalFormat formatter = new DecimalFormat(" 0.000E0;-");
String str = toString(formatter);
StringBuffer res = new StringBuffer();
int eIndex = Integer.MIN_VALUE;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == 'E') {
eIndex = i;
} else if (c == ' ' && eIndex == i - 1) {
// workaround Java 1.4 DecimalFormat bug
res.append('+');
continue;
} else if (Character.isDigit(c) && eIndex == i - 1) {
res.append('+');
}
res.append(c);
}
return res.toString();
}
/**
* Return a string representation of this matrix by formatting the matrix elements with the given {@link NumberFormat}.
*
* @param formatter
* the {@link NumberFormat} used to format the matrix values with
* @return the string representation
*/
public String toString(NumberFormat formatter) {
return formatter.format(m00) + " " + formatter.format(m10) + " " + formatter.format(m20) + "\n"
+ formatter.format(m01) + " " + formatter.format(m11) + " " + formatter.format(m21) + "\n"
+ formatter.format(m02) + " " + formatter.format(m12) + " " + formatter.format(m22) + "\n";
}
/**
* Get the current values of <code>this</code> matrix and store them into
* <code>dest</code>.
* <p>
* This is the reverse method of {@link #set(Matrix3dc)} and allows to obtain
* intermediate calculation results when chaining multiple transformations.
*
* @see #set(Matrix3dc)
*
* @param dest
* the destination matrix
* @return the passed in destination
*/
public Matrix3d get(Matrix3d dest) {
return dest.set(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getRotation(org.joml.AxisAngle4f)
*/
public AxisAngle4f getRotation(AxisAngle4f dest) {
return dest.set(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getUnnormalizedRotation(org.joml.Quaternionf)
*/
public Quaternionf getUnnormalizedRotation(Quaternionf dest) {
return dest.setFromUnnormalized(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getNormalizedRotation(org.joml.Quaternionf)
*/
public Quaternionf getNormalizedRotation(Quaternionf dest) {
return dest.setFromNormalized(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getUnnormalizedRotation(org.joml.Quaterniond)
*/
public Quaterniond getUnnormalizedRotation(Quaterniond dest) {
return dest.setFromUnnormalized(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getNormalizedRotation(org.joml.Quaterniond)
*/
public Quaterniond getNormalizedRotation(Quaterniond dest) {
return dest.setFromNormalized(this);
}
//#ifdef __HAS_NIO__
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(java.nio.DoubleBuffer)
*/
public DoubleBuffer get(DoubleBuffer buffer) {
return get(buffer.position(), buffer);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(int, java.nio.DoubleBuffer)
*/
public DoubleBuffer get(int index, DoubleBuffer buffer) {
MemUtil.INSTANCE.put(this, index, buffer);
return buffer;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(java.nio.FloatBuffer)
*/
public FloatBuffer get(FloatBuffer buffer) {
return get(buffer.position(), buffer);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(int, java.nio.FloatBuffer)
*/
public FloatBuffer get(int index, FloatBuffer buffer) {
MemUtil.INSTANCE.putf(this, index, buffer);
return buffer;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(java.nio.ByteBuffer)
*/
public ByteBuffer get(ByteBuffer buffer) {
return get(buffer.position(), buffer);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(int, java.nio.ByteBuffer)
*/
public ByteBuffer get(int index, ByteBuffer buffer) {
MemUtil.INSTANCE.put(this, index, buffer);
return buffer;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getFloats(java.nio.ByteBuffer)
*/
public ByteBuffer getFloats(ByteBuffer buffer) {
return getFloats(buffer.position(), buffer);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getFloats(int, java.nio.ByteBuffer)
*/
public ByteBuffer getFloats(int index, ByteBuffer buffer) {
MemUtil.INSTANCE.putf(this, index, buffer);
return buffer;
}
//#endif
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(double[], int)
*/
public double[] get(double[] arr, int offset) {
arr[offset+0] = m00;
arr[offset+1] = m01;
arr[offset+2] = m02;
arr[offset+3] = m10;
arr[offset+4] = m11;
arr[offset+5] = m12;
arr[offset+6] = m20;
arr[offset+7] = m21;
arr[offset+8] = m22;
return arr;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(double[])
*/
public double[] get(double[] arr) {
return get(arr, 0);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(float[], int)
*/
public float[] get(float[] arr, int offset) {
arr[offset+0] = (float)m00;
arr[offset+1] = (float)m01;
arr[offset+2] = (float)m02;
arr[offset+3] = (float)m10;
arr[offset+4] = (float)m11;
arr[offset+5] = (float)m12;
arr[offset+6] = (float)m20;
arr[offset+7] = (float)m21;
arr[offset+8] = (float)m22;
return arr;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#get(float[])
*/
public float[] get(float[] arr) {
return get(arr, 0);
}
//#ifdef __HAS_NIO__
/**
* Set the values of this matrix by reading 9 double values from the given {@link DoubleBuffer} in column-major order,
* starting at its current position.
* <p>
* The DoubleBuffer is expected to contain the values in column-major order.
* <p>
* The position of the DoubleBuffer will not be changed by this method.
*
* @param buffer
* the DoubleBuffer to read the matrix values from in column-major order
* @return this
*/
public Matrix3d set(DoubleBuffer buffer) {
MemUtil.INSTANCE.get(this, buffer.position(), buffer);
return this;
}
/**
* Set the values of this matrix by reading 9 float values from the given {@link FloatBuffer} in column-major order,
* starting at its current position.
* <p>
* The FloatBuffer is expected to contain the values in column-major order.
* <p>
* The position of the FloatBuffer will not be changed by this method.
*
* @param buffer
* the FloatBuffer to read the matrix values from in column-major order
* @return this
*/
public Matrix3d set(FloatBuffer buffer) {
MemUtil.INSTANCE.getf(this, buffer.position(), buffer);
return this;
}
/**
* Set the values of this matrix by reading 9 double values from the given {@link ByteBuffer} in column-major order,
* starting at its current position.
* <p>
* The ByteBuffer is expected to contain the values in column-major order.
* <p>
* The position of the ByteBuffer will not be changed by this method.
*
* @param buffer
* the ByteBuffer to read the matrix values from in column-major order
* @return this
*/
public Matrix3d set(ByteBuffer buffer) {
MemUtil.INSTANCE.get(this, buffer.position(), buffer);
return this;
}
/**
* Set the values of this matrix by reading 9 float values from the given {@link ByteBuffer} in column-major order,
* starting at its current position.
* <p>
* The ByteBuffer is expected to contain the values in column-major order.
* <p>
* The position of the ByteBuffer will not be changed by this method.
*
* @param buffer
* the ByteBuffer to read the matrix values from in column-major order
* @return this
*/
public Matrix3d setFloats(ByteBuffer buffer) {
MemUtil.INSTANCE.getf(this, buffer.position(), buffer);
return this;
}
//#endif
/**
* Set the three columns of this matrix to the supplied vectors, respectively.
*
* @param col0
* the first column
* @param col1
* the second column
* @param col2
* the third column
* @return this
*/
public Matrix3d set(Vector3dc col0,
Vector3dc col1,
Vector3dc col2) {
this.m00 = col0.x();
this.m01 = col0.y();
this.m02 = col0.z();
this.m10 = col1.x();
this.m11 = col1.y();
this.m12 = col1.z();
this.m20 = col2.x();
this.m21 = col2.y();
this.m22 = col2.z();
return this;
}
/**
* Set all the values within this matrix to 0.
*
* @return this
*/
public Matrix3d zero() {
m00 = 0.0;
m01 = 0.0;
m02 = 0.0;
m10 = 0.0;
m11 = 0.0;
m12 = 0.0;
m20 = 0.0;
m21 = 0.0;
m22 = 0.0;
return this;
}
/**
* Set this matrix to the identity.
*
* @return this
*/
public Matrix3d identity() {
m00 = 1.0;
m01 = 0.0;
m02 = 0.0;
m10 = 0.0;
m11 = 1.0;
m12 = 0.0;
m20 = 0.0;
m21 = 0.0;
m22 = 1.0;
return this;
}
/**
* Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional scaling.
* <p>
* In order to post-multiply a scaling transformation directly to a
* matrix, use {@link #scale(double) scale()} instead.
*
* @see #scale(double)
*
* @param factor
* the scale factor in x, y and z
* @return this
*/
public Matrix3d scaling(double factor) {
m00 = factor;
m01 = 0.0;
m02 = 0.0;
m10 = 0.0;
m11 = factor;
m12 = 0.0;
m20 = 0.0;
m21 = 0.0;
m22 = factor;
return this;
}
/**
* Set this matrix to be a simple scale matrix.
*
* @param x
* the scale in x
* @param y
* the scale in y
* @param z
* the scale in z
* @return this
*/
public Matrix3d scaling(double x, double y, double z) {
m00 = x;
m01 = 0.0;
m02 = 0.0;
m10 = 0.0;
m11 = y;
m12 = 0.0;
m20 = 0.0;
m21 = 0.0;
m22 = z;
return this;
}
/**
* Set this matrix to be a simple scale matrix which scales the base axes by <tt>xyz.x</tt>, <tt>xyz.y</tt> and <tt>xyz.z</tt> respectively.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional scaling.
* <p>
* In order to post-multiply a scaling transformation directly to a
* matrix use {@link #scale(Vector3dc) scale()} instead.
*
* @see #scale(Vector3dc)
*
* @param xyz
* the scale in x, y and z respectively
* @return this
*/
public Matrix3d scaling(Vector3dc xyz) {
m00 = xyz.x();
m01 = 0.0;
m02 = 0.0;
m10 = 0.0;
m11 = xyz.y();
m12 = 0.0;
m20 = 0.0;
m21 = 0.0;
m22 = xyz.z();
return this;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#scale(org.joml.Vector3dc, org.joml.Matrix3d)
*/
public Matrix3d scale(Vector3dc xyz, Matrix3d dest) {
return scale(xyz.x(), xyz.y(), xyz.z(), dest);
}
/**
* Apply scaling to this matrix by scaling the base axes by the given <tt>xyz.x</tt>,
* <tt>xyz.y</tt> and <tt>xyz.z</tt> factors, respectively.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the
* scaling will be applied first!
*
* @param xyz
* the factors of the x, y and z component, respectively
* @return this
*/
public Matrix3d scale(Vector3dc xyz) {
return scale(xyz.x(), xyz.y(), xyz.z(), this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#scale(double, double, double, org.joml.Matrix3d)
*/
public Matrix3d scale(double x, double y, double z, Matrix3d dest) {
// scale matrix elements:
// m00 = x, m11 = y, m22 = z
// all others = 0
dest.m00 = m00 * x;
dest.m01 = m01 * x;
dest.m02 = m02 * x;
dest.m10 = m10 * y;
dest.m11 = m11 * y;
dest.m12 = m12 * y;
dest.m20 = m20 * z;
dest.m21 = m21 * z;
dest.m22 = m22 * z;
return dest;
}
/**
* Apply scaling to this matrix by scaling the base axes by the given x,
* y and z factors.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @param x
* the factor of the x component
* @param y
* the factor of the y component
* @param z
* the factor of the z component
* @return this
*/
public Matrix3d scale(double x, double y, double z) {
return scale(x, y, z, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#scale(double, org.joml.Matrix3d)
*/
public Matrix3d scale(double xyz, Matrix3d dest) {
return scale(xyz, xyz, xyz, dest);
}
/**
* Apply scaling to this matrix by uniformly scaling all base axes by the given <code>xyz</code> factor.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @see #scale(double, double, double)
*
* @param xyz
* the factor for all components
* @return this
*/
public Matrix3d scale(double xyz) {
return scale(xyz, xyz, xyz);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#scaleLocal(double, double, double, org.joml.Matrix3d)
*/
public Matrix3d scaleLocal(double x, double y, double z, Matrix3d dest) {
double nm00 = x * m00;
double nm01 = y * m01;
double nm02 = z * m02;
double nm10 = x * m10;
double nm11 = y * m11;
double nm12 = z * m12;
double nm20 = x * m20;
double nm21 = y * m21;
double nm22 = z * m22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Pre-multiply scaling to this matrix by scaling the base axes by the given x,
* y and z factors.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>S * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the
* scaling will be applied last!
*
* @param x
* the factor of the x component
* @param y
* the factor of the y component
* @param z
* the factor of the z component
* @return this
*/
public Matrix3d scaleLocal(double x, double y, double z) {
return scaleLocal(x, y, z, this);
}
/**
* Set this matrix to a rotation matrix which rotates the given radians about a given axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional rotation.
* <p>
* In order to post-multiply a rotation transformation directly to a
* matrix, use {@link #rotate(double, Vector3dc) rotate()} instead.
*
* @see #rotate(double, Vector3dc)
*
* @param angle
* the angle in radians
* @param axis
* the axis to rotate about (needs to be {@link Vector3d#normalize() normalized})
* @return this
*/
public Matrix3d rotation(double angle, Vector3dc axis) {
return rotation(angle, axis.x(), axis.y(), axis.z());
}
/**
* Set this matrix to a rotation matrix which rotates the given radians about a given axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional rotation.
* <p>
* In order to post-multiply a rotation transformation directly to a
* matrix, use {@link #rotate(double, Vector3fc) rotate()} instead.
*
* @see #rotate(double, Vector3fc)
*
* @param angle
* the angle in radians
* @param axis
* the axis to rotate about (needs to be {@link Vector3f#normalize() normalized})
* @return this
*/
public Matrix3d rotation(double angle, Vector3fc axis) {
return rotation(angle, axis.x(), axis.y(), axis.z());
}
/**
* Set this matrix to a rotation transformation using the given {@link AxisAngle4f}.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional rotation.
* <p>
* In order to apply the rotation transformation to an existing transformation,
* use {@link #rotate(AxisAngle4f) rotate()} instead.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(AxisAngle4f)
*
* @param axisAngle
* the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized})
* @return this
*/
public Matrix3d rotation(AxisAngle4f axisAngle) {
return rotation(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z);
}
/**
* Set this matrix to a rotation transformation using the given {@link AxisAngle4d}.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional rotation.
* <p>
* In order to apply the rotation transformation to an existing transformation,
* use {@link #rotate(AxisAngle4d) rotate()} instead.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(AxisAngle4d)
*
* @param axisAngle
* the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized})
* @return this
*/
public Matrix3d rotation(AxisAngle4d axisAngle) {
return rotation(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z);
}
/**
* Set this matrix to a rotation matrix which rotates the given radians about a given axis.
* <p>
* The axis described by the three components needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional rotation.
* <p>
* In order to apply the rotation transformation to an existing transformation,
* use {@link #rotate(double, double, double, double) rotate()} instead.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
*
* @param angle
* the angle in radians
* @param x
* the x-component of the rotation axis
* @param y
* the y-component of the rotation axis
* @param z
* the z-component of the rotation axis
* @return this
*/
public Matrix3d rotation(double angle, double x, double y, double z) {
double sin = Math.sin(angle);
double cos = Math.cosFromSin(sin, angle);
double C = 1.0 - cos;
double xy = x * y, xz = x * z, yz = y * z;
m00 = cos + x * x * C;
m10 = xy * C - z * sin;
m20 = xz * C + y * sin;
m01 = xy * C + z * sin;
m11 = cos + y * y * C;
m21 = yz * C - x * sin;
m02 = xz * C - y * sin;
m12 = yz * C + x * sin;
m22 = cos + z * z * C;
return this;
}
/**
* Set this matrix to a rotation transformation about the X axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @return this
*/
public Matrix3d rotationX(double ang) {
double sin, cos;
sin = Math.sin(ang);
cos = Math.cosFromSin(sin, ang);
m00 = 1.0;
m01 = 0.0;
m02 = 0.0;
m10 = 0.0;
m11 = cos;
m12 = sin;
m20 = 0.0;
m21 = -sin;
m22 = cos;
return this;
}
/**
* Set this matrix to a rotation transformation about the Y axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @return this
*/
public Matrix3d rotationY(double ang) {
double sin, cos;
sin = Math.sin(ang);
cos = Math.cosFromSin(sin, ang);
m00 = cos;
m01 = 0.0;
m02 = -sin;
m10 = 0.0;
m11 = 1.0;
m12 = 0.0;
m20 = sin;
m21 = 0.0;
m22 = cos;
return this;
}
/**
* Set this matrix to a rotation transformation about the Z axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @return this
*/
public Matrix3d rotationZ(double ang) {
double sin, cos;
sin = Math.sin(ang);
cos = Math.cosFromSin(sin, ang);
m00 = cos;
m01 = sin;
m02 = 0.0;
m10 = -sin;
m11 = cos;
m12 = 0.0;
m20 = 0.0;
m21 = 0.0;
m22 = 1.0;
return this;
}
/**
* Set this matrix to a rotation of <code>angleX</code> radians about the X axis, followed by a rotation
* of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleZ</code> radians about the Z axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* This method is equivalent to calling: <tt>rotationX(angleX).rotateY(angleY).rotateZ(angleZ)</tt>
*
* @param angleX
* the angle to rotate about X
* @param angleY
* the angle to rotate about Y
* @param angleZ
* the angle to rotate about Z
* @return this
*/
public Matrix3d rotationXYZ(double angleX, double angleY, double angleZ) {
double sinX = Math.sin(angleX);
double cosX = Math.cosFromSin(sinX, angleX);
double sinY = Math.sin(angleY);
double cosY = Math.cosFromSin(sinY, angleY);
double sinZ = Math.sin(angleZ);
double cosZ = Math.cosFromSin(sinZ, angleZ);
double m_sinX = -sinX;
double m_sinY = -sinY;
double m_sinZ = -sinZ;
// rotateX
double nm11 = cosX;
double nm12 = sinX;
double nm21 = m_sinX;
double nm22 = cosX;
// rotateY
double nm00 = cosY;
double nm01 = nm21 * m_sinY;
double nm02 = nm22 * m_sinY;
m20 = sinY;
m21 = nm21 * cosY;
m22 = nm22 * cosY;
// rotateZ
m00 = nm00 * cosZ;
m01 = nm01 * cosZ + nm11 * sinZ;
m02 = nm02 * cosZ + nm12 * sinZ;
m10 = nm00 * m_sinZ;
m11 = nm01 * m_sinZ + nm11 * cosZ;
m12 = nm02 * m_sinZ + nm12 * cosZ;
return this;
}
/**
* Set this matrix to a rotation of <code>angleZ</code> radians about the Z axis, followed by a rotation
* of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleX</code> radians about the X axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* This method is equivalent to calling: <tt>rotationZ(angleZ).rotateY(angleY).rotateX(angleX)</tt>
*
* @param angleZ
* the angle to rotate about Z
* @param angleY
* the angle to rotate about Y
* @param angleX
* the angle to rotate about X
* @return this
*/
public Matrix3d rotationZYX(double angleZ, double angleY, double angleX) {
double sinX = Math.sin(angleX);
double cosX = Math.cosFromSin(sinX, angleX);
double sinY = Math.sin(angleY);
double cosY = Math.cosFromSin(sinY, angleY);
double sinZ = Math.sin(angleZ);
double cosZ = Math.cosFromSin(sinZ, angleZ);
double m_sinZ = -sinZ;
double m_sinY = -sinY;
double m_sinX = -sinX;
// rotateZ
double nm00 = cosZ;
double nm01 = sinZ;
double nm10 = m_sinZ;
double nm11 = cosZ;
// rotateY
double nm20 = nm00 * sinY;
double nm21 = nm01 * sinY;
double nm22 = cosY;
m00 = nm00 * cosY;
m01 = nm01 * cosY;
m02 = m_sinY;
// rotateX
m10 = nm10 * cosX + nm20 * sinX;
m11 = nm11 * cosX + nm21 * sinX;
m12 = nm22 * sinX;
m20 = nm10 * m_sinX + nm20 * cosX;
m21 = nm11 * m_sinX + nm21 * cosX;
m22 = nm22 * cosX;
return this;
}
/**
* Set this matrix to a rotation of <code>angleY</code> radians about the Y axis, followed by a rotation
* of <code>angleX</code> radians about the X axis and followed by a rotation of <code>angleZ</code> radians about the Z axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* This method is equivalent to calling: <tt>rotationY(angleY).rotateX(angleX).rotateZ(angleZ)</tt>
*
* @param angleY
* the angle to rotate about Y
* @param angleX
* the angle to rotate about X
* @param angleZ
* the angle to rotate about Z
* @return this
*/
public Matrix3d rotationYXZ(double angleY, double angleX, double angleZ) {
double sinX = Math.sin(angleX);
double cosX = Math.cosFromSin(sinX, angleX);
double sinY = Math.sin(angleY);
double cosY = Math.cosFromSin(sinY, angleY);
double sinZ = Math.sin(angleZ);
double cosZ = Math.cosFromSin(sinZ, angleZ);
double m_sinY = -sinY;
double m_sinX = -sinX;
double m_sinZ = -sinZ;
// rotateY
double nm00 = cosY;
double nm02 = m_sinY;
double nm20 = sinY;
double nm22 = cosY;
// rotateX
double nm10 = nm20 * sinX;
double nm11 = cosX;
double nm12 = nm22 * sinX;
m20 = nm20 * cosX;
m21 = m_sinX;
m22 = nm22 * cosX;
// rotateZ
m00 = nm00 * cosZ + nm10 * sinZ;
m01 = nm11 * sinZ;
m02 = nm02 * cosZ + nm12 * sinZ;
m10 = nm00 * m_sinZ + nm10 * cosZ;
m11 = nm11 * cosZ;
m12 = nm02 * m_sinZ + nm12 * cosZ;
return this;
}
/**
* Set this matrix to the rotation - and possibly scaling - transformation of the given {@link Quaterniondc}.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional rotation.
* <p>
* In order to apply the rotation transformation to an existing transformation,
* use {@link #rotate(Quaterniondc) rotate()} instead.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotate(Quaterniondc)
*
* @param quat
* the {@link Quaterniondc}
* @return this
*/
public Matrix3d rotation(Quaterniondc quat) {
double w2 = quat.w() * quat.w();
double x2 = quat.x() * quat.x();
double y2 = quat.y() * quat.y();
double z2 = quat.z() * quat.z();
double zw = quat.z() * quat.w();
double xy = quat.x() * quat.y();
double xz = quat.x() * quat.z();
double yw = quat.y() * quat.w();
double yz = quat.y() * quat.z();
double xw = quat.x() * quat.w();
m00 = w2 + x2 - z2 - y2;
m01 = xy + zw + zw + xy;
m02 = xz - yw + xz - yw;
m10 = -zw + xy - zw + xy;
m11 = y2 - z2 + w2 - x2;
m12 = yz + yz + xw + xw;
m20 = yw + xz + xz + yw;
m21 = yz + yz - xw - xw;
m22 = z2 - y2 - x2 + w2;
return this;
}
/**
* Set this matrix to the rotation - and possibly scaling - transformation of the given {@link Quaternionfc}.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* The resulting matrix can be multiplied against another transformation
* matrix to obtain an additional rotation.
* <p>
* In order to apply the rotation transformation to an existing transformation,
* use {@link #rotate(Quaternionfc) rotate()} instead.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotate(Quaternionfc)
*
* @param quat
* the {@link Quaternionfc}
* @return this
*/
public Matrix3d rotation(Quaternionfc quat) {
double w2 = quat.w() * quat.w();
double x2 = quat.x() * quat.x();
double y2 = quat.y() * quat.y();
double z2 = quat.z() * quat.z();
double zw = quat.z() * quat.w();
double xy = quat.x() * quat.y();
double xz = quat.x() * quat.z();
double yw = quat.y() * quat.w();
double yz = quat.y() * quat.z();
double xw = quat.x() * quat.w();
m00 = w2 + x2 - z2 - y2;
m01 = xy + zw + zw + xy;
m02 = xz - yw + xz - yw;
m10 = -zw + xy - zw + xy;
m11 = y2 - z2 + w2 - x2;
m12 = yz + yz + xw + xw;
m20 = yw + xz + xz + yw;
m21 = yz + yz - xw - xw;
m22 = z2 - y2 - x2 + w2;
return this;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#transform(org.joml.Vector3d)
*/
public Vector3d transform(Vector3d v) {
return v.mul(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#transform(org.joml.Vector3dc, org.joml.Vector3d)
*/
public Vector3d transform(Vector3dc v, Vector3d dest) {
v.mul(this, dest);
return dest;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#transform(org.joml.Vector3f)
*/
public Vector3f transform(Vector3f v) {
return v.mul(this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#transform(org.joml.Vector3fc, org.joml.Vector3f)
*/
public Vector3f transform(Vector3fc v, Vector3f dest) {
v.mul(this, dest);
return dest;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#transform(double, double, double, org.joml.Vector3d)
*/
public Vector3d transform(double x, double y, double z, Vector3d dest) {
dest.set(m00 * x + m10 * y + m20 * z,
m01 * x + m11 * y + m21 * z,
m02 * x + m12 * y + m22 * z);
return dest;
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeDouble(m00);
out.writeDouble(m01);
out.writeDouble(m02);
out.writeDouble(m10);
out.writeDouble(m11);
out.writeDouble(m12);
out.writeDouble(m20);
out.writeDouble(m21);
out.writeDouble(m22);
}
public void readExternal(ObjectInput in) throws IOException {
m00 = in.readDouble();
m01 = in.readDouble();
m02 = in.readDouble();
m10 = in.readDouble();
m11 = in.readDouble();
m12 = in.readDouble();
m20 = in.readDouble();
m21 = in.readDouble();
m22 = in.readDouble();
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#rotateX(double, org.joml.Matrix3d)
*/
public Matrix3d rotateX(double ang, Matrix3d dest) {
double sin, cos;
sin = Math.sin(ang);
cos = Math.cosFromSin(sin, ang);
double rm11 = cos;
double rm21 = -sin;
double rm12 = sin;
double rm22 = cos;
// add temporaries for dependent values
double nm10 = m10 * rm11 + m20 * rm12;
double nm11 = m11 * rm11 + m21 * rm12;
double nm12 = m12 * rm11 + m22 * rm12;
// set non-dependent values directly
dest.m20 = m10 * rm21 + m20 * rm22;
dest.m21 = m11 * rm21 + m21 * rm22;
dest.m22 = m12 * rm21 + m22 * rm22;
// set other values
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m00 = m00;
dest.m01 = m01;
dest.m02 = m02;
return dest;
}
/**
* Apply rotation about the X axis to this matrix by rotating the given amount of radians.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>
* , the rotation will be applied first!
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @return this
*/
public Matrix3d rotateX(double ang) {
return rotateX(ang, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#rotateY(double, org.joml.Matrix3d)
*/
public Matrix3d rotateY(double ang, Matrix3d dest) {
double sin, cos;
sin = Math.sin(ang);
cos = Math.cosFromSin(sin, ang);
double rm00 = cos;
double rm20 = sin;
double rm02 = -sin;
double rm22 = cos;
// add temporaries for dependent values
double nm00 = m00 * rm00 + m20 * rm02;
double nm01 = m01 * rm00 + m21 * rm02;
double nm02 = m02 * rm00 + m22 * rm02;
// set non-dependent values directly
dest.m20 = m00 * rm20 + m20 * rm22;
dest.m21 = m01 * rm20 + m21 * rm22;
dest.m22 = m02 * rm20 + m22 * rm22;
// set other values
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = m10;
dest.m11 = m11;
dest.m12 = m12;
return dest;
}
/**
* Apply rotation about the Y axis to this matrix by rotating the given amount of radians.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>
* , the rotation will be applied first!
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @return this
*/
public Matrix3d rotateY(double ang) {
return rotateY(ang, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#rotateZ(double, org.joml.Matrix3d)
*/
public Matrix3d rotateZ(double ang, Matrix3d dest) {
double sin, cos;
sin = Math.sin(ang);
cos = Math.cosFromSin(sin, ang);
double rm00 = cos;
double rm10 = -sin;
double rm01 = sin;
double rm11 = cos;
// add temporaries for dependent values
double nm00 = m00 * rm00 + m10 * rm01;
double nm01 = m01 * rm00 + m11 * rm01;
double nm02 = m02 * rm00 + m12 * rm01;
// set non-dependent values directly
dest.m10 = m00 * rm10 + m10 * rm11;
dest.m11 = m01 * rm10 + m11 * rm11;
dest.m12 = m02 * rm10 + m12 * rm11;
// set other values
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m20 = m20;
dest.m21 = m21;
dest.m22 = m22;
return dest;
}
/**
* Apply rotation about the Z axis to this matrix by rotating the given amount of radians.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>
* , the rotation will be applied first!
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @return this
*/
public Matrix3d rotateZ(double ang) {
return rotateZ(ang, this);
}
/**
* Apply rotation of <code>angleX</code> radians about the X axis, followed by a rotation of <code>angleY</code> radians about the Y axis and
* followed by a rotation of <code>angleZ</code> radians about the Z axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* rotation will be applied first!
* <p>
* This method is equivalent to calling: <tt>rotateX(angleX).rotateY(angleY).rotateZ(angleZ)</tt>
*
* @param angleX
* the angle to rotate about X
* @param angleY
* the angle to rotate about Y
* @param angleZ
* the angle to rotate about Z
* @return this
*/
public Matrix3d rotateXYZ(double angleX, double angleY, double angleZ) {
return rotateXYZ(angleX, angleY, angleZ, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#rotateXYZ(double, double, double, org.joml.Matrix3d)
*/
public Matrix3d rotateXYZ(double angleX, double angleY, double angleZ, Matrix3d dest) {
double sinX = Math.sin(angleX);
double cosX = Math.cosFromSin(sinX, angleX);
double sinY = Math.sin(angleY);
double cosY = Math.cosFromSin(sinY, angleY);
double sinZ = Math.sin(angleZ);
double cosZ = Math.cosFromSin(sinZ, angleZ);
double m_sinX = -sinX;
double m_sinY = -sinY;
double m_sinZ = -sinZ;
// rotateX
double nm10 = m10 * cosX + m20 * sinX;
double nm11 = m11 * cosX + m21 * sinX;
double nm12 = m12 * cosX + m22 * sinX;
double nm20 = m10 * m_sinX + m20 * cosX;
double nm21 = m11 * m_sinX + m21 * cosX;
double nm22 = m12 * m_sinX + m22 * cosX;
// rotateY
double nm00 = m00 * cosY + nm20 * m_sinY;
double nm01 = m01 * cosY + nm21 * m_sinY;
double nm02 = m02 * cosY + nm22 * m_sinY;
dest.m20 = m00 * sinY + nm20 * cosY;
dest.m21 = m01 * sinY + nm21 * cosY;
dest.m22 = m02 * sinY + nm22 * cosY;
// rotateZ
dest.m00 = nm00 * cosZ + nm10 * sinZ;
dest.m01 = nm01 * cosZ + nm11 * sinZ;
dest.m02 = nm02 * cosZ + nm12 * sinZ;
dest.m10 = nm00 * m_sinZ + nm10 * cosZ;
dest.m11 = nm01 * m_sinZ + nm11 * cosZ;
dest.m12 = nm02 * m_sinZ + nm12 * cosZ;
return dest;
}
/**
* Apply rotation of <code>angleZ</code> radians about the Z axis, followed by a rotation of <code>angleY</code> radians about the Y axis and
* followed by a rotation of <code>angleX</code> radians about the X axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* rotation will be applied first!
* <p>
* This method is equivalent to calling: <tt>rotateZ(angleZ).rotateY(angleY).rotateX(angleX)</tt>
*
* @param angleZ
* the angle to rotate about Z
* @param angleY
* the angle to rotate about Y
* @param angleX
* the angle to rotate about X
* @return this
*/
public Matrix3d rotateZYX(double angleZ, double angleY, double angleX) {
return rotateZYX(angleZ, angleY, angleX, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#rotateZYX(double, double, double, org.joml.Matrix3d)
*/
public Matrix3d rotateZYX(double angleZ, double angleY, double angleX, Matrix3d dest) {
double sinX = Math.sin(angleX);
double cosX = Math.cosFromSin(sinX, angleX);
double sinY = Math.sin(angleY);
double cosY = Math.cosFromSin(sinY, angleY);
double sinZ = Math.sin(angleZ);
double cosZ = Math.cosFromSin(sinZ, angleZ);
double m_sinZ = -sinZ;
double m_sinY = -sinY;
double m_sinX = -sinX;
// rotateZ
double nm00 = m00 * cosZ + m10 * sinZ;
double nm01 = m01 * cosZ + m11 * sinZ;
double nm02 = m02 * cosZ + m12 * sinZ;
double nm10 = m00 * m_sinZ + m10 * cosZ;
double nm11 = m01 * m_sinZ + m11 * cosZ;
double nm12 = m02 * m_sinZ + m12 * cosZ;
// rotateY
double nm20 = nm00 * sinY + m20 * cosY;
double nm21 = nm01 * sinY + m21 * cosY;
double nm22 = nm02 * sinY + m22 * cosY;
dest.m00 = nm00 * cosY + m20 * m_sinY;
dest.m01 = nm01 * cosY + m21 * m_sinY;
dest.m02 = nm02 * cosY + m22 * m_sinY;
// rotateX
dest.m10 = nm10 * cosX + nm20 * sinX;
dest.m11 = nm11 * cosX + nm21 * sinX;
dest.m12 = nm12 * cosX + nm22 * sinX;
dest.m20 = nm10 * m_sinX + nm20 * cosX;
dest.m21 = nm11 * m_sinX + nm21 * cosX;
dest.m22 = nm12 * m_sinX + nm22 * cosX;
return dest;
}
/**
* Apply rotation of <code>angles.y</code> radians about the Y axis, followed by a rotation of <code>angles.x</code> radians about the X axis and
* followed by a rotation of <code>angles.z</code> radians about the Z axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* rotation will be applied first!
* <p>
* This method is equivalent to calling: <tt>rotateY(angles.y).rotateX(angles.x).rotateZ(angles.z)</tt>
*
* @param angles
* the Euler angles
* @return this
*/
public Matrix3d rotateYXZ(Vector3d angles) {
return rotateYXZ(angles.y, angles.x, angles.z);
}
/**
* Apply rotation of <code>angleY</code> radians about the Y axis, followed by a rotation of <code>angleX</code> radians about the X axis and
* followed by a rotation of <code>angleZ</code> radians about the Z axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* rotation will be applied first!
* <p>
* This method is equivalent to calling: <tt>rotateY(angleY).rotateX(angleX).rotateZ(angleZ)</tt>
*
* @param angleY
* the angle to rotate about Y
* @param angleX
* the angle to rotate about X
* @param angleZ
* the angle to rotate about Z
* @return this
*/
public Matrix3d rotateYXZ(double angleY, double angleX, double angleZ) {
return rotateYXZ(angleY, angleX, angleZ, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#rotateYXZ(double, double, double, org.joml.Matrix3d)
*/
public Matrix3d rotateYXZ(double angleY, double angleX, double angleZ, Matrix3d dest) {
double sinX = Math.sin(angleX);
double cosX = Math.cosFromSin(sinX, angleX);
double sinY = Math.sin(angleY);
double cosY = Math.cosFromSin(sinY, angleY);
double sinZ = Math.sin(angleZ);
double cosZ = Math.cosFromSin(sinZ, angleZ);
double m_sinY = -sinY;
double m_sinX = -sinX;
double m_sinZ = -sinZ;
// rotateY
double nm20 = m00 * sinY + m20 * cosY;
double nm21 = m01 * sinY + m21 * cosY;
double nm22 = m02 * sinY + m22 * cosY;
double nm00 = m00 * cosY + m20 * m_sinY;
double nm01 = m01 * cosY + m21 * m_sinY;
double nm02 = m02 * cosY + m22 * m_sinY;
// rotateX
double nm10 = m10 * cosX + nm20 * sinX;
double nm11 = m11 * cosX + nm21 * sinX;
double nm12 = m12 * cosX + nm22 * sinX;
dest.m20 = m10 * m_sinX + nm20 * cosX;
dest.m21 = m11 * m_sinX + nm21 * cosX;
dest.m22 = m12 * m_sinX + nm22 * cosX;
// rotateZ
dest.m00 = nm00 * cosZ + nm10 * sinZ;
dest.m01 = nm01 * cosZ + nm11 * sinZ;
dest.m02 = nm02 * cosZ + nm12 * sinZ;
dest.m10 = nm00 * m_sinZ + nm10 * cosZ;
dest.m11 = nm01 * m_sinZ + nm11 * cosZ;
dest.m12 = nm02 * m_sinZ + nm12 * cosZ;
return dest;
}
/**
* Apply rotation to this matrix by rotating the given amount of radians
* about the given axis specified as x, y and z components.
* <p>
* The axis described by the three components needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>
* , the rotation will be applied first!
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @param x
* the x component of the axis
* @param y
* the y component of the axis
* @param z
* the z component of the axis
* @return this
*/
public Matrix3d rotate(double ang, double x, double y, double z) {
return rotate(ang, x, y, z, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#rotate(double, double, double, double, org.joml.Matrix3d)
*/
public Matrix3d rotate(double ang, double x, double y, double z, Matrix3d dest) {
double s = Math.sin(ang);
double c = Math.cosFromSin(s, ang);
double C = 1.0 - c;
// rotation matrix elements:
// m30, m31, m32, m03, m13, m23 = 0
double xx = x * x, xy = x * y, xz = x * z;
double yy = y * y, yz = y * z;
double zz = z * z;
double rm00 = xx * C + c;
double rm01 = xy * C + z * s;
double rm02 = xz * C - y * s;
double rm10 = xy * C - z * s;
double rm11 = yy * C + c;
double rm12 = yz * C + x * s;
double rm20 = xz * C + y * s;
double rm21 = yz * C - x * s;
double rm22 = zz * C + c;
// add temporaries for dependent values
double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02;
double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02;
double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02;
double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12;
double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12;
double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12;
// set non-dependent values directly
dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22;
dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22;
dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22;
// set other values
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
return dest;
}
/**
* Pre-multiply a rotation to this matrix by rotating the given amount of radians
* about the specified <tt>(x, y, z)</tt> axis and store the result in <code>dest</code>.
* <p>
* The axis described by the three components needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotation(double, double, double, double) rotation()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotation(double, double, double, double)
*
* @param ang
* the angle in radians
* @param x
* the x component of the axis
* @param y
* the y component of the axis
* @param z
* the z component of the axis
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotateLocal(double ang, double x, double y, double z, Matrix3d dest) {
double s = Math.sin(ang);
double c = Math.cosFromSin(s, ang);
double C = 1.0 - c;
double xx = x * x, xy = x * y, xz = x * z;
double yy = y * y, yz = y * z;
double zz = z * z;
double lm00 = xx * C + c;
double lm01 = xy * C + z * s;
double lm02 = xz * C - y * s;
double lm10 = xy * C - z * s;
double lm11 = yy * C + c;
double lm12 = yz * C + x * s;
double lm20 = xz * C + y * s;
double lm21 = yz * C - x * s;
double lm22 = zz * C + c;
double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02;
double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02;
double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02;
double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12;
double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12;
double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12;
double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22;
double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22;
double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Pre-multiply a rotation to this matrix by rotating the given amount of radians
* about the specified <tt>(x, y, z)</tt> axis.
* <p>
* The axis described by the three components needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotation(double, double, double, double) rotation()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotation(double, double, double, double)
*
* @param ang
* the angle in radians
* @param x
* the x component of the axis
* @param y
* the y component of the axis
* @param z
* the z component of the axis
* @return this
*/
public Matrix3d rotateLocal(double ang, double x, double y, double z) {
return rotateLocal(ang, x, y, z, this);
}
/**
* Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians
* about the X axis and store the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotationX(double) rotationX()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotationX(double)
*
* @param ang
* the angle in radians to rotate about the X axis
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotateLocalX(double ang, Matrix3d dest) {
double sin = Math.sin(ang);
double cos = Math.cosFromSin(sin, ang);
double nm01 = cos * m01 - sin * m02;
double nm02 = sin * m01 + cos * m02;
double nm11 = cos * m11 - sin * m12;
double nm12 = sin * m11 + cos * m12;
double nm21 = cos * m21 - sin * m22;
double nm22 = sin * m21 + cos * m22;
dest.m00 = m00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = m10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = m20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Pre-multiply a rotation to this matrix by rotating the given amount of radians about the X axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotationX(double) rotationX()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotationX(double)
*
* @param ang
* the angle in radians to rotate about the X axis
* @return this
*/
public Matrix3d rotateLocalX(double ang) {
return rotateLocalX(ang, this);
}
/**
* Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians
* about the Y axis and store the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotationY(double) rotationY()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotationY(double)
*
* @param ang
* the angle in radians to rotate about the Y axis
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotateLocalY(double ang, Matrix3d dest) {
double sin = Math.sin(ang);
double cos = Math.cosFromSin(sin, ang);
double nm00 = cos * m00 + sin * m02;
double nm02 = -sin * m00 + cos * m02;
double nm10 = cos * m10 + sin * m12;
double nm12 = -sin * m10 + cos * m12;
double nm20 = cos * m20 + sin * m22;
double nm22 = -sin * m20 + cos * m22;
dest.m00 = nm00;
dest.m01 = m01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = m11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = m21;
dest.m22 = nm22;
return dest;
}
/**
* Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Y axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotationY(double) rotationY()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotationY(double)
*
* @param ang
* the angle in radians to rotate about the Y axis
* @return this
*/
public Matrix3d rotateLocalY(double ang) {
return rotateLocalY(ang, this);
}
/**
* Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians
* about the Z axis and store the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotationZ(double) rotationZ()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotationZ(double)
*
* @param ang
* the angle in radians to rotate about the Z axis
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotateLocalZ(double ang, Matrix3d dest) {
double sin = Math.sin(ang);
double cos = Math.cosFromSin(sin, ang);
double nm00 = cos * m00 - sin * m01;
double nm01 = sin * m00 + cos * m01;
double nm10 = cos * m10 - sin * m11;
double nm11 = sin * m10 + cos * m11;
double nm20 = cos * m20 - sin * m21;
double nm21 = sin * m20 + cos * m21;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = m02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = m12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = m22;
return dest;
}
/**
* Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Z axis.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* In order to set the matrix to a rotation matrix without pre-multiplying the rotation
* transformation, use {@link #rotationZ(double) rotationY()}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotationY(double)
*
* @param ang
* the angle in radians to rotate about the Z axis
* @return this
*/
public Matrix3d rotateLocalZ(double ang) {
return rotateLocalZ(ang, this);
}
/**
* Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaterniondc} to this matrix and store
* the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>Q * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>Q * M * v</code>,
* the quaternion rotation will be applied last!
* <p>
* In order to set the matrix to a rotation transformation without pre-multiplying,
* use {@link #rotation(Quaterniondc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaterniondc)
*
* @param quat
* the {@link Quaterniondc}
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotateLocal(Quaterniondc quat, Matrix3d dest) {
double w2 = quat.w() * quat.w();
double x2 = quat.x() * quat.x();
double y2 = quat.y() * quat.y();
double z2 = quat.z() * quat.z();
double zw = quat.z() * quat.w();
double xy = quat.x() * quat.y();
double xz = quat.x() * quat.z();
double yw = quat.y() * quat.w();
double yz = quat.y() * quat.z();
double xw = quat.x() * quat.w();
double lm00 = w2 + x2 - z2 - y2;
double lm01 = xy + zw + zw + xy;
double lm02 = xz - yw + xz - yw;
double lm10 = -zw + xy - zw + xy;
double lm11 = y2 - z2 + w2 - x2;
double lm12 = yz + yz + xw + xw;
double lm20 = yw + xz + xz + yw;
double lm21 = yz + yz - xw - xw;
double lm22 = z2 - y2 - x2 + w2;
double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02;
double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02;
double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02;
double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12;
double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12;
double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12;
double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22;
double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22;
double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaterniondc} to this matrix.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>Q * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>Q * M * v</code>,
* the quaternion rotation will be applied last!
* <p>
* In order to set the matrix to a rotation transformation without pre-multiplying,
* use {@link #rotation(Quaterniondc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaterniondc)
*
* @param quat
* the {@link Quaterniondc}
* @return this
*/
public Matrix3d rotateLocal(Quaterniondc quat) {
return rotateLocal(quat, this);
}
/**
* Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store
* the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>Q * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>Q * M * v</code>,
* the quaternion rotation will be applied last!
* <p>
* In order to set the matrix to a rotation transformation without pre-multiplying,
* use {@link #rotation(Quaternionfc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaternionfc)
*
* @param quat
* the {@link Quaternionfc}
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotateLocal(Quaternionfc quat, Matrix3d dest) {
double w2 = quat.w() * quat.w();
double x2 = quat.x() * quat.x();
double y2 = quat.y() * quat.y();
double z2 = quat.z() * quat.z();
double zw = quat.z() * quat.w();
double xy = quat.x() * quat.y();
double xz = quat.x() * quat.z();
double yw = quat.y() * quat.w();
double yz = quat.y() * quat.z();
double xw = quat.x() * quat.w();
double lm00 = w2 + x2 - z2 - y2;
double lm01 = xy + zw + zw + xy;
double lm02 = xz - yw + xz - yw;
double lm10 = -zw + xy - zw + xy;
double lm11 = y2 - z2 + w2 - x2;
double lm12 = yz + yz + xw + xw;
double lm20 = yw + xz + xz + yw;
double lm21 = yz + yz - xw - xw;
double lm22 = z2 - y2 - x2 + w2;
double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02;
double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02;
double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02;
double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12;
double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12;
double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12;
double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22;
double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22;
double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>Q * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>Q * M * v</code>,
* the quaternion rotation will be applied last!
* <p>
* In order to set the matrix to a rotation transformation without pre-multiplying,
* use {@link #rotation(Quaternionfc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaternionfc)
*
* @param quat
* the {@link Quaternionfc}
* @return this
*/
public Matrix3d rotateLocal(Quaternionfc quat) {
return rotateLocal(quat, this);
}
/**
* Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniondc} to this matrix.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>M * Q</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * Q * v</code>,
* the quaternion rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(Quaterniondc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaterniondc)
*
* @param quat
* the {@link Quaterniondc}
* @return this
*/
public Matrix3d rotate(Quaterniondc quat) {
return rotate(quat, this);
}
/**
* Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniondc} to this matrix and store
* the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>M * Q</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * Q * v</code>,
* the quaternion rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(Quaterniondc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaterniondc)
*
* @param quat
* the {@link Quaterniondc}
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotate(Quaterniondc quat, Matrix3d dest) {
double w2 = quat.w() * quat.w();
double x2 = quat.x() * quat.x();
double y2 = quat.y() * quat.y();
double z2 = quat.z() * quat.z();
double zw = quat.z() * quat.w();
double xy = quat.x() * quat.y();
double xz = quat.x() * quat.z();
double yw = quat.y() * quat.w();
double yz = quat.y() * quat.z();
double xw = quat.x() * quat.w();
double rm00 = w2 + x2 - z2 - y2;
double rm01 = xy + zw + zw + xy;
double rm02 = xz - yw + xz - yw;
double rm10 = -zw + xy - zw + xy;
double rm11 = y2 - z2 + w2 - x2;
double rm12 = yz + yz + xw + xw;
double rm20 = yw + xz + xz + yw;
double rm21 = yz + yz - xw - xw;
double rm22 = z2 - y2 - x2 + w2;
double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02;
double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02;
double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02;
double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12;
double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12;
double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12;
dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22;
dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22;
dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
return dest;
}
/**
* Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>M * Q</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * Q * v</code>,
* the quaternion rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(Quaternionfc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaternionfc)
*
* @param quat
* the {@link Quaternionfc}
* @return this
*/
public Matrix3d rotate(Quaternionfc quat) {
return rotate(quat, this);
}
/**
* Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store
* the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion,
* then the new matrix will be <code>M * Q</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * Q * v</code>,
* the quaternion rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(Quaternionfc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a>
*
* @see #rotation(Quaternionfc)
*
* @param quat
* the {@link Quaternionfc}
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotate(Quaternionfc quat, Matrix3d dest) {
double w2 = quat.w() * quat.w();
double x2 = quat.x() * quat.x();
double y2 = quat.y() * quat.y();
double z2 = quat.z() * quat.z();
double zw = quat.z() * quat.w();
double xy = quat.x() * quat.y();
double xz = quat.x() * quat.z();
double yw = quat.y() * quat.w();
double yz = quat.y() * quat.z();
double xw = quat.x() * quat.w();
double rm00 = w2 + x2 - z2 - y2;
double rm01 = xy + zw + zw + xy;
double rm02 = xz - yw + xz - yw;
double rm10 = -zw + xy - zw + xy;
double rm11 = y2 - z2 + w2 - x2;
double rm12 = yz + yz + xw + xw;
double rm20 = yw + xz + xz + yw;
double rm21 = yz + yz - xw - xw;
double rm22 = z2 - y2 - x2 + w2;
double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02;
double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02;
double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02;
double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12;
double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12;
double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12;
dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22;
dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22;
dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
return dest;
}
/**
* Apply a rotation transformation, rotating about the given {@link AxisAngle4f}, to this matrix.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4f},
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the {@link AxisAngle4f} rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(AxisAngle4f)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(AxisAngle4f)
*
* @param axisAngle
* the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized})
* @return this
*/
public Matrix3d rotate(AxisAngle4f axisAngle) {
return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z);
}
/**
* Apply a rotation transformation, rotating about the given {@link AxisAngle4f} and store the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4f},
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the {@link AxisAngle4f} rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(AxisAngle4f)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(AxisAngle4f)
*
* @param axisAngle
* the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized})
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotate(AxisAngle4f axisAngle, Matrix3d dest) {
return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z, dest);
}
/**
* Apply a rotation transformation, rotating about the given {@link AxisAngle4d}, to this matrix.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d},
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the {@link AxisAngle4d} rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(AxisAngle4d)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(AxisAngle4d)
*
* @param axisAngle
* the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized})
* @return this
*/
public Matrix3d rotate(AxisAngle4d axisAngle) {
return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z);
}
/**
* Apply a rotation transformation, rotating about the given {@link AxisAngle4d} and store the result in <code>dest</code>.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d},
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the {@link AxisAngle4d} rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(AxisAngle4d)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(AxisAngle4d)
*
* @param axisAngle
* the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized})
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotate(AxisAngle4d axisAngle, Matrix3d dest) {
return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z, dest);
}
/**
* Apply a rotation transformation, rotating the given radians about the specified axis, to this matrix.
* <p>
* The axis described by the <code>axis</code> vector needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given angle and axis,
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the axis-angle rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(double, Vector3dc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(double, Vector3dc)
*
* @param angle
* the angle in radians
* @param axis
* the rotation axis (needs to be {@link Vector3d#normalize() normalized})
* @return this
*/
public Matrix3d rotate(double angle, Vector3dc axis) {
return rotate(angle, axis.x(), axis.y(), axis.z());
}
/**
* Apply a rotation transformation, rotating the given radians about the specified axis and store the result in <code>dest</code>.
* <p>
* The axis described by the <code>axis</code> vector needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given axis and angle,
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the axis-angle rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(double, Vector3dc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(double, Vector3dc)
*
* @param angle
* the angle in radians
* @param axis
* the rotation axis (needs to be {@link Vector3d#normalize() normalized})
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotate(double angle, Vector3dc axis, Matrix3d dest) {
return rotate(angle, axis.x(), axis.y(), axis.z(), dest);
}
/**
* Apply a rotation transformation, rotating the given radians about the specified axis, to this matrix.
* <p>
* The axis described by the <code>axis</code> vector needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given angle and axis,
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the axis-angle rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(double, Vector3fc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(double, Vector3fc)
*
* @param angle
* the angle in radians
* @param axis
* the rotation axis (needs to be {@link Vector3f#normalize() normalized})
* @return this
*/
public Matrix3d rotate(double angle, Vector3fc axis) {
return rotate(angle, axis.x(), axis.y(), axis.z());
}
/**
* Apply a rotation transformation, rotating the given radians about the specified axis and store the result in <code>dest</code>.
* <p>
* The axis described by the <code>axis</code> vector needs to be a unit vector.
* <p>
* When used with a right-handed coordinate system, the produced rotation will rotate a vector
* counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin.
* When used with a left-handed coordinate system, the rotation is clockwise.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given axis and angle,
* then the new matrix will be <code>M * A</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * A * v</code>,
* the axis-angle rotation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying,
* use {@link #rotation(double, Vector3fc)}.
* <p>
* Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a>
*
* @see #rotate(double, double, double, double)
* @see #rotation(double, Vector3fc)
*
* @param angle
* the angle in radians
* @param axis
* the rotation axis (needs to be {@link Vector3f#normalize() normalized})
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotate(double angle, Vector3fc axis, Matrix3d dest) {
return rotate(angle, axis.x(), axis.y(), axis.z(), dest);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getRow(int, org.joml.Vector3d)
*/
public Vector3d getRow(int row, Vector3d dest) throws IndexOutOfBoundsException {
switch (row) {
case 0:
dest.x = m00;
dest.y = m10;
dest.z = m20;
break;
case 1:
dest.x = m01;
dest.y = m11;
dest.z = m21;
break;
case 2:
dest.x = m02;
dest.y = m12;
dest.z = m22;
break;
default:
throw new IndexOutOfBoundsException();
}
return dest;
}
/**
* Set the row at the given <code>row</code> index, starting with <code>0</code>.
*
* @param row
* the row index in <tt>[0..2]</tt>
* @param src
* the row components to set
* @return this
* @throws IndexOutOfBoundsException if <code>row</code> is not in <tt>[0..2]</tt>
*/
public Matrix3d setRow(int row, Vector3dc src) throws IndexOutOfBoundsException {
return setRow(row, src.x(), src.y(), src.z());
}
/**
* Set the row at the given <code>row</code> index, starting with <code>0</code>.
*
* @param row
* the column index in <tt>[0..2]</tt>
* @param x
* the first element in the row
* @param y
* the second element in the row
* @param z
* the third element in the row
* @return this
* @throws IndexOutOfBoundsException if <code>row</code> is not in <tt>[0..2]</tt>
*/
public Matrix3d setRow(int row, double x, double y, double z) throws IndexOutOfBoundsException {
switch (row) {
case 0:
this.m00 = x;
this.m01 = y;
this.m02 = z;
break;
case 1:
this.m10 = x;
this.m11 = y;
this.m12 = z;
break;
case 2:
this.m20 = x;
this.m21 = y;
this.m22 = z;
break;
default:
throw new IndexOutOfBoundsException();
}
return this;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getColumn(int, org.joml.Vector3d)
*/
public Vector3d getColumn(int column, Vector3d dest) throws IndexOutOfBoundsException {
switch (column) {
case 0:
dest.x = m00;
dest.y = m01;
dest.z = m02;
break;
case 1:
dest.x = m10;
dest.y = m11;
dest.z = m12;
break;
case 2:
dest.x = m20;
dest.y = m21;
dest.z = m22;
break;
default:
throw new IndexOutOfBoundsException();
}
return dest;
}
/**
* Set the column at the given <code>column</code> index, starting with <code>0</code>.
*
* @param column
* the column index in <tt>[0..2]</tt>
* @param src
* the column components to set
* @return this
* @throws IndexOutOfBoundsException if <code>column</code> is not in <tt>[0..2]</tt>
*/
public Matrix3d setColumn(int column, Vector3dc src) throws IndexOutOfBoundsException {
return setColumn(column, src.x(), src.y(), src.z());
}
/**
* Set the column at the given <code>column</code> index, starting with <code>0</code>.
*
* @param column
* the column index in <tt>[0..2]</tt>
* @param x
* the first element in the column
* @param y
* the second element in the column
* @param z
* the third element in the column
* @return this
* @throws IndexOutOfBoundsException if <code>column</code> is not in <tt>[0..2]</tt>
*/
public Matrix3d setColumn(int column, double x, double y, double z) throws IndexOutOfBoundsException {
switch (column) {
case 0:
this.m00 = x;
this.m01 = y;
this.m02 = z;
break;
case 1:
this.m10 = x;
this.m11 = y;
this.m12 = z;
break;
case 2:
this.m20 = x;
this.m21 = y;
this.m22 = z;
break;
default:
throw new IndexOutOfBoundsException();
}
return this;
}
/*
* (non-Javadoc)
* @see org.joml.Matrix3dc#get(int, int)
*/
public double get(int column, int row) {
switch (column) {
case 0:
switch (row) {
case 0:
return m00;
case 1:
return m01;
case 2:
return m02;
default:
break;
}
break;
case 1:
switch (row) {
case 0:
return m10;
case 1:
return m11;
case 2:
return m12;
default:
break;
}
break;
case 2:
switch (row) {
case 0:
return m20;
case 1:
return m21;
case 2:
return m22;
default:
break;
}
break;
default:
break;
}
throw new IllegalArgumentException();
}
/**
* Set the matrix element at the given column and row to the specified value.
*
* @param column
* the colum index in <tt>[0..2]</tt>
* @param row
* the row index in <tt>[0..2]</tt>
* @param value
* the value
* @return this
*/
public Matrix3d set(int column, int row, double value) {
switch (column) {
case 0:
switch (row) {
case 0:
this.m00 = value;
return this;
case 1:
this.m01 = value;
return this;
case 2:
this.m02 = value;
return this;
default:
break;
}
break;
case 1:
switch (row) {
case 0:
this.m10 = value;
return this;
case 1:
this.m11 = value;
return this;
case 2:
this.m12 = value;
return this;
default:
break;
}
break;
case 2:
switch (row) {
case 0:
this.m20 = value;
return this;
case 1:
this.m21 = value;
return this;
case 2:
this.m22 = value;
return this;
default:
break;
}
break;
default:
break;
}
throw new IllegalArgumentException();
}
/**
* Set <code>this</code> matrix to its own normal matrix.
* <p>
* Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors,
* then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix.
* In this case, use {@link #set(Matrix3dc)} to set a given Matrix3f to this matrix.
*
* @see #set(Matrix3dc)
*
* @return this
*/
public Matrix3d normal() {
return normal(this);
}
/**
* Compute a normal matrix from <code>this</code> matrix and store it into <code>dest</code>.
* <p>
* Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors,
* then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix.
* In this case, use {@link #set(Matrix3dc)} to set a given Matrix3d to this matrix.
*
* @see #set(Matrix3dc)
*
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d normal(Matrix3d dest) {
double m00m11 = m00 * m11;
double m01m10 = m01 * m10;
double m02m10 = m02 * m10;
double m00m12 = m00 * m12;
double m01m12 = m01 * m12;
double m02m11 = m02 * m11;
double det = (m00m11 - m01m10) * m22 + (m02m10 - m00m12) * m21 + (m01m12 - m02m11) * m20;
double s = 1.0 / det;
/* Invert and transpose in one go */
double nm00 = (m11 * m22 - m21 * m12) * s;
double nm01 = (m20 * m12 - m10 * m22) * s;
double nm02 = (m10 * m21 - m20 * m11) * s;
double nm10 = (m21 * m02 - m01 * m22) * s;
double nm11 = (m00 * m22 - m20 * m02) * s;
double nm12 = (m20 * m01 - m00 * m21) * s;
double nm20 = (m01m12 - m02m11) * s;
double nm21 = (m02m10 - m00m12) * s;
double nm22 = (m00m11 - m01m10) * s;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m20 = nm20;
dest.m21 = nm21;
dest.m22 = nm22;
return dest;
}
/**
* Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the
* lookalong rotation transformation will be applied first!
* <p>
* In order to set the matrix to a lookalong transformation without post-multiplying it,
* use {@link #setLookAlong(Vector3dc, Vector3dc) setLookAlong()}.
*
* @see #lookAlong(double, double, double, double, double, double)
* @see #setLookAlong(Vector3dc, Vector3dc)
*
* @param dir
* the direction in space to look along
* @param up
* the direction of 'up'
* @return this
*/
public Matrix3d lookAlong(Vector3dc dir, Vector3dc up) {
return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), this);
}
/**
* Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the
* lookalong rotation transformation will be applied first!
* <p>
* In order to set the matrix to a lookalong transformation without post-multiplying it,
* use {@link #setLookAlong(Vector3dc, Vector3dc) setLookAlong()}.
*
* @see #lookAlong(double, double, double, double, double, double)
* @see #setLookAlong(Vector3dc, Vector3dc)
*
* @param dir
* the direction in space to look along
* @param up
* the direction of 'up'
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d lookAlong(Vector3dc dir, Vector3dc up, Matrix3d dest) {
return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), dest);
}
/**
* Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the
* lookalong rotation transformation will be applied first!
* <p>
* In order to set the matrix to a lookalong transformation without post-multiplying it,
* use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()}
*
* @see #setLookAlong(double, double, double, double, double, double)
*
* @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
*/
public Matrix3d lookAlong(double dirX, double dirY, double dirZ,
double upX, double upY, double upZ, Matrix3d dest) {
// Normalize direction
double invDirLength = 1.0 / Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
double dirnX = dirX * invDirLength;
double dirnY = dirY * invDirLength;
double dirnZ = dirZ * invDirLength;
// right = direction x up
double rightX, rightY, rightZ;
rightX = dirnY * upZ - dirnZ * upY;
rightY = dirnZ * upX - dirnX * upZ;
rightZ = dirnX * upY - dirnY * upX;
// normalize right
double invRightLength = 1.0 / Math.sqrt(rightX * rightX + rightY * rightY + rightZ * rightZ);
rightX *= invRightLength;
rightY *= invRightLength;
rightZ *= invRightLength;
// up = right x direction
double upnX = rightY * dirnZ - rightZ * dirnY;
double upnY = rightZ * dirnX - rightX * dirnZ;
double upnZ = rightX * dirnY - rightY * dirnX;
// calculate right matrix elements
double rm00 = rightX;
double rm01 = upnX;
double rm02 = -dirnX;
double rm10 = rightY;
double rm11 = upnY;
double rm12 = -dirnY;
double rm20 = rightZ;
double rm21 = upnZ;
double rm22 = -dirnZ;
// perform optimized matrix multiplication
// introduce temporaries for dependent results
double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02;
double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02;
double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02;
double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12;
double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12;
double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12;
dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22;
dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22;
dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22;
// set the rest of the matrix elements
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
return dest;
}
/**
* Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the
* lookalong rotation transformation will be applied first!
* <p>
* In order to set the matrix to a lookalong transformation without post-multiplying it,
* use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()}
*
* @see #setLookAlong(double, double, double, double, double, double)
*
* @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
* @return this
*/
public Matrix3d lookAlong(double dirX, double dirY, double dirZ,
double upX, double upY, double upZ) {
return lookAlong(dirX, dirY, dirZ, upX, upY, upZ, this);
}
/**
* Set this matrix to a rotation transformation to make <code>-z</code>
* point along <code>dir</code>.
* <p>
* In order to apply the lookalong transformation to any previous existing transformation,
* use {@link #lookAlong(Vector3dc, Vector3dc)}.
*
* @see #setLookAlong(Vector3dc, Vector3dc)
* @see #lookAlong(Vector3dc, Vector3dc)
*
* @param dir
* the direction in space to look along
* @param up
* the direction of 'up'
* @return this
*/
public Matrix3d setLookAlong(Vector3dc dir, Vector3dc up) {
return setLookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z());
}
/**
* Set this matrix to a rotation transformation to make <code>-z</code>
* point along <code>dir</code>.
* <p>
* In order to apply the lookalong transformation to any previous existing transformation,
* use {@link #lookAlong(double, double, double, double, double, double) lookAlong()}
*
* @see #setLookAlong(double, double, double, double, double, double)
* @see #lookAlong(double, double, double, double, double, double)
*
* @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
* @return this
*/
public Matrix3d setLookAlong(double dirX, double dirY, double dirZ,
double upX, double upY, double upZ) {
// Normalize direction
double invDirLength = 1.0 / Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
double dirnX = dirX * invDirLength;
double dirnY = dirY * invDirLength;
double dirnZ = dirZ * invDirLength;
// right = direction x up
double rightX, rightY, rightZ;
rightX = dirnY * upZ - dirnZ * upY;
rightY = dirnZ * upX - dirnX * upZ;
rightZ = dirnX * upY - dirnY * upX;
// normalize right
double invRightLength = 1.0 / Math.sqrt(rightX * rightX + rightY * rightY + rightZ * rightZ);
rightX *= invRightLength;
rightY *= invRightLength;
rightZ *= invRightLength;
// up = right x direction
double upnX = rightY * dirnZ - rightZ * dirnY;
double upnY = rightZ * dirnX - rightX * dirnZ;
double upnZ = rightX * dirnY - rightY * dirnX;
m00 = rightX;
m01 = upnX;
m02 = -dirnX;
m10 = rightY;
m11 = upnY;
m12 = -dirnY;
m20 = rightZ;
m21 = upnZ;
m22 = -dirnZ;
return this;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#getScale(org.joml.Vector3d)
*/
public Vector3d getScale(Vector3d dest) {
dest.x = Math.sqrt(m00 * m00 + m01 * m01 + m02 * m02);
dest.y = Math.sqrt(m10 * m10 + m11 * m11 + m12 * m12);
dest.z = Math.sqrt(m20 * m20 + m21 * m21 + m22 * m22);
return dest;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#positiveZ(org.joml.Vector3d)
*/
public Vector3d positiveZ(Vector3d dir) {
dir.x = m10 * m21 - m11 * m20;
dir.y = m20 * m01 - m21 * m00;
dir.z = m00 * m11 - m01 * m10;
dir.normalize();
return dir;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#normalizedPositiveZ(org.joml.Vector3d)
*/
public Vector3d normalizedPositiveZ(Vector3d dir) {
dir.x = m02;
dir.y = m12;
dir.z = m22;
return dir;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#positiveX(org.joml.Vector3d)
*/
public Vector3d positiveX(Vector3d dir) {
dir.x = m11 * m22 - m12 * m21;
dir.y = m02 * m21 - m01 * m22;
dir.z = m01 * m12 - m02 * m11;
dir.normalize();
return dir;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#normalizedPositiveX(org.joml.Vector3d)
*/
public Vector3d normalizedPositiveX(Vector3d dir) {
dir.x = m00;
dir.y = m10;
dir.z = m20;
return dir;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#positiveY(org.joml.Vector3d)
*/
public Vector3d positiveY(Vector3d dir) {
dir.x = m12 * m20 - m10 * m22;
dir.y = m00 * m22 - m02 * m20;
dir.z = m02 * m10 - m00 * m12;
dir.normalize();
return dir;
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#normalizedPositiveY(org.joml.Vector3d)
*/
public Vector3d normalizedPositiveY(Vector3d dir) {
dir.x = m01;
dir.y = m11;
dir.z = m21;
return dir;
}
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(m00);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m01);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m02);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m10);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m11);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m12);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m20);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m21);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(m22);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Matrix3d other = (Matrix3d) obj;
if (Double.doubleToLongBits(m00) != Double.doubleToLongBits(other.m00))
return false;
if (Double.doubleToLongBits(m01) != Double.doubleToLongBits(other.m01))
return false;
if (Double.doubleToLongBits(m02) != Double.doubleToLongBits(other.m02))
return false;
if (Double.doubleToLongBits(m10) != Double.doubleToLongBits(other.m10))
return false;
if (Double.doubleToLongBits(m11) != Double.doubleToLongBits(other.m11))
return false;
if (Double.doubleToLongBits(m12) != Double.doubleToLongBits(other.m12))
return false;
if (Double.doubleToLongBits(m20) != Double.doubleToLongBits(other.m20))
return false;
if (Double.doubleToLongBits(m21) != Double.doubleToLongBits(other.m21))
return false;
if (Double.doubleToLongBits(m22) != Double.doubleToLongBits(other.m22))
return false;
return true;
}
/**
* Exchange the values of <code>this</code> matrix with the given <code>other</code> matrix.
*
* @param other
* the other matrix to exchange the values with
* @return this
*/
public Matrix3d swap(Matrix3d other) {
double tmp;
tmp = m00; m00 = other.m00; other.m00 = tmp;
tmp = m01; m01 = other.m01; other.m01 = tmp;
tmp = m02; m02 = other.m02; other.m02 = tmp;
tmp = m10; m10 = other.m10; other.m10 = tmp;
tmp = m11; m11 = other.m11; other.m11 = tmp;
tmp = m12; m12 = other.m12; other.m12 = tmp;
tmp = m20; m20 = other.m20; other.m20 = tmp;
tmp = m21; m21 = other.m21; other.m21 = tmp;
tmp = m22; m22 = other.m22; other.m22 = tmp;
return this;
}
/**
* Component-wise add <code>this</code> and <code>other</code>.
*
* @param other
* the other addend
* @return this
*/
public Matrix3d add(Matrix3dc other) {
return add(other, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#add(org.joml.Matrix3dc, org.joml.Matrix3d)
*/
public Matrix3d add(Matrix3dc other, Matrix3d dest) {
dest.m00 = m00 + other.m00();
dest.m01 = m01 + other.m01();
dest.m02 = m02 + other.m02();
dest.m10 = m10 + other.m10();
dest.m11 = m11 + other.m11();
dest.m12 = m12 + other.m12();
dest.m20 = m20 + other.m20();
dest.m21 = m21 + other.m21();
dest.m22 = m22 + other.m22();
return dest;
}
/**
* Component-wise subtract <code>subtrahend</code> from <code>this</code>.
*
* @param subtrahend
* the subtrahend
* @return this
*/
public Matrix3d sub(Matrix3dc subtrahend) {
return sub(subtrahend, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#sub(org.joml.Matrix3dc, org.joml.Matrix3d)
*/
public Matrix3d sub(Matrix3dc subtrahend, Matrix3d dest) {
dest.m00 = m00 - subtrahend.m00();
dest.m01 = m01 - subtrahend.m01();
dest.m02 = m02 - subtrahend.m02();
dest.m10 = m10 - subtrahend.m10();
dest.m11 = m11 - subtrahend.m11();
dest.m12 = m12 - subtrahend.m12();
dest.m20 = m20 - subtrahend.m20();
dest.m21 = m21 - subtrahend.m21();
dest.m22 = m22 - subtrahend.m22();
return dest;
}
/**
* Component-wise multiply <code>this</code> by <code>other</code>.
*
* @param other
* the other matrix
* @return this
*/
public Matrix3d mulComponentWise(Matrix3dc other) {
return mulComponentWise(other, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#mulComponentWise(org.joml.Matrix3dc, org.joml.Matrix3d)
*/
public Matrix3d mulComponentWise(Matrix3dc other, Matrix3d dest) {
dest.m00 = m00 * other.m00();
dest.m01 = m01 * other.m01();
dest.m02 = m02 * other.m02();
dest.m10 = m10 * other.m10();
dest.m11 = m11 * other.m11();
dest.m12 = m12 * other.m12();
dest.m20 = m20 * other.m20();
dest.m21 = m21 * other.m21();
dest.m22 = m22 * other.m22();
return dest;
}
/**
* Set this matrix to a skew-symmetric matrix using the following layout:
* <pre>
* 0, a, -b
* -a, 0, c
* b, -c, 0
* </pre>
*
* Reference: <a href="https://en.wikipedia.org/wiki/Skew-symmetric_matrix">https://en.wikipedia.org</a>
*
* @param a
* the value used for the matrix elements m01 and m10
* @param b
* the value used for the matrix elements m02 and m20
* @param c
* the value used for the matrix elements m12 and m21
* @return this
*/
public Matrix3d setSkewSymmetric(double a, double b, double c) {
m00 = m11 = m22 = 0;
m01 = -a;
m02 = b;
m10 = a;
m12 = -c;
m20 = -b;
m21 = c;
return this;
}
/**
* Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
* and store the result in <code>this</code>.
* <p>
* If <code>t</code> is <tt>0.0</tt> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
* then the result is <code>other</code>.
*
* @param other
* the other matrix
* @param t
* the interpolation factor between 0.0 and 1.0
* @return this
*/
public Matrix3d lerp(Matrix3dc other, double t) {
return lerp(other, t, this);
}
/* (non-Javadoc)
* @see org.joml.Matrix3dc#lerp(org.joml.Matrix3dc, double, org.joml.Matrix3d)
*/
public Matrix3d lerp(Matrix3dc other, double t, Matrix3d dest) {
dest.m00 = m00 + (other.m00() - m00) * t;
dest.m01 = m01 + (other.m01() - m01) * t;
dest.m02 = m02 + (other.m02() - m02) * t;
dest.m10 = m10 + (other.m10() - m10) * t;
dest.m11 = m11 + (other.m11() - m11) * t;
dest.m12 = m12 + (other.m12() - m12) * t;
dest.m20 = m20 + (other.m20() - m20) * t;
dest.m21 = m21 + (other.m21() - m21) * t;
dest.m22 = m22 + (other.m22() - m22) * t;
return dest;
}
/**
* Apply a model transformation to this matrix for a right-handed coordinate system,
* that aligns the local <code>+Z</code> axis with <code>direction</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>,
* the lookat transformation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying it,
* use {@link #rotationTowards(Vector3dc, Vector3dc) rotationTowards()}.
* <p>
* This method is equivalent to calling: <tt>mul(new Matrix3d().lookAlong(new Vector3d(dir).negate(), up).invert(), dest)</tt>
*
* @see #rotateTowards(double, double, double, double, double, double, Matrix3d)
* @see #rotationTowards(Vector3dc, Vector3dc)
*
* @param direction
* the direction to rotate towards
* @param up
* the model's up vector
* @param dest
* will hold the result
* @return dest
*/
public Matrix3d rotateTowards(Vector3dc direction, Vector3dc up, Matrix3d dest) {
return rotateTowards(direction.x(), direction.y(), direction.z(), up.x(), up.y(), up.z(), dest);
}
/**
* Apply a model transformation to this matrix for a right-handed coordinate system,
* that aligns the local <code>+Z</code> axis with <code>direction</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>,
* the lookat transformation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying it,
* use {@link #rotationTowards(Vector3dc, Vector3dc) rotationTowards()}.
* <p>
* This method is equivalent to calling: <tt>mul(new Matrix3d().lookAlong(new Vector3d(dir).negate(), up).invert())</tt>
*
* @see #rotateTowards(double, double, double, double, double, double)
* @see #rotationTowards(Vector3dc, Vector3dc)
*
* @param direction
* the direction to orient towards
* @param up
* the up vector
* @return this
*/
public Matrix3d rotateTowards(Vector3dc direction, Vector3dc up) {
return rotateTowards(direction.x(), direction.y(), direction.z(), up.x(), up.y(), up.z(), this);
}
/**
* Apply a model transformation to this matrix for a right-handed coordinate system,
* that aligns the local <code>+Z</code> axis with <code>direction</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>,
* the lookat transformation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying it,
* use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}.
* <p>
* This method is equivalent to calling: <tt>mul(new Matrix3d().lookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert())</tt>
*
* @see #rotateTowards(Vector3dc, Vector3dc)
* @see #rotationTowards(double, double, double, double, double, double)
*
* @param dirX
* the x-coordinate of the direction to rotate towards
* @param dirY
* the y-coordinate of the direction to rotate towards
* @param dirZ
* the z-coordinate of the direction to rotate towards
* @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
* @return this
*/
public Matrix3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) {
return rotateTowards(dirX, dirY, dirZ, upX, upY, upZ, this);
}
/**
* Apply a model transformation to this matrix for a right-handed coordinate system,
* that aligns the local <code>+Z</code> axis with <code>dir</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix,
* then the new matrix will be <code>M * L</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * L * v</code>,
* the lookat transformation will be applied first!
* <p>
* In order to set the matrix to a rotation transformation without post-multiplying it,
* use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}.
* <p>
* This method is equivalent to calling: <tt>mul(new Matrix3d().lookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert(), dest)</tt>
*
* @see #rotateTowards(Vector3dc, Vector3dc)
* @see #rotationTowards(double, double, double, double, double, double)
*
* @param dirX
* the x-coordinate of the direction to rotate towards
* @param dirY
* the y-coordinate of the direction to rotate towards
* @param dirZ
* the z-coordinate of the direction to rotate towards
* @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
*/
public Matrix3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ, Matrix3d dest) {
// Normalize direction
double invDirLength = 1.0 / Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
double ndirX = dirX * invDirLength;
double ndirY = dirY * invDirLength;
double ndirZ = dirZ * invDirLength;
// left = up x direction
double leftX, leftY, leftZ;
leftX = upY * ndirZ - upZ * ndirY;
leftY = upZ * ndirX - upX * ndirZ;
leftZ = upX * ndirY - upY * ndirX;
// normalize left
double invLeftLength = 1.0 / Math.sqrt(leftX * leftX + leftY * leftY + leftZ * leftZ);
leftX *= invLeftLength;
leftY *= invLeftLength;
leftZ *= invLeftLength;
// up = direction x left
double upnX = ndirY * leftZ - ndirZ * leftY;
double upnY = ndirZ * leftX - ndirX * leftZ;
double upnZ = ndirX * leftY - ndirY * leftX;
double rm00 = leftX;
double rm01 = leftY;
double rm02 = leftZ;
double rm10 = upnX;
double rm11 = upnY;
double rm12 = upnZ;
double rm20 = ndirX;
double rm21 = ndirY;
double rm22 = ndirZ;
double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02;
double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02;
double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02;
double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12;
double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12;
double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12;
dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22;
dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22;
dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
return dest;
}
/**
* Set this matrix to a model transformation for a right-handed coordinate system,
* that aligns the local <code>-z</code> axis with <code>center - eye</code>.
* <p>
* In order to apply the rotation transformation to a previous existing transformation,
* use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}.
* <p>
* This method is equivalent to calling: <tt>setLookAlong(new Vector3d(dir).negate(), up).invert()</tt>
*
* @see #rotationTowards(Vector3dc, Vector3dc)
* @see #rotateTowards(double, double, double, double, double, double)
*
* @param dir
* the direction to orient the local -z axis towards
* @param up
* the up vector
* @return this
*/
public Matrix3d rotationTowards(Vector3dc dir, Vector3dc up) {
return rotationTowards(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z());
}
/**
* Set this matrix to a model transformation for a right-handed coordinate system,
* that aligns the local <code>-z</code> axis with <code>center - eye</code>.
* <p>
* In order to apply the rotation transformation to a previous existing transformation,
* use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}.
* <p>
* This method is equivalent to calling: <tt>setLookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert()</tt>
*
* @see #rotateTowards(Vector3dc, Vector3dc)
* @see #rotationTowards(double, double, double, double, double, double)
*
* @param dirX
* the x-coordinate of the direction to rotate towards
* @param dirY
* the y-coordinate of the direction to rotate towards
* @param dirZ
* the z-coordinate of the direction to rotate towards
* @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
* @return this
*/
public Matrix3d rotationTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) {
// Normalize direction
double invDirLength = 1.0 / Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
double ndirX = dirX * invDirLength;
double ndirY = dirY * invDirLength;
double ndirZ = dirZ * invDirLength;
// left = up x direction
double leftX, leftY, leftZ;
leftX = upY * ndirZ - upZ * ndirY;
leftY = upZ * ndirX - upX * ndirZ;
leftZ = upX * ndirY - upY * ndirX;
// normalize left
double invLeftLength = 1.0 / Math.sqrt(leftX * leftX + leftY * leftY + leftZ * leftZ);
leftX *= invLeftLength;
leftY *= invLeftLength;
leftZ *= invLeftLength;
// up = direction x left
double upnX = ndirY * leftZ - ndirZ * leftY;
double upnY = ndirZ * leftX - ndirX * leftZ;
double upnZ = ndirX * leftY - ndirY * leftX;
this.m00 = leftX;
this.m01 = leftY;
this.m02 = leftZ;
this.m10 = upnX;
this.m11 = upnY;
this.m12 = upnZ;
this.m20 = ndirX;
this.m21 = ndirY;
this.m22 = ndirZ;
return this;
}
/**
* Extract the Euler angles from the rotation represented by <code>this</code> matrix and store the extracted Euler angles in <code>dest</code>.
* <p>
* This method assumes that <code>this</code> matrix only represents a rotation without scaling.
* <p>
* Note that the returned Euler angles must be applied in the order <tt>Z * Y * X</tt> to obtain the identical matrix.
* This means that calling {@link Matrix3d#rotateZYX(double, double, double)} using the obtained Euler angles will yield
* the same rotation as the original matrix from which the Euler angles were obtained, so in the below code the matrix
* <tt>m2</tt> should be identical to <tt>m</tt> (disregarding possible floating-point inaccuracies).
* <pre>
* Matrix3d m = ...; // <- matrix only representing rotation
* Matrix3d n = new Matrix3d();
* n.rotateZYX(m.getEulerAnglesZYX(new Vector3d()));
* </pre>
* <p>
* Reference: <a href="http://nghiaho.com/?page_id=846">http://nghiaho.com/</a>
*
* @param dest
* will hold the extracted Euler angles
* @return dest
*/
public Vector3d getEulerAnglesZYX(Vector3d dest) {
dest.x = (float) Math.atan2(m12, m22);
dest.y = (float) Math.atan2(-m02, Math.sqrt(m12 * m12 + m22 * m22));
dest.z = (float) Math.atan2(m01, m00);
return dest;
}
/**
* Create a new immutable view of this {@link Matrix3d}.
* <p>
* The observable state of the returned object is the same as that of <code>this</code>, but casting
* the returned object to Matrix3d will not be possible.
* <p>
* This method allocates a new instance of a class implementing Matrix3dc on every call.
*
* @return the immutable instance
*/
public Matrix3dc toImmutable() {
if (!Options.DEBUG)
return this;
return new Proxy(this);
}
}