@awayjs/core
Version:
AwayJS core classes
1,062 lines (1,061 loc) • 43.1 kB
JavaScript
import { ArgumentError } from '../errors/ArgumentError';
import { Box } from './Box';
import { MathConsts } from './MathConsts';
import { Orientation3D } from './Orientation3D';
import { Sphere } from './Sphere';
import { Vector3D } from './Vector3D';
var Matrix3D = /** @class */ (function () {
/**
* Creates a Matrix3D object.
*/
function Matrix3D(rawData) {
if (rawData === void 0) { rawData = null; }
if (rawData != null) {
this._rawData = rawData;
}
else {
this._rawData = new Float32Array(16);
this.identity();
}
}
Matrix3D.getAxisRotationMatrix = function (x, y, z, degrees, target) {
if (target === void 0) { target = null; }
if (target == null)
target = new Matrix3D();
var targetData = target._rawData;
var rad = degrees * MathConsts.DEGREES_TO_RADIANS;
var c = Math.cos(rad);
var s = Math.sin(rad);
var t = 1 - c;
var tmp1, tmp2;
targetData[0] = c + x * x * t;
targetData[5] = c + y * y * t;
targetData[10] = c + z * z * t;
tmp1 = x * y * t;
tmp2 = z * s;
targetData[1] = tmp1 + tmp2;
targetData[4] = tmp1 - tmp2;
tmp1 = x * z * t;
tmp2 = y * s;
targetData[8] = tmp1 + tmp2;
targetData[2] = tmp1 - tmp2;
tmp1 = y * z * t;
tmp2 = x * s;
targetData[9] = tmp1 - tmp2;
targetData[6] = tmp1 + tmp2;
targetData[3] = 0;
targetData[7] = 0;
targetData[11] = 0;
targetData[12] = 0;
targetData[13] = 0;
targetData[14] = 0;
targetData[15] = 1;
return target;
};
Matrix3D.getPointAtMatrix = function (pos, dir, up, target) {
if (target === void 0) { target = null; }
var upN;
if (target == null)
target = new Matrix3D();
var targetData = target._rawData;
var dirN = dir.clone();
dirN.normalize();
upN = up.clone();
upN.normalize();
var lftN = upN.crossProduct(dirN);
lftN.normalize();
if (lftN.length < 0.05) {
lftN.x = upN.y;
lftN.y = upN.x;
lftN.z = 0;
lftN.normalize();
}
upN = dirN.crossProduct(lftN);
targetData[0] = lftN.x;
targetData[1] = lftN.y;
targetData[2] = lftN.z;
targetData[3] = 0;
targetData[4] = upN.x;
targetData[5] = upN.y;
targetData[6] = upN.z;
targetData[7] = 0;
targetData[8] = dirN.x;
targetData[9] = dirN.y;
targetData[10] = dirN.z;
targetData[11] = 0;
targetData[12] = lftN.dotProduct(pos);
targetData[13] = upN.dotProduct(pos);
targetData[14] = dirN.dotProduct(pos);
targetData[15] = 1;
return target;
};
/**
* Fills the 3d matrix with values representing the transformation made by the given quaternion.
*
* @param quarternion The quarterion object to convert.
*/
Matrix3D.getQuaternionMatrix = function (quarternion, target) {
if (target === void 0) { target = null; }
if (target == null)
target = new Matrix3D();
var targetData = target._rawData;
var x = quarternion.x;
var y = quarternion.y;
var z = quarternion.z;
var w = quarternion.w;
var xx = x * x;
var xy = x * y;
var xz = x * z;
var xw = x * w;
var yy = y * y;
var yz = y * z;
var yw = y * w;
var zz = z * z;
var zw = z * w;
targetData[0] = 1 - 2 * (yy + zz);
targetData[1] = 2 * (xy + zw);
targetData[2] = 2 * (xz - yw);
targetData[4] = 2 * (xy - zw);
targetData[5] = 1 - 2 * (xx + zz);
targetData[6] = 2 * (yz + xw);
targetData[8] = 2 * (xz + yw);
targetData[9] = 2 * (yz - xw);
targetData[10] = 1 - 2 * (xx + yy);
targetData[3] = 0;
targetData[7] = 0;
targetData[11] = 0;
targetData[12] = 0;
targetData[13] = 0;
targetData[14] = 0;
targetData[15] = 1;
return target;
};
/**
* Returns a boolean value representing whether there is any difference between the two given 3d matrices.
*/
Matrix3D.compare = function (m1, m2) {
var r1 = m1._rawData;
var r2 = m2._rawData;
for (var i = 0; i < 16; ++i)
if (r1[i] != r2[i])
return false;
return true;
};
Object.defineProperty(Matrix3D.prototype, "determinant", {
/**
* [read-only] A number that determines whether a matrix is invertible.
*/
get: function () {
var raw = this._rawData;
return ((raw[0] * raw[5] - raw[4] * raw[1]) * (raw[10] * raw[15] - raw[14] * raw[11])
- (raw[0] * raw[9] - raw[8] * raw[1]) * (raw[6] * raw[15] - raw[14] * raw[7])
+ (raw[0] * raw[13] - raw[12] * raw[1]) * (raw[6] * raw[11] - raw[10] * raw[7])
+ (raw[4] * raw[9] - raw[8] * raw[5]) * (raw[2] * raw[15] - raw[14] * raw[3])
- (raw[4] * raw[13] - raw[12] * raw[5]) * (raw[2] * raw[11] - raw[10] * raw[3])
+ (raw[8] * raw[13] - raw[12] * raw[9]) * (raw[2] * raw[7] - raw[6] * raw[3]));
},
enumerable: false,
configurable: true
});
Object.defineProperty(Matrix3D.prototype, "position", {
/**
* A Vector3D object that holds the position, the 3D coordinate (x,y,z) of a display object within the
* transformation's frame of reference.
*/
get: function () {
if (!this._position)
this._position = new Vector3D(new Float32Array(this._rawData.buffer, 48, 4));
return this._position;
},
enumerable: false,
configurable: true
});
/**
* Appends the matrix by multiplying another Matrix3D object by the current Matrix3D object.
*/
Matrix3D.prototype.append = function (lhs) {
var raw = this._rawData;
var rawLhs = lhs._rawData;
var m111 = raw[0];
var m112 = raw[1];
var m113 = raw[2];
var m114 = raw[3];
var m121 = raw[4];
var m122 = raw[5];
var m123 = raw[6];
var m124 = raw[7];
var m131 = raw[8];
var m132 = raw[9];
var m133 = raw[10];
var m134 = raw[11];
var m141 = raw[12];
var m142 = raw[13];
var m143 = raw[14];
var m144 = raw[15];
var m211 = rawLhs[0];
var m212 = rawLhs[1];
var m213 = rawLhs[2];
var m214 = rawLhs[3];
var m221 = rawLhs[4];
var m222 = rawLhs[5];
var m223 = rawLhs[6];
var m224 = rawLhs[7];
var m231 = rawLhs[8];
var m232 = rawLhs[9];
var m233 = rawLhs[10];
var m234 = rawLhs[11];
var m241 = rawLhs[12];
var m242 = rawLhs[13];
var m243 = rawLhs[14];
var m244 = rawLhs[15];
raw[0] = m111 * m211 + m112 * m221 + m113 * m231 + m114 * m241;
raw[1] = m111 * m212 + m112 * m222 + m113 * m232 + m114 * m242;
raw[2] = m111 * m213 + m112 * m223 + m113 * m233 + m114 * m243;
raw[3] = m111 * m214 + m112 * m224 + m113 * m234 + m114 * m244;
raw[4] = m121 * m211 + m122 * m221 + m123 * m231 + m124 * m241;
raw[5] = m121 * m212 + m122 * m222 + m123 * m232 + m124 * m242;
raw[6] = m121 * m213 + m122 * m223 + m123 * m233 + m124 * m243;
raw[7] = m121 * m214 + m122 * m224 + m123 * m234 + m124 * m244;
raw[8] = m131 * m211 + m132 * m221 + m133 * m231 + m134 * m241;
raw[9] = m131 * m212 + m132 * m222 + m133 * m232 + m134 * m242;
raw[10] = m131 * m213 + m132 * m223 + m133 * m233 + m134 * m243;
raw[11] = m131 * m214 + m132 * m224 + m133 * m234 + m134 * m244;
raw[12] = m141 * m211 + m142 * m221 + m143 * m231 + m144 * m241;
raw[13] = m141 * m212 + m142 * m222 + m143 * m232 + m144 * m242;
raw[14] = m141 * m213 + m142 * m223 + m143 * m233 + m144 * m243;
raw[15] = m141 * m214 + m142 * m224 + m143 * m234 + m144 * m244;
};
/**
* Appends an incremental rotation to a Matrix3D object.
*/
Matrix3D.prototype.appendRotation = function (degrees, axis) {
this.append(Matrix3D.getAxisRotationMatrix(axis.x, axis.y, axis.z, degrees, Matrix3D._tempMatrix));
};
/**
* Appends an incremental skew change along the x, y, and z axes to a Matrix3D object.
*/
Matrix3D.prototype.appendSkew = function (xSkew, ySkew, zSkew) {
if (xSkew == 0 && ySkew == 0 && zSkew == 0)
return;
var rawData = Matrix3D._tempMatrix._rawData;
rawData[0] = 1;
rawData[1] = 0;
rawData[2] = 0;
rawData[3] = 0;
rawData[4] = xSkew;
rawData[5] = 1;
rawData[6] = 0;
rawData[7] = 0;
rawData[8] = ySkew;
rawData[9] = zSkew;
rawData[10] = 1;
rawData[11] = 0;
rawData[12] = 0;
rawData[13] = 0;
rawData[14] = 0;
rawData[15] = 1;
this.append(Matrix3D._tempMatrix);
};
/**
* Appends an incremental scale change along the x, y, and z axes to a Matrix3D object.
*/
Matrix3D.prototype.appendScale = function (xScale, yScale, zScale) {
if (xScale == 1 && yScale == 1 && zScale == 1)
return;
var rawData = Matrix3D._tempMatrix._rawData;
rawData[0] = xScale;
rawData[1] = 0;
rawData[2] = 0;
rawData[3] = 0;
rawData[4] = 0;
rawData[5] = yScale;
rawData[6] = 0;
rawData[7] = 0;
rawData[8] = 0;
rawData[9] = 0;
rawData[10] = zScale;
rawData[11] = 0;
rawData[12] = 0;
rawData[13] = 0;
rawData[14] = 0;
rawData[15] = 1;
this.append(Matrix3D._tempMatrix);
};
/**
*Appends an incremental translation, a repositioning along the x, y, and z axes, to a Matrix3D object.
*/
Matrix3D.prototype.appendTranslation = function (x, y, z) {
var raw = this._rawData;
var m41 = raw[3], m42 = raw[7], m43 = raw[11], m44 = raw[15];
raw[0] += x * m41;
raw[1] += y * m41;
raw[2] += z * m41;
raw[4] += x * m42;
raw[5] += y * m42;
raw[6] += z * m42;
raw[8] += x * m43;
raw[9] += y * m43;
raw[10] += z * m43;
raw[12] += x * m44;
raw[13] += y * m44;
raw[14] += z * m44;
};
/**
* Returns a new Matrix3D object that is an exact copy of the current Matrix3D object.
*/
Matrix3D.prototype.clone = function () {
var matrix3D = new Matrix3D();
matrix3D.copyFrom(this);
return matrix3D;
};
/**
* Copies a Vector3D object into specific column of the calling Matrix3D object.
*/
Matrix3D.prototype.copyColumnFrom = function (column, vector3D) {
if (column < 0 || column > 3)
throw new ArgumentError('ArgumentError, Column ' + column + ' out of bounds [0, ..., 3]');
var targetData = this._rawData;
var vectorData = vector3D._rawData;
column *= 4;
targetData[column] = vectorData[0];
targetData[column + 1] = vectorData[1];
targetData[column + 2] = vectorData[2];
targetData[column + 3] = vectorData[3];
};
/**
* Copies specific column of the calling Matrix3D object into the Vector3D object.
*/
Matrix3D.prototype.copyColumnTo = function (column, vector3D, negate) {
if (negate === void 0) { negate = false; }
if (column < 0 || column > 3)
throw new ArgumentError('ArgumentError, Column ' + column + ' out of bounds [0, ..., 3]');
column *= 4;
var sourceData = this._rawData;
var vectorData = vector3D._rawData;
if (negate) {
vectorData[0] = -sourceData[column];
vectorData[1] = -sourceData[column + 1];
vectorData[2] = -sourceData[column + 2];
vectorData[3] = -sourceData[column + 3];
}
else {
vectorData[0] = sourceData[column];
vectorData[1] = sourceData[column + 1];
vectorData[2] = sourceData[column + 2];
vectorData[3] = sourceData[column + 3];
}
};
/**
* Copies all of the matrix data from the source Matrix3D object into the calling Matrix3D object.
*/
Matrix3D.prototype.copyFrom = function (source, transpose) {
if (transpose === void 0) { transpose = false; }
var sourceData = source._rawData, targetData = this._rawData;
if (transpose) {
targetData[0] = sourceData[0];
targetData[1] = sourceData[4];
targetData[2] = sourceData[8];
targetData[3] = sourceData[12];
targetData[4] = sourceData[1];
targetData[5] = sourceData[5];
targetData[6] = sourceData[9];
targetData[7] = sourceData[13];
targetData[8] = sourceData[2];
targetData[9] = sourceData[6];
targetData[10] = sourceData[10];
targetData[11] = sourceData[14];
targetData[12] = sourceData[3];
targetData[13] = sourceData[7];
targetData[14] = sourceData[11];
targetData[15] = sourceData[15];
}
else {
targetData.set(sourceData);
}
};
/**
* Copies this Matrix3D object into a destination Matrix3D object.
*/
Matrix3D.prototype.copyTo = function (target, transpose) {
if (transpose === void 0) { transpose = false; }
target.copyFrom(this, transpose);
};
Matrix3D.prototype.copyRawDataFrom = function (sourceData, offset, transpose) {
if (offset === void 0) { offset = 0; }
if (transpose === void 0) { transpose = false; }
var targetData = this._rawData;
if (transpose) {
targetData[0] = sourceData[offset + 0];
targetData[1] = sourceData[offset + 4];
targetData[2] = sourceData[offset + 8];
targetData[3] = sourceData[offset + 12];
targetData[4] = sourceData[offset + 1];
targetData[5] = sourceData[offset + 5];
targetData[6] = sourceData[offset + 9];
targetData[7] = sourceData[offset + 13];
targetData[8] = sourceData[offset + 2];
targetData[9] = sourceData[offset + 6];
targetData[10] = sourceData[offset + 10];
targetData[11] = sourceData[offset + 14];
targetData[12] = sourceData[offset + 3];
targetData[13] = sourceData[offset + 7];
targetData[14] = sourceData[offset + 11];
targetData[15] = sourceData[offset + 15];
}
else {
targetData.set(sourceData.subarray(offset, offset + 16));
}
};
Matrix3D.prototype.copyRawDataTo = function (targetData, offset, transpose) {
if (offset === void 0) { offset = 0; }
if (transpose === void 0) { transpose = false; }
var sourceData = this._rawData;
if (transpose) {
targetData[offset] = sourceData[0];
targetData[offset + 1] = sourceData[4];
targetData[offset + 2] = sourceData[8];
targetData[offset + 3] = sourceData[12];
targetData[offset + 4] = sourceData[1];
targetData[offset + 5] = sourceData[5];
targetData[offset + 6] = sourceData[9];
targetData[offset + 7] = sourceData[13];
targetData[offset + 8] = sourceData[2];
targetData[offset + 9] = sourceData[6];
targetData[offset + 10] = sourceData[10];
targetData[offset + 11] = sourceData[14];
targetData[offset + 12] = sourceData[3];
targetData[offset + 13] = sourceData[7];
targetData[offset + 14] = sourceData[11];
targetData[offset + 15] = sourceData[15];
}
else {
targetData.set(sourceData, offset);
}
};
/**
* Copies a Vector3D object into specific row of the calling Matrix3D object.
*/
Matrix3D.prototype.copyRowFrom = function (row, vector3D) {
if (row < 0 || row > 3)
throw new ArgumentError('ArgumentError, Row ' + row + ' out of bounds [0, ..., 3]');
var targetData = this._rawData;
var vectorData = vector3D._rawData;
targetData[row] = vectorData[0];
targetData[row + 4] = vectorData[1];
targetData[row + 8] = vectorData[2];
targetData[row + 12] = vectorData[3];
};
/**
* Copies specific row of the calling Matrix3D object into the Vector3D object.
*/
Matrix3D.prototype.copyRowTo = function (row, vector3D, negate) {
if (negate === void 0) { negate = false; }
if (row < 0 || row > 3)
throw new ArgumentError('ArgumentError, Row ' + row + ' out of bounds [0, ..., 3]');
var sourceData = this._rawData;
var vectorData = vector3D._rawData;
if (negate) {
vectorData[0] = -sourceData[row];
vectorData[1] = -sourceData[row + 4];
vectorData[2] = -sourceData[row + 8];
vectorData[3] = -sourceData[row + 12];
}
else {
vectorData[0] = sourceData[row];
vectorData[1] = sourceData[row + 4];
vectorData[2] = sourceData[row + 8];
vectorData[3] = sourceData[row + 12];
}
};
/**
* Returns the transformation matrix's translation, rotation, and scale
* settings as a Vector of three Vector3D objects.
*/
Matrix3D.prototype.decompose = function (orientationStyle) {
if (orientationStyle === void 0) { orientationStyle = 'eulerAngles'; }
if (this._components == null)
this._components = [new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D()];
/// use TMP for avoid realocation
var colX = Matrix3D.COL_X;
colX.setTo(this._rawData[0], this._rawData[1], this._rawData[2]);
var colY = Matrix3D.COL_Y;
colY.setTo(this._rawData[4], this._rawData[5], this._rawData[6]);
var colZ = Matrix3D.COL_Z;
colZ.setTo(this._rawData[8], this._rawData[9], this._rawData[10]);
var skew = this._components[3];
var scale = this._components[2];
//compute X scale factor and normalise colX
scale.x = colX.length;
if (scale.x)
colX.scaleBy(1 / scale.x);
//compute XY shear factor and make colY orthogonal to colX
skew.x = colX.dotProduct(colY);
Vector3D.combine(colY, colX, 1, -skew.x, colY);
//compute Y scale factor and normalise colY
scale.y = colY.length;
if (scale.y) {
colY.scaleBy(1 / scale.y);
skew.x /= scale.y;
}
//compute XZ and YZ shears and make colZ orthogonal to colX and colY
skew.y = colX.dotProduct(colZ);
Vector3D.combine(colZ, colX, 1, -skew.y, colZ);
skew.z = colY.dotProduct(colZ);
Vector3D.combine(colZ, colY, 1, -skew.z, colZ);
//compute Z scale and normalise colZ
scale.z = colZ.length;
if (scale.z) {
colZ.scaleBy(1 / scale.z);
skew.y /= scale.z;
skew.z /= scale.z;
}
//at this point, the matrix (in cols) is orthonormal
//check for a coordinate system flip. If the determinant is -1, negate the z scaling factor
if (colX.dotProduct(colY.crossProduct(colZ)) < 0) {
scale.z = -scale.z;
colZ.x = -colZ.x;
colZ.y = -colZ.y;
colZ.z = -colZ.z;
}
var rot = this._components[1];
switch (orientationStyle) {
case Orientation3D.AXIS_ANGLE: {
rot.w = Math.acos((colX.x + colY.y + colZ.z - 1) / 2);
var len = Math.sqrt((colY.z - colZ.y) * (colY.z - colZ.y) +
(colZ.x - colX.z) * (colZ.x - colX.z) +
(colX.y - colY.x) * (colX.y - colY.x));
rot.x = len ? (colY.z - colZ.y) / len : 0;
rot.y = len ? (colZ.x - colX.z) / len : 0;
rot.z = len ? (colX.y - colY.x) / len : 0;
break;
}
case Orientation3D.QUATERNION: {
var tr = colX.x + colY.y + colZ.z;
if (tr > 0) {
rot.w = Math.sqrt(1 + tr) / 2;
rot.x = (colY.z - colZ.y) / (4 * rot.w);
rot.y = (colZ.x - colX.z) / (4 * rot.w);
rot.z = (colX.y - colY.x) / (4 * rot.w);
}
else if ((colX.x > colY.y) && (colX.x > colZ.z)) {
rot.x = Math.sqrt(1 + colX.x - colY.y - colZ.z) / 2;
rot.w = (colY.z - colZ.y) / (4 * rot.x);
rot.y = (colX.y + colY.x) / (4 * rot.x);
rot.z = (colZ.x + colX.z) / (4 * rot.x);
}
else if (colY.y > colZ.z) {
rot.y = Math.sqrt(1 + colY.y - colX.x - colZ.z) / 2;
rot.x = (colX.y + colY.x) / (4 * rot.y);
rot.w = (colZ.x - colX.z) / (4 * rot.y);
rot.z = (colY.z + colZ.y) / (4 * rot.y);
}
else {
rot.z = Math.sqrt(1 + colZ.z - colX.x - colY.y) / 2;
rot.x = (colZ.x + colX.z) / (4 * rot.z);
rot.y = (colY.z + colZ.y) / (4 * rot.z);
rot.w = (colX.y - colY.x) / (4 * rot.z);
}
break;
}
case Orientation3D.EULER_ANGLES:
rot.y = Math.asin(-colX.z) * MathConsts.RADIANS_TO_DEGREES;
//var cos:number = Math.cos(rot.y);
if (colX.z != 1 && colX.z != -1) {
rot.x = Math.atan2(colY.z, colZ.z) * MathConsts.RADIANS_TO_DEGREES;
rot.z = Math.atan2(colX.y, colX.x) * MathConsts.RADIANS_TO_DEGREES;
}
else {
rot.z = 0;
rot.x = Math.atan2(colY.x, colY.y) * MathConsts.RADIANS_TO_DEGREES;
}
break;
}
this._components[0].copyFrom(this.position);
return this._components;
};
/**
* Uses the transformation matrix without its translation elements to transform a Vector3D object from one space
* coordinate to another.
*/
Matrix3D.prototype.deltaTransformVector = function (v, t) {
if (t === void 0) { t = null; }
var x = v.x;
var y = v.y;
var z = v.z;
if (!t)
t = new Vector3D();
var raw = this._rawData;
var rawT = t._rawData;
rawT[0] = x * raw[0] + y * raw[4] + z * raw[8];
rawT[1] = x * raw[1] + y * raw[5] + z * raw[9];
rawT[2] = x * raw[2] + y * raw[6] + z * raw[10];
rawT[3] = x * raw[3] + y * raw[7] + z * raw[11];
return t;
};
Matrix3D.prototype.deltaTransformVectors = function (vin, vout) {
var raw = this._rawData;
var a = raw[0];
var e = raw[1];
var i = raw[2];
var b = raw[4];
var f = raw[5];
var j = raw[6];
var c = raw[8];
var g = raw[9];
var k = raw[10];
var outIndex = 0;
var length = vin.length;
for (var index = 0; index < length; index += 3) {
var x = vin[index];
var y = vin[index + 1];
var z = vin[index + 2];
vout[outIndex++] = a * x + b * y + c * z;
vout[outIndex++] = e * x + f * y + g * z;
vout[outIndex++] = i * x + j * y + k * z;
}
};
/**
* Converts the current matrix to an identity or unit matrix.
*/
Matrix3D.prototype.identity = function () {
this._rawData.set(Matrix3D._identityData);
};
/**
* Inverts the current matrix.
*/
Matrix3D.prototype.invert = function () {
var d = this.determinant;
var invertable = Math.abs(d) > 0.00000000001;
var raw = this._rawData;
if (invertable) {
d = 1 / d;
var m11 = raw[0];
var m12 = raw[1];
var m13 = raw[2];
var m14 = raw[3];
var m21 = raw[4];
var m22 = raw[5];
var m23 = raw[6];
var m24 = raw[7];
var m31 = raw[8];
var m32 = raw[9];
var m33 = raw[10];
var m34 = raw[11];
var m41 = raw[12];
var m42 = raw[13];
var m43 = raw[14];
var m44 = raw[15];
/* eslint-disable */
raw[0] = d * (m22 * (m33 * m44 - m43 * m34) - m32 * (m23 * m44 - m43 * m24) + m42 * (m23 * m34 - m33 * m24));
raw[1] = -d * (m12 * (m33 * m44 - m43 * m34) - m32 * (m13 * m44 - m43 * m14) + m42 * (m13 * m34 - m33 * m14));
raw[2] = d * (m12 * (m23 * m44 - m43 * m24) - m22 * (m13 * m44 - m43 * m14) + m42 * (m13 * m24 - m23 * m14));
raw[3] = -d * (m12 * (m23 * m34 - m33 * m24) - m22 * (m13 * m34 - m33 * m14) + m32 * (m13 * m24 - m23 * m14));
raw[4] = -d * (m21 * (m33 * m44 - m43 * m34) - m31 * (m23 * m44 - m43 * m24) + m41 * (m23 * m34 - m33 * m24));
raw[5] = d * (m11 * (m33 * m44 - m43 * m34) - m31 * (m13 * m44 - m43 * m14) + m41 * (m13 * m34 - m33 * m14));
raw[6] = -d * (m11 * (m23 * m44 - m43 * m24) - m21 * (m13 * m44 - m43 * m14) + m41 * (m13 * m24 - m23 * m14));
raw[7] = d * (m11 * (m23 * m34 - m33 * m24) - m21 * (m13 * m34 - m33 * m14) + m31 * (m13 * m24 - m23 * m14));
raw[8] = d * (m21 * (m32 * m44 - m42 * m34) - m31 * (m22 * m44 - m42 * m24) + m41 * (m22 * m34 - m32 * m24));
raw[9] = -d * (m11 * (m32 * m44 - m42 * m34) - m31 * (m12 * m44 - m42 * m14) + m41 * (m12 * m34 - m32 * m14));
raw[10] = d * (m11 * (m22 * m44 - m42 * m24) - m21 * (m12 * m44 - m42 * m14) + m41 * (m12 * m24 - m22 * m14));
raw[11] = -d * (m11 * (m22 * m34 - m32 * m24) - m21 * (m12 * m34 - m32 * m14) + m31 * (m12 * m24 - m22 * m14));
raw[12] = -d * (m21 * (m32 * m43 - m42 * m33) - m31 * (m22 * m43 - m42 * m23) + m41 * (m22 * m33 - m32 * m23));
raw[13] = d * (m11 * (m32 * m43 - m42 * m33) - m31 * (m12 * m43 - m42 * m13) + m41 * (m12 * m33 - m32 * m13));
raw[14] = -d * (m11 * (m22 * m43 - m42 * m23) - m21 * (m12 * m43 - m42 * m13) + m41 * (m12 * m23 - m22 * m13));
raw[15] = d * (m11 * (m22 * m33 - m32 * m23) - m21 * (m12 * m33 - m32 * m13) + m31 * (m12 * m23 - m22 * m13));
/* eslint-enable */
}
return invertable;
};
Matrix3D.prototype.isIdentity = function () {
var raw = this._rawData;
if (raw[0] == 1 &&
raw[1] == 0 &&
raw[2] == 0 &&
raw[3] == 0 &&
raw[4] == 0 &&
raw[5] == 1 &&
raw[6] == 0 &&
raw[7] == 0 &&
raw[8] == 0 &&
raw[9] == 0 &&
raw[10] == 1 &&
raw[11] == 0 &&
raw[12] == 0 &&
raw[13] == 0 &&
raw[14] == 0 &&
raw[15] == 1)
return true;
return false;
};
/**
* Prepends a matrix by multiplying the current Matrix3D object by another Matrix3D object.
*/
Matrix3D.prototype.prepend = function (rhs) {
var raw = this._rawData;
var rawRhs = rhs._rawData;
var m111 = rawRhs[0];
var m112 = rawRhs[1];
var m113 = rawRhs[2];
var m114 = rawRhs[3];
var m121 = rawRhs[4];
var m122 = rawRhs[5];
var m123 = rawRhs[6];
var m124 = rawRhs[7];
var m131 = rawRhs[8];
var m132 = rawRhs[9];
var m133 = rawRhs[10];
var m134 = rawRhs[11];
var m141 = rawRhs[12];
var m142 = rawRhs[13];
var m143 = rawRhs[14];
var m144 = rawRhs[15];
var m211 = raw[0];
var m212 = raw[1];
var m213 = raw[2];
var m214 = raw[3];
var m221 = raw[4];
var m222 = raw[5];
var m223 = raw[6];
var m224 = raw[7];
var m231 = raw[8];
var m232 = raw[9];
var m233 = raw[10];
var m234 = raw[11];
var m241 = raw[12];
var m242 = raw[13];
var m243 = raw[14];
var m244 = raw[15];
raw[0] = m111 * m211 + m112 * m221 + m113 * m231 + m114 * m241;
raw[1] = m111 * m212 + m112 * m222 + m113 * m232 + m114 * m242;
raw[2] = m111 * m213 + m112 * m223 + m113 * m233 + m114 * m243;
raw[3] = m111 * m214 + m112 * m224 + m113 * m234 + m114 * m244;
raw[4] = m121 * m211 + m122 * m221 + m123 * m231 + m124 * m241;
raw[5] = m121 * m212 + m122 * m222 + m123 * m232 + m124 * m242;
raw[6] = m121 * m213 + m122 * m223 + m123 * m233 + m124 * m243;
raw[7] = m121 * m214 + m122 * m224 + m123 * m234 + m124 * m244;
raw[8] = m131 * m211 + m132 * m221 + m133 * m231 + m134 * m241;
raw[9] = m131 * m212 + m132 * m222 + m133 * m232 + m134 * m242;
raw[10] = m131 * m213 + m132 * m223 + m133 * m233 + m134 * m243;
raw[11] = m131 * m214 + m132 * m224 + m133 * m234 + m134 * m244;
raw[12] = m141 * m211 + m142 * m221 + m143 * m231 + m144 * m241;
raw[13] = m141 * m212 + m142 * m222 + m143 * m232 + m144 * m242;
raw[14] = m141 * m213 + m142 * m223 + m143 * m233 + m144 * m243;
raw[15] = m141 * m214 + m142 * m224 + m143 * m234 + m144 * m244;
};
/**
* Prepends an incremental rotation to a Matrix3D object.
*/
Matrix3D.prototype.prependRotation = function (degrees, axis) {
this.prepend(Matrix3D.getAxisRotationMatrix(axis.x, axis.y, axis.z, degrees, Matrix3D._tempMatrix));
};
/**
* Prepends an incremental scale change along the x, y, and z axes to a Matrix3D object.
*/
Matrix3D.prototype.prependScale = function (xScale, yScale, zScale) {
if (xScale == 1 && yScale == 1 && zScale == 1)
return;
var rawData = Matrix3D._tempMatrix._rawData;
rawData[0] = xScale;
rawData[1] = 0;
rawData[2] = 0;
rawData[3] = 0;
rawData[4] = 0;
rawData[5] = yScale;
rawData[6] = 0;
rawData[7] = 0;
rawData[8] = 0;
rawData[9] = 0;
rawData[10] = zScale;
rawData[11] = 0;
rawData[12] = 0;
rawData[13] = 0;
rawData[14] = 0;
rawData[15] = 1;
this.prepend(Matrix3D._tempMatrix);
};
/**
* Prepends an incremental translation, a repositioning along the x, y, and z axes, to a Matrix3D object.
*/
Matrix3D.prototype.prependTranslation = function (x, y, z) {
var rawData = Matrix3D._tempMatrix._rawData;
rawData[0] = 1;
rawData[1] = 0;
rawData[2] = 0;
rawData[3] = 0;
rawData[4] = 0;
rawData[5] = 1;
rawData[6] = 0;
rawData[7] = 0;
rawData[8] = 0;
rawData[9] = 0;
rawData[10] = 1;
rawData[11] = 0;
rawData[12] = x;
rawData[13] = y;
rawData[14] = z;
rawData[15] = 1;
this.prepend(Matrix3D._tempMatrix);
};
// TODO orientationStyle
/**
* Sets the transformation matrix's translation, rotation, and scale settings.
*/
Matrix3D.prototype.recompose = function (components) {
//reset matrix ready for recompose
this.identity();
var skew = components[3];
if (skew && (skew.x != 0 || skew.y != 0 || skew.z != 0))
this.appendSkew(skew.x, skew.y, skew.z);
var scale = components[2];
if (scale && (scale.x != 1 || scale.y != 1 || scale.z != 1))
this.appendScale(scale.x, scale.y, scale.z);
var sin;
var cos;
var rawData = Matrix3D._tempMatrix._rawData;
rawData[12] = 0;
rawData[13] = 0;
rawData[14] = 0;
rawData[15] = 0;
var rotation = components[1];
if (rotation) {
var angle = -rotation.x * MathConsts.DEGREES_TO_RADIANS;
if (angle != 0) {
sin = Math.sin(angle);
cos = Math.cos(angle);
rawData[0] = 1;
rawData[1] = 0;
rawData[2] = 0;
rawData[3] = 0;
rawData[4] = 0;
rawData[5] = cos;
rawData[6] = -sin;
rawData[7] = 0;
rawData[8] = 0;
rawData[9] = sin;
rawData[10] = cos;
rawData[11] = 0;
this.append(Matrix3D._tempMatrix);
}
angle = -rotation.y * MathConsts.DEGREES_TO_RADIANS;
if (angle != 0) {
sin = Math.sin(angle);
cos = Math.cos(angle);
rawData[0] = cos;
rawData[1] = 0;
rawData[2] = sin;
rawData[3] = 0;
rawData[4] = 0;
rawData[5] = 1;
rawData[6] = 0;
rawData[7] = 0;
rawData[8] = -sin;
rawData[9] = 0;
rawData[10] = cos;
rawData[11] = 0;
this.append(Matrix3D._tempMatrix);
}
angle = -rotation.z * MathConsts.DEGREES_TO_RADIANS;
if (angle != 0) {
sin = Math.sin(angle);
cos = Math.cos(angle);
rawData[0] = cos;
rawData[1] = -sin;
rawData[2] = 0;
rawData[3] = 0;
rawData[4] = sin;
rawData[5] = cos;
rawData[6] = 0;
rawData[7] = 0;
rawData[8] = 0;
rawData[9] = 0;
rawData[10] = 1;
rawData[11] = 0;
this.append(Matrix3D._tempMatrix);
}
}
var pos = components[0];
if (pos) {
this._rawData[12] = pos.x;
this._rawData[13] = pos.y;
this._rawData[14] = pos.z;
this._rawData[15] = 1;
}
};
Matrix3D.prototype.reflect = function (plane) {
var a = plane.a, b = plane.b, c = plane.c, d = plane.d;
var ab2 = -2 * a * b;
var ac2 = -2 * a * c;
var bc2 = -2 * b * c;
// reflection matrix
var rawData = this._rawData;
rawData[0] = 1 - 2 * a * a;
rawData[4] = ab2;
rawData[8] = ac2;
rawData[12] = -2 * a * d;
rawData[1] = ab2;
rawData[5] = 1 - 2 * b * b;
rawData[9] = bc2;
rawData[13] = -2 * b * d;
rawData[2] = ac2;
rawData[6] = bc2;
rawData[10] = 1 - 2 * c * c;
rawData[14] = -2 * c * d;
rawData[3] = 0;
rawData[7] = 0;
rawData[11] = 0;
rawData[15] = 1;
};
Matrix3D.prototype.transformBox = function (box, target) {
if (target === void 0) { target = null; }
if (box == null)
throw new ArgumentError('ArgumentError, box cannot be null');
if (!target)
target = new Box();
var hx = box.width / 2;
var hy = box.height / 2;
var hz = box.depth / 2;
var cx = box.x + hx;
var cy = box.y + hy;
var cz = box.z + hz;
var m11 = this._rawData[0], m12 = this._rawData[4], m13 = this._rawData[8], m14 = this._rawData[12];
var m21 = this._rawData[1], m22 = this._rawData[5], m23 = this._rawData[9], m24 = this._rawData[13];
var m31 = this._rawData[2], m32 = this._rawData[6], m33 = this._rawData[10], m34 = this._rawData[14];
var centerX = cx * m11 + cy * m12 + cz * m13 + m14;
var centerY = cx * m21 + cy * m22 + cz * m23 + m24;
var centerZ = cx * m31 + cy * m32 + cz * m33 + m34;
var halfExtentsX = Math.max(Math.abs(hx * m11 + hy * m12 + hz * m13), Math.abs(-hx * m11 + hy * m12 + hz * m13), Math.abs(hx * m11 - hy * m12 + hz * m13), Math.abs(hx * m11 + hy * m12 - hz * m13));
var halfExtentsY = Math.max(Math.abs(hx * m21 + hy * m22 + hz * m23), Math.abs(-hx * m21 + hy * m22 + hz * m23), Math.abs(hx * m21 - hy * m22 + hz * m23), Math.abs(hx * m21 + hy * m22 - hz * m23));
var halfExtentsZ = Math.max(Math.abs(hx * m31 + hy * m32 + hz * m33), Math.abs(-hx * m31 + hy * m32 + hz * m33), Math.abs(hx * m31 - hy * m32 + hz * m33), Math.abs(hx * m31 + hy * m32 - hz * m33));
target.width = halfExtentsX * 2;
target.height = halfExtentsY * 2;
target.depth = halfExtentsZ * 2;
target.x = centerX - halfExtentsX;
target.y = centerY - halfExtentsY;
target.z = centerZ - halfExtentsZ;
return target;
};
Matrix3D.prototype.transformSphere = function (sphere, target) {
if (target === void 0) { target = null; }
//TODO: use a better solution than this
if (sphere == null)
throw new ArgumentError('ArgumentError, sphere cannot be null');
var box = new Box(sphere.x - sphere.radius, // x
sphere.y - sphere.radius, // y
sphere.z - sphere.radius, // z
sphere.radius * 2, // w
sphere.radius * 2, // h
sphere.radius * 2); // d
this.transformBox(box, box);
if (!target)
target = new Sphere();
target.x = box.x + box.width / 2;
target.y = box.y + box.height / 2;
target.z = box.z + box.depth / 2;
target.radius = Math.max(box.width, box.height, box.depth);
return target;
};
Matrix3D.prototype.transformVector = function (vector, target, ignoreW) {
if (target === void 0) { target = null; }
if (ignoreW === void 0) { ignoreW = false; }
if (vector == null)
throw new ArgumentError('ArgumentError, vector cannot be null');
var x = vector.x;
var y = vector.y;
var z = vector.z;
var w = ignoreW ? 1 : vector.w;
if (!target)
target = new Vector3D();
var raw = this._rawData;
var rawTarget = target._rawData;
rawTarget[0] = x * raw[0] + y * raw[4] + z * raw[8] + w * raw[12];
rawTarget[1] = x * raw[1] + y * raw[5] + z * raw[9] + w * raw[13];
rawTarget[2] = x * raw[2] + y * raw[6] + z * raw[10] + w * raw[14];
rawTarget[3] = x * raw[3] + y * raw[7] + z * raw[11] + w * raw[15];
return target;
};
/**
* Uses the transformation matrix to transform a Vector of Numbers from one coordinate space to another.
*/
Matrix3D.prototype.transformVectors = function (vin, vout) {
var i = 0;
var x = 0, y = 0, z = 0;
var raw = this._rawData;
while (i + 3 <= vin.length) {
x = vin[i];
y = vin[i + 1];
z = vin[i + 2];
vout[i] = x * raw[0] + y * raw[4] + z * raw[8] + raw[12];
vout[i + 1] = x * raw[1] + y * raw[5] + z * raw[9] + raw[13];
vout[i + 2] = x * raw[2] + y * raw[6] + z * raw[10] + raw[14];
i += 3;
}
};
/**
* Converts the current Matrix3D object to a matrix where the rows and columns are swapped.
*/
Matrix3D.prototype.transpose = function () {
var raw = this._rawData;
var rawTemp = Matrix3D._tempMatrix._rawData;
this.copyRawDataTo(rawTemp, 0, true);
raw[1] = rawTemp[1];
raw[2] = rawTemp[2];
raw[3] = rawTemp[3];
raw[4] = rawTemp[4];
raw[6] = rawTemp[6];
raw[7] = rawTemp[7];
raw[8] = rawTemp[8];
raw[9] = rawTemp[9];
raw[11] = rawTemp[11];
raw[12] = rawTemp[12];
raw[13] = rawTemp[13];
raw[14] = rawTemp[14];
};
Matrix3D.prototype.toFixed = function (decimalPlace) {
var magnitude = Math.pow(10, decimalPlace);
return 'matrix3d(' + Math.round(this._rawData[0] * magnitude) / magnitude +
',' + Math.round(this._rawData[1] * magnitude) / magnitude +
',' + Math.round(this._rawData[2] * magnitude) / magnitude +
',' + Math.round(this._rawData[3] * magnitude) / magnitude +
',' + Math.round(this._rawData[4] * magnitude) / magnitude +
',' + Math.round(this._rawData[5] * magnitude) / magnitude +
',' + Math.round(this._rawData[6] * magnitude) / magnitude +
',' + Math.round(this._rawData[7] * magnitude) / magnitude +
',' + Math.round(this._rawData[8] * magnitude) / magnitude +
',' + Math.round(this._rawData[9] * magnitude) / magnitude +
',' + Math.round(this._rawData[10] * magnitude) / magnitude +
',' + Math.round(this._rawData[11] * magnitude) / magnitude +
',' + Math.round(this._rawData[12] * magnitude) / magnitude +
',' + Math.round(this._rawData[13] * magnitude) / magnitude +
',' + Math.round(this._rawData[14] * magnitude) / magnitude +
',' + Math.round(this._rawData[15] * magnitude) / magnitude + ')';
};
Matrix3D.prototype.toString = function () {
return 'matrix3d(' + Math.round(this._rawData[0] * 1000) / 1000 +
',' + Math.round(this._rawData[1] * 1000) / 1000 +
',' + Math.round(this._rawData[2] * 1000) / 1000 +
',' + Math.round(this._rawData[3] * 1000) / 1000 +
',' + Math.round(this._rawData[4] * 1000) / 1000 +
',' + Math.round(this._rawData[5] * 1000) / 1000 +
',' + Math.round(this._rawData[6] * 1000) / 1000 +
',' + Math.round(this._rawData[7] * 1000) / 1000 +
',' + Math.round(this._rawData[8] * 1000) / 1000 +
',' + Math.round(this._rawData[9] * 1000) / 1000 +
',' + Math.round(this._rawData[10] * 1000) / 1000 +
',' + Math.round(this._rawData[11] * 1000) / 1000 +
',' + Math.round(this._rawData[12] * 1000) / 1000 +
',' + Math.round(this._rawData[13] * 1000) / 1000 +
',' + Math.round(this._rawData[14] * 1000) / 1000 +
',' + Math.round(this._rawData[15] * 1000) / 1000 + ')';
};
Matrix3D._identityData = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
Matrix3D._tempMatrix = new Matrix3D();
/**
* A reference to a Matrix3D to be used as a temporary data container, preventing object creation.
*/
Matrix3D.CALCULATION_MATRIX = new Matrix3D();
Matrix3D.COL_X = new Vector3D();
Matrix3D.COL_Y = new Vector3D();
Matrix3D.COL_Z = new Vector3D();
return Matrix3D;
}());
export { Matrix3D };