import { Vector3 } from './Vector3.js';
var _vec3_1 = new Vector3();
var _mat4_1 = new Matrix4();
var _x = new Vector3();
var _y = new Vector3();
var _z = new Vector3();
/**
* a 4x4 matrix class
* @constructor
* @memberof zen3d
*/
function Matrix4() {
this.elements = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
]);
}
Object.assign(Matrix4.prototype, /** @lends zen3d.Matrix4.prototype */{
/**
*
*/
identity: function() {
this.set(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
return this;
},
/**
*
*/
set: function(n11, n12, n13, n14,
n21, n22, n23, n24,
n31, n32, n33, n34,
n41, n42, n43, n44) {
var ele = this.elements;
ele[0] = n11;
ele[4] = n12;
ele[8] = n13;
ele[12] = n14;
ele[1] = n21;
ele[5] = n22;
ele[9] = n23;
ele[13] = n24;
ele[2] = n31;
ele[6] = n32;
ele[10] = n33;
ele[14] = n34;
ele[3] = n41;
ele[7] = n42;
ele[11] = n43;
ele[15] = n44;
return this;
},
/**
*
*/
copy: function(m) {
this.elements.set(m.elements);
return this;
},
/**
*
*/
makeTranslation: function(x, y, z) {
this.set(
1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1
);
return this;
},
/**
*
*/
multiply: function(m) {
return this.multiplyMatrices(this, m);
},
/**
*
*/
premultiply: function(m) {
return this.multiplyMatrices(m, this);
},
/**
*
*/
multiplyMatrices: function(a, b) {
var ae = a.elements;
var be = b.elements;
var te = this.elements;
var a11 = ae[0],
a12 = ae[4],
a13 = ae[8],
a14 = ae[12];
var a21 = ae[1],
a22 = ae[5],
a23 = ae[9],
a24 = ae[13];
var a31 = ae[2],
a32 = ae[6],
a33 = ae[10],
a34 = ae[14];
var a41 = ae[3],
a42 = ae[7],
a43 = ae[11],
a44 = ae[15];
var b11 = be[0],
b12 = be[4],
b13 = be[8],
b14 = be[12];
var b21 = be[1],
b22 = be[5],
b23 = be[9],
b24 = be[13];
var b31 = be[2],
b32 = be[6],
b33 = be[10],
b34 = be[14];
var b41 = be[3],
b42 = be[7],
b43 = be[11],
b44 = be[15];
te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
return this;
},
/**
*
*/
transpose: function() {
var te = this.elements;
var tmp;
tmp = te[1];
te[1] = te[4];
te[4] = tmp;
tmp = te[2];
te[2] = te[8];
te[8] = tmp;
tmp = te[6];
te[6] = te[9];
te[9] = tmp;
tmp = te[3];
te[3] = te[12];
te[12] = tmp;
tmp = te[7];
te[7] = te[13];
te[13] = tmp;
tmp = te[11];
te[11] = te[14];
te[14] = tmp;
return this;
},
/**
*
*/
inverse: function() {
return this.getInverse(this);
},
/**
*
*/
getInverse: function(m) {
// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
var te = this.elements,
me = m.elements,
n11 = me[0],
n21 = me[1],
n31 = me[2],
n41 = me[3],
n12 = me[4],
n22 = me[5],
n32 = me[6],
n42 = me[7],
n13 = me[8],
n23 = me[9],
n33 = me[10],
n43 = me[11],
n14 = me[12],
n24 = me[13],
n34 = me[14],
n44 = me[15],
t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
if (det === 0) {
console.warn("can't invert matrix, determinant is 0");
return this.identity();
}
var detInv = 1 / det;
te[0] = t11 * detInv;
te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv;
te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv;
te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv;
te[4] = t12 * detInv;
te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv;
te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv;
te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv;
te[8] = t13 * detInv;
te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv;
te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv;
te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv;
te[12] = t14 * detInv;
te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv;
te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv;
te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv;
return this;
},
/**
* Make transform from pos&scale&rotation(Quaternion).
* @method
*/
transform: function(pos, scale, rot) {
var rotMatrix = rot.toMatrix4(_mat4_1);
var rele = rotMatrix.elements;
var ele = this.elements;
ele[0] = rele[0] * scale.x;
ele[1] = rele[1] * scale.x;
ele[2] = rele[2] * scale.x;
ele[3] = 0;
ele[4] = rele[4] * scale.y;
ele[5] = rele[5] * scale.y;
ele[6] = rele[6] * scale.y;
ele[7] = 0;
ele[8] = rele[8] * scale.z;
ele[9] = rele[9] * scale.z;
ele[10] = rele[10] * scale.z;
ele[11] = 0;
ele[12] = pos.x;
ele[13] = pos.y;
ele[14] = pos.z;
ele[15] = 1;
return this;
},
/**
*
*/
makeRotationFromQuaternion: function(q) {
var te = this.elements;
var x = q.x,
y = q.y,
z = q.z,
w = q.w;
var x2 = x + x,
y2 = y + y,
z2 = z + z;
var xx = x * x2,
xy = x * y2,
xz = x * z2;
var yy = y * y2,
yz = y * z2,
zz = z * z2;
var wx = w * x2,
wy = w * y2,
wz = w * z2;
te[0] = 1 - (yy + zz);
te[4] = xy - wz;
te[8] = xz + wy;
te[1] = xy + wz;
te[5] = 1 - (xx + zz);
te[9] = yz - wx;
te[2] = xz - wy;
te[6] = yz + wx;
te[10] = 1 - (xx + yy);
// last column
te[3] = 0;
te[7] = 0;
te[11] = 0;
// bottom row
te[12] = 0;
te[13] = 0;
te[14] = 0;
te[15] = 1;
return this;
},
/**
* @method
*/
extractRotation: function(m) {
// this method does not support reflection matrices
var te = this.elements;
var me = m.elements;
var scaleX = 1 / _vec3_1.setFromMatrixColumn(m, 0).getLength();
var scaleY = 1 / _vec3_1.setFromMatrixColumn(m, 1).getLength();
var scaleZ = 1 / _vec3_1.setFromMatrixColumn(m, 2).getLength();
te[0] = me[0] * scaleX;
te[1] = me[1] * scaleX;
te[2] = me[2] * scaleX;
te[3] = 0;
te[4] = me[4] * scaleY;
te[5] = me[5] * scaleY;
te[6] = me[6] * scaleY;
te[7] = 0;
te[8] = me[8] * scaleZ;
te[9] = me[9] * scaleZ;
te[10] = me[10] * scaleZ;
te[11] = 0;
te[12] = 0;
te[13] = 0;
te[14] = 0;
te[15] = 1;
return this;
},
/**
* @method
*/
lookAtRH: function(eye, target, up) {
var te = this.elements;
_z.subVectors(eye, target);
if (_z.getLengthSquared() === 0) {
// eye and target are in the same position
_z.z = 1;
}
_z.normalize();
_x.crossVectors(up, _z);
if (_x.getLengthSquared() === 0) {
// up and z are parallel
if (Math.abs(up.z) === 1) {
_z.x += 0.0001;
} else {
_z.z += 0.0001;
}
_z.normalize();
_x.crossVectors(up, _z);
}
_x.normalize();
_y.crossVectors(_z, _x);
te[0] = _x.x; te[4] = _y.x; te[8] = _z.x;
te[1] = _x.y; te[5] = _y.y; te[9] = _z.y;
te[2] = _x.z; te[6] = _y.z; te[10] = _z.z;
return this;
},
/**
* @method
*/
decompose: function(position, quaternion, scale) {
var te = this.elements;
var sx = _vec3_1.set(te[0], te[1], te[2]).getLength();
var sy = _vec3_1.set(te[4], te[5], te[6]).getLength();
var sz = _vec3_1.set(te[8], te[9], te[10]).getLength();
// if determine is negative, we need to invert one scale
var det = this.determinant();
if (det < 0) {
sx = -sx;
}
position.x = te[12];
position.y = te[13];
position.z = te[14];
// scale the rotation part
_mat4_1.copy(this);
var invSX = 1 / sx;
var invSY = 1 / sy;
var invSZ = 1 / sz;
_mat4_1.elements[0] *= invSX;
_mat4_1.elements[1] *= invSX;
_mat4_1.elements[2] *= invSX;
_mat4_1.elements[4] *= invSY;
_mat4_1.elements[5] *= invSY;
_mat4_1.elements[6] *= invSY;
_mat4_1.elements[8] *= invSZ;
_mat4_1.elements[9] *= invSZ;
_mat4_1.elements[10] *= invSZ;
quaternion.setFromRotationMatrix(_mat4_1);
scale.x = sx;
scale.y = sy;
scale.z = sz;
return this;
},
/**
* @method
*/
determinant: function() {
var te = this.elements;
var n11 = te[0],
n12 = te[4],
n13 = te[8],
n14 = te[12];
var n21 = te[1],
n22 = te[5],
n23 = te[9],
n24 = te[13];
var n31 = te[2],
n32 = te[6],
n33 = te[10],
n34 = te[14];
var n41 = te[3],
n42 = te[7],
n43 = te[11],
n44 = te[15];
// TODO: make this more efficient
// ( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
return (
n41 * (+n14 * n23 * n32 -
n13 * n24 * n32 -
n14 * n22 * n33 +
n12 * n24 * n33 +
n13 * n22 * n34 -
n12 * n23 * n34
) +
n42 * (+n11 * n23 * n34 -
n11 * n24 * n33 +
n14 * n21 * n33 -
n13 * n21 * n34 +
n13 * n24 * n31 -
n14 * n23 * n31
) +
n43 * (+n11 * n24 * n32 -
n11 * n22 * n34 -
n14 * n21 * n32 +
n12 * n21 * n34 +
n14 * n22 * n31 -
n12 * n24 * n31
) +
n44 * (-n13 * n22 * n31 -
n11 * n23 * n32 +
n11 * n22 * n33 +
n13 * n21 * n32 -
n12 * n21 * n33 +
n12 * n23 * n31
)
);
},
/**
*
*/
fromArray: function(array, offset) {
if (offset === undefined) offset = 0;
for (var i = 0; i < 16; i++) {
this.elements[i] = array[i + offset];
}
return this;
},
/**
*
*/
getMaxScaleOnAxis: function() {
var te = this.elements;
var scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
var scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
var scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq));
},
/**
*
*/
toArray: function(array, offset) {
if (array === undefined) array = [];
if (offset === undefined) offset = 0;
var te = this.elements;
array[offset] = te[0];
array[offset + 1] = te[1];
array[offset + 2] = te[2];
array[offset + 3] = te[3];
array[offset + 4] = te[4];
array[offset + 5] = te[5];
array[offset + 6] = te[6];
array[offset + 7] = te[7];
array[offset + 8] = te[8];
array[offset + 9] = te[9];
array[offset + 10] = te[10];
array[offset + 11] = te[11];
array[offset + 12] = te[12];
array[offset + 13] = te[13];
array[offset + 14] = te[14];
array[offset + 15] = te[15];
return array;
}
});
export { Matrix4 };