Skip to content

Commit 7a7e4c1

Browse files
committed
add 3d rotation to mat3
rotateX rotationX rotateY rotationY rotateZ rotationZ
1 parent 024d32c commit 7a7e4c1

File tree

2 files changed

+207
-0
lines changed

2 files changed

+207
-0
lines changed

src/mat3-impl.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,135 @@ function rotate<T extends Mat3Arg = MatType>(m: Mat3Arg, angleInRadians: number,
661661
return newDst;
662662
}
663663

664+
/**
665+
* Creates a 3-by-3 matrix which rotates around the x-axis by the given angle.
666+
* @param angleInRadians - The angle by which to rotate (in radians).
667+
* @param dst - matrix to hold result. If not passed a new one is created.
668+
* @returns The rotation matrix.
669+
*/
670+
function rotationX<T extends Mat3Arg = MatType>(angleInRadians: number, dst?: T) {
671+
const newDst = (dst ?? new Ctor(12)) as T;
672+
673+
const c = Math.cos(angleInRadians);
674+
const s = Math.sin(angleInRadians);
675+
676+
newDst[ 0] = 1; newDst[ 1] = 0; newDst[ 2] = 0;
677+
newDst[ 4] = 0; newDst[ 5] = c; newDst[ 6] = s;
678+
newDst[ 8] = 0; newDst[ 9] = -s; newDst[10] = c;
679+
680+
return newDst;
681+
}
682+
683+
/**
684+
* Rotates the given 3-by-3 matrix around the x-axis by the given
685+
* angle.
686+
* @param m - The matrix.
687+
* @param angleInRadians - The angle by which to rotate (in radians).
688+
* @param dst - matrix to hold result. If not passed a new one is created.
689+
* @returns The rotated matrix.
690+
*/
691+
function rotateX<T extends Mat3Arg = MatType>(m: Mat3Arg, angleInRadians: number, dst?: T) {
692+
const newDst = (dst ?? new Ctor(12)) as T;
693+
694+
const m10 = m[4];
695+
const m11 = m[5];
696+
const m12 = m[6];
697+
const m20 = m[8];
698+
const m21 = m[9];
699+
const m22 = m[10];
700+
701+
const c = Math.cos(angleInRadians);
702+
const s = Math.sin(angleInRadians);
703+
704+
newDst[4] = c * m10 + s * m20;
705+
newDst[5] = c * m11 + s * m21;
706+
newDst[6] = c * m12 + s * m22;
707+
newDst[8] = c * m20 - s * m10;
708+
newDst[9] = c * m21 - s * m11;
709+
newDst[10] = c * m22 - s * m12;
710+
711+
if (m !== newDst) {
712+
newDst[ 0] = m[ 0];
713+
newDst[ 1] = m[ 1];
714+
newDst[ 2] = m[ 2];
715+
}
716+
717+
return newDst;
718+
}
719+
720+
/**
721+
* Creates a 3-by-3 matrix which rotates around the y-axis by the given angle.
722+
* @param angleInRadians - The angle by which to rotate (in radians).
723+
* @param dst - matrix to hold result. If not passed a new one is created.
724+
* @returns The rotation matrix.
725+
*/
726+
function rotationY<T extends Mat3Arg = MatType>(angleInRadians: number, dst?: T) {
727+
const newDst = (dst ?? new Ctor(12)) as T;
728+
729+
const c = Math.cos(angleInRadians);
730+
const s = Math.sin(angleInRadians);
731+
732+
newDst[ 0] = c; newDst[ 1] = 0; newDst[ 2] = -s;
733+
newDst[ 4] = 0; newDst[ 5] = 1; newDst[ 6] = 0;
734+
newDst[ 8] = s; newDst[ 9] = 0; newDst[10] = c;
735+
736+
return newDst;
737+
}
738+
739+
/**
740+
* Rotates the given 3-by-3 matrix around the y-axis by the given
741+
* angle.
742+
* @param m - The matrix.
743+
* @param angleInRadians - The angle by which to rotate (in radians).
744+
* @param dst - matrix to hold result. If not passed a new one is created.
745+
* @returns The rotated matrix.
746+
*/
747+
function rotateY<T extends Mat3Arg = MatType>(m: Mat3Arg, angleInRadians: number, dst?: T) {
748+
const newDst = (dst ?? new Ctor(12)) as T;
749+
750+
const m00 = m[0 * 4 + 0];
751+
const m01 = m[0 * 4 + 1];
752+
const m02 = m[0 * 4 + 2];
753+
const m20 = m[2 * 4 + 0];
754+
const m21 = m[2 * 4 + 1];
755+
const m22 = m[2 * 4 + 2];
756+
const c = Math.cos(angleInRadians);
757+
const s = Math.sin(angleInRadians);
758+
759+
newDst[ 0] = c * m00 - s * m20;
760+
newDst[ 1] = c * m01 - s * m21;
761+
newDst[ 2] = c * m02 - s * m22;
762+
newDst[ 8] = c * m20 + s * m00;
763+
newDst[ 9] = c * m21 + s * m01;
764+
newDst[10] = c * m22 + s * m02;
765+
766+
if (m !== newDst) {
767+
newDst[ 4] = m[ 4];
768+
newDst[ 5] = m[ 5];
769+
newDst[ 6] = m[ 6];
770+
}
771+
772+
return newDst;
773+
}
774+
775+
/**
776+
* Creates a 3-by-3 matrix which rotates around the z-axis by the given angle.
777+
* @param angleInRadians - The angle by which to rotate (in radians).
778+
* @param dst - matrix to hold result. If not passed a new one is created.
779+
* @returns The rotation matrix.
780+
*/
781+
const rotationZ = rotation;
782+
783+
/**
784+
* Rotates the given 3-by-3 matrix around the z-axis by the given
785+
* angle.
786+
* @param m - The matrix.
787+
* @param angleInRadians - The angle by which to rotate (in radians).
788+
* @param dst - matrix to hold result. If not passed a new one is created.
789+
* @returns The rotated matrix.
790+
*/
791+
const rotateZ = rotate;
792+
664793
/**
665794
* Creates a 3-by-3 matrix which scales in each dimension by an amount given by
666795
* the corresponding entry in the given vector; assumes the vector has three
@@ -784,6 +913,12 @@ return {
784913
translate,
785914
rotation,
786915
rotate,
916+
rotationX,
917+
rotateX,
918+
rotationY,
919+
rotateY,
920+
rotationZ,
921+
rotateZ,
787922
scaling,
788923
scale,
789924
uniformScaling,

test/tests/mat3-test.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,78 @@ function check(mat3, Type) {
448448
}, expected);
449449
});
450450

451+
it('should make rotationX matrix', () => {
452+
const angle = 1.23;
453+
const c = Math.cos(angle);
454+
const s = Math.sin(angle);
455+
const expected = [
456+
1, 0, 0, 0,
457+
0, c, s, 0,
458+
0, -s, c, 0,
459+
];
460+
testMat3WithAndWithoutDest((newDst) => {
461+
return mat3.rotationX(angle, newDst);
462+
}, expected);
463+
});
464+
465+
it('should rotateX', () => {
466+
const angle = 1.23;
467+
// switch to Array type to keep precision high for expected
468+
const expected = mat3n.multiply(m, mat3.rotationX(angle));
469+
470+
testMat3WithAndWithoutDest((newDst) => {
471+
return mat3.rotateX(m, angle, newDst);
472+
}, expected);
473+
});
474+
475+
it('should make rotationY matrix', () => {
476+
const angle = 1.23;
477+
const c = Math.cos(angle);
478+
const s = Math.sin(angle);
479+
const expected = [
480+
c, 0, -s, 0,
481+
0, 1, 0, 0,
482+
s, 0, c, 0,
483+
];
484+
testMat3WithAndWithoutDest((newDst) => {
485+
return mat3.rotationY(angle, newDst);
486+
}, expected);
487+
});
488+
489+
it('should rotateY', () => {
490+
const angle = 1.23;
491+
// switch to Array type to keep precision high for expected
492+
const expected = mat3n.multiply(m, mat3.rotationY(angle));
493+
494+
testMat3WithAndWithoutDest((newDst) => {
495+
return mat3.rotateY(m, angle, newDst);
496+
}, expected);
497+
});
498+
499+
it('should make rotationZ matrix', () => {
500+
const angle = 1.23;
501+
const c = Math.cos(angle);
502+
const s = Math.sin(angle);
503+
const expected = [
504+
c, s, 0, 0,
505+
-s, c, 0, 0,
506+
0, 0, 1, 0,
507+
];
508+
testMat3WithAndWithoutDest((newDst) => {
509+
return mat3.rotationZ(angle, newDst);
510+
}, expected);
511+
});
512+
513+
it('should rotateZ', () => {
514+
const angle = 1.23;
515+
// switch to Array type to keep precision high for expected
516+
const expected = mat3n.multiply(m, mat3.rotationZ(angle));
517+
518+
testMat3WithAndWithoutDest((newDst) => {
519+
return mat3.rotateZ(m, angle, newDst);
520+
}, expected);
521+
});
522+
451523
it('should make scaling matrix', () => {
452524
const expected = [
453525
2, 0, 0, 0,

0 commit comments

Comments
 (0)