123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @noflow
- */
- 'use strict';
- const invariant = require('invariant');
- /**
- * Memory conservative (mutative) matrix math utilities. Uses "command"
- * matrices, which are reusable.
- */
- const MatrixMath = {
- createIdentityMatrix: function() {
- return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
- },
- createCopy: function(m) {
- return [
- m[0],
- m[1],
- m[2],
- m[3],
- m[4],
- m[5],
- m[6],
- m[7],
- m[8],
- m[9],
- m[10],
- m[11],
- m[12],
- m[13],
- m[14],
- m[15],
- ];
- },
- createOrthographic: function(left, right, bottom, top, near, far) {
- const a = 2 / (right - left);
- const b = 2 / (top - bottom);
- const c = -2 / (far - near);
- const tx = -(right + left) / (right - left);
- const ty = -(top + bottom) / (top - bottom);
- const tz = -(far + near) / (far - near);
- return [a, 0, 0, 0, 0, b, 0, 0, 0, 0, c, 0, tx, ty, tz, 1];
- },
- createFrustum: function(left, right, bottom, top, near, far) {
- const r_width = 1 / (right - left);
- const r_height = 1 / (top - bottom);
- const r_depth = 1 / (near - far);
- const x = 2 * (near * r_width);
- const y = 2 * (near * r_height);
- const A = (right + left) * r_width;
- const B = (top + bottom) * r_height;
- const C = (far + near) * r_depth;
- const D = 2 * (far * near * r_depth);
- return [x, 0, 0, 0, 0, y, 0, 0, A, B, C, -1, 0, 0, D, 0];
- },
- /**
- * This create a perspective projection towards negative z
- * Clipping the z range of [-near, -far]
- *
- * @param fovInRadians - field of view in randians
- */
- createPerspective: function(fovInRadians, aspect, near, far) {
- const h = 1 / Math.tan(fovInRadians / 2);
- const r_depth = 1 / (near - far);
- const C = (far + near) * r_depth;
- const D = 2 * (far * near * r_depth);
- return [h / aspect, 0, 0, 0, 0, h, 0, 0, 0, 0, C, -1, 0, 0, D, 0];
- },
- createTranslate2d: function(x, y) {
- const mat = MatrixMath.createIdentityMatrix();
- MatrixMath.reuseTranslate2dCommand(mat, x, y);
- return mat;
- },
- reuseTranslate2dCommand: function(matrixCommand, x, y) {
- matrixCommand[12] = x;
- matrixCommand[13] = y;
- },
- reuseTranslate3dCommand: function(matrixCommand, x, y, z) {
- matrixCommand[12] = x;
- matrixCommand[13] = y;
- matrixCommand[14] = z;
- },
- createScale: function(factor) {
- const mat = MatrixMath.createIdentityMatrix();
- MatrixMath.reuseScaleCommand(mat, factor);
- return mat;
- },
- reuseScaleCommand: function(matrixCommand, factor) {
- matrixCommand[0] = factor;
- matrixCommand[5] = factor;
- },
- reuseScale3dCommand: function(matrixCommand, x, y, z) {
- matrixCommand[0] = x;
- matrixCommand[5] = y;
- matrixCommand[10] = z;
- },
- reusePerspectiveCommand: function(matrixCommand, p) {
- matrixCommand[11] = -1 / p;
- },
- reuseScaleXCommand(matrixCommand, factor) {
- matrixCommand[0] = factor;
- },
- reuseScaleYCommand(matrixCommand, factor) {
- matrixCommand[5] = factor;
- },
- reuseScaleZCommand(matrixCommand, factor) {
- matrixCommand[10] = factor;
- },
- reuseRotateXCommand: function(matrixCommand, radians) {
- matrixCommand[5] = Math.cos(radians);
- matrixCommand[6] = Math.sin(radians);
- matrixCommand[9] = -Math.sin(radians);
- matrixCommand[10] = Math.cos(radians);
- },
- reuseRotateYCommand: function(matrixCommand, amount) {
- matrixCommand[0] = Math.cos(amount);
- matrixCommand[2] = -Math.sin(amount);
- matrixCommand[8] = Math.sin(amount);
- matrixCommand[10] = Math.cos(amount);
- },
- // http://www.w3.org/TR/css3-transforms/#recomposing-to-a-2d-matrix
- reuseRotateZCommand: function(matrixCommand, radians) {
- matrixCommand[0] = Math.cos(radians);
- matrixCommand[1] = Math.sin(radians);
- matrixCommand[4] = -Math.sin(radians);
- matrixCommand[5] = Math.cos(radians);
- },
- createRotateZ: function(radians) {
- const mat = MatrixMath.createIdentityMatrix();
- MatrixMath.reuseRotateZCommand(mat, radians);
- return mat;
- },
- reuseSkewXCommand: function(matrixCommand, radians) {
- matrixCommand[4] = Math.tan(radians);
- },
- reuseSkewYCommand: function(matrixCommand, radians) {
- matrixCommand[1] = Math.tan(radians);
- },
- multiplyInto: function(out, a, b) {
- const a00 = a[0],
- a01 = a[1],
- a02 = a[2],
- a03 = a[3],
- a10 = a[4],
- a11 = a[5],
- a12 = a[6],
- a13 = a[7],
- a20 = a[8],
- a21 = a[9],
- a22 = a[10],
- a23 = a[11],
- a30 = a[12],
- a31 = a[13],
- a32 = a[14],
- a33 = a[15];
- let b0 = b[0],
- b1 = b[1],
- b2 = b[2],
- b3 = b[3];
- out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
- out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
- out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
- out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
- b0 = b[4];
- b1 = b[5];
- b2 = b[6];
- b3 = b[7];
- out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
- out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
- out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
- out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
- b0 = b[8];
- b1 = b[9];
- b2 = b[10];
- b3 = b[11];
- out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
- out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
- out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
- out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
- b0 = b[12];
- b1 = b[13];
- b2 = b[14];
- b3 = b[15];
- out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
- out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
- out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
- out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
- },
- determinant(matrix: Array<number>): number {
- const [
- m00,
- m01,
- m02,
- m03,
- m10,
- m11,
- m12,
- m13,
- m20,
- m21,
- m22,
- m23,
- m30,
- m31,
- m32,
- m33,
- ] = matrix;
- return (
- m03 * m12 * m21 * m30 -
- m02 * m13 * m21 * m30 -
- m03 * m11 * m22 * m30 +
- m01 * m13 * m22 * m30 +
- m02 * m11 * m23 * m30 -
- m01 * m12 * m23 * m30 -
- m03 * m12 * m20 * m31 +
- m02 * m13 * m20 * m31 +
- m03 * m10 * m22 * m31 -
- m00 * m13 * m22 * m31 -
- m02 * m10 * m23 * m31 +
- m00 * m12 * m23 * m31 +
- m03 * m11 * m20 * m32 -
- m01 * m13 * m20 * m32 -
- m03 * m10 * m21 * m32 +
- m00 * m13 * m21 * m32 +
- m01 * m10 * m23 * m32 -
- m00 * m11 * m23 * m32 -
- m02 * m11 * m20 * m33 +
- m01 * m12 * m20 * m33 +
- m02 * m10 * m21 * m33 -
- m00 * m12 * m21 * m33 -
- m01 * m10 * m22 * m33 +
- m00 * m11 * m22 * m33
- );
- },
- /**
- * Inverse of a matrix. Multiplying by the inverse is used in matrix math
- * instead of division.
- *
- * Formula from:
- * http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
- */
- inverse(matrix: Array<number>): Array<number> {
- const det = MatrixMath.determinant(matrix);
- if (!det) {
- return matrix;
- }
- const [
- m00,
- m01,
- m02,
- m03,
- m10,
- m11,
- m12,
- m13,
- m20,
- m21,
- m22,
- m23,
- m30,
- m31,
- m32,
- m33,
- ] = matrix;
- return [
- (m12 * m23 * m31 -
- m13 * m22 * m31 +
- m13 * m21 * m32 -
- m11 * m23 * m32 -
- m12 * m21 * m33 +
- m11 * m22 * m33) /
- det,
- (m03 * m22 * m31 -
- m02 * m23 * m31 -
- m03 * m21 * m32 +
- m01 * m23 * m32 +
- m02 * m21 * m33 -
- m01 * m22 * m33) /
- det,
- (m02 * m13 * m31 -
- m03 * m12 * m31 +
- m03 * m11 * m32 -
- m01 * m13 * m32 -
- m02 * m11 * m33 +
- m01 * m12 * m33) /
- det,
- (m03 * m12 * m21 -
- m02 * m13 * m21 -
- m03 * m11 * m22 +
- m01 * m13 * m22 +
- m02 * m11 * m23 -
- m01 * m12 * m23) /
- det,
- (m13 * m22 * m30 -
- m12 * m23 * m30 -
- m13 * m20 * m32 +
- m10 * m23 * m32 +
- m12 * m20 * m33 -
- m10 * m22 * m33) /
- det,
- (m02 * m23 * m30 -
- m03 * m22 * m30 +
- m03 * m20 * m32 -
- m00 * m23 * m32 -
- m02 * m20 * m33 +
- m00 * m22 * m33) /
- det,
- (m03 * m12 * m30 -
- m02 * m13 * m30 -
- m03 * m10 * m32 +
- m00 * m13 * m32 +
- m02 * m10 * m33 -
- m00 * m12 * m33) /
- det,
- (m02 * m13 * m20 -
- m03 * m12 * m20 +
- m03 * m10 * m22 -
- m00 * m13 * m22 -
- m02 * m10 * m23 +
- m00 * m12 * m23) /
- det,
- (m11 * m23 * m30 -
- m13 * m21 * m30 +
- m13 * m20 * m31 -
- m10 * m23 * m31 -
- m11 * m20 * m33 +
- m10 * m21 * m33) /
- det,
- (m03 * m21 * m30 -
- m01 * m23 * m30 -
- m03 * m20 * m31 +
- m00 * m23 * m31 +
- m01 * m20 * m33 -
- m00 * m21 * m33) /
- det,
- (m01 * m13 * m30 -
- m03 * m11 * m30 +
- m03 * m10 * m31 -
- m00 * m13 * m31 -
- m01 * m10 * m33 +
- m00 * m11 * m33) /
- det,
- (m03 * m11 * m20 -
- m01 * m13 * m20 -
- m03 * m10 * m21 +
- m00 * m13 * m21 +
- m01 * m10 * m23 -
- m00 * m11 * m23) /
- det,
- (m12 * m21 * m30 -
- m11 * m22 * m30 -
- m12 * m20 * m31 +
- m10 * m22 * m31 +
- m11 * m20 * m32 -
- m10 * m21 * m32) /
- det,
- (m01 * m22 * m30 -
- m02 * m21 * m30 +
- m02 * m20 * m31 -
- m00 * m22 * m31 -
- m01 * m20 * m32 +
- m00 * m21 * m32) /
- det,
- (m02 * m11 * m30 -
- m01 * m12 * m30 -
- m02 * m10 * m31 +
- m00 * m12 * m31 +
- m01 * m10 * m32 -
- m00 * m11 * m32) /
- det,
- (m01 * m12 * m20 -
- m02 * m11 * m20 +
- m02 * m10 * m21 -
- m00 * m12 * m21 -
- m01 * m10 * m22 +
- m00 * m11 * m22) /
- det,
- ];
- },
- /**
- * Turns columns into rows and rows into columns.
- */
- transpose(m: Array<number>): Array<number> {
- return [
- m[0],
- m[4],
- m[8],
- m[12],
- m[1],
- m[5],
- m[9],
- m[13],
- m[2],
- m[6],
- m[10],
- m[14],
- m[3],
- m[7],
- m[11],
- m[15],
- ];
- },
- /**
- * Based on: http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c
- */
- multiplyVectorByMatrix(v: Array<number>, m: Array<number>): Array<number> {
- const [vx, vy, vz, vw] = v;
- return [
- vx * m[0] + vy * m[4] + vz * m[8] + vw * m[12],
- vx * m[1] + vy * m[5] + vz * m[9] + vw * m[13],
- vx * m[2] + vy * m[6] + vz * m[10] + vw * m[14],
- vx * m[3] + vy * m[7] + vz * m[11] + vw * m[15],
- ];
- },
- /**
- * From: https://code.google.com/p/webgl-mjs/source/browse/mjs.js
- */
- v3Length(a: Array<number>): number {
- return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
- },
- /**
- * Based on: https://code.google.com/p/webgl-mjs/source/browse/mjs.js
- */
- v3Normalize(vector: Array<number>, v3Length: number): Array<number> {
- const im = 1 / (v3Length || MatrixMath.v3Length(vector));
- return [vector[0] * im, vector[1] * im, vector[2] * im];
- },
- /**
- * The dot product of a and b, two 3-element vectors.
- * From: https://code.google.com/p/webgl-mjs/source/browse/mjs.js
- */
- v3Dot(a, b) {
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
- },
- /**
- * From:
- * http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp
- */
- v3Combine(
- a: Array<number>,
- b: Array<number>,
- aScale: number,
- bScale: number,
- ): Array<number> {
- return [
- aScale * a[0] + bScale * b[0],
- aScale * a[1] + bScale * b[1],
- aScale * a[2] + bScale * b[2],
- ];
- },
- /**
- * From:
- * http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp
- */
- v3Cross(a: Array<number>, b: Array<number>): Array<number> {
- return [
- a[1] * b[2] - a[2] * b[1],
- a[2] * b[0] - a[0] * b[2],
- a[0] * b[1] - a[1] * b[0],
- ];
- },
- /**
- * Based on:
- * http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
- * and:
- * http://quat.zachbennett.com/
- *
- * Note that this rounds degrees to the thousandth of a degree, due to
- * floating point errors in the creation of the quaternion.
- *
- * Also note that this expects the qw value to be last, not first.
- *
- * Also, when researching this, remember that:
- * yaw === heading === z-axis
- * pitch === elevation/attitude === y-axis
- * roll === bank === x-axis
- */
- quaternionToDegreesXYZ(q: Array<number>, matrix, row): Array<number> {
- const [qx, qy, qz, qw] = q;
- const qw2 = qw * qw;
- const qx2 = qx * qx;
- const qy2 = qy * qy;
- const qz2 = qz * qz;
- const test = qx * qy + qz * qw;
- const unit = qw2 + qx2 + qy2 + qz2;
- const conv = 180 / Math.PI;
- if (test > 0.49999 * unit) {
- return [0, 2 * Math.atan2(qx, qw) * conv, 90];
- }
- if (test < -0.49999 * unit) {
- return [0, -2 * Math.atan2(qx, qw) * conv, -90];
- }
- return [
- MatrixMath.roundTo3Places(
- Math.atan2(2 * qx * qw - 2 * qy * qz, 1 - 2 * qx2 - 2 * qz2) * conv,
- ),
- MatrixMath.roundTo3Places(
- Math.atan2(2 * qy * qw - 2 * qx * qz, 1 - 2 * qy2 - 2 * qz2) * conv,
- ),
- MatrixMath.roundTo3Places(Math.asin(2 * qx * qy + 2 * qz * qw) * conv),
- ];
- },
- /**
- * Based on:
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
- */
- roundTo3Places(n: number): number {
- const arr = n.toString().split('e');
- return Math.round(arr[0] + 'e' + (arr[1] ? +arr[1] - 3 : 3)) * 0.001;
- },
- /**
- * Decompose a matrix into separate transform values, for use on platforms
- * where applying a precomposed matrix is not possible, and transforms are
- * applied in an inflexible ordering (e.g. Android).
- *
- * Implementation based on
- * http://www.w3.org/TR/css3-transforms/#decomposing-a-2d-matrix
- * http://www.w3.org/TR/css3-transforms/#decomposing-a-3d-matrix
- * which was based on
- * http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c
- */
- decomposeMatrix(transformMatrix: Array<number>): ?Object {
- invariant(
- transformMatrix.length === 16,
- 'Matrix decomposition needs a list of 3d matrix values, received %s',
- transformMatrix,
- );
- // output values
- let perspective = [];
- const quaternion = [];
- const scale = [];
- const skew = [];
- const translation = [];
- // create normalized, 2d array matrix
- // and normalized 1d array perspectiveMatrix with redefined 4th column
- if (!transformMatrix[15]) {
- return;
- }
- const matrix = [];
- const perspectiveMatrix = [];
- for (let i = 0; i < 4; i++) {
- matrix.push([]);
- for (let j = 0; j < 4; j++) {
- const value = transformMatrix[i * 4 + j] / transformMatrix[15];
- matrix[i].push(value);
- perspectiveMatrix.push(j === 3 ? 0 : value);
- }
- }
- perspectiveMatrix[15] = 1;
- // test for singularity of upper 3x3 part of the perspective matrix
- if (!MatrixMath.determinant(perspectiveMatrix)) {
- return;
- }
- // isolate perspective
- if (matrix[0][3] !== 0 || matrix[1][3] !== 0 || matrix[2][3] !== 0) {
- // rightHandSide is the right hand side of the equation.
- // rightHandSide is a vector, or point in 3d space relative to the origin.
- const rightHandSide = [
- matrix[0][3],
- matrix[1][3],
- matrix[2][3],
- matrix[3][3],
- ];
- // Solve the equation by inverting perspectiveMatrix and multiplying
- // rightHandSide by the inverse.
- const inversePerspectiveMatrix = MatrixMath.inverse(perspectiveMatrix);
- const transposedInversePerspectiveMatrix = MatrixMath.transpose(
- inversePerspectiveMatrix,
- );
- perspective = MatrixMath.multiplyVectorByMatrix(
- rightHandSide,
- transposedInversePerspectiveMatrix,
- );
- } else {
- // no perspective
- perspective[0] = perspective[1] = perspective[2] = 0;
- perspective[3] = 1;
- }
- // translation is simple
- for (let i = 0; i < 3; i++) {
- translation[i] = matrix[3][i];
- }
- // Now get scale and shear.
- // 'row' is a 3 element array of 3 component vectors
- const row = [];
- for (let i = 0; i < 3; i++) {
- row[i] = [matrix[i][0], matrix[i][1], matrix[i][2]];
- }
- // Compute X scale factor and normalize first row.
- scale[0] = MatrixMath.v3Length(row[0]);
- row[0] = MatrixMath.v3Normalize(row[0], scale[0]);
- // Compute XY shear factor and make 2nd row orthogonal to 1st.
- skew[0] = MatrixMath.v3Dot(row[0], row[1]);
- row[1] = MatrixMath.v3Combine(row[1], row[0], 1.0, -skew[0]);
- // Now, compute Y scale and normalize 2nd row.
- scale[1] = MatrixMath.v3Length(row[1]);
- row[1] = MatrixMath.v3Normalize(row[1], scale[1]);
- skew[0] /= scale[1];
- // Compute XZ and YZ shears, orthogonalize 3rd row
- skew[1] = MatrixMath.v3Dot(row[0], row[2]);
- row[2] = MatrixMath.v3Combine(row[2], row[0], 1.0, -skew[1]);
- skew[2] = MatrixMath.v3Dot(row[1], row[2]);
- row[2] = MatrixMath.v3Combine(row[2], row[1], 1.0, -skew[2]);
- // Next, get Z scale and normalize 3rd row.
- scale[2] = MatrixMath.v3Length(row[2]);
- row[2] = MatrixMath.v3Normalize(row[2], scale[2]);
- skew[1] /= scale[2];
- skew[2] /= scale[2];
- // At this point, the matrix (in rows) is orthonormal.
- // Check for a coordinate system flip. If the determinant
- // is -1, then negate the matrix and the scaling factors.
- const pdum3 = MatrixMath.v3Cross(row[1], row[2]);
- if (MatrixMath.v3Dot(row[0], pdum3) < 0) {
- for (let i = 0; i < 3; i++) {
- scale[i] *= -1;
- row[i][0] *= -1;
- row[i][1] *= -1;
- row[i][2] *= -1;
- }
- }
- // Now, get the rotations out
- quaternion[0] =
- 0.5 * Math.sqrt(Math.max(1 + row[0][0] - row[1][1] - row[2][2], 0));
- quaternion[1] =
- 0.5 * Math.sqrt(Math.max(1 - row[0][0] + row[1][1] - row[2][2], 0));
- quaternion[2] =
- 0.5 * Math.sqrt(Math.max(1 - row[0][0] - row[1][1] + row[2][2], 0));
- quaternion[3] =
- 0.5 * Math.sqrt(Math.max(1 + row[0][0] + row[1][1] + row[2][2], 0));
- if (row[2][1] > row[1][2]) {
- quaternion[0] = -quaternion[0];
- }
- if (row[0][2] > row[2][0]) {
- quaternion[1] = -quaternion[1];
- }
- if (row[1][0] > row[0][1]) {
- quaternion[2] = -quaternion[2];
- }
- // correct for occasional, weird Euler synonyms for 2d rotation
- let rotationDegrees;
- if (
- quaternion[0] < 0.001 &&
- quaternion[0] >= 0 &&
- quaternion[1] < 0.001 &&
- quaternion[1] >= 0
- ) {
- // this is a 2d rotation on the z-axis
- rotationDegrees = [
- 0,
- 0,
- MatrixMath.roundTo3Places(
- (Math.atan2(row[0][1], row[0][0]) * 180) / Math.PI,
- ),
- ];
- } else {
- rotationDegrees = MatrixMath.quaternionToDegreesXYZ(
- quaternion,
- matrix,
- row,
- );
- }
- // expose both base data and convenience names
- return {
- rotationDegrees,
- perspective,
- quaternion,
- scale,
- skew,
- translation,
- rotate: rotationDegrees[2],
- rotateX: rotationDegrees[0],
- rotateY: rotationDegrees[1],
- scaleX: scale[0],
- scaleY: scale[1],
- translateX: translation[0],
- translateY: translation[1],
- };
- },
- };
- module.exports = MatrixMath;
|