NMV 0.8.0 - Big refactor and linting fixes
This commit is contained in:
463
lib/classes/Matrix3.ts
Normal file
463
lib/classes/Matrix3.ts
Normal file
@@ -0,0 +1,463 @@
|
||||
import { Vector2 } from './Vector2';
|
||||
import { Vector3 } from './Vector3';
|
||||
import { Matrix4 } from './Matrix4';
|
||||
import { Quaternion } from './Quaternion';
|
||||
|
||||
export class Matrix3
|
||||
{
|
||||
public static readonly identity: Matrix3 = new Matrix3().setIdentity();
|
||||
|
||||
private static readonly EPSILON: number = 1e-6;
|
||||
|
||||
private values: Float32Array = new Float32Array(9);
|
||||
|
||||
public constructor(values?: number[])
|
||||
{
|
||||
if (values)
|
||||
{
|
||||
this.init(values);
|
||||
}
|
||||
}
|
||||
|
||||
public at(index: number): number
|
||||
{
|
||||
return this.values[index];
|
||||
}
|
||||
|
||||
public init(values: number[]): this
|
||||
{
|
||||
if (values.length !== 9)
|
||||
{
|
||||
throw new Error("Matrix3 requires exactly 9 values.");
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
for (const value of values)
|
||||
{
|
||||
this.values[i] = value;
|
||||
i++;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public reset(): void
|
||||
{
|
||||
let i = 0;
|
||||
for (const _ of this.values)
|
||||
{
|
||||
this.values[i] = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public copy(dest?: Matrix3): Matrix3
|
||||
{
|
||||
if (!dest)
|
||||
{
|
||||
dest = new Matrix3();
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
for (const value of this.values)
|
||||
{
|
||||
dest.values[i] = value;
|
||||
i++;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public all(): number[]
|
||||
{
|
||||
const data: number[] = [];
|
||||
for (const value of this.values)
|
||||
{
|
||||
data.push(value);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public row(index: number): number[]
|
||||
{
|
||||
return [
|
||||
this.values[index * 3],
|
||||
this.values[index * 3 + 1],
|
||||
this.values[index * 3 + 2]
|
||||
];
|
||||
}
|
||||
|
||||
public col(index: number): number[]
|
||||
{
|
||||
return [
|
||||
this.values[index],
|
||||
this.values[index + 3],
|
||||
this.values[index + 6]
|
||||
];
|
||||
}
|
||||
|
||||
public equals(matrix: Matrix3, threshold: number = Matrix3.EPSILON): boolean
|
||||
{
|
||||
let i = 0;
|
||||
for (const value of this.values)
|
||||
{
|
||||
if (Math.abs(value - matrix.at(i)) > threshold)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public determinant(): number
|
||||
{
|
||||
const a00: number = this.values[0];
|
||||
const a01: number = this.values[1];
|
||||
const a02: number = this.values[2];
|
||||
const a10: number = this.values[3];
|
||||
const a11: number = this.values[4];
|
||||
const a12: number = this.values[5];
|
||||
const a20: number = this.values[6];
|
||||
const a21: number = this.values[7];
|
||||
const a22: number = this.values[8];
|
||||
|
||||
const det01: number = a22 * a11 - a12 * a21;
|
||||
const det11: number = -a22 * a10 + a12 * a20;
|
||||
const det21: number = a21 * a10 - a11 * a20;
|
||||
|
||||
return a00 * det01 + a01 * det11 + a02 * det21;
|
||||
}
|
||||
|
||||
public setIdentity(): this
|
||||
{
|
||||
this.reset();
|
||||
|
||||
this.values[0] = 1;
|
||||
this.values[4] = 1;
|
||||
this.values[8] = 1;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public transpose(): Matrix3
|
||||
{
|
||||
const transposedValues: number[] = [
|
||||
this.values[0],
|
||||
this.values[3],
|
||||
this.values[6],
|
||||
|
||||
this.values[1],
|
||||
this.values[4],
|
||||
this.values[7],
|
||||
|
||||
this.values[2],
|
||||
this.values[5],
|
||||
this.values[8]
|
||||
];
|
||||
|
||||
return new Matrix3(transposedValues);
|
||||
}
|
||||
|
||||
public inverse(): Matrix3 | null
|
||||
{
|
||||
const a00: number = this.values[0];
|
||||
const a01: number = this.values[1];
|
||||
const a02: number = this.values[2];
|
||||
const a10: number = this.values[3];
|
||||
const a11: number = this.values[4];
|
||||
const a12: number = this.values[5];
|
||||
const a20: number = this.values[6];
|
||||
const a21: number = this.values[7];
|
||||
const a22: number = this.values[8];
|
||||
|
||||
const det01: number = a22 * a11 - a12 * a21;
|
||||
const det11: number = -a22 * a10 + a12 * a20;
|
||||
const det21: number = a21 * a10 - a11 * a20;
|
||||
|
||||
let det: number = a00 * det01 + a01 * det11 + a02 * det21;
|
||||
|
||||
if (Math.abs(det) < Matrix3.EPSILON)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
det = 1.0 / det;
|
||||
|
||||
const invValues: number[] = [
|
||||
det01 * det,
|
||||
(-a22 * a01 + a02 * a21) * det,
|
||||
(a12 * a01 - a02 * a11) * det,
|
||||
|
||||
det11 * det,
|
||||
(a22 * a00 - a02 * a20) * det,
|
||||
(-a12 * a00 + a02 * a10) * det,
|
||||
|
||||
det21 * det,
|
||||
(-a21 * a00 + a01 * a20) * det,
|
||||
(a11 * a00 - a01 * a10) * det
|
||||
];
|
||||
|
||||
return new Matrix3(invValues);
|
||||
}
|
||||
|
||||
public multiply(matrix: Matrix3): Matrix3
|
||||
{
|
||||
const a00: number = this.values[0];
|
||||
const a01: number = this.values[1];
|
||||
const a02: number = this.values[2];
|
||||
const a10: number = this.values[3];
|
||||
const a11: number = this.values[4];
|
||||
const a12: number = this.values[5];
|
||||
const a20: number = this.values[6];
|
||||
const a21: number = this.values[7];
|
||||
const a22: number = this.values[8];
|
||||
|
||||
const b00: number = matrix.at(0);
|
||||
const b01: number = matrix.at(1);
|
||||
const b02: number = matrix.at(2);
|
||||
const b10: number = matrix.at(3);
|
||||
const b11: number = matrix.at(4);
|
||||
const b12: number = matrix.at(5);
|
||||
const b20: number = matrix.at(6);
|
||||
const b21: number = matrix.at(7);
|
||||
const b22: number = matrix.at(8);
|
||||
|
||||
const resultValues: number[] = [
|
||||
b00 * a00 + b01 * a10 + b02 * a20,
|
||||
b00 * a01 + b01 * a11 + b02 * a21,
|
||||
b00 * a02 + b01 * a12 + b02 * a22,
|
||||
|
||||
b10 * a00 + b11 * a10 + b12 * a20,
|
||||
b10 * a01 + b11 * a11 + b12 * a21,
|
||||
b10 * a02 + b11 * a12 + b12 * a22,
|
||||
|
||||
b20 * a00 + b21 * a10 + b22 * a20,
|
||||
b20 * a01 + b21 * a11 + b22 * a21,
|
||||
b20 * a02 + b21 * a12 + b22 * a22
|
||||
];
|
||||
|
||||
return new Matrix3(resultValues);
|
||||
}
|
||||
|
||||
public multiplyVector2(vector: Vector2, result?: Vector2): Vector2
|
||||
{
|
||||
const x: number = vector.x;
|
||||
const y: number = vector.y;
|
||||
|
||||
if (result)
|
||||
{
|
||||
result.x = x * this.values[0] + y * this.values[3] + this.values[6];
|
||||
result.y = x * this.values[1] + y * this.values[4] + this.values[7];
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Vector2([
|
||||
x * this.values[0] + y * this.values[3] + this.values[6],
|
||||
x * this.values[1] + y * this.values[4] + this.values[7]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public multiplyVector3(vector: Vector3, result?: Vector3): Vector3
|
||||
{
|
||||
const x: number = vector.x;
|
||||
const y: number = vector.y;
|
||||
const z: number = vector.z;
|
||||
|
||||
if (result)
|
||||
{
|
||||
result.x = x * this.values[0] + y * this.values[3] + z * this.values[6];
|
||||
result.y = x * this.values[1] + y * this.values[4] + z * this.values[7];
|
||||
result.z = x * this.values[2] + y * this.values[5] + z * this.values[8];
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Vector3([
|
||||
x * this.values[0] + y * this.values[3] + z * this.values[6],
|
||||
x * this.values[1] + y * this.values[4] + z * this.values[7],
|
||||
x * this.values[2] + y * this.values[5] + z * this.values[8]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public toMatrix4(result?: Matrix4): Matrix4
|
||||
{
|
||||
const mat4Values: number[] = [
|
||||
this.values[0],
|
||||
this.values[1],
|
||||
this.values[2],
|
||||
0,
|
||||
|
||||
this.values[3],
|
||||
this.values[4],
|
||||
this.values[5],
|
||||
0,
|
||||
|
||||
this.values[6],
|
||||
this.values[7],
|
||||
this.values[8],
|
||||
0,
|
||||
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
];
|
||||
|
||||
if (result)
|
||||
{
|
||||
result.init(mat4Values);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Matrix4(mat4Values);
|
||||
}
|
||||
}
|
||||
|
||||
public toQuaternion(): Quaternion
|
||||
{
|
||||
const m00: number = this.values[0];
|
||||
const m01: number = this.values[1];
|
||||
const m02: number = this.values[2];
|
||||
const m10: number = this.values[3];
|
||||
const m11: number = this.values[4];
|
||||
const m12: number = this.values[5];
|
||||
const m20: number = this.values[6];
|
||||
const m21: number = this.values[7];
|
||||
const m22: number = this.values[8];
|
||||
|
||||
const fourXSquaredMinus1: number = m00 - m11 - m22;
|
||||
const fourYSquaredMinus1: number = m11 - m00 - m22;
|
||||
const fourZSquaredMinus1: number = m22 - m00 - m11;
|
||||
const fourWSquaredMinus1: number = m00 + m11 + m22;
|
||||
|
||||
let biggestIndex = 0;
|
||||
let fourBiggestSquaredMinus1: number = fourWSquaredMinus1;
|
||||
|
||||
if (fourXSquaredMinus1 > fourBiggestSquaredMinus1)
|
||||
{
|
||||
fourBiggestSquaredMinus1 = fourXSquaredMinus1;
|
||||
biggestIndex = 1;
|
||||
}
|
||||
|
||||
if (fourYSquaredMinus1 > fourBiggestSquaredMinus1)
|
||||
{
|
||||
fourBiggestSquaredMinus1 = fourYSquaredMinus1;
|
||||
biggestIndex = 2;
|
||||
}
|
||||
|
||||
if (fourZSquaredMinus1 > fourBiggestSquaredMinus1)
|
||||
{
|
||||
fourBiggestSquaredMinus1 = fourZSquaredMinus1;
|
||||
biggestIndex = 3;
|
||||
}
|
||||
|
||||
const biggestVal: number = Math.sqrt(fourBiggestSquaredMinus1 + 1) * 0.5;
|
||||
const mult: number = 0.25 / biggestVal;
|
||||
|
||||
const quat: Quaternion = new Quaternion();
|
||||
|
||||
switch (biggestIndex)
|
||||
{
|
||||
case 0:
|
||||
quat.w = biggestVal;
|
||||
quat.x = (m12 - m21) * mult;
|
||||
quat.y = (m20 - m02) * mult;
|
||||
quat.z = (m01 - m10) * mult;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
quat.w = (m12 - m21) * mult;
|
||||
quat.x = biggestVal;
|
||||
quat.y = (m01 + m10) * mult;
|
||||
quat.z = (m20 + m02) * mult;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
quat.w = (m20 - m02) * mult;
|
||||
quat.x = (m01 + m10) * mult;
|
||||
quat.y = biggestVal;
|
||||
quat.z = (m12 + m21) * mult;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
quat.w = (m01 - m10) * mult;
|
||||
quat.x = (m20 + m02) * mult;
|
||||
quat.y = (m12 + m21) * mult;
|
||||
quat.z = biggestVal;
|
||||
break;
|
||||
}
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
public rotate(angle: number, axis: Vector3): Matrix3 | null
|
||||
{
|
||||
let x: number = axis.x;
|
||||
let y: number = axis.y;
|
||||
let z: number = axis.z;
|
||||
|
||||
let length: number = Math.sqrt(x * x + y * y + z * z);
|
||||
|
||||
if (length < Matrix3.EPSILON)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (length !== 1)
|
||||
{
|
||||
length = 1 / length;
|
||||
x *= length;
|
||||
y *= length;
|
||||
z *= length;
|
||||
}
|
||||
|
||||
const s: number = Math.sin(angle);
|
||||
const c: number = Math.cos(angle);
|
||||
const t: number = 1.0 - c;
|
||||
|
||||
const b00: number = x * x * t + c;
|
||||
const b01: number = y * x * t + z * s;
|
||||
const b02: number = z * x * t - y * s;
|
||||
|
||||
const b10: number = x * y * t - z * s;
|
||||
const b11: number = y * y * t + c;
|
||||
const b12: number = z * y * t + x * s;
|
||||
|
||||
const b20: number = x * z * t + y * s;
|
||||
const b21: number = y * z * t - x * s;
|
||||
const b22: number = z * z * t + c;
|
||||
|
||||
const a00: number = this.values[0];
|
||||
const a01: number = this.values[1];
|
||||
const a02: number = this.values[2];
|
||||
const a10: number = this.values[3];
|
||||
const a11: number = this.values[4];
|
||||
const a12: number = this.values[5];
|
||||
const a20: number = this.values[6];
|
||||
const a21: number = this.values[7];
|
||||
const a22: number = this.values[8];
|
||||
|
||||
const resultValues: number[] = [
|
||||
a00 * b00 + a10 * b01 + a20 * b02,
|
||||
a01 * b00 + a11 * b01 + a21 * b02,
|
||||
a02 * b00 + a12 * b01 + a22 * b02,
|
||||
|
||||
a00 * b10 + a10 * b11 + a20 * b12,
|
||||
a01 * b10 + a11 * b11 + a21 * b12,
|
||||
a02 * b10 + a12 * b11 + a22 * b12,
|
||||
|
||||
a00 * b20 + a10 * b21 + a20 * b22,
|
||||
a01 * b20 + a11 * b21 + a21 * b22,
|
||||
a02 * b20 + a12 * b21 + a22 * b22
|
||||
];
|
||||
|
||||
return new Matrix3(resultValues);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user