UNPKG

@lightningtv/renderer

Version:
230 lines 6.41 kB
/* * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * * Copyright 2023 Comcast Cable Communications Management, LLC. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * A 3D matrix representing a 2D graphics transformation * * @remarks * For convenience, entries in the first two rows can be accessed by the following * properties: * | ta tb tx | * | tc td ty | * | 0 0 1 | * * This matrix is optimized for 2D transformations and hence the last row will * always be considered [0, 0 ,1]. * * To access a column major array for WebGL, use the {@link getFloatArr} method. */ export class Matrix3d { ta; tb; tx; tc; td; ty; _floatArr = null; /** * Potential Mutation Flag * * @remarks * This flag is set to true whenever the matrix is potentially modified. * We don't waste CPU trying to identify if each operation actually modifies * the matrix. Instead, we set this flag to true whenever we think the matrix * is modified. This signals that the `floatArr` should to be updated. */ mutation; /** * Creates a new 3x3 matrix. * * @param entries Row-major 3x3 matrix */ constructor() { this.ta = 0; this.tb = 0; this.tx = 0; this.tc = 0; this.td = 0; this.ty = 0; this.mutation = true; } /** * Returns a temporary matrix that can be used for calculations. * * @remarks * This is useful for avoiding allocations in tight loops. * * The matrix is not guaranteed to be the same between calls. * * @returns */ static get temp() { return tempMatrix; } static multiply(a, b, out) { const e0 = a.ta * b.ta + a.tb * b.tc; const e1 = a.ta * b.tb + a.tb * b.td; const e2 = a.ta * b.tx + a.tb * b.ty + a.tx; const e3 = a.tc * b.ta + a.td * b.tc; const e4 = a.tc * b.tb + a.td * b.td; const e5 = a.tc * b.tx + a.td * b.ty + a.ty; if (!out) { out = new Matrix3d(); } out.ta = e0; out.tb = e1; out.tx = e2; out.tc = e3; out.td = e4; out.ty = e5; out.mutation = true; return out; } static identity(out) { if (!out) { out = new Matrix3d(); } out.ta = 1; out.tb = 0; out.tx = 0; out.tc = 0; out.td = 1; out.ty = 0; out.mutation = true; return out; } static translate(x, y, out) { if (!out) { out = new Matrix3d(); } out.ta = 1; out.tb = 0; out.tx = x; out.tc = 0; out.td = 1; out.ty = y; out.mutation = true; return out; } static scale(sx, sy, out) { if (!out) { out = new Matrix3d(); } out.ta = sx; out.tb = 0; out.tx = 0; out.tc = 0; out.td = sy; out.ty = 0; out.mutation = true; return out; } static rotate(angle, out) { const cos = Math.cos(angle); const sin = Math.sin(angle); if (!out) { out = new Matrix3d(); } out.ta = cos; out.tb = -sin; out.tx = 0; out.tc = sin; out.td = cos; out.ty = 0; out.mutation = true; return out; } static copy(src, dst) { if (!dst) { dst = new Matrix3d(); } dst.ta = src.ta; dst.tc = src.tc; dst.tb = src.tb; dst.td = src.td; dst.tx = src.tx; dst.ty = src.ty; dst.mutation = true; return dst; } translate(x, y) { this.tx = this.ta * x + this.tb * y + this.tx; this.ty = this.tc * x + this.td * y + this.ty; this.mutation = true; return this; } scale(sx, sy) { this.ta = this.ta * sx; this.tb = this.tb * sy; this.tc = this.tc * sx; this.td = this.td * sy; this.mutation = true; return this; } rotate(angle) { if (angle === 0 || !((angle % Math.PI) * 2)) { return this; } const cos = Math.cos(angle); const sin = Math.sin(angle); const e0 = this.ta * cos + this.tb * sin; const e1 = this.tb * cos - this.ta * sin; const e3 = this.tc * cos + this.td * sin; const e4 = this.td * cos - this.tc * sin; this.ta = e0; this.tb = e1; this.tc = e3; this.td = e4; this.mutation = true; return this; } multiply(other) { return Matrix3d.multiply(this, other, this); } /** * Returns the matrix as a Float32Array in column-major order. * * @remarks * This method is optimized to avoid unnecessary allocations. The same array * is returned every time this method is called, and is updated in place. * * WARNING: Use the array only for passing directly to a WebGL shader uniform * during a frame render. Do not modify or hold onto the array for longer than * a frame. */ getFloatArr() { if (!this._floatArr) { this._floatArr = new Float32Array(9); } if (this.mutation) { this._floatArr[0] = this.ta; this._floatArr[1] = this.tc; this._floatArr[2] = 0; this._floatArr[3] = this.tb; this._floatArr[4] = this.td; this._floatArr[5] = 0; this._floatArr[6] = this.tx; this._floatArr[7] = this.ty; this._floatArr[8] = 1; this.mutation = false; } return this._floatArr; } } const tempMatrix = new Matrix3d(); //# sourceMappingURL=Matrix3d.js.map