blob: 3a2ef1e6ec1cc5b2f758defe48143208a5000452 [file] [log] [blame]
/*
Copyright (C) 2013 John McCutchan <john@johnmccutchan.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
part of vector_math_64;
/// 3D Matrix.
/// Values are stored in column major order.
class Matrix3 {
final Float64List storage = new Float64List(9);
/// Solve [A] * [x] = [b].
static void solve2(Matrix3 A, Vector2 x, Vector2 b) {
final double a11 = A.entry(0, 0);
final double a12 = A.entry(0, 1);
final double a21 = A.entry(1, 0);
final double a22 = A.entry(1, 1);
final double bx = b.x - A.storage[6];
final double by = b.y - A.storage[7];
double det = a11 * a22 - a12 * a21;
if (det != 0.0) {
det = 1.0 / det;
}
x.x = det * (a22 * bx - a12 * by);
x.y = det * (a11 * by - a21 * bx);
}
/// Solve [A] * [x] = [b].
static void solve(Matrix3 A, Vector3 x, Vector3 b) {
final double A0x = A.entry(0, 0);
final double A0y = A.entry(1, 0);
final double A0z = A.entry(2, 0);
final double A1x = A.entry(0, 1);
final double A1y = A.entry(1, 1);
final double A1z = A.entry(2, 1);
final double A2x = A.entry(0, 2);
final double A2y = A.entry(1, 2);
final double A2z = A.entry(2, 2);
double rx, ry, rz;
double det;
// Column1 cross Column 2
rx = A1y * A2z - A1z * A2y;
ry = A1z * A2x - A1x * A2z;
rz = A1x * A2y - A1y * A2x;
// A.getColumn(0).dot(x)
det = A0x * rx + A0y * ry + A0z * rz;
if (det != 0.0) {
det = 1.0 / det;
}
// b dot [Column1 cross Column 2]
final double x_ = det * (b.x * rx + b.y * ry + b.z * rz);
// Column2 cross b
rx = -(A2y * b.z - A2z * b.y);
ry = -(A2z * b.x - A2x * b.z);
rz = -(A2x * b.y - A2y * b.x);
// Column0 dot -[Column2 cross b (Column3)]
final double y_ = det * (A0x * rx + A0y * ry + A0z * rz);
// b cross Column 1
rx = -(b.y * A1z - b.z * A1y);
ry = -(b.z * A1x - b.x * A1z);
rz = -(b.x * A1y - b.y * A1x);
// Column0 dot -[b cross Column 1]
final double z_ = det * (A0x * rx + A0y * ry + A0z * rz);
x.x = x_;
x.y = y_;
x.z = z_;
}
/// Return index in storage for [row], [col] value.
int index(int row, int col) => (col * 3) + row;
/// Value at [row], [col].
double entry(int row, int col) => storage[index(row, col)];
/// Set value at [row], [col] to be [v].
setEntry(int row, int col, double v) { storage[index(row, col)] = v; }
/// New matrix with specified values.
Matrix3(double arg0, double arg1, double arg2,
double arg3, double arg4, double arg5,
double arg6, double arg7, double arg8) {
setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
/// Constructs a new [Matrix3] filled with zeros.
Matrix3.zero();
/// Identity matrix.
Matrix3.identity() {
setIdentity();
}
/// Copes values from [other].
Matrix3.copy(Matrix3 other) {
setFrom(other);
}
/// Constructs a new mat3 from columns.
Matrix3.columns(Vector3 arg0, Vector3 arg1, Vector3 arg2) {
setColumns(arg0, arg1, arg2);
}
/// Outer product of [u] and [v].
Matrix3.outer(Vector3 u, Vector3 v) {
storage[0] = u.storage[0] * v.storage[0];
storage[1] = u.storage[0] * v.storage[1];
storage[2] = u.storage[0] * v.storage[2];
storage[3] = u.storage[1] * v.storage[0];
storage[4] = u.storage[1] * v.storage[1];
storage[5] = u.storage[1] * v.storage[2];
storage[6] = u.storage[2] * v.storage[0];
storage[7] = u.storage[2] * v.storage[1];
storage[8] = u.storage[2] * v.storage[2];
}
//// Rotation of [radians_] around X axis.
Matrix3.rotationX(double radians_) {
setRotationX(radians_);
}
//// Rotation of [radians_] around Y axis.
Matrix3.rotationY(double radians_) {
setRotationY(radians_);
}
//// Rotation of [radians_] around Z axis.
Matrix3.rotationZ(double radians_) {
setRotationZ(radians_);
}
/// Sets the matrix with specified values.
Matrix3 setValues(double arg0, double arg1, double arg2,
double arg3, double arg4, double arg5,
double arg6, double arg7, double arg8) {
storage[8] = arg8;
storage[7] = arg7;
storage[6] = arg6;
storage[5] = arg5;
storage[4] = arg4;
storage[3] = arg3;
storage[2] = arg2;
storage[1] = arg1;
storage[0] = arg0;
return this;
}
/// Sets the entire matrix to the column values.
Matrix3 setColumns(Vector3 arg0, Vector3 arg1, Vector3 arg2) {
storage[0] = arg0.storage[0];
storage[1] = arg0.storage[1];
storage[2] = arg0.storage[2];
storage[3] = arg1.storage[0];
storage[4] = arg1.storage[1];
storage[5] = arg1.storage[2];
storage[6] = arg2.storage[0];
storage[7] = arg2.storage[1];
storage[8] = arg2.storage[2];
return this;
}
/// Sets the entire matrix to the matrix in [arg].
Matrix3 setFrom(Matrix3 arg) {
storage[8] = arg.storage[8];
storage[7] = arg.storage[7];
storage[6] = arg.storage[6];
storage[5] = arg.storage[5];
storage[4] = arg.storage[4];
storage[3] = arg.storage[3];
storage[2] = arg.storage[2];
storage[1] = arg.storage[1];
storage[0] = arg.storage[0];
return this;
}
/// Set the diagonal of the matrix.
Matrix3 splatDiagonal(double arg) {
storage[0] = arg;
storage[4] = arg;
storage[8] = arg;
return this;
}
/// Set the diagonal of the matrix.
Matrix3 setDiagonal(Vector3 arg) {
storage[0] = arg.storage[0];
storage[4] = arg.storage[1];
storage[8] = arg.storage[2];
return this;
}
/// Sets the upper 2x2 of the matrix to be [arg].
Matrix3 setUpper2x2(Matrix2 arg) {
storage[0] = storage[0];
storage[1] = storage[1];
storage[3] = storage[2];
storage[4] = storage[3];
return this;
}
/// Returns a printable string
String toString() {
String s = '';
s = '$s[0] ${getRow(0)}\n';
s = '$s[1] ${getRow(1)}\n';
s = '$s[2] ${getRow(2)}\n';
return s;
}
/// Dimension of the matrix.
int get dimension => 3;
double operator [](int i) => storage[i];
void operator[]=(int i, double v) { storage[i] = v; }
/// Returns row 0
Vector3 get row0 => getRow(0);
/// Returns row 1
Vector3 get row1 => getRow(1);
/// Returns row 2
Vector3 get row2 => getRow(2);
/// Sets row 0 to [arg]
set row0(Vector3 arg) => setRow(0, arg);
/// Sets row 1 to [arg]
set row1(Vector3 arg) => setRow(1, arg);
/// Sets row 2 to [arg]
set row2(Vector3 arg) => setRow(2, arg);
/// Assigns the [row] of to [arg].
void setRow(int row, Vector3 arg) {
storage[index(row, 0)] = arg.storage[0];
storage[index(row, 1)] = arg.storage[1];
storage[index(row, 2)] = arg.storage[2];
}
/// Gets the [row] of the matrix
Vector3 getRow(int row) {
Vector3 r = new Vector3.zero();
r.storage[0] = storage[index(row, 0)];
r.storage[1] = storage[index(row, 1)];
r.storage[2] = storage[index(row, 2)];
return r;
}
/// Assigns the [column] of the matrix [arg]
void setColumn(int column, Vector3 arg) {
int entry = column * 3;
storage[entry + 2] = arg.storage[2];
storage[entry + 1] = arg.storage[1];
storage[entry + 0] = arg.storage[0];
}
/// Gets the [column] of the matrix
Vector3 getColumn(int column) {
Vector3 r = new Vector3.zero();
int entry = column * 3;
r.storage[2] = storage[entry + 2];
r.storage[1] = storage[entry + 1];
r.storage[0] = storage[entry + 0];
return r;
}
/// Clone of [this].
Matrix3 clone() {
return new Matrix3.copy(this);
}
/// Copy [this] into [arg].
Matrix3 copyInto(Matrix3 arg) {
arg.storage[0] = storage[0];
arg.storage[1] = storage[1];
arg.storage[2] = storage[2];
arg.storage[3] = storage[3];
arg.storage[4] = storage[4];
arg.storage[5] = storage[5];
arg.storage[6] = storage[6];
arg.storage[7] = storage[7];
arg.storage[8] = storage[8];
return arg;
}
// TODO: Clean up functions below here.
Matrix3 _mul_scale(double arg) {
Matrix3 r = new Matrix3.zero();
r.storage[8] = storage[8] * arg;
r.storage[7] = storage[7] * arg;
r.storage[6] = storage[6] * arg;
r.storage[5] = storage[5] * arg;
r.storage[4] = storage[4] * arg;
r.storage[3] = storage[3] * arg;
r.storage[2] = storage[2] * arg;
r.storage[1] = storage[1] * arg;
r.storage[0] = storage[0] * arg;
return r;
}
Matrix3 _mul_matrix(Matrix3 arg) {
var r = new Matrix3.zero();
r.storage[0] = (storage[0] * arg.storage[0]) +
(storage[3] * arg.storage[1]) +
(storage[6] * arg.storage[2]);
r.storage[3] = (storage[0] * arg.storage[3]) +
(storage[3] * arg.storage[4]) +
(storage[6] * arg.storage[5]);
r.storage[6] = (storage[0] * arg.storage[6]) +
(storage[3] * arg.storage[7]) +
(storage[6] * arg.storage[8]);
r.storage[1] = (storage[1] * arg.storage[0]) +
(storage[4] * arg.storage[1]) +
(storage[7] * arg.storage[2]);
r.storage[4] = (storage[1] * arg.storage[3]) +
(storage[4] * arg.storage[4]) +
(storage[7] * arg.storage[5]);
r.storage[7] = (storage[1] * arg.storage[6]) +
(storage[4] * arg.storage[7]) +
(storage[7] * arg.storage[8]);
r.storage[2] = (storage[2] * arg.storage[0]) +
(storage[5] * arg.storage[1]) +
(storage[8] * arg.storage[2]);
r.storage[5] = (storage[2] * arg.storage[3]) +
(storage[5] * arg.storage[4]) +
(storage[8] * arg.storage[5]);
r.storage[8] = (storage[2] * arg.storage[6]) +
(storage[5] * arg.storage[7]) +
(storage[8] * arg.storage[8]);
return r;
}
Vector3 _mul_vector(Vector3 arg) {
Vector3 r = new Vector3.zero();
r.storage[2] = (storage[2] * arg.storage[0]) +
(storage[5] * arg.storage[1]) +
(storage[8] * arg.storage[2]);
r.storage[1] = (storage[1] * arg.storage[0]) +
(storage[4] * arg.storage[1]) +
(storage[7] * arg.storage[2]);
r.storage[0] = (storage[0] * arg.storage[0]) +
(storage[3] * arg.storage[1]) +
(storage[6] * arg.storage[2]);
return r;
}
/// Returns a new vector or matrix by multiplying [this] with [arg].
dynamic operator *(dynamic arg) {
if (arg is double) {
return _mul_scale(arg);
}
if (arg is Vector3) {
return _mul_vector(arg);
}
if (3 == arg.dimension) {
return _mul_matrix(arg);
}
throw new ArgumentError(arg);
}
/// Returns new matrix after component wise [this] + [arg]
Matrix3 operator +(Matrix3 arg) {
Matrix3 r = new Matrix3.zero();
r.storage[0] = storage[0] + arg.storage[0];
r.storage[1] = storage[1] + arg.storage[1];
r.storage[2] = storage[2] + arg.storage[2];
r.storage[3] = storage[3] + arg.storage[3];
r.storage[4] = storage[4] + arg.storage[4];
r.storage[5] = storage[5] + arg.storage[5];
r.storage[6] = storage[6] + arg.storage[6];
r.storage[7] = storage[7] + arg.storage[7];
r.storage[8] = storage[8] + arg.storage[8];
return r;
}
/// Returns new matrix after component wise [this] - [arg]
Matrix3 operator -(Matrix3 arg) {
Matrix3 r = new Matrix3.zero();
r.storage[0] = storage[0] - arg.storage[0];
r.storage[1] = storage[1] - arg.storage[1];
r.storage[2] = storage[2] - arg.storage[2];
r.storage[3] = storage[3] - arg.storage[3];
r.storage[4] = storage[4] - arg.storage[4];
r.storage[5] = storage[5] - arg.storage[5];
r.storage[6] = storage[6] - arg.storage[6];
r.storage[7] = storage[7] - arg.storage[7];
r.storage[8] = storage[8] - arg.storage[8];
return r;
}
/// Returns new matrix -this
Matrix3 operator -() {
Matrix3 r = new Matrix3.zero();
r[0] = -storage[0];
r[1] = -storage[1];
r[2] = -storage[2];
return r;
}
/// Zeros [this].
Matrix3 setZero() {
storage[0] = 0.0;
storage[1] = 0.0;
storage[2] = 0.0;
storage[3] = 0.0;
storage[4] = 0.0;
storage[5] = 0.0;
storage[6] = 0.0;
storage[7] = 0.0;
storage[8] = 0.0;
return this;
}
/// Makes [this] into the identity matrix.
Matrix3 setIdentity() {
storage[0] = 1.0;
storage[1] = 0.0;
storage[2] = 0.0;
storage[3] = 0.0;
storage[4] = 1.0;
storage[5] = 0.0;
storage[6] = 0.0;
storage[7] = 0.0;
storage[8] = 1.0;
return this;
}
/// Returns the tranpose of this.
Matrix3 transposed() {
Matrix3 r = new Matrix3.zero();
r.storage[0] = storage[0];
r.storage[1] = storage[3];
r.storage[2] = storage[6];
r.storage[3] = storage[1];
r.storage[4] = storage[4];
r.storage[5] = storage[7];
r.storage[6] = storage[2];
r.storage[7] = storage[5];
r.storage[8] = storage[8];
return r;
}
Matrix3 transpose() {
double temp;
temp = storage[3];
storage[3] = storage[1];
storage[1] = temp;
temp = storage[6];
storage[6] = storage[2];
storage[2] = temp;
temp = storage[7];
storage[7] = storage[5];
storage[5] = temp;
return this;
}
/// Returns the component wise absolute value of this.
Matrix3 absolute() {
Matrix3 r = new Matrix3.zero();
r.storage[0] = storage[0].abs();
r.storage[1] = storage[1].abs();
r.storage[2] = storage[2].abs();
r.storage[3] = storage[3].abs();
r.storage[4] = storage[4].abs();
r.storage[5] = storage[5].abs();
r.storage[6] = storage[6].abs();
r.storage[7] = storage[7].abs();
r.storage[8] = storage[8].abs();
return r;
}
/// Returns the determinant of this matrix.
double determinant() {
double x = storage[0] *
((storage[4] * storage[8]) - (storage[5] * storage[7]));
double y = storage[1] *
((storage[3] * storage[8]) - (storage[5] * storage[6]));
double z = storage[2] *
((storage[3] * storage[7]) - (storage[4] * storage[6]));
return x - y + z;
}
/// Returns the dot product of row [i] and [v].
double dotRow(int i, Vector3 v) {
return storage[i] * v.storage[0]
+ storage[3+i] * v.storage[1]
+ storage[6+i] * v.storage[2];
}
/// Returns the dot product of column [j] and [v].
double dotColumn(int j, Vector3 v) {
return storage[j*3] * v.storage[0]
+ storage[j*3+1] * v.storage[1]
+ storage[j*3+2] * v.storage[2];
}
/// Returns the trace of the matrix. The trace of a matrix is the sum of
/// the diagonal entries.
double trace() {
double t = 0.0;
t += storage[0];
t += storage[4];
t += storage[8];
return t;
}
/// Returns infinity norm of the matrix. Used for numerical analysis.
double infinityNorm() {
double norm = 0.0;
{
double row_norm = 0.0;
row_norm += storage[0].abs();
row_norm += storage[1].abs();
row_norm += storage[2].abs();
norm = row_norm > norm ? row_norm : norm;
}
{
double row_norm = 0.0;
row_norm += storage[3].abs();
row_norm += storage[4].abs();
row_norm += storage[5].abs();
norm = row_norm > norm ? row_norm : norm;
}
{
double row_norm = 0.0;
row_norm += storage[6].abs();
row_norm += storage[7].abs();
row_norm += storage[8].abs();
norm = row_norm > norm ? row_norm : norm;
}
return norm;
}
/// Returns relative error between [this] and [correct]
double relativeError(Matrix3 correct) {
Matrix3 diff = correct - this;
double correct_norm = correct.infinityNorm();
double diff_norm = diff.infinityNorm();
return diff_norm / correct_norm;
}
/// Returns absolute error between [this] and [correct]
double absoluteError(Matrix3 correct) {
double this_norm = infinityNorm();
double correct_norm = correct.infinityNorm();
double diff_norm = (this_norm - correct_norm).abs();
return diff_norm;
}
/// Invert the matrix. Returns the determinant.
double invert() {
double det = determinant();
if (det == 0.0) {
return 0.0;
}
double invDet = 1.0 / det;
double ix = invDet * (storage[4] * storage[8] - storage[5] * storage[7]);
double iy = invDet * (storage[2] * storage[7] - storage[1] * storage[8]);
double iz = invDet * (storage[1] * storage[5] - storage[2] * storage[4]);
double jx = invDet * (storage[5] * storage[6] - storage[3] * storage[8]);
double jy = invDet * (storage[0] * storage[8] - storage[2] * storage[6]);
double jz = invDet * (storage[2] * storage[3] - storage[0] * storage[5]);
double kx = invDet * (storage[3] * storage[7] - storage[4] * storage[6]);
double ky = invDet * (storage[1] * storage[6] - storage[0] * storage[7]);
double kz = invDet * (storage[0] * storage[4] - storage[1] * storage[3]);
storage[0] = ix;
storage[1] = iy;
storage[2] = iz;
storage[3] = jx;
storage[4] = jy;
storage[5] = jz;
storage[6] = kx;
storage[7] = ky;
storage[8] = kz;
return det;
}
/// Set this matrix to be the inverse of [arg]
double copyInverse(Matrix3 arg) {
double det = arg.determinant();
if (det == 0.0) {
setFrom(arg);
return 0.0;
}
double invDet = 1.0 / det;
double ix = invDet * (arg.storage[4] * arg.storage[8]
- arg.storage[5] * arg.storage[7]);
double iy = invDet * (arg.storage[2] * arg.storage[7]
- arg.storage[1] * arg.storage[8]);
double iz = invDet * (arg.storage[1] * arg.storage[5]
- arg.storage[2] * arg.storage[4]);
double jx = invDet * (arg.storage[5] * arg.storage[6]
- arg.storage[3] * arg.storage[8]);
double jy = invDet * (arg.storage[0] * arg.storage[8]
- arg.storage[2] * arg.storage[6]);
double jz = invDet * (arg.storage[2] * arg.storage[3]
- arg.storage[0] * arg.storage[5]);
double kx = invDet * (arg.storage[3] * arg.storage[7]
- arg.storage[4] * arg.storage[6]);
double ky = invDet * (arg.storage[1] * arg.storage[6]
- arg.storage[0] * arg.storage[7]);
double kz = invDet * (arg.storage[0] * arg.storage[4]
- arg.storage[1] * arg.storage[3]);
storage[0] = ix;
storage[1] = iy;
storage[2] = iz;
storage[3] = jx;
storage[4] = jy;
storage[5] = jz;
storage[6] = kx;
storage[7] = ky;
storage[8] = kz;
return det;
}
/// Turns the matrix into a rotation of [radians] around X
void setRotationX(double radians) {
double c = Math.cos(radians);
double s = Math.sin(radians);
storage[0] = 1.0;
storage[1] = 0.0;
storage[2] = 0.0;
storage[3] = 0.0;
storage[4] = c;
storage[5] = s;
storage[6] = 0.0;
storage[7] = -s;
storage[8] = c;
}
/// Turns the matrix into a rotation of [radians] around Y
void setRotationY(double radians) {
double c = Math.cos(radians);
double s = Math.sin(radians);
storage[0] = c;
storage[1] = 0.0;
storage[2] = s;
storage[3] = 0.0;
storage[4] = 1.0;
storage[5] = 0.0;
storage[6] = -s;
storage[7] = 0.0;
storage[8] = c;
}
/// Turns the matrix into a rotation of [radians] around Z
void setRotationZ(double radians) {
double c = Math.cos(radians);
double s = Math.sin(radians);
storage[0] = c;
storage[1] = s;
storage[2] = 0.0;
storage[3] = -s;
storage[4] = c;
storage[5] = 0.0;
storage[6] = 0.0;
storage[7] = 0.0;
storage[8] = 1.0;
}
/// Converts into Adjugate matrix and scales by [scale]
Matrix3 scaleAdjoint(double scale) {
double m00 = storage[0];
double m01 = storage[3];
double m02 = storage[6];
double m10 = storage[1];
double m11 = storage[4];
double m12 = storage[7];
double m20 = storage[2];
double m21 = storage[5];
double m22 = storage[8];
storage[0] = (m11 * m22 - m12 * m21) * scale;
storage[1] = (m12 * m20 - m10 * m22) * scale;
storage[2] = (m10 * m21 - m11 * m20) * scale;
storage[3] = (m02 * m21 - m01 * m22) * scale;
storage[4] = (m00 * m22 - m02 * m20) * scale;
storage[5] = (m01 * m20 - m00 * m21) * scale;
storage[6] = (m01 * m12 - m02 * m11) * scale;
storage[7] = (m02 * m10 - m00 * m12) * scale;
storage[8] = (m00 * m11 - m01 * m10) * scale;
return this;
}
/// Rotates [arg] by the absolute rotation of [this]
/// Returns [arg].
/// Primarily used by AABB transformation code.
Vector3 absoluteRotate(Vector3 arg) {
double m00 = storage[0].abs();
double m01 = storage[3].abs();
double m02 = storage[6].abs();
double m10 = storage[1].abs();
double m11 = storage[4].abs();
double m12 = storage[7].abs();
double m20 = storage[2].abs();
double m21 = storage[5].abs();
double m22 = storage[8].abs();
double x = arg.x;
double y = arg.y;
double z = arg.z;
arg.x = x * m00 + y * m01 + z * m02;
arg.y = x * m10 + y * m11 + z * m12;
arg.z = x * m20 + y * m21 + z * m22;
return arg;
}
/// Rotates [arg] by the absolute rotation of [this]
/// Returns [arg].
/// Primarily used by AABB transformation code.
Vector2 absoluteRotate2(Vector2 arg) {
double m00 = storage[0].abs();
double m01 = storage[3].abs();
double m10 = storage[1].abs();
double m11 = storage[4].abs();
double x = arg.x;
double y = arg.y;
arg.x = x * m00 + y * m01;
arg.y = x * m10 + y * m11;
return arg;
}
/// Transforms [arg] with [this].
Vector2 transform2(Vector2 arg) {
double x_ = (storage[0] * arg.storage[0]) + (storage[3] * arg.storage[1]) + storage[6];
double y_ = (storage[1] * arg.storage[0]) + (storage[4] * arg.storage[1]) + storage[7];
arg.x = x_;
arg.y = y_;
return arg;
}
Matrix3 add(Matrix3 o) {
storage[0] = storage[0] + o.storage[0];
storage[1] = storage[1] + o.storage[1];
storage[2] = storage[2] + o.storage[2];
storage[3] = storage[3] + o.storage[3];
storage[4] = storage[4] + o.storage[4];
storage[5] = storage[5] + o.storage[5];
storage[6] = storage[6] + o.storage[6];
storage[7] = storage[7] + o.storage[7];
storage[8] = storage[8] + o.storage[8];
return this;
}
Matrix3 sub(Matrix3 o) {
storage[0] = storage[0] - o.storage[0];
storage[1] = storage[1] - o.storage[1];
storage[2] = storage[2] - o.storage[2];
storage[3] = storage[3] - o.storage[3];
storage[4] = storage[4] - o.storage[4];
storage[5] = storage[5] - o.storage[5];
storage[6] = storage[6] - o.storage[6];
storage[7] = storage[7] - o.storage[7];
storage[8] = storage[8] - o.storage[8];
return this;
}
Matrix3 negate() {
storage[0] = -storage[0];
storage[1] = -storage[1];
storage[2] = -storage[2];
storage[3] = -storage[3];
storage[4] = -storage[4];
storage[5] = -storage[5];
storage[6] = -storage[6];
storage[7] = -storage[7];
storage[8] = -storage[8];
return this;
}
Matrix3 multiply(Matrix3 arg) {
final double m00 = storage[0];
final double m01 = storage[3];
final double m02 = storage[6];
final double m10 = storage[1];
final double m11 = storage[4];
final double m12 = storage[7];
final double m20 = storage[2];
final double m21 = storage[5];
final double m22 = storage[8];
final double n00 = arg.storage[0];
final double n01 = arg.storage[3];
final double n02 = arg.storage[6];
final double n10 = arg.storage[1];
final double n11 = arg.storage[4];
final double n12 = arg.storage[7];
final double n20 = arg.storage[2];
final double n21 = arg.storage[5];
final double n22 = arg.storage[8];
storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20);
storage[3] = (m00 * n01) + (m01 * n11) + (m02 * n21);
storage[6] = (m00 * n02) + (m01 * n12) + (m02 * n22);
storage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20);
storage[4] = (m10 * n01) + (m11 * n11) + (m12 * n21);
storage[7] = (m10 * n02) + (m11 * n12) + (m12 * n22);
storage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20);
storage[5] = (m20 * n01) + (m21 * n11) + (m22 * n21);
storage[8] = (m20 * n02) + (m21 * n12) + (m22 * n22);
return this;
}
Matrix3 transposeMultiply(Matrix3 arg) {
double m00 = storage[0];
double m01 = storage[1];
double m02 = storage[2];
double m10 = storage[3];
double m11 = storage[4];
double m12 = storage[5];
double m20 = storage[6];
double m21 = storage[7];
double m22 = storage[8];
storage[0] = (m00 * arg.storage[0]) + (m01 * arg.storage[1]) +
(m02 * arg.storage[2]);
storage[3] = (m00 * arg.storage[3]) + (m01 * arg.storage[4]) +
(m02 * arg.storage[5]);
storage[6] = (m00 * arg.storage[6]) + (m01 * arg.storage[7]) +
(m02 * arg.storage[8]);
storage[1] = (m10 * arg.storage[0]) + (m11 * arg.storage[1]) +
(m12 * arg.storage[2]);
storage[4] = (m10 * arg.storage[3]) + (m11 * arg.storage[4]) +
(m12 * arg.storage[5]);
storage[7] = (m10 * arg.storage[6]) + (m11 * arg.storage[7]) +
(m12 * arg.storage[8]);
storage[2] = (m20 * arg.storage[0]) + (m21 * arg.storage[1]) +
(m22 * arg.storage[2]);
storage[5] = (m20 * arg.storage[3]) + (m21 * arg.storage[4]) +
(m22 * arg.storage[5]);
storage[8] = (m20 * arg.storage[6]) + (m21 * arg.storage[7]) +
(m22 * arg.storage[8]);
return this;
}
Matrix3 multiplyTranspose(Matrix3 arg) {
double m00 = storage[0];
double m01 = storage[3];
double m02 = storage[6];
double m10 = storage[1];
double m11 = storage[4];
double m12 = storage[7];
double m20 = storage[2];
double m21 = storage[5];
double m22 = storage[8];
storage[0] = (m00 * arg.storage[0]) + (m01 * arg.storage[3]) +
(m02 * arg.storage[6]);
storage[3] = (m00 * arg.storage[1]) + (m01 * arg.storage[4]) +
(m02 * arg.storage[7]);
storage[6] = (m00 * arg.storage[2]) + (m01 * arg.storage[5]) +
(m02 * arg.storage[8]);
storage[1] = (m10 * arg.storage[0]) + (m11 * arg.storage[3]) +
(m12 * arg.storage[6]);
storage[4] = (m10 * arg.storage[1]) + (m11 * arg.storage[4]) +
(m12 * arg.storage[7]);
storage[7] = (m10 * arg.storage[2]) + (m11 * arg.storage[5]) +
(m12 * arg.storage[8]);
storage[2] = (m20 * arg.storage[0]) + (m21 * arg.storage[3]) +
(m22 * arg.storage[6]);
storage[5] = (m20 * arg.storage[1]) + (m21 * arg.storage[4]) +
(m22 * arg.storage[7]);
storage[8] = (m20 * arg.storage[2]) + (m21 * arg.storage[5]) +
(m22 * arg.storage[8]);
return this;
}
Vector3 transform(Vector3 arg) {
double x_ = (storage[0] * arg.storage[0]) +
(storage[3] * arg.storage[1]) +
(storage[6] * arg.storage[2]);
double y_ = (storage[1] * arg.storage[0]) +
(storage[4] * arg.storage[1]) +
(storage[7] * arg.storage[2]);
double z_ = (storage[2] * arg.storage[0]) +
(storage[5] * arg.storage[1]) +
(storage[8] * arg.storage[2]);
arg.x = x_;
arg.y = y_;
arg.z = z_;
return arg;
}
Vector3 transformed(Vector3 arg, [Vector3 out = null]) {
if (out == null) {
out = new Vector3.copy(arg);
} else {
out.setFrom(arg);
}
return transform(out);
}
/// Copies [this] into [array] starting at [offset].
void copyIntoArray(List<num> array, [int offset = 0]) {
int i = offset;
array[i + 8] = storage[8];
array[i + 7] = storage[7];
array[i + 6] = storage[6];
array[i + 5] = storage[5];
array[i + 4] = storage[4];
array[i + 3] = storage[3];
array[i + 2] = storage[2];
array[i + 1] = storage[1];
array[i + 0] = storage[0];
}
/// Copies elements from [array] into [this] starting at [offset].
void copyFromArray(List<double> array, [int offset = 0]) {
int i = offset;
storage[8] = array[i + 8];
storage[7] = array[i + 7];
storage[6] = array[i + 6];
storage[5] = array[i + 5];
storage[4] = array[i + 4];
storage[3] = array[i + 3];
storage[2] = array[i + 2];
storage[1] = array[i + 1];
storage[0] = array[i + 0];
}
Vector3 get right {
double x = storage[0];
double y = storage[1];
double z = storage[2];
return new Vector3(x, y, z);
}
Vector3 get up {
double x = storage[3];
double y = storage[4];
double z = storage[5];
return new Vector3(x, y, z);
}
Vector3 get forward {
double x = storage[6];
double y = storage[7];
double z = storage[8];
return new Vector3(x, y, z);
}
}