import vec2 from './vec2'; import { epsilon } from './constants'; export default class mat2 { constructor(values) { this.values = new Float32Array(4); if (values !== undefined) { this.init(values); } } at(index) { return this.values[index]; } init(values) { for (let i = 0; i < 4; i++) { this.values[i] = values[i]; } return this; } reset() { for (let i = 0; i < 4; i++) { this.values[i] = 0; } } copy(dest) { if (!dest) { dest = new mat2(); } for (let i = 0; i < 4; i++) { dest.values[i] = this.values[i]; } return dest; } all() { const data = []; for (let i = 0; i < 4; i++) { data[i] = this.values[i]; } return data; } row(index) { return [this.values[index * 2 + 0], this.values[index * 2 + 1]]; } col(index) { return [this.values[index], this.values[index + 2]]; } equals(matrix, threshold = epsilon) { for (let i = 0; i < 4; i++) { if (Math.abs(this.values[i] - matrix.at(i)) > threshold) { return false; } } return true; } determinant() { return this.values[0] * this.values[3] - this.values[2] * this.values[1]; } setIdentity() { this.values[0] = 1; this.values[1] = 0; this.values[2] = 0; this.values[3] = 1; return this; } transpose() { const temp = this.values[1]; this.values[1] = this.values[2]; this.values[2] = temp; return this; } inverse() { let det = this.determinant(); if (!det) { return null; } det = 1.0 / det; const a11 = this.values[0]; this.values[0] = det * this.values[3]; this.values[1] = det * -this.values[1]; this.values[2] = det * -this.values[2]; this.values[3] = det * a11; return this; } multiply(matrix) { const a11 = this.values[0]; const a12 = this.values[1]; const a21 = this.values[2]; const a22 = this.values[3]; this.values[0] = a11 * matrix.at(0) + a12 * matrix.at(2); this.values[1] = a11 * matrix.at(1) + a12 * matrix.at(3); this.values[2] = a21 * matrix.at(0) + a22 * matrix.at(2); this.values[3] = a21 * matrix.at(1) + a22 * matrix.at(3); return this; } rotate(angle) { const a11 = this.values[0]; const a12 = this.values[1]; const a21 = this.values[2]; const a22 = this.values[3]; const sin = Math.sin(angle); const cos = Math.cos(angle); this.values[0] = a11 * cos + a12 * sin; this.values[1] = a11 * -sin + a12 * cos; this.values[2] = a21 * cos + a22 * sin; this.values[3] = a21 * -sin + a22 * cos; return this; } multiplyVec2(vector, result) { const x = vector.x; const y = vector.y; if (result) { result.xy = [ x * this.values[0] + y * this.values[1], x * this.values[2] + y * this.values[3] ]; return result; } else { return new vec2([ x * this.values[0] + y * this.values[1], x * this.values[2] + y * this.values[3] ]); } } scale(vector) { const a11 = this.values[0]; const a12 = this.values[1]; const a21 = this.values[2]; const a22 = this.values[3]; const x = vector.x; const y = vector.y; this.values[0] = a11 * x; this.values[1] = a12 * y; this.values[2] = a21 * x; this.values[3] = a22 * y; return this; } static product(m1, m2, result) { const a11 = m1.at(0); const a12 = m1.at(1); const a21 = m1.at(2); const a22 = m1.at(3); if (result) { result.init([ a11 * m2.at(0) + a12 * m2.at(2), a11 * m2.at(1) + a12 * m2.at(3), a21 * m2.at(0) + a22 * m2.at(2), a21 * m2.at(1) + a22 * m2.at(3) ]); return result; } else { return new mat2([ a11 * m2.at(0) + a12 * m2.at(2), a11 * m2.at(1) + a12 * m2.at(3), a21 * m2.at(0) + a22 * m2.at(2), a21 * m2.at(1) + a22 * m2.at(3) ]); } } } mat2.identity = new mat2().setIdentity();