Skip to content

Commit

Permalink
add 3d rotation to mat3
Browse files Browse the repository at this point in the history
rotateX
rotationX
rotateY
rotationY
rotateZ
rotationZ
  • Loading branch information
greggman committed Sep 9, 2024
1 parent 024d32c commit 7a7e4c1
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 0 deletions.
135 changes: 135 additions & 0 deletions src/mat3-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,135 @@ function rotate<T extends Mat3Arg = MatType>(m: Mat3Arg, angleInRadians: number,
return newDst;
}

/**
* Creates a 3-by-3 matrix which rotates around the x-axis by the given angle.
* @param angleInRadians - The angle by which to rotate (in radians).
* @param dst - matrix to hold result. If not passed a new one is created.
* @returns The rotation matrix.
*/
function rotationX<T extends Mat3Arg = MatType>(angleInRadians: number, dst?: T) {
const newDst = (dst ?? new Ctor(12)) as T;

const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);

newDst[ 0] = 1; newDst[ 1] = 0; newDst[ 2] = 0;
newDst[ 4] = 0; newDst[ 5] = c; newDst[ 6] = s;
newDst[ 8] = 0; newDst[ 9] = -s; newDst[10] = c;

return newDst;
}

/**
* Rotates the given 3-by-3 matrix around the x-axis by the given
* angle.
* @param m - The matrix.
* @param angleInRadians - The angle by which to rotate (in radians).
* @param dst - matrix to hold result. If not passed a new one is created.
* @returns The rotated matrix.
*/
function rotateX<T extends Mat3Arg = MatType>(m: Mat3Arg, angleInRadians: number, dst?: T) {
const newDst = (dst ?? new Ctor(12)) as T;

const m10 = m[4];
const m11 = m[5];
const m12 = m[6];
const m20 = m[8];
const m21 = m[9];
const m22 = m[10];

const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);

newDst[4] = c * m10 + s * m20;
newDst[5] = c * m11 + s * m21;
newDst[6] = c * m12 + s * m22;
newDst[8] = c * m20 - s * m10;
newDst[9] = c * m21 - s * m11;
newDst[10] = c * m22 - s * m12;

if (m !== newDst) {
newDst[ 0] = m[ 0];
newDst[ 1] = m[ 1];
newDst[ 2] = m[ 2];
}

return newDst;
}

/**
* Creates a 3-by-3 matrix which rotates around the y-axis by the given angle.
* @param angleInRadians - The angle by which to rotate (in radians).
* @param dst - matrix to hold result. If not passed a new one is created.
* @returns The rotation matrix.
*/
function rotationY<T extends Mat3Arg = MatType>(angleInRadians: number, dst?: T) {
const newDst = (dst ?? new Ctor(12)) as T;

const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);

newDst[ 0] = c; newDst[ 1] = 0; newDst[ 2] = -s;
newDst[ 4] = 0; newDst[ 5] = 1; newDst[ 6] = 0;
newDst[ 8] = s; newDst[ 9] = 0; newDst[10] = c;

return newDst;
}

/**
* Rotates the given 3-by-3 matrix around the y-axis by the given
* angle.
* @param m - The matrix.
* @param angleInRadians - The angle by which to rotate (in radians).
* @param dst - matrix to hold result. If not passed a new one is created.
* @returns The rotated matrix.
*/
function rotateY<T extends Mat3Arg = MatType>(m: Mat3Arg, angleInRadians: number, dst?: T) {
const newDst = (dst ?? new Ctor(12)) as T;

const m00 = m[0 * 4 + 0];
const m01 = m[0 * 4 + 1];
const m02 = m[0 * 4 + 2];
const m20 = m[2 * 4 + 0];
const m21 = m[2 * 4 + 1];
const m22 = m[2 * 4 + 2];
const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);

newDst[ 0] = c * m00 - s * m20;
newDst[ 1] = c * m01 - s * m21;
newDst[ 2] = c * m02 - s * m22;
newDst[ 8] = c * m20 + s * m00;
newDst[ 9] = c * m21 + s * m01;
newDst[10] = c * m22 + s * m02;

if (m !== newDst) {
newDst[ 4] = m[ 4];
newDst[ 5] = m[ 5];
newDst[ 6] = m[ 6];
}

return newDst;
}

/**
* Creates a 3-by-3 matrix which rotates around the z-axis by the given angle.
* @param angleInRadians - The angle by which to rotate (in radians).
* @param dst - matrix to hold result. If not passed a new one is created.
* @returns The rotation matrix.
*/
const rotationZ = rotation;

/**
* Rotates the given 3-by-3 matrix around the z-axis by the given
* angle.
* @param m - The matrix.
* @param angleInRadians - The angle by which to rotate (in radians).
* @param dst - matrix to hold result. If not passed a new one is created.
* @returns The rotated matrix.
*/
const rotateZ = rotate;

/**
* Creates a 3-by-3 matrix which scales in each dimension by an amount given by
* the corresponding entry in the given vector; assumes the vector has three
Expand Down Expand Up @@ -784,6 +913,12 @@ return {
translate,
rotation,
rotate,
rotationX,
rotateX,
rotationY,
rotateY,
rotationZ,
rotateZ,
scaling,
scale,
uniformScaling,
Expand Down
72 changes: 72 additions & 0 deletions test/tests/mat3-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,78 @@ function check(mat3, Type) {
}, expected);
});

it('should make rotationX matrix', () => {
const angle = 1.23;
const c = Math.cos(angle);
const s = Math.sin(angle);
const expected = [
1, 0, 0, 0,
0, c, s, 0,
0, -s, c, 0,
];
testMat3WithAndWithoutDest((newDst) => {
return mat3.rotationX(angle, newDst);
}, expected);
});

it('should rotateX', () => {
const angle = 1.23;
// switch to Array type to keep precision high for expected
const expected = mat3n.multiply(m, mat3.rotationX(angle));

testMat3WithAndWithoutDest((newDst) => {
return mat3.rotateX(m, angle, newDst);
}, expected);
});

it('should make rotationY matrix', () => {
const angle = 1.23;
const c = Math.cos(angle);
const s = Math.sin(angle);
const expected = [
c, 0, -s, 0,
0, 1, 0, 0,
s, 0, c, 0,
];
testMat3WithAndWithoutDest((newDst) => {
return mat3.rotationY(angle, newDst);
}, expected);
});

it('should rotateY', () => {
const angle = 1.23;
// switch to Array type to keep precision high for expected
const expected = mat3n.multiply(m, mat3.rotationY(angle));

testMat3WithAndWithoutDest((newDst) => {
return mat3.rotateY(m, angle, newDst);
}, expected);
});

it('should make rotationZ matrix', () => {
const angle = 1.23;
const c = Math.cos(angle);
const s = Math.sin(angle);
const expected = [
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
];
testMat3WithAndWithoutDest((newDst) => {
return mat3.rotationZ(angle, newDst);
}, expected);
});

it('should rotateZ', () => {
const angle = 1.23;
// switch to Array type to keep precision high for expected
const expected = mat3n.multiply(m, mat3.rotationZ(angle));

testMat3WithAndWithoutDest((newDst) => {
return mat3.rotateZ(m, angle, newDst);
}, expected);
});

it('should make scaling matrix', () => {
const expected = [
2, 0, 0, 0,
Expand Down

0 comments on commit 7a7e4c1

Please sign in to comment.