blob: 89892d33cc08db9ed94e2ca5f01ff361523b34a7 [file] [log] [blame]
// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
part of '../../vector_math_64.dart';
/// 3D Matrix.
/// Values are stored in column major order.
class Matrix3 {
final Float64List _m3storage;
/// The components of the matrix.
Float64List get storage => _m3storage;
/// Solve [A] * [x] = [b].
static void solve2(Matrix3 A, Vector2 x, Vector2 b) {
final a11 = A.entry(0, 0);
final a12 = A.entry(0, 1);
final a21 = A.entry(1, 0);
final a22 = A.entry(1, 1);
final bx = b.x - A.storage[6];
final by = b.y - A.storage[7];
var det = a11 * a22 - a12 * a21;
if (det != 0.0) {
det = 1.0 / det;
}
x
..x = det * (a22 * bx - a12 * by)
..y = det * (a11 * by - a21 * bx);
}
/// Solve [A] * [x] = [b].
static void solve(Matrix3 A, Vector3 x, Vector3 b) {
final A0x = A.entry(0, 0);
final A0y = A.entry(1, 0);
final A0z = A.entry(2, 0);
final A1x = A.entry(0, 1);
final A1y = A.entry(1, 1);
final A1z = A.entry(2, 1);
final A2x = A.entry(0, 2);
final A2y = A.entry(1, 2);
final 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 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 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 z_ = det * (A0x * rx + A0y * ry + A0z * rz);
x
..x = x_
..y = y_
..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) {
assert((row >= 0) && (row < dimension));
assert((col >= 0) && (col < dimension));
return _m3storage[index(row, col)];
}
/// Set value at [row], [col] to be [v].
void setEntry(int row, int col, double v) {
assert((row >= 0) && (row < dimension));
assert((col >= 0) && (col < dimension));
_m3storage[index(row, col)] = v;
}
/// New matrix with specified values.
factory Matrix3(double arg0, double arg1, double arg2, double arg3,
double arg4, double arg5, double arg6, double arg7, double arg8) =>
Matrix3.zero()
..setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
/// New matrix from [values].
factory Matrix3.fromList(List<double> values) => Matrix3.zero()
..setValues(values[0], values[1], values[2], values[3], values[4],
values[5], values[6], values[7], values[8]);
/// Constructs a new [Matrix3] filled with zeros.
Matrix3.zero() : _m3storage = Float64List(9);
/// Identity matrix.
factory Matrix3.identity() => Matrix3.zero()..setIdentity();
/// Copes values from [other].
factory Matrix3.copy(Matrix3 other) => Matrix3.zero()..setFrom(other);
/// Constructs a new mat3 from columns.
factory Matrix3.columns(Vector3 arg0, Vector3 arg1, Vector3 arg2) =>
Matrix3.zero()..setColumns(arg0, arg1, arg2);
/// Outer product of [u] and [v].
factory Matrix3.outer(Vector3 u, Vector3 v) => Matrix3.zero()..setOuter(u, v);
/// Rotation of [radians] around X axis.
factory Matrix3.rotationX(double radians) =>
Matrix3.zero()..setRotationX(radians);
/// Rotation of [radians] around Y axis.
factory Matrix3.rotationY(double radians) =>
Matrix3.zero()..setRotationY(radians);
/// Rotation of [radians] around Z axis.
factory Matrix3.rotationZ(double radians) =>
Matrix3.zero()..setRotationZ(radians);
/// Sets the matrix with specified values.
void setValues(double arg0, double arg1, double arg2, double arg3,
double arg4, double arg5, double arg6, double arg7, double arg8) {
_m3storage[8] = arg8;
_m3storage[7] = arg7;
_m3storage[6] = arg6;
_m3storage[5] = arg5;
_m3storage[4] = arg4;
_m3storage[3] = arg3;
_m3storage[2] = arg2;
_m3storage[1] = arg1;
_m3storage[0] = arg0;
}
/// Sets the entire matrix to the column values.
void setColumns(Vector3 arg0, Vector3 arg1, Vector3 arg2) {
final arg0Storage = arg0._v3storage;
final arg1Storage = arg1._v3storage;
final arg2Storage = arg2._v3storage;
_m3storage[0] = arg0Storage[0];
_m3storage[1] = arg0Storage[1];
_m3storage[2] = arg0Storage[2];
_m3storage[3] = arg1Storage[0];
_m3storage[4] = arg1Storage[1];
_m3storage[5] = arg1Storage[2];
_m3storage[6] = arg2Storage[0];
_m3storage[7] = arg2Storage[1];
_m3storage[8] = arg2Storage[2];
}
/// Sets the entire matrix to the matrix in [arg].
void setFrom(Matrix3 arg) {
final argStorage = arg._m3storage;
_m3storage[8] = argStorage[8];
_m3storage[7] = argStorage[7];
_m3storage[6] = argStorage[6];
_m3storage[5] = argStorage[5];
_m3storage[4] = argStorage[4];
_m3storage[3] = argStorage[3];
_m3storage[2] = argStorage[2];
_m3storage[1] = argStorage[1];
_m3storage[0] = argStorage[0];
}
/// Set this to the outer product of [u] and [v].
void setOuter(Vector3 u, Vector3 v) {
final uStorage = u._v3storage;
final vStorage = v._v3storage;
_m3storage[0] = uStorage[0] * vStorage[0];
_m3storage[1] = uStorage[0] * vStorage[1];
_m3storage[2] = uStorage[0] * vStorage[2];
_m3storage[3] = uStorage[1] * vStorage[0];
_m3storage[4] = uStorage[1] * vStorage[1];
_m3storage[5] = uStorage[1] * vStorage[2];
_m3storage[6] = uStorage[2] * vStorage[0];
_m3storage[7] = uStorage[2] * vStorage[1];
_m3storage[8] = uStorage[2] * vStorage[2];
}
/// Set the diagonal of the matrix.
void splatDiagonal(double arg) {
_m3storage[0] = arg;
_m3storage[4] = arg;
_m3storage[8] = arg;
}
/// Set the diagonal of the matrix.
void setDiagonal(Vector3 arg) {
_m3storage[0] = arg.storage[0];
_m3storage[4] = arg.storage[1];
_m3storage[8] = arg.storage[2];
}
/// Sets the upper 2x2 of the matrix to be [arg].
void setUpper2x2(Matrix2 arg) {
final argStorage = arg._m2storage;
_m3storage[0] = argStorage[0];
_m3storage[1] = argStorage[1];
_m3storage[3] = argStorage[2];
_m3storage[4] = argStorage[3];
}
/// Returns a printable string
@override
String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n[2] ${getRow(2)}\n';
/// Dimension of the matrix.
int get dimension => 3;
/// Access the element of the matrix at the index [i].
double operator [](int i) => _m3storage[i];
/// Set the element of the matrix at the index [i].
void operator []=(int i, double v) {
_m3storage[i] = v;
}
/// Check if two matrices are the same.
@override
bool operator ==(Object other) =>
(other is Matrix3) &&
(_m3storage[0] == other._m3storage[0]) &&
(_m3storage[1] == other._m3storage[1]) &&
(_m3storage[2] == other._m3storage[2]) &&
(_m3storage[3] == other._m3storage[3]) &&
(_m3storage[4] == other._m3storage[4]) &&
(_m3storage[5] == other._m3storage[5]) &&
(_m3storage[6] == other._m3storage[6]) &&
(_m3storage[7] == other._m3storage[7]) &&
(_m3storage[8] == other._m3storage[8]);
@override
int get hashCode => Object.hashAll(_m3storage);
/// 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) {
final argStorage = arg._v3storage;
_m3storage[index(row, 0)] = argStorage[0];
_m3storage[index(row, 1)] = argStorage[1];
_m3storage[index(row, 2)] = argStorage[2];
}
/// Gets the [row] of the matrix
Vector3 getRow(int row) {
final r = Vector3.zero();
final rStorage = r._v3storage;
rStorage[0] = _m3storage[index(row, 0)];
rStorage[1] = _m3storage[index(row, 1)];
rStorage[2] = _m3storage[index(row, 2)];
return r;
}
/// Assigns the [column] of the matrix [arg]
void setColumn(int column, Vector3 arg) {
final argStorage = arg._v3storage;
final entry = column * 3;
_m3storage[entry + 2] = argStorage[2];
_m3storage[entry + 1] = argStorage[1];
_m3storage[entry + 0] = argStorage[0];
}
/// Gets the [column] of the matrix
Vector3 getColumn(int column) {
final r = Vector3.zero();
final rStorage = r._v3storage;
final entry = column * 3;
rStorage[2] = _m3storage[entry + 2];
rStorage[1] = _m3storage[entry + 1];
rStorage[0] = _m3storage[entry + 0];
return r;
}
/// Clone of this.
Matrix3 clone() => Matrix3.copy(this);
/// Copy this into [arg].
Matrix3 copyInto(Matrix3 arg) {
final argStorage = arg._m3storage;
argStorage[0] = _m3storage[0];
argStorage[1] = _m3storage[1];
argStorage[2] = _m3storage[2];
argStorage[3] = _m3storage[3];
argStorage[4] = _m3storage[4];
argStorage[5] = _m3storage[5];
argStorage[6] = _m3storage[6];
argStorage[7] = _m3storage[7];
argStorage[8] = _m3storage[8];
return arg;
}
/// Returns a new vector or matrix by multiplying this with [arg].
dynamic operator *(dynamic arg) {
if (arg is double) {
return scaled(arg);
}
if (arg is Vector3) {
return transformed(arg);
}
if (arg is Matrix3) {
return multiplied(arg);
}
throw ArgumentError(arg);
}
/// Returns new matrix after component wise this + [arg]
Matrix3 operator +(Matrix3 arg) => clone()..add(arg);
/// Returns new matrix after component wise this - [arg]
Matrix3 operator -(Matrix3 arg) => clone()..sub(arg);
/// Returns new matrix -this
Matrix3 operator -() => clone()..negate();
/// Zeros this.
void setZero() {
_m3storage[0] = 0.0;
_m3storage[1] = 0.0;
_m3storage[2] = 0.0;
_m3storage[3] = 0.0;
_m3storage[4] = 0.0;
_m3storage[5] = 0.0;
_m3storage[6] = 0.0;
_m3storage[7] = 0.0;
_m3storage[8] = 0.0;
}
/// Makes this into the identity matrix.
void setIdentity() {
_m3storage[0] = 1.0;
_m3storage[1] = 0.0;
_m3storage[2] = 0.0;
_m3storage[3] = 0.0;
_m3storage[4] = 1.0;
_m3storage[5] = 0.0;
_m3storage[6] = 0.0;
_m3storage[7] = 0.0;
_m3storage[8] = 1.0;
}
/// Returns the tranpose of this.
Matrix3 transposed() => clone()..transpose();
/// Transpose this.
void transpose() {
double temp;
temp = _m3storage[3];
_m3storage[3] = _m3storage[1];
_m3storage[1] = temp;
temp = _m3storage[6];
_m3storage[6] = _m3storage[2];
_m3storage[2] = temp;
temp = _m3storage[7];
_m3storage[7] = _m3storage[5];
_m3storage[5] = temp;
}
/// Returns the component wise absolute value of this.
Matrix3 absolute() {
final r = Matrix3.zero();
final rStorage = r._m3storage;
rStorage[0] = _m3storage[0].abs();
rStorage[1] = _m3storage[1].abs();
rStorage[2] = _m3storage[2].abs();
rStorage[3] = _m3storage[3].abs();
rStorage[4] = _m3storage[4].abs();
rStorage[5] = _m3storage[5].abs();
rStorage[6] = _m3storage[6].abs();
rStorage[7] = _m3storage[7].abs();
rStorage[8] = _m3storage[8].abs();
return r;
}
/// Returns the determinant of this matrix.
double determinant() {
final x = _m3storage[0] *
((_m3storage[4] * _m3storage[8]) - (_m3storage[5] * _m3storage[7]));
final y = _m3storage[1] *
((_m3storage[3] * _m3storage[8]) - (_m3storage[5] * _m3storage[6]));
final z = _m3storage[2] *
((_m3storage[3] * _m3storage[7]) - (_m3storage[4] * _m3storage[6]));
return x - y + z;
}
/// Returns the dot product of row [i] and [v].
double dotRow(int i, Vector3 v) {
final vStorage = v._v3storage;
return _m3storage[i] * vStorage[0] +
_m3storage[3 + i] * vStorage[1] +
_m3storage[6 + i] * vStorage[2];
}
/// Returns the dot product of column [j] and [v].
double dotColumn(int j, Vector3 v) {
final vStorage = v._v3storage;
return _m3storage[j * 3] * vStorage[0] +
_m3storage[j * 3 + 1] * vStorage[1] +
_m3storage[j * 3 + 2] * vStorage[2];
}
/// Returns the trace of the matrix. The trace of a matrix is the sum of
/// the diagonal entries.
double trace() {
var t = 0.0;
t += _m3storage[0];
t += _m3storage[4];
t += _m3storage[8];
return t;
}
/// Returns infinity norm of the matrix. Used for numerical analysis.
double infinityNorm() {
var norm = 0.0;
{
var row_norm = 0.0;
row_norm += _m3storage[0].abs();
row_norm += _m3storage[1].abs();
row_norm += _m3storage[2].abs();
norm = row_norm > norm ? row_norm : norm;
}
{
var row_norm = 0.0;
row_norm += _m3storage[3].abs();
row_norm += _m3storage[4].abs();
row_norm += _m3storage[5].abs();
norm = row_norm > norm ? row_norm : norm;
}
{
var row_norm = 0.0;
row_norm += _m3storage[6].abs();
row_norm += _m3storage[7].abs();
row_norm += _m3storage[8].abs();
norm = row_norm > norm ? row_norm : norm;
}
return norm;
}
/// Returns relative error between this and [correct]
double relativeError(Matrix3 correct) {
final diff = correct - this;
final correct_norm = correct.infinityNorm();
final diff_norm = diff.infinityNorm();
return diff_norm / correct_norm;
}
/// Returns absolute error between this and [correct]
double absoluteError(Matrix3 correct) {
final this_norm = infinityNorm();
final correct_norm = correct.infinityNorm();
final diff_norm = (this_norm - correct_norm).abs();
return diff_norm;
}
/// Invert the matrix. Returns the determinant.
double invert() => copyInverse(this);
/// Set this matrix to be the inverse of [arg]
double copyInverse(Matrix3 arg) {
final det = arg.determinant();
if (det == 0.0) {
setFrom(arg);
return 0.0;
}
final invDet = 1.0 / det;
final argStorage = arg._m3storage;
final ix = invDet *
(argStorage[4] * argStorage[8] - argStorage[5] * argStorage[7]);
final iy = invDet *
(argStorage[2] * argStorage[7] - argStorage[1] * argStorage[8]);
final iz = invDet *
(argStorage[1] * argStorage[5] - argStorage[2] * argStorage[4]);
final jx = invDet *
(argStorage[5] * argStorage[6] - argStorage[3] * argStorage[8]);
final jy = invDet *
(argStorage[0] * argStorage[8] - argStorage[2] * argStorage[6]);
final jz = invDet *
(argStorage[2] * argStorage[3] - argStorage[0] * argStorage[5]);
final kx = invDet *
(argStorage[3] * argStorage[7] - argStorage[4] * argStorage[6]);
final ky = invDet *
(argStorage[1] * argStorage[6] - argStorage[0] * argStorage[7]);
final kz = invDet *
(argStorage[0] * argStorage[4] - argStorage[1] * argStorage[3]);
_m3storage[0] = ix;
_m3storage[1] = iy;
_m3storage[2] = iz;
_m3storage[3] = jx;
_m3storage[4] = jy;
_m3storage[5] = jz;
_m3storage[6] = kx;
_m3storage[7] = ky;
_m3storage[8] = kz;
return det;
}
/// Set this matrix to be the normal matrix of [arg].
void copyNormalMatrix(Matrix4 arg) {
copyInverse(arg.getRotation());
transpose();
}
/// Turns the matrix into a rotation of [radians] around X
void setRotationX(double radians) {
final c = math.cos(radians);
final s = math.sin(radians);
_m3storage[0] = 1.0;
_m3storage[1] = 0.0;
_m3storage[2] = 0.0;
_m3storage[3] = 0.0;
_m3storage[4] = c;
_m3storage[5] = s;
_m3storage[6] = 0.0;
_m3storage[7] = -s;
_m3storage[8] = c;
}
/// Turns the matrix into a rotation of [radians] around Y
void setRotationY(double radians) {
final c = math.cos(radians);
final s = math.sin(radians);
_m3storage[0] = c;
_m3storage[1] = 0.0;
_m3storage[2] = -s;
_m3storage[3] = 0.0;
_m3storage[4] = 1.0;
_m3storage[5] = 0.0;
_m3storage[6] = s;
_m3storage[7] = 0.0;
_m3storage[8] = c;
}
/// Turns the matrix into a rotation of [radians] around Z
void setRotationZ(double radians) {
final c = math.cos(radians);
final s = math.sin(radians);
_m3storage[0] = c;
_m3storage[1] = s;
_m3storage[2] = 0.0;
_m3storage[3] = -s;
_m3storage[4] = c;
_m3storage[5] = 0.0;
_m3storage[6] = 0.0;
_m3storage[7] = 0.0;
_m3storage[8] = 1.0;
}
/// Converts into Adjugate matrix and scales by [scale]
void scaleAdjoint(double scale) {
final m00 = _m3storage[0];
final m01 = _m3storage[3];
final m02 = _m3storage[6];
final m10 = _m3storage[1];
final m11 = _m3storage[4];
final m12 = _m3storage[7];
final m20 = _m3storage[2];
final m21 = _m3storage[5];
final m22 = _m3storage[8];
_m3storage[0] = (m11 * m22 - m12 * m21) * scale;
_m3storage[1] = (m12 * m20 - m10 * m22) * scale;
_m3storage[2] = (m10 * m21 - m11 * m20) * scale;
_m3storage[3] = (m02 * m21 - m01 * m22) * scale;
_m3storage[4] = (m00 * m22 - m02 * m20) * scale;
_m3storage[5] = (m01 * m20 - m00 * m21) * scale;
_m3storage[6] = (m01 * m12 - m02 * m11) * scale;
_m3storage[7] = (m02 * m10 - m00 * m12) * scale;
_m3storage[8] = (m00 * m11 - m01 * m10) * scale;
}
/// Rotates [arg] by the absolute rotation of this
/// Returns [arg].
/// Primarily used by AABB transformation code.
Vector3 absoluteRotate(Vector3 arg) {
final m00 = _m3storage[0].abs();
final m01 = _m3storage[3].abs();
final m02 = _m3storage[6].abs();
final m10 = _m3storage[1].abs();
final m11 = _m3storage[4].abs();
final m12 = _m3storage[7].abs();
final m20 = _m3storage[2].abs();
final m21 = _m3storage[5].abs();
final m22 = _m3storage[8].abs();
final argStorage = arg._v3storage;
final x = argStorage[0];
final y = argStorage[1];
final z = argStorage[2];
argStorage[0] = x * m00 + y * m01 + z * m02;
argStorage[1] = x * m10 + y * m11 + z * m12;
argStorage[2] = 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) {
final m00 = _m3storage[0].abs();
final m01 = _m3storage[3].abs();
final m10 = _m3storage[1].abs();
final m11 = _m3storage[4].abs();
final argStorage = arg._v2storage;
final x = argStorage[0];
final y = argStorage[1];
argStorage[0] = x * m00 + y * m01;
argStorage[1] = x * m10 + y * m11;
return arg;
}
/// Transforms [arg] with this.
Vector2 transform2(Vector2 arg) {
final argStorage = arg._v2storage;
final x_ = (_m3storage[0] * argStorage[0]) +
(_m3storage[3] * argStorage[1]) +
_m3storage[6];
final y_ = (_m3storage[1] * argStorage[0]) +
(_m3storage[4] * argStorage[1]) +
_m3storage[7];
argStorage[0] = x_;
argStorage[1] = y_;
return arg;
}
/// Scales this by [scale].
void scale(double scale) {
_m3storage[0] = _m3storage[0] * scale;
_m3storage[1] = _m3storage[1] * scale;
_m3storage[2] = _m3storage[2] * scale;
_m3storage[3] = _m3storage[3] * scale;
_m3storage[4] = _m3storage[4] * scale;
_m3storage[5] = _m3storage[5] * scale;
_m3storage[6] = _m3storage[6] * scale;
_m3storage[7] = _m3storage[7] * scale;
_m3storage[8] = _m3storage[8] * scale;
}
/// Create a copy of this and scale it by [scale].
Matrix3 scaled(double scale) => clone()..scale(scale);
/// Add [o] to this.
void add(Matrix3 o) {
final oStorage = o._m3storage;
_m3storage[0] = _m3storage[0] + oStorage[0];
_m3storage[1] = _m3storage[1] + oStorage[1];
_m3storage[2] = _m3storage[2] + oStorage[2];
_m3storage[3] = _m3storage[3] + oStorage[3];
_m3storage[4] = _m3storage[4] + oStorage[4];
_m3storage[5] = _m3storage[5] + oStorage[5];
_m3storage[6] = _m3storage[6] + oStorage[6];
_m3storage[7] = _m3storage[7] + oStorage[7];
_m3storage[8] = _m3storage[8] + oStorage[8];
}
/// Subtract [o] from this.
void sub(Matrix3 o) {
final oStorage = o._m3storage;
_m3storage[0] = _m3storage[0] - oStorage[0];
_m3storage[1] = _m3storage[1] - oStorage[1];
_m3storage[2] = _m3storage[2] - oStorage[2];
_m3storage[3] = _m3storage[3] - oStorage[3];
_m3storage[4] = _m3storage[4] - oStorage[4];
_m3storage[5] = _m3storage[5] - oStorage[5];
_m3storage[6] = _m3storage[6] - oStorage[6];
_m3storage[7] = _m3storage[7] - oStorage[7];
_m3storage[8] = _m3storage[8] - oStorage[8];
}
/// Negate this.
void negate() {
_m3storage[0] = -_m3storage[0];
_m3storage[1] = -_m3storage[1];
_m3storage[2] = -_m3storage[2];
_m3storage[3] = -_m3storage[3];
_m3storage[4] = -_m3storage[4];
_m3storage[5] = -_m3storage[5];
_m3storage[6] = -_m3storage[6];
_m3storage[7] = -_m3storage[7];
_m3storage[8] = -_m3storage[8];
}
/// Multiply this by [arg].
void multiply(Matrix3 arg) {
final m00 = _m3storage[0];
final m01 = _m3storage[3];
final m02 = _m3storage[6];
final m10 = _m3storage[1];
final m11 = _m3storage[4];
final m12 = _m3storage[7];
final m20 = _m3storage[2];
final m21 = _m3storage[5];
final m22 = _m3storage[8];
final argStorage = arg._m3storage;
final n00 = argStorage[0];
final n01 = argStorage[3];
final n02 = argStorage[6];
final n10 = argStorage[1];
final n11 = argStorage[4];
final n12 = argStorage[7];
final n20 = argStorage[2];
final n21 = argStorage[5];
final n22 = argStorage[8];
_m3storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20);
_m3storage[3] = (m00 * n01) + (m01 * n11) + (m02 * n21);
_m3storage[6] = (m00 * n02) + (m01 * n12) + (m02 * n22);
_m3storage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20);
_m3storage[4] = (m10 * n01) + (m11 * n11) + (m12 * n21);
_m3storage[7] = (m10 * n02) + (m11 * n12) + (m12 * n22);
_m3storage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20);
_m3storage[5] = (m20 * n01) + (m21 * n11) + (m22 * n21);
_m3storage[8] = (m20 * n02) + (m21 * n12) + (m22 * n22);
}
/// Create a copy of this and multiply it by [arg].
Matrix3 multiplied(Matrix3 arg) => clone()..multiply(arg);
void transposeMultiply(Matrix3 arg) {
final m00 = _m3storage[0];
final m01 = _m3storage[1];
final m02 = _m3storage[2];
final m10 = _m3storage[3];
final m11 = _m3storage[4];
final m12 = _m3storage[5];
final m20 = _m3storage[6];
final m21 = _m3storage[7];
final m22 = _m3storage[8];
final argStorage = arg._m3storage;
_m3storage[0] =
(m00 * argStorage[0]) + (m01 * argStorage[1]) + (m02 * argStorage[2]);
_m3storage[3] =
(m00 * argStorage[3]) + (m01 * argStorage[4]) + (m02 * argStorage[5]);
_m3storage[6] =
(m00 * argStorage[6]) + (m01 * argStorage[7]) + (m02 * argStorage[8]);
_m3storage[1] =
(m10 * argStorage[0]) + (m11 * argStorage[1]) + (m12 * argStorage[2]);
_m3storage[4] =
(m10 * argStorage[3]) + (m11 * argStorage[4]) + (m12 * argStorage[5]);
_m3storage[7] =
(m10 * argStorage[6]) + (m11 * argStorage[7]) + (m12 * argStorage[8]);
_m3storage[2] =
(m20 * argStorage[0]) + (m21 * argStorage[1]) + (m22 * argStorage[2]);
_m3storage[5] =
(m20 * argStorage[3]) + (m21 * argStorage[4]) + (m22 * argStorage[5]);
_m3storage[8] =
(m20 * argStorage[6]) + (m21 * argStorage[7]) + (m22 * argStorage[8]);
}
void multiplyTranspose(Matrix3 arg) {
final m00 = _m3storage[0];
final m01 = _m3storage[3];
final m02 = _m3storage[6];
final m10 = _m3storage[1];
final m11 = _m3storage[4];
final m12 = _m3storage[7];
final m20 = _m3storage[2];
final m21 = _m3storage[5];
final m22 = _m3storage[8];
final argStorage = arg._m3storage;
_m3storage[0] =
(m00 * argStorage[0]) + (m01 * argStorage[3]) + (m02 * argStorage[6]);
_m3storage[3] =
(m00 * argStorage[1]) + (m01 * argStorage[4]) + (m02 * argStorage[7]);
_m3storage[6] =
(m00 * argStorage[2]) + (m01 * argStorage[5]) + (m02 * argStorage[8]);
_m3storage[1] =
(m10 * argStorage[0]) + (m11 * argStorage[3]) + (m12 * argStorage[6]);
_m3storage[4] =
(m10 * argStorage[1]) + (m11 * argStorage[4]) + (m12 * argStorage[7]);
_m3storage[7] =
(m10 * argStorage[2]) + (m11 * argStorage[5]) + (m12 * argStorage[8]);
_m3storage[2] =
(m20 * argStorage[0]) + (m21 * argStorage[3]) + (m22 * argStorage[6]);
_m3storage[5] =
(m20 * argStorage[1]) + (m21 * argStorage[4]) + (m22 * argStorage[7]);
_m3storage[8] =
(m20 * argStorage[2]) + (m21 * argStorage[5]) + (m22 * argStorage[8]);
}
/// Transform [arg] of type [Vector3] using the transformation defined by
/// this.
Vector3 transform(Vector3 arg) {
final argStorage = arg._v3storage;
final x_ = (_m3storage[0] * argStorage[0]) +
(_m3storage[3] * argStorage[1]) +
(_m3storage[6] * argStorage[2]);
final y_ = (_m3storage[1] * argStorage[0]) +
(_m3storage[4] * argStorage[1]) +
(_m3storage[7] * argStorage[2]);
final z_ = (_m3storage[2] * argStorage[0]) +
(_m3storage[5] * argStorage[1]) +
(_m3storage[8] * argStorage[2]);
arg
..x = x_
..y = y_
..z = z_;
return arg;
}
/// Transform a copy of [arg] of type [Vector3] using the transformation
/// defined by this. If a [out] parameter is supplied, the copy is stored in
/// [out].
Vector3 transformed(Vector3 arg, [Vector3? out]) {
if (out == null) {
out = 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]) {
final i = offset;
array[i + 8] = _m3storage[8];
array[i + 7] = _m3storage[7];
array[i + 6] = _m3storage[6];
array[i + 5] = _m3storage[5];
array[i + 4] = _m3storage[4];
array[i + 3] = _m3storage[3];
array[i + 2] = _m3storage[2];
array[i + 1] = _m3storage[1];
array[i + 0] = _m3storage[0];
}
/// Copies elements from [array] into this starting at [offset].
void copyFromArray(List<double> array, [int offset = 0]) {
final i = offset;
_m3storage[8] = array[i + 8];
_m3storage[7] = array[i + 7];
_m3storage[6] = array[i + 6];
_m3storage[5] = array[i + 5];
_m3storage[4] = array[i + 4];
_m3storage[3] = array[i + 3];
_m3storage[2] = array[i + 2];
_m3storage[1] = array[i + 1];
_m3storage[0] = array[i + 0];
}
/// Multiply this to each set of xyz values in [array] starting at [offset].
List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
final v = Vector3.array(array, j)..applyMatrix3(this);
array[j] = v.storage[0];
array[j + 1] = v.storage[1];
array[j + 2] = v.storage[2];
}
return array;
}
Vector3 get right {
final x = _m3storage[0];
final y = _m3storage[1];
final z = _m3storage[2];
return Vector3(x, y, z);
}
Vector3 get up {
final x = _m3storage[3];
final y = _m3storage[4];
final z = _m3storage[5];
return Vector3(x, y, z);
}
Vector3 get forward {
final x = _m3storage[6];
final y = _m3storage[7];
final z = _m3storage[8];
return Vector3(x, y, z);
}
/// Is this the identity matrix?
bool isIdentity() =>
_m3storage[0] == 1.0 // col 1
&&
_m3storage[1] == 0.0 &&
_m3storage[2] == 0.0 &&
_m3storage[3] == 0.0 // col 2
&&
_m3storage[4] == 1.0 &&
_m3storage[5] == 0.0 &&
_m3storage[6] == 0.0 // col 3
&&
_m3storage[7] == 0.0 &&
_m3storage[8] == 1.0;
/// Is this the zero matrix?
bool isZero() =>
_m3storage[0] == 0.0 // col 1
&&
_m3storage[1] == 0.0 &&
_m3storage[2] == 0.0 &&
_m3storage[3] == 0.0 // col 2
&&
_m3storage[4] == 0.0 &&
_m3storage[5] == 0.0 &&
_m3storage[6] == 0.0 // col 3
&&
_m3storage[7] == 0.0 &&
_m3storage[8] == 0.0;
}