UNPKG

rc-js-util

Version:

A collection of TS and C++ utilities to help writing performant and correct applications, achieved through strict typing and (removable) invariant checking.

278 lines (241 loc) 8.64 kB
import { IMat3Ctor, IReadonlyMat3, Mat3, TMat3CtorArgs } from "./mat3.js"; import { Mat3Factory } from "./mat3-factory.js"; import { _Debug } from "../../../debug/_debug.js"; import { TTypedArrayCtor } from "../t-typed-array-ctor.js"; import { ITypedArrayCtor } from "../i-typed-array-ctor.js"; import { NormalizedDataViewProvider } from "../normalized-data-view/normalized-data-view-provider.js"; import { Mat2 } from "../mat2/mat2.js"; import { IReadonlyVec3, Vec3 } from "../vec3/vec3.js"; import { TTypedArray } from "../t-typed-array.js"; /** * @internal */ export function getMat3Ctor<TCtor extends TTypedArrayCtor> ( ctor: TCtor ) : IMat3Ctor<InstanceType<TCtor>> { return class Mat3Impl extends (ctor as unknown as ITypedArrayCtor<Mat3<InstanceType<TCtor>>>) { public static factory: Mat3Factory<Mat3<InstanceType<TCtor>>> = new Mat3Factory(Mat3Impl, NormalizedDataViewProvider.getView(ctor)); protected static vec3Ctor = Vec3.getCtor(ctor); public ["constructor"]!: typeof Mat3Impl; public constructor ( bufferOrLength: number | ArrayBufferLike = 9, offset?: number, length?: number, ) { super(bufferOrLength as ArrayBufferLike, offset, length); } public override isEqualTo(other: Mat3<TTypedArray>): boolean { let isEqual = true; for (let i = 0; i < 9 && isEqual; ++i) { isEqual &&= this[i as 0] === other[i as 0]; } return isEqual; } public override setIdentityMatrix(): Mat3<InstanceType<TCtor>> { this.fill(0); this[0] = 1; this[4] = 1; this[8] = 1; return this; } public override getValueAt(column: number, row: number): number { _BUILD.DEBUG && _Debug.assert(column >= 0 && column < 3 && row >= 0 && row < 3, "out of bounds"); return this[row * 3 + column as Extract<keyof Mat3<never>, number>]; } public override setValueAt(column: number, row: number, value: number): void { _BUILD.DEBUG && _Debug.assert(column >= 0 && column < 3 && row >= 0 && row < 3, "out of bounds"); this[row * 3 + column as Extract<keyof Mat2<never>, number>] = value; } public override getRow<TResult extends TTypedArray = InstanceType<TCtor>> ( row: number, writeTo: Vec3<TResult> = this.constructor.vec3Ctor.factory.createOneEmpty() as Vec3<TResult>, ) : Vec3<TResult> { _BUILD.DEBUG && _Debug.assert(row >= 0 && row < 3, "index out of bounds"); writeTo[0] = this.getValueAt(0, row); writeTo[1] = this.getValueAt(1, row); writeTo[2] = this.getValueAt(2, row); return writeTo; } public override setRow ( row: number, writeFrom: IReadonlyVec3<TTypedArray>, ) : void { _BUILD.DEBUG && _Debug.assert(row >= 0 && row < 3, "index out of bounds"); this.setValueAt(0, row, writeFrom[0]); this.setValueAt(1, row, writeFrom[1]); this.setValueAt(2, row, writeFrom[2]); } public override setRotationMatrix ( angle: number, ) : Mat3<InstanceType<TCtor>> { const sine = Math.sin(angle); const cosine = Math.cos(angle); this[0] = cosine; this[1] = -sine; this[2] = 0; this[3] = sine; this[4] = cosine; this[5] = 0; this[6] = 0; this[7] = 0; this[8] = 1; return this; } public override setScalingMatrix(scalingFactorX: number, scalingFactorY: number): Mat3<InstanceType<TCtor>> { this[0] = scalingFactorX; this[1] = 0; this[2] = 0; this[3] = 0; this[4] = scalingFactorY; this[5] = 0; this[6] = 0; this[7] = 0; this[8] = 1; return this; } public override setTranslationMatrix ( translationX: number, translationY: number, ) : Mat3<InstanceType<TCtor>> { this[0] = 1; this[1] = 0; this[2] = 0; this[3] = 0; this[4] = 1; this[5] = 0; this[6] = translationX; this[7] = translationY; this[8] = 1; return this; } public scalarMultiply<TResult extends TTypedArray = InstanceType<TCtor>> ( value: number, result: Mat3<TResult> = this.constructor.factory.createOneEmpty() as Mat3<TResult>, ) : Mat3<TResult> { result[0] = this[0] * value; result[1] = this[1] * value; result[2] = this[2] * value; result[3] = this[3] * value; result[4] = this[4] * value; result[5] = this[5] * value; result[6] = this[6] * value; result[7] = this[7] * value; result[8] = this[8] * value; return result; } public scalarAdd<TResult extends TTypedArray = InstanceType<TCtor>> ( value: number, result: Mat3<TResult> = this.constructor.factory.createOneEmpty() as Mat3<TResult>, ) : Mat3<TResult> { result[0] = this[0] + value; result[1] = this[1] + value; result[2] = this[2] + value; result[3] = this[3] + value; result[4] = this[4] + value; result[5] = this[5] + value; result[6] = this[6] + value; result[7] = this[7] + value; result[8] = this[8] + value; return result; } public override multiplyMat3<TResult extends TTypedArray = InstanceType<TCtor>> ( mat: IReadonlyMat3<TTypedArray>, result: Mat3<TResult> = this.constructor.factory.createOneEmpty() as Mat3<TResult>, ) : Mat3<TResult> { const [a0, a1, a2, a3, a4, a5, a6, a7, a8] = this as unknown as TMat3CtorArgs; const [b0, b1, b2, b3, b4, b5, b6, b7, b8] = mat as unknown as TMat3CtorArgs; result[0] = a0 * b0 + a1 * b3 + a2 * b6; result[1] = a0 * b1 + a1 * b4 + a2 * b7; result[2] = a0 * b2 + a1 * b5 + a2 * b8; result[3] = a3 * b0 + a4 * b3 + a5 * b6; result[4] = a3 * b1 + a4 * b4 + a5 * b7; result[5] = a3 * b2 + a4 * b5 + a5 * b8; result[6] = a6 * b0 + a7 * b3 + a8 * b6; result[7] = a6 * b1 + a7 * b4 + a8 * b7; result[8] = a6 * b2 + a7 * b5 + a8 * b8; return result; } public override getVec3MultiplyX(x: number): number { return this[0] * x + this[3] * x + this[6]; } public override getVec3MultiplyY(y: number): number { return this[1] * y + this[4] * y + this[7]; } public override getTransformedXLength(min: number, max: number): number { return this.getVec3MultiplyX(max) - this.getVec3MultiplyX(min); } public override getTransformedYLength(min: number, max: number): number { return this.getVec3MultiplyY(max) - this.getVec3MultiplyY(min); } public override getLoggableValue(): number[][] { return [ [this[0], this[1], this[2]], [this[3], this[4], this[5]], [this[6], this[7], this[8]], ]; } public copyFromBuffer ( memoryDataView: DataView, pointer: number, littleEndian?: boolean, ) : void { this.constructor.factory.copyFromBuffer(memoryDataView, pointer, this, littleEndian); } public copyToBuffer ( memoryDataView: DataView, pointer: number, littleEndian?: boolean, ) : void { this.constructor.factory.copyToBuffer(memoryDataView, this, pointer, littleEndian); } public castToBaseType(): InstanceType<TCtor> { return this as InstanceType<TCtor>; } }; }