Skip to content

Commit

Permalink
chore(core): added Matrix4.fromTranslationQuaternion and allowed getS…
Browse files Browse the repository at this point in the history
…cale, getTranslation, getRotation and getRotationMatrix3 to return same type as input parameter's
  • Loading branch information
jfayot committed Jan 20, 2024
1 parent f165d09 commit 0ecfc00
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 23 deletions.
9 changes: 9 additions & 0 deletions docs/modules/core/api-reference/matrix4.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ Sets the matrix to a transformation corresponding to the rotations represented b

- `quaternion` (`Quaternion`) - the quaternion to create matrix from

##### fromTranslationQuaternion(translation: Vector3, quaternion: Quaternion): this

Sets the matrix to a transformation corresponding to the translation and rotations represented by the given parameters.

`matrix4.fromTranslationQuaternion(translation, quaternion)`

- `translation` (`Vector3`) - the translation to create matrix from
- `quaternion` (`Quaternion`) - the quaternion to create matrix from

##### `frustum(options: {left: number, right: number, bottom: number, top: number, near: number, far: number}): this`

Generates a frustum matrix with the given bounds. The frustum far plane can be infinite.
Expand Down
39 changes: 33 additions & 6 deletions modules/core/src/classes/matrix4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {vec2_transformMat4AsVector, vec3_transformMat4AsVector} from '../lib/gl-
// @ts-ignore gl-matrix types...
import {
fromQuat as mat4_fromQuat,
fromRotationTranslation as mat4_fromRotationTranslation,
frustum as mat4_frustum,
lookAt as mat4_lookAt,
ortho as mat4_ortho,
Expand Down Expand Up @@ -231,6 +232,20 @@ export class Matrix4 extends Matrix {
return this.check();
}

/**
* Calculates a 4x4 matrix from the given translation and quaternion
* @param translation Vector3 to create matrix from
* @param quaternion Quaternion to create matrix from
* @returns self
*/
fromTranslationQuaternion(
translation: Readonly<NumericArray>,
quaternion: Readonly<NumericArray>
): this {
mat4_fromRotationTranslation(this, quaternion, translation);
return this.check();
}

/**
* Generates a frustum matrix with the given bounds
* @param view.left - Left bound of the frustum
Expand Down Expand Up @@ -368,7 +383,9 @@ export class Matrix4 extends Matrix {
* @param result
* @returns self
*/
getScale(result: NumericArray = [-0, -0, -0]): NumericArray {
getScale(): NumericArray;
getScale<T extends NumericArray>(result: T): T;
getScale(result = [-0, -0, -0]): NumericArray {
// explicit is faster than hypot...
result[0] = Math.sqrt(this[0] * this[0] + this[1] * this[1] + this[2] * this[2]);
result[1] = Math.sqrt(this[4] * this[4] + this[5] * this[5] + this[6] * this[6]);
Expand All @@ -384,7 +401,9 @@ export class Matrix4 extends Matrix {
* @param result
* @returns self
*/
getTranslation(result: NumericArray = [-0, -0, -0]): NumericArray {
getTranslation(): NumericArray;
getTranslation<T extends NumericArray>(result: T): T;
getTranslation(result = [-0, -0, -0]): NumericArray {
result[0] = this[12];
result[1] = this[13];
result[2] = this[14];
Expand All @@ -397,8 +416,12 @@ export class Matrix4 extends Matrix {
* @param scaleResult
* @returns self
*/
getRotation(result?: NumericArray, scaleResult?: NumericArray): NumericArray {
result = result || [-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0];
getRotation(scaleResult?: NumericArray): NumericArray;
getRotation<T extends NumericArray>(result: T, scaleResult?: NumericArray): T;
getRotation(
result = [-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0],
scaleResult?: NumericArray
): NumericArray {
scaleResult = scaleResult || [-0, -0, -0];
const scale = this.getScale(scaleResult);
const inverseScale0 = 1 / scale[0];
Expand Down Expand Up @@ -429,8 +452,12 @@ export class Matrix4 extends Matrix {
* @param scaleResult
* @returns self
*/
getRotationMatrix3(result?: NumericArray, scaleResult?: NumericArray): NumericArray {
result = result || [-0, -0, -0, -0, -0, -0, -0, -0, -0];
getRotationMatrix3(scaleResult?: NumericArray): NumericArray;
getRotationMatrix3<T extends NumericArray>(result: T, scaleResult?: NumericArray): T;
getRotationMatrix3(
result = [-0, -0, -0, -0, -0, -0, -0, -0, -0],
scaleResult?: NumericArray
): NumericArray {
scaleResult = scaleResult || [-0, -0, -0];
const scale = this.getScale(scaleResult);
const inverseScale0 = 1 / scale[0];
Expand Down
32 changes: 16 additions & 16 deletions modules/core/src/gl-matrix/quat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,22 +354,22 @@ export function slerp(out, a, b, t) {
* @param {quat} out the receiving quaternion
* @returns {quat} out
*/
// export function random(out) {
// // Implementation of http://planning.cs.uiuc.edu/node198.html
// // TODO: Calling random 3 times is probably not the fastest solution
// let u1 = glMatrix.RANDOM();
// let u2 = glMatrix.RANDOM();
// let u3 = glMatrix.RANDOM();

// let sqrt1MinusU1 = Math.sqrt(1 - u1);
// let sqrtU1 = Math.sqrt(u1);

// out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);
// out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);
// out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);
// out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);
// return out;
// }
export function random(out) {
// Implementation of http://planning.cs.uiuc.edu/node198.html
// TODO: Calling random 3 times is probably not the fastest solution
let u1 = glMatrix.RANDOM();
let u2 = glMatrix.RANDOM();
let u3 = glMatrix.RANDOM();

let sqrt1MinusU1 = Math.sqrt(1 - u1);
let sqrtU1 = Math.sqrt(u1);

out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);
out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);
out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);
out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);
return out;
}

/**
* Calculates the inverse of a quat
Expand Down
71 changes: 70 additions & 1 deletion modules/core/test/classes/matrix4.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// MIT License

/* eslint-disable max-statements */
import {Matrix4, Vector3, config, configure} from '@math.gl/core';
import {Matrix3, Matrix4, Quaternion, Vector3, config, configure} from '@math.gl/core';
import {random as vec3_random} from '../../src/gl-matrix/vec3';
import {random as quat_random} from '../../src/gl-matrix/quat';
import test from 'tape-promise/tape';
import {tapeEquals, tapeEqualsEpsilon} from 'test/utils/tape-assertions';

Expand Down Expand Up @@ -42,6 +44,20 @@ test('Matrix4#fromQuaternion', (t) => {
t.end();
});

test('Matrix4#fromTranslationQuaternion', (t) => {
const translation = new Vector3(vec3_random([-0, -0, -0], 100 * Math.random()));
const quaternion = new Quaternion(quat_random([-0, -0, -0, -0]));

tapeEquals(
t,
new Matrix4().fromTranslationQuaternion(translation, quaternion),
new Matrix4()
.fromQuaternion(quaternion)
.multiplyLeft(new Matrix4().identity().translate(translation))
);
t.end();
});

test('Matrix4#from', (t) => {
tapeEquals(t, new Matrix4().from(INDICES_MATRIX), INDICES_MATRIX);
// tapeEquals(t, new Matrix4().from({x: 1, y: 2, z: 3, w: 4}), [1, 2, 3, 4]);
Expand Down Expand Up @@ -159,6 +175,18 @@ test('Matrix4#getScale', (t) => {
t.end();
});

test('Matrix4#getScaleAsVector3', (t) => {
const INPUT = INDICES_MATRIX;
const RESULT = new Vector3([3.7416573867739413, 10.488088481701515, 17.37814719698276]);

const scale = new Matrix4(INPUT).getScale(new Vector3());

tapeEquals(t, scale instanceof Vector3, true);
tapeEquals(t, scale, RESULT, 'getScale gave the right result');

t.end();
});

test('Matrix4#getRotation', (t) => {
const INPUT = INDICES_MATRIX;
const RESULT = [
Expand All @@ -173,6 +201,21 @@ test('Matrix4#getRotation', (t) => {
t.end();
});

test('Matrix4#getRotationAsMatrix4', (t) => {
const INPUT = INDICES_MATRIX;
const RESULT = new Matrix4([
0.2672612419124244, 0.19069251784911848, 0.17263060129453078, 0, 1.3363062095621219,
0.5720775535473555, 0.4028047363539052, 0, 2.4053511772118195, 0.9534625892455924,
0.6329788714132796, 0, 0, 0, 0, 1
]);

const m = new Matrix4(INPUT).getRotation(new Matrix4(), [...INDICES_MATRIX]);
tapeEquals(t, m instanceof Matrix4, true);
tapeEquals(t, m, RESULT, 'getRotation gave the right result');

t.end();
});

test('Matrix4#getRotationMatrix3', (t) => {
const INPUT = INDICES_MATRIX;
const RESULT = [
Expand All @@ -187,6 +230,21 @@ test('Matrix4#getRotationMatrix3', (t) => {
t.end();
});

test('Matrix4#getRotationMatrix3AsMatrix3', (t) => {
const INPUT = INDICES_MATRIX;
const RESULT = new Matrix3([
0.2672612419124244, 0.19069251784911848, 0.17263060129453078, 1.3363062095621219,
0.5720775535473555, 0.4028047363539052, 2.4053511772118195, 0.9534625892455924,
0.6329788714132796
]);

const m = new Matrix4(INPUT).getRotationMatrix3(new Matrix3(), [...INDICES_MATRIX.slice(0, 9)]);
tapeEquals(t, m instanceof Matrix3, true);
tapeEquals(t, m, RESULT, 'getRotationMatrix3 gave the right result');

t.end();
});

test('Matrix4#getTranslation', (t) => {
const INPUT = INDICES_MATRIX;
const RESULT = [13, 14, 15];
Expand All @@ -197,6 +255,17 @@ test('Matrix4#getTranslation', (t) => {
t.end();
});

test('Matrix4#getTranslationAsVector3', (t) => {
const INPUT = INDICES_MATRIX;
const RESULT = new Vector3([13, 14, 15]);

const m = new Matrix4(INPUT).getTranslation(new Vector3());
tapeEquals(t, m instanceof Vector3, true);
tapeEquals(t, m, RESULT, 'getTranslation gave the right result');

t.end();
});

test('Matrix4#perspective#', (t) => {
const fovy = Math.PI * 0.5;
const result = new Matrix4().perspective({fovy, aspect: 1, near: 0, far: 1});
Expand Down

0 comments on commit 0ecfc00

Please sign in to comment.