@engaging-computing/aframe-physics-system
Version:
Physics system for A-Frame VR, built on Cannon.js
1,993 lines (1,693 loc) • 530 kB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
var CANNON = require('cannon-es');
require('./src/components/math');
require('./src/components/body/ammo-body');
require('./src/components/body/body');
require('./src/components/body/dynamic-body');
require('./src/components/body/static-body');
require('./src/components/shape/shape');
require('./src/components/shape/ammo-shape')
require('./src/components/ammo-constraint');
require('./src/components/constraint');
require('./src/components/spring');
require('./src/system');
module.exports = {
registerAll: function () {
console.warn('registerAll() is deprecated. Components are automatically registered.');
}
};
// Export CANNON.js.
window.CANNON = window.CANNON || CANNON;
},{"./src/components/ammo-constraint":8,"./src/components/body/ammo-body":9,"./src/components/body/body":10,"./src/components/body/dynamic-body":11,"./src/components/body/static-body":12,"./src/components/constraint":13,"./src/components/math":14,"./src/components/shape/ammo-shape":16,"./src/components/shape/shape":17,"./src/components/spring":18,"./src/system":28,"cannon-es":4}],2:[function(require,module,exports){
/**
* CANNON.shape2mesh
*
* Source: http://schteppe.github.io/cannon.js/build/cannon.demo.js
* Author: @schteppe
*/
var CANNON = require('cannon-es');
CANNON.shape2mesh = function(body){
var obj = new THREE.Object3D();
for (var l = 0; l < body.shapes.length; l++) {
var shape = body.shapes[l];
var mesh;
switch(shape.type){
case CANNON.Shape.types.SPHERE:
var sphere_geometry = new THREE.SphereGeometry( shape.radius, 8, 8);
mesh = new THREE.Mesh( sphere_geometry, this.currentMaterial );
break;
case CANNON.Shape.types.PARTICLE:
mesh = new THREE.Mesh( this.particleGeo, this.particleMaterial );
var s = this.settings;
mesh.scale.set(s.particleSize,s.particleSize,s.particleSize);
break;
case CANNON.Shape.types.PLANE:
var geometry = new THREE.PlaneGeometry(10, 10, 4, 4);
mesh = new THREE.Object3D();
var submesh = new THREE.Object3D();
var ground = new THREE.Mesh( geometry, this.currentMaterial );
ground.scale.set(100, 100, 100);
submesh.add(ground);
ground.castShadow = true;
ground.receiveShadow = true;
mesh.add(submesh);
break;
case CANNON.Shape.types.BOX:
var box_geometry = new THREE.BoxGeometry( shape.halfExtents.x*2,
shape.halfExtents.y*2,
shape.halfExtents.z*2 );
mesh = new THREE.Mesh( box_geometry, this.currentMaterial );
break;
case CANNON.Shape.types.CONVEXPOLYHEDRON:
var geo = new THREE.Geometry();
// Add vertices
for (var i = 0; i < shape.vertices.length; i++) {
var v = shape.vertices[i];
geo.vertices.push(new THREE.Vector3(v.x, v.y, v.z));
}
for(var i=0; i < shape.faces.length; i++){
var face = shape.faces[i];
// add triangles
var a = face[0];
for (var j = 1; j < face.length - 1; j++) {
var b = face[j];
var c = face[j + 1];
geo.faces.push(new THREE.Face3(a, b, c));
}
}
geo.computeBoundingSphere();
geo.computeFaceNormals();
mesh = new THREE.Mesh( geo, this.currentMaterial );
break;
case CANNON.Shape.types.HEIGHTFIELD:
var geometry = new THREE.Geometry();
var v0 = new CANNON.Vec3();
var v1 = new CANNON.Vec3();
var v2 = new CANNON.Vec3();
for (var xi = 0; xi < shape.data.length - 1; xi++) {
for (var yi = 0; yi < shape.data[xi].length - 1; yi++) {
for (var k = 0; k < 2; k++) {
shape.getConvexTrianglePillar(xi, yi, k===0);
v0.copy(shape.pillarConvex.vertices[0]);
v1.copy(shape.pillarConvex.vertices[1]);
v2.copy(shape.pillarConvex.vertices[2]);
v0.vadd(shape.pillarOffset, v0);
v1.vadd(shape.pillarOffset, v1);
v2.vadd(shape.pillarOffset, v2);
geometry.vertices.push(
new THREE.Vector3(v0.x, v0.y, v0.z),
new THREE.Vector3(v1.x, v1.y, v1.z),
new THREE.Vector3(v2.x, v2.y, v2.z)
);
var i = geometry.vertices.length - 3;
geometry.faces.push(new THREE.Face3(i, i+1, i+2));
}
}
}
geometry.computeBoundingSphere();
geometry.computeFaceNormals();
mesh = new THREE.Mesh(geometry, this.currentMaterial);
break;
case CANNON.Shape.types.TRIMESH:
var geometry = new THREE.Geometry();
var v0 = new CANNON.Vec3();
var v1 = new CANNON.Vec3();
var v2 = new CANNON.Vec3();
for (var i = 0; i < shape.indices.length / 3; i++) {
shape.getTriangleVertices(i, v0, v1, v2);
geometry.vertices.push(
new THREE.Vector3(v0.x, v0.y, v0.z),
new THREE.Vector3(v1.x, v1.y, v1.z),
new THREE.Vector3(v2.x, v2.y, v2.z)
);
var j = geometry.vertices.length - 3;
geometry.faces.push(new THREE.Face3(j, j+1, j+2));
}
geometry.computeBoundingSphere();
geometry.computeFaceNormals();
mesh = new THREE.Mesh(geometry, this.currentMaterial);
break;
default:
throw "Visual type not recognized: "+shape.type;
}
mesh.receiveShadow = true;
mesh.castShadow = true;
if(mesh.children){
for(var i=0; i<mesh.children.length; i++){
mesh.children[i].castShadow = true;
mesh.children[i].receiveShadow = true;
if(mesh.children[i]){
for(var j=0; j<mesh.children[i].length; j++){
mesh.children[i].children[j].castShadow = true;
mesh.children[i].children[j].receiveShadow = true;
}
}
}
}
var o = body.shapeOffsets[l];
var q = body.shapeOrientations[l];
mesh.position.set(o.x, o.y, o.z);
mesh.quaternion.set(q.x, q.y, q.z, q.w);
obj.add(mesh);
}
return obj;
};
module.exports = CANNON.shape2mesh;
},{"cannon-es":4}],3:[function(require,module,exports){
/* global Ammo,THREE */
THREE.AmmoDebugConstants = {
NoDebug: 0,
DrawWireframe: 1,
DrawAabb: 2,
DrawFeaturesText: 4,
DrawContactPoints: 8,
NoDeactivation: 16,
NoHelpText: 32,
DrawText: 64,
ProfileTimings: 128,
EnableSatComparison: 256,
DisableBulletLCP: 512,
EnableCCD: 1024,
DrawConstraints: 1 << 11, //2048
DrawConstraintLimits: 1 << 12, //4096
FastWireframe: 1 << 13, //8192
DrawNormals: 1 << 14, //16384
DrawOnTop: 1 << 15, //32768
MAX_DEBUG_DRAW_MODE: 0xffffffff
};
/**
* An implementation of the btIDebugDraw interface in Ammo.js, for debug rendering of Ammo shapes
* @class AmmoDebugDrawer
* @param {THREE.Scene} scene
* @param {Ammo.btCollisionWorld} world
* @param {object} [options]
*/
THREE.AmmoDebugDrawer = function(scene, world, options) {
this.scene = scene;
this.world = world;
options = options || {};
this.debugDrawMode = options.debugDrawMode || THREE.AmmoDebugConstants.DrawWireframe;
var drawOnTop = this.debugDrawMode & THREE.AmmoDebugConstants.DrawOnTop || false;
var maxBufferSize = options.maxBufferSize || 1000000;
this.geometry = new THREE.BufferGeometry();
var vertices = new Float32Array(maxBufferSize * 3);
var colors = new Float32Array(maxBufferSize * 3);
this.geometry.addAttribute("position", new THREE.BufferAttribute(vertices, 3).setDynamic(true));
this.geometry.addAttribute("color", new THREE.BufferAttribute(colors, 3).setDynamic(true));
this.index = 0;
var material = new THREE.LineBasicMaterial({
vertexColors: THREE.VertexColors,
depthTest: !drawOnTop
});
this.mesh = new THREE.LineSegments(this.geometry, material);
if (drawOnTop) this.mesh.renderOrder = 999;
this.mesh.frustumCulled = false;
this.enabled = false;
this.debugDrawer = new Ammo.DebugDrawer();
this.debugDrawer.drawLine = this.drawLine.bind(this);
this.debugDrawer.drawContactPoint = this.drawContactPoint.bind(this);
this.debugDrawer.reportErrorWarning = this.reportErrorWarning.bind(this);
this.debugDrawer.draw3dText = this.draw3dText.bind(this);
this.debugDrawer.setDebugMode = this.setDebugMode.bind(this);
this.debugDrawer.getDebugMode = this.getDebugMode.bind(this);
this.debugDrawer.enable = this.enable.bind(this);
this.debugDrawer.disable = this.disable.bind(this);
this.debugDrawer.update = this.update.bind(this);
this.world.setDebugDrawer(this.debugDrawer);
};
THREE.AmmoDebugDrawer.prototype = function() {
return this.debugDrawer;
};
THREE.AmmoDebugDrawer.prototype.enable = function() {
this.enabled = true;
this.scene.add(this.mesh);
};
THREE.AmmoDebugDrawer.prototype.disable = function() {
this.enabled = false;
this.scene.remove(this.mesh);
};
THREE.AmmoDebugDrawer.prototype.update = function() {
if (!this.enabled) {
return;
}
if (this.index != 0) {
this.geometry.attributes.position.needsUpdate = true;
this.geometry.attributes.color.needsUpdate = true;
}
this.index = 0;
this.world.debugDrawWorld();
this.geometry.setDrawRange(0, this.index);
};
THREE.AmmoDebugDrawer.prototype.drawLine = function(from, to, color) {
const heap = Ammo.HEAPF32;
const r = heap[(color + 0) / 4];
const g = heap[(color + 4) / 4];
const b = heap[(color + 8) / 4];
const fromX = heap[(from + 0) / 4];
const fromY = heap[(from + 4) / 4];
const fromZ = heap[(from + 8) / 4];
this.geometry.attributes.position.setXYZ(this.index, fromX, fromY, fromZ);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
const toX = heap[(to + 0) / 4];
const toY = heap[(to + 4) / 4];
const toZ = heap[(to + 8) / 4];
this.geometry.attributes.position.setXYZ(this.index, toX, toY, toZ);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
};
//TODO: figure out how to make lifeTime work
THREE.AmmoDebugDrawer.prototype.drawContactPoint = function(pointOnB, normalOnB, distance, lifeTime, color) {
const heap = Ammo.HEAPF32;
const r = heap[(color + 0) / 4];
const g = heap[(color + 4) / 4];
const b = heap[(color + 8) / 4];
const x = heap[(pointOnB + 0) / 4];
const y = heap[(pointOnB + 4) / 4];
const z = heap[(pointOnB + 8) / 4];
this.geometry.attributes.position.setXYZ(this.index, x, y, z);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
const dx = heap[(normalOnB + 0) / 4] * distance;
const dy = heap[(normalOnB + 4) / 4] * distance;
const dz = heap[(normalOnB + 8) / 4] * distance;
this.geometry.attributes.position.setXYZ(this.index, x + dx, y + dy, z + dz);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
};
THREE.AmmoDebugDrawer.prototype.reportErrorWarning = function(warningString) {
if (Ammo.hasOwnProperty("Pointer_stringify")) {
console.warn(Ammo.Pointer_stringify(warningString));
} else if (!this.warnedOnce) {
this.warnedOnce = true;
console.warn("Cannot print warningString, please rebuild Ammo.js using 'debug' flag");
}
};
THREE.AmmoDebugDrawer.prototype.draw3dText = function(location, textString) {
//TODO
console.warn("TODO: draw3dText");
};
THREE.AmmoDebugDrawer.prototype.setDebugMode = function(debugMode) {
this.debugDrawMode = debugMode;
};
THREE.AmmoDebugDrawer.prototype.getDebugMode = function() {
return this.debugDrawMode;
};
},{}],4:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/**
* Records what objects are colliding with each other
* @class ObjectCollisionMatrix
* @constructor
*/
var ObjectCollisionMatrix = /*#__PURE__*/function () {
// The matrix storage.
function ObjectCollisionMatrix() {
this.matrix = {};
}
/**
* @method get
* @param {Body} i
* @param {Body} j
* @return {boolean}
*/
var _proto = ObjectCollisionMatrix.prototype;
_proto.get = function get(bi, bj) {
var i = bi.id;
var j = bj.id;
if (j > i) {
var temp = j;
j = i;
i = temp;
}
return i + "-" + j in this.matrix;
}
/**
* @method set
* @param {Body} i
* @param {Body} j
* @param {boolean} value
*/
;
_proto.set = function set(bi, bj, value) {
var i = bi.id;
var j = bj.id;
if (j > i) {
var temp = j;
j = i;
i = temp;
}
if (value) {
this.matrix[i + "-" + j] = true;
} else {
delete this.matrix[i + "-" + j];
}
}
/**
* Empty the matrix
* @method reset
*/
;
_proto.reset = function reset() {
this.matrix = {};
}
/**
* Set max number of objects
* @method setNumObjects
* @param {Number} n
*/
;
_proto.setNumObjects = function setNumObjects(n) {};
return ObjectCollisionMatrix;
}();
/**
* A 3x3 matrix.
* @class Mat3
* @constructor
* @param {Array} elements A vector of length 9, containing all matrix elements. Optional.
* @author schteppe / http://github.com/schteppe
*/
var Mat3 = /*#__PURE__*/function () {
function Mat3(elements) {
if (elements === void 0) {
elements = [0, 0, 0, 0, 0, 0, 0, 0, 0];
}
this.elements = elements;
}
/**
* Sets the matrix to identity
* @method identity
* @todo Should perhaps be renamed to setIdentity() to be more clear.
* @todo Create another function that immediately creates an identity matrix eg. eye()
*/
var _proto = Mat3.prototype;
_proto.identity = function identity() {
var e = this.elements;
e[0] = 1;
e[1] = 0;
e[2] = 0;
e[3] = 0;
e[4] = 1;
e[5] = 0;
e[6] = 0;
e[7] = 0;
e[8] = 1;
}
/**
* Set all elements to zero
* @method setZero
*/
;
_proto.setZero = function setZero() {
var e = this.elements;
e[0] = 0;
e[1] = 0;
e[2] = 0;
e[3] = 0;
e[4] = 0;
e[5] = 0;
e[6] = 0;
e[7] = 0;
e[8] = 0;
}
/**
* Sets the matrix diagonal elements from a Vec3
* @method setTrace
* @param {Vec3} vec3
*/
;
_proto.setTrace = function setTrace(vector) {
var e = this.elements;
e[0] = vector.x;
e[4] = vector.y;
e[8] = vector.z;
}
/**
* Gets the matrix diagonal elements
* @method getTrace
* @return {Vec3}
*/
;
_proto.getTrace = function getTrace(target) {
if (target === void 0) {
target = new Vec3();
}
var e = this.elements;
target.x = e[0];
target.y = e[4];
target.z = e[8];
}
/**
* Matrix-Vector multiplication
* @method vmult
* @param {Vec3} v The vector to multiply with
* @param {Vec3} target Optional, target to save the result in.
*/
;
_proto.vmult = function vmult(v, target) {
if (target === void 0) {
target = new Vec3();
}
var e = this.elements;
var x = v.x;
var y = v.y;
var z = v.z;
target.x = e[0] * x + e[1] * y + e[2] * z;
target.y = e[3] * x + e[4] * y + e[5] * z;
target.z = e[6] * x + e[7] * y + e[8] * z;
return target;
}
/**
* Matrix-scalar multiplication
* @method smult
* @param {Number} s
*/
;
_proto.smult = function smult(s) {
for (var i = 0; i < this.elements.length; i++) {
this.elements[i] *= s;
}
}
/**
* Matrix multiplication
* @method mmult
* @param {Mat3} matrix Matrix to multiply with from left side.
* @return {Mat3} The result.
*/
;
_proto.mmult = function mmult(matrix, target) {
if (target === void 0) {
target = new Mat3();
}
var elements = matrix.elements;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var sum = 0.0;
for (var k = 0; k < 3; k++) {
sum += elements[i + k * 3] * this.elements[k + j * 3];
}
target.elements[i + j * 3] = sum;
}
}
return target;
}
/**
* Scale each column of the matrix
* @method scale
* @param {Vec3} v
* @return {Mat3} The result.
*/
;
_proto.scale = function scale(vector, target) {
if (target === void 0) {
target = new Mat3();
}
var e = this.elements;
var t = target.elements;
for (var i = 0; i !== 3; i++) {
t[3 * i + 0] = vector.x * e[3 * i + 0];
t[3 * i + 1] = vector.y * e[3 * i + 1];
t[3 * i + 2] = vector.z * e[3 * i + 2];
}
return target;
}
/**
* Solve Ax=b
* @method solve
* @param {Vec3} b The right hand side
* @param {Vec3} target Optional. Target vector to save in.
* @return {Vec3} The solution x
* @todo should reuse arrays
*/
;
_proto.solve = function solve(b, target) {
if (target === void 0) {
target = new Vec3();
}
// Construct equations
var nr = 3; // num rows
var nc = 4; // num cols
var eqns = [];
var i;
var j;
for (i = 0; i < nr * nc; i++) {
eqns.push(0);
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
eqns[i + nc * j] = this.elements[i + 3 * j];
}
}
eqns[3 + 4 * 0] = b.x;
eqns[3 + 4 * 1] = b.y;
eqns[3 + 4 * 2] = b.z; // Compute right upper triangular version of the matrix - Gauss elimination
var n = 3;
var k = n;
var np;
var kp = 4; // num rows
var p;
do {
i = k - n;
if (eqns[i + nc * i] === 0) {
// the pivot is null, swap lines
for (j = i + 1; j < k; j++) {
if (eqns[i + nc * j] !== 0) {
np = kp;
do {
// do ligne( i ) = ligne( i ) + ligne( k )
p = kp - np;
eqns[p + nc * i] += eqns[p + nc * j];
} while (--np);
break;
}
}
}
if (eqns[i + nc * i] !== 0) {
for (j = i + 1; j < k; j++) {
var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
np = kp;
do {
// do ligne( k ) = ligne( k ) - multiplier * ligne( i )
p = kp - np;
eqns[p + nc * j] = p <= i ? 0 : eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
} while (--np);
}
}
} while (--n); // Get the solution
target.z = eqns[2 * nc + 3] / eqns[2 * nc + 2];
target.y = (eqns[1 * nc + 3] - eqns[1 * nc + 2] * target.z) / eqns[1 * nc + 1];
target.x = (eqns[0 * nc + 3] - eqns[0 * nc + 2] * target.z - eqns[0 * nc + 1] * target.y) / eqns[0 * nc + 0];
if (isNaN(target.x) || isNaN(target.y) || isNaN(target.z) || target.x === Infinity || target.y === Infinity || target.z === Infinity) {
throw "Could not solve equation! Got x=[" + target.toString() + "], b=[" + b.toString() + "], A=[" + this.toString() + "]";
}
return target;
}
/**
* Get an element in the matrix by index. Index starts at 0, not 1!!!
* @method e
* @param {Number} row
* @param {Number} column
* @param {Number} value Optional. If provided, the matrix element will be set to this value.
* @return {Number}
*/
;
_proto.e = function e(row, column, value) {
if (value === undefined) {
return this.elements[column + 3 * row];
} else {
// Set value
this.elements[column + 3 * row] = value;
}
}
/**
* Copy another matrix into this matrix object.
* @method copy
* @param {Mat3} source
* @return {Mat3} this
*/
;
_proto.copy = function copy(matrix) {
for (var i = 0; i < matrix.elements.length; i++) {
this.elements[i] = matrix.elements[i];
}
return this;
}
/**
* Returns a string representation of the matrix.
* @method toString
* @return string
*/
;
_proto.toString = function toString() {
var r = '';
var sep = ',';
for (var i = 0; i < 9; i++) {
r += this.elements[i] + sep;
}
return r;
}
/**
* reverse the matrix
* @method reverse
* @param {Mat3} target Optional. Target matrix to save in.
* @return {Mat3} The solution x
*/
;
_proto.reverse = function reverse(target) {
if (target === void 0) {
target = new Mat3();
}
// Construct equations
var nr = 3; // num rows
var nc = 6; // num cols
var eqns = [];
var i;
var j;
for (i = 0; i < nr * nc; i++) {
eqns.push(0);
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
eqns[i + nc * j] = this.elements[i + 3 * j];
}
}
eqns[3 + 6 * 0] = 1;
eqns[3 + 6 * 1] = 0;
eqns[3 + 6 * 2] = 0;
eqns[4 + 6 * 0] = 0;
eqns[4 + 6 * 1] = 1;
eqns[4 + 6 * 2] = 0;
eqns[5 + 6 * 0] = 0;
eqns[5 + 6 * 1] = 0;
eqns[5 + 6 * 2] = 1; // Compute right upper triangular version of the matrix - Gauss elimination
var n = 3;
var k = n;
var np;
var kp = nc; // num rows
var p;
do {
i = k - n;
if (eqns[i + nc * i] === 0) {
// the pivot is null, swap lines
for (j = i + 1; j < k; j++) {
if (eqns[i + nc * j] !== 0) {
np = kp;
do {
// do line( i ) = line( i ) + line( k )
p = kp - np;
eqns[p + nc * i] += eqns[p + nc * j];
} while (--np);
break;
}
}
}
if (eqns[i + nc * i] !== 0) {
for (j = i + 1; j < k; j++) {
var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
np = kp;
do {
// do line( k ) = line( k ) - multiplier * line( i )
p = kp - np;
eqns[p + nc * j] = p <= i ? 0 : eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
} while (--np);
}
}
} while (--n); // eliminate the upper left triangle of the matrix
i = 2;
do {
j = i - 1;
do {
var _multiplier = eqns[i + nc * j] / eqns[i + nc * i];
np = nc;
do {
p = nc - np;
eqns[p + nc * j] = eqns[p + nc * j] - eqns[p + nc * i] * _multiplier;
} while (--np);
} while (j--);
} while (--i); // operations on the diagonal
i = 2;
do {
var _multiplier2 = 1 / eqns[i + nc * i];
np = nc;
do {
p = nc - np;
eqns[p + nc * i] = eqns[p + nc * i] * _multiplier2;
} while (--np);
} while (i--);
i = 2;
do {
j = 2;
do {
p = eqns[nr + j + nc * i];
if (isNaN(p) || p === Infinity) {
throw "Could not reverse! A=[" + this.toString() + "]";
}
target.e(i, j, p);
} while (j--);
} while (i--);
return target;
}
/**
* Set the matrix from a quaterion
* @method setRotationFromQuaternion
* @param {Quaternion} q
*/
;
_proto.setRotationFromQuaternion = function setRotationFromQuaternion(q) {
var x = q.x;
var y = q.y;
var z = q.z;
var w = q.w;
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x * x2;
var xy = x * y2;
var xz = x * z2;
var yy = y * y2;
var yz = y * z2;
var zz = z * z2;
var wx = w * x2;
var wy = w * y2;
var wz = w * z2;
var e = this.elements;
e[3 * 0 + 0] = 1 - (yy + zz);
e[3 * 0 + 1] = xy - wz;
e[3 * 0 + 2] = xz + wy;
e[3 * 1 + 0] = xy + wz;
e[3 * 1 + 1] = 1 - (xx + zz);
e[3 * 1 + 2] = yz - wx;
e[3 * 2 + 0] = xz - wy;
e[3 * 2 + 1] = yz + wx;
e[3 * 2 + 2] = 1 - (xx + yy);
return this;
}
/**
* Transpose the matrix
* @method transpose
* @param {Mat3} target Optional. Where to store the result.
* @return {Mat3} The target Mat3, or a new Mat3 if target was omitted.
*/
;
_proto.transpose = function transpose(target) {
if (target === void 0) {
target = new Mat3();
}
var Mt = target.elements;
var M = this.elements;
for (var i = 0; i !== 3; i++) {
for (var j = 0; j !== 3; j++) {
Mt[3 * i + j] = M[3 * j + i];
}
}
return target;
};
return Mat3;
}();
/**
* 3-dimensional vector
* @class Vec3
* @constructor
* @param {Number} x
* @param {Number} y
* @param {Number} z
* @author schteppe
* @example
* const v = new Vec3(1, 2, 3);
* console.log('x=' + v.x); // x=1
*/
var Vec3 = /*#__PURE__*/function () {
function Vec3(x, y, z) {
if (x === void 0) {
x = 0.0;
}
if (y === void 0) {
y = 0.0;
}
if (z === void 0) {
z = 0.0;
}
this.x = x;
this.y = y;
this.z = z;
}
/**
* Vector cross product
* @method cross
* @param {Vec3} v
* @param {Vec3} target Optional. Target to save in.
* @return {Vec3}
*/
var _proto = Vec3.prototype;
_proto.cross = function cross(vector, target) {
if (target === void 0) {
target = new Vec3();
}
var vx = vector.x;
var vy = vector.y;
var vz = vector.z;
var x = this.x;
var y = this.y;
var z = this.z;
target.x = y * vz - z * vy;
target.y = z * vx - x * vz;
target.z = x * vy - y * vx;
return target;
}
/**
* Set the vectors' 3 elements
* @method set
* @param {Number} x
* @param {Number} y
* @param {Number} z
* @return Vec3
*/
;
_proto.set = function set(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
return this;
}
/**
* Set all components of the vector to zero.
* @method setZero
*/
;
_proto.setZero = function setZero() {
this.x = this.y = this.z = 0;
}
/**
* Vector addition
* @method vadd
* @param {Vec3} v
* @param {Vec3} target Optional.
* @return {Vec3}
*/
;
_proto.vadd = function vadd(vector, target) {
if (target) {
target.x = vector.x + this.x;
target.y = vector.y + this.y;
target.z = vector.z + this.z;
} else {
return new Vec3(this.x + vector.x, this.y + vector.y, this.z + vector.z);
}
}
/**
* Vector subtraction
* @method vsub
* @param {Vec3} v
* @param {Vec3} target Optional. Target to save in.
* @return {Vec3}
*/
;
_proto.vsub = function vsub(vector, target) {
if (target) {
target.x = this.x - vector.x;
target.y = this.y - vector.y;
target.z = this.z - vector.z;
} else {
return new Vec3(this.x - vector.x, this.y - vector.y, this.z - vector.z);
}
}
/**
* Get the cross product matrix a_cross from a vector, such that a x b = a_cross * b = c
* @method crossmat
* @see http://www8.cs.umu.se/kurser/TDBD24/VT06/lectures/Lecture6.pdf
* @return {Mat3}
*/
;
_proto.crossmat = function crossmat() {
return new Mat3([0, -this.z, this.y, this.z, 0, -this.x, -this.y, this.x, 0]);
}
/**
* Normalize the vector. Note that this changes the values in the vector.
* @method normalize
* @return {Number} Returns the norm of the vector
*/
;
_proto.normalize = function normalize() {
var x = this.x;
var y = this.y;
var z = this.z;
var n = Math.sqrt(x * x + y * y + z * z);
if (n > 0.0) {
var invN = 1 / n;
this.x *= invN;
this.y *= invN;
this.z *= invN;
} else {
// Make something up
this.x = 0;
this.y = 0;
this.z = 0;
}
return n;
}
/**
* Get the version of this vector that is of length 1.
* @method unit
* @param {Vec3} target Optional target to save in
* @return {Vec3} Returns the unit vector
*/
;
_proto.unit = function unit(target) {
if (target === void 0) {
target = new Vec3();
}
var x = this.x;
var y = this.y;
var z = this.z;
var ninv = Math.sqrt(x * x + y * y + z * z);
if (ninv > 0.0) {
ninv = 1.0 / ninv;
target.x = x * ninv;
target.y = y * ninv;
target.z = z * ninv;
} else {
target.x = 1;
target.y = 0;
target.z = 0;
}
return target;
}
/**
* Get the length of the vector
* @method length
* @return {Number}
*/
;
_proto.length = function length() {
var x = this.x;
var y = this.y;
var z = this.z;
return Math.sqrt(x * x + y * y + z * z);
}
/**
* Get the squared length of the vector.
* @method lengthSquared
* @return {Number}
*/
;
_proto.lengthSquared = function lengthSquared() {
return this.dot(this);
}
/**
* Get distance from this point to another point
* @method distanceTo
* @param {Vec3} p
* @return {Number}
*/
;
_proto.distanceTo = function distanceTo(p) {
var x = this.x;
var y = this.y;
var z = this.z;
var px = p.x;
var py = p.y;
var pz = p.z;
return Math.sqrt((px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z));
}
/**
* Get squared distance from this point to another point
* @method distanceSquared
* @param {Vec3} p
* @return {Number}
*/
;
_proto.distanceSquared = function distanceSquared(p) {
var x = this.x;
var y = this.y;
var z = this.z;
var px = p.x;
var py = p.y;
var pz = p.z;
return (px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z);
}
/**
* Multiply all the components of the vector with a scalar.
* @method scale
* @param {Number} scalar
* @param {Vec3} target The vector to save the result in.
* @return {Vec3}
*/
;
_proto.scale = function scale(scalar, target) {
if (target === void 0) {
target = new Vec3();
}
var x = this.x;
var y = this.y;
var z = this.z;
target.x = scalar * x;
target.y = scalar * y;
target.z = scalar * z;
return target;
}
/**
* Multiply the vector with an other vector, component-wise.
* @method vmult
* @param {Number} vector
* @param {Vec3} target The vector to save the result in.
* @return {Vec3}
*/
;
_proto.vmul = function vmul(vector, target) {
if (target === void 0) {
target = new Vec3();
}
target.x = vector.x * this.x;
target.y = vector.y * this.y;
target.z = vector.z * this.z;
return target;
}
/**
* Scale a vector and add it to this vector. Save the result in "target". (target = this + vector * scalar)
* @method addScaledVector
* @param {Number} scalar
* @param {Vec3} vector
* @param {Vec3} target The vector to save the result in.
* @return {Vec3}
*/
;
_proto.addScaledVector = function addScaledVector(scalar, vector, target) {
if (target === void 0) {
target = new Vec3();
}
target.x = this.x + scalar * vector.x;
target.y = this.y + scalar * vector.y;
target.z = this.z + scalar * vector.z;
return target;
}
/**
* Calculate dot product
* @method dot
* @param {Vec3} v
* @return {Number}
*/
;
_proto.dot = function dot(vector) {
return this.x * vector.x + this.y * vector.y + this.z * vector.z;
}
/**
* @method isZero
* @return bool
*/
;
_proto.isZero = function isZero() {
return this.x === 0 && this.y === 0 && this.z === 0;
}
/**
* Make the vector point in the opposite direction.
* @method negate
* @param {Vec3} target Optional target to save in
* @return {Vec3}
*/
;
_proto.negate = function negate(target) {
if (target === void 0) {
target = new Vec3();
}
target.x = -this.x;
target.y = -this.y;
target.z = -this.z;
return target;
}
/**
* Compute two artificial tangents to the vector
* @method tangents
* @param {Vec3} t1 Vector object to save the first tangent in
* @param {Vec3} t2 Vector object to save the second tangent in
*/
;
_proto.tangents = function tangents(t1, t2) {
var norm = this.length();
if (norm > 0.0) {
var n = Vec3_tangents_n;
var inorm = 1 / norm;
n.set(this.x * inorm, this.y * inorm, this.z * inorm);
var randVec = Vec3_tangents_randVec;
if (Math.abs(n.x) < 0.9) {
randVec.set(1, 0, 0);
n.cross(randVec, t1);
} else {
randVec.set(0, 1, 0);
n.cross(randVec, t1);
}
n.cross(t1, t2);
} else {
// The normal length is zero, make something up
t1.set(1, 0, 0);
t2.set(0, 1, 0);
}
}
/**
* Converts to a more readable format
* @method toString
* @return string
*/
;
_proto.toString = function toString() {
return this.x + "," + this.y + "," + this.z;
}
/**
* Converts to an array
* @method toArray
* @return Array
*/
;
_proto.toArray = function toArray() {
return [this.x, this.y, this.z];
}
/**
* Copies value of source to this vector.
* @method copy
* @param {Vec3} source
* @return {Vec3} this
*/
;
_proto.copy = function copy(vector) {
this.x = vector.x;
this.y = vector.y;
this.z = vector.z;
return this;
}
/**
* Do a linear interpolation between two vectors
* @method lerp
* @param {Vec3} v
* @param {Number} t A number between 0 and 1. 0 will make this function return u, and 1 will make it return v. Numbers in between will generate a vector in between them.
* @param {Vec3} target
*/
;
_proto.lerp = function lerp(vector, t, target) {
var x = this.x;
var y = this.y;
var z = this.z;
target.x = x + (vector.x - x) * t;
target.y = y + (vector.y - y) * t;
target.z = z + (vector.z - z) * t;
}
/**
* Check if a vector equals is almost equal to another one.
* @method almostEquals
* @param {Vec3} v
* @param {Number} precision
* @return bool
*/
;
_proto.almostEquals = function almostEquals(vector, precision) {
if (precision === void 0) {
precision = 1e-6;
}
if (Math.abs(this.x - vector.x) > precision || Math.abs(this.y - vector.y) > precision || Math.abs(this.z - vector.z) > precision) {
return false;
}
return true;
}
/**
* Check if a vector is almost zero
* @method almostZero
* @param {Number} precision
*/
;
_proto.almostZero = function almostZero(precision) {
if (precision === void 0) {
precision = 1e-6;
}
if (Math.abs(this.x) > precision || Math.abs(this.y) > precision || Math.abs(this.z) > precision) {
return false;
}
return true;
}
/**
* Check if the vector is anti-parallel to another vector.
* @method isAntiparallelTo
* @param {Vec3} v
* @param {Number} precision Set to zero for exact comparisons
* @return {Boolean}
*/
;
_proto.isAntiparallelTo = function isAntiparallelTo(vector, precision) {
this.negate(antip_neg);
return antip_neg.almostEquals(vector, precision);
}
/**
* Clone the vector
* @method clone
* @return {Vec3}
*/
;
_proto.clone = function clone() {
return new Vec3(this.x, this.y, this.z);
};
return Vec3;
}();
Vec3.ZERO = new Vec3(0, 0, 0);
Vec3.UNIT_X = new Vec3(1, 0, 0);
Vec3.UNIT_Y = new Vec3(0, 1, 0);
Vec3.UNIT_Z = new Vec3(0, 0, 1);
/**
* Compute two artificial tangents to the vector
* @method tangents
* @param {Vec3} t1 Vector object to save the first tangent in
* @param {Vec3} t2 Vector object to save the second tangent in
*/
var Vec3_tangents_n = new Vec3();
var Vec3_tangents_randVec = new Vec3();
var antip_neg = new Vec3();
/**
* Axis aligned bounding box class.
* @class AABB
* @constructor
* @param {Object} [options]
* @param {Vec3} [options.upperBound] The upper bound of the bounding box.
* @param {Vec3} [options.lowerBound] The lower bound of the bounding box
*/
var AABB = /*#__PURE__*/function () {
// The lower bound of the bounding box
// The upper bound of the bounding box
function AABB(options) {
if (options === void 0) {
options = {};
}
this.lowerBound = new Vec3();
this.upperBound = new Vec3();
if (options.lowerBound) {
this.lowerBound.copy(options.lowerBound);
}
if (options.upperBound) {
this.upperBound.copy(options.upperBound);
}
}
/**
* Set the AABB bounds from a set of points.
* @method setFromPoints
* @param {Array} points An array of Vec3's.
* @param {Vec3} position Optional.
* @param {Quaternion} quaternion Optional.
* @param {number} skinSize Optional.
* @return {AABB} The self object
*/
var _proto = AABB.prototype;
_proto.setFromPoints = function setFromPoints(points, position, quaternion, skinSize) {
var l = this.lowerBound;
var u = this.upperBound;
var q = quaternion; // Set to the first point
l.copy(points[0]);
if (q) {
q.vmult(l, l);
}
u.copy(l);
for (var i = 1; i < points.length; i++) {
var p = points[i];
if (q) {
q.vmult(p, tmp);
p = tmp;
}
if (p.x > u.x) {
u.x = p.x;
}
if (p.x < l.x) {
l.x = p.x;
}
if (p.y > u.y) {
u.y = p.y;
}
if (p.y < l.y) {
l.y = p.y;
}
if (p.z > u.z) {
u.z = p.z;
}
if (p.z < l.z) {
l.z = p.z;
}
} // Add offset
if (position) {
position.vadd(l, l);
position.vadd(u, u);
}
if (skinSize) {
l.x -= skinSize;
l.y -= skinSize;
l.z -= skinSize;
u.x += skinSize;
u.y += skinSize;
u.z += skinSize;
}
return this;
}
/**
* Copy bounds from an AABB to this AABB
* @method copy
* @param {AABB} aabb Source to copy from
* @return {AABB} The this object, for chainability
*/
;
_proto.copy = function copy(aabb) {
this.lowerBound.copy(aabb.lowerBound);
this.upperBound.copy(aabb.upperBound);
return this;
}
/**
* Clone an AABB
* @method clone
*/
;
_proto.clone = function clone() {
return new AABB().copy(this);
}
/**
* Extend this AABB so that it covers the given AABB too.
* @method extend
* @param {AABB} aabb
*/
;
_proto.extend = function extend(aabb) {
this.lowerBound.x = Math.min(this.lowerBound.x, aabb.lowerBound.x);
this.upperBound.x = Math.max(this.upperBound.x, aabb.upperBound.x);
this.lowerBound.y = Math.min(this.lowerBound.y, aabb.lowerBound.y);
this.upperBound.y = Math.max(this.upperBound.y, aabb.upperBound.y);
this.lowerBound.z = Math.min(this.lowerBound.z, aabb.lowerBound.z);
this.upperBound.z = Math.max(this.upperBound.z, aabb.upperBound.z);
}
/**
* Returns true if the given AABB overlaps this AABB.
* @method overlaps
* @param {AABB} aabb
* @return {Boolean}
*/
;
_proto.overlaps = function overlaps(aabb) {
var l1 = this.lowerBound;
var u1 = this.upperBound;
var l2 = aabb.lowerBound;
var u2 = aabb.upperBound; // l2 u2
// |---------|
// |--------|
// l1 u1
var overlapsX = l2.x <= u1.x && u1.x <= u2.x || l1.x <= u2.x && u2.x <= u1.x;
var overlapsY = l2.y <= u1.y && u1.y <= u2.y || l1.y <= u2.y && u2.y <= u1.y;
var overlapsZ = l2.z <= u1.z && u1.z <= u2.z || l1.z <= u2.z && u2.z <= u1.z;
return overlapsX && overlapsY && overlapsZ;
} // Mostly for debugging
;
_proto.volume = function volume() {
var l = this.lowerBound;
var u = this.upperBound;
return (u.x - l.x) * (u.y - l.y) * (u.z - l.z);
}
/**
* Returns true if the given AABB is fully contained in this AABB.
* @method contains
* @param {AABB} aabb
* @return {Boolean}
*/
;
_proto.contains = function contains(aabb) {
var l1 = this.lowerBound;
var u1 = this.upperBound;
var l2 = aabb.lowerBound;
var u2 = aabb.upperBound; // l2 u2
// |---------|
// |---------------|
// l1 u1
return l1.x <= l2.x && u1.x >= u2.x && l1.y <= l2.y && u1.y >= u2.y && l1.z <= l2.z && u1.z >= u2.z;
}
/**
* @method getCorners
* @param {Vec3} a
* @param {Vec3} b
* @param {Vec3} c
* @param {Vec3} d
* @param {Vec3} e
* @param {Vec3} f
* @param {Vec3} g
* @param {Vec3} h
*/
;
_proto.getCorners = function getCorners(a, b, c, d, e, f, g, h) {
var l = this.lowerBound;
var u = this.upperBound;
a.copy(l);
b.set(u.x, l.y, l.z);
c.set(u.x, u.y, l.z);
d.set(l.x, u.y, u.z);
e.set(u.x, l.y, u.z);
f.set(l.x, u.y, l.z);
g.set(l.x, l.y, u.z);
h.copy(u);
}
/**
* Get the representation of an AABB in another frame.
* @method toLocalFrame
* @param {Transform} frame
* @param {AABB} target
* @return {AABB} The "target" AABB object.
*/
;
_proto.toLocalFrame = function toLocalFrame(frame, target) {
var corners = transformIntoFrame_corners;
var a = corners[0];
var b = corners[1];
var c = corners[2];
var d = corners[3];
var e = corners[4];
var f = corners[5];
var g = corners[6];
var h = corners[7]; // Get corners in current frame
this.getCorners(a, b, c, d, e, f, g, h); // Transform them to new local frame
for (var i = 0; i !== 8; i++) {
var corner = corners[i];
frame.pointToLocal(corner, corner);
}
return target.setFromPoints(corners);
}
/**
* Get the representation of an AABB in the global frame.
* @method toWorldFrame
* @param {Transform} frame
* @param {AABB} target
* @return {AABB} The "target" AABB object.
*/
;
_proto.toWorldFrame = function toWorldFrame(frame, target) {
var corners = transformIntoFrame_corners;
var a = corners[0];
var b = corners[1];
var c = corners[2];
var d = corners[3];
var e = corners[4];
var f = corners[5];
var g = corners[6];
var h = corners[7]; // Get corners in current frame
this.getCorners(a, b, c, d, e, f, g, h); // Transform them to new local frame
for (var i = 0; i !== 8; i++) {
var corner = corners[i];
frame.pointToWorld(corner, corner);
}
return target.setFromPoints(corners);
}
/**
* Check if the AABB is hit by a ray.
* @param {Ray} ray
* @return {Boolean}
*/
;
_proto.overlapsRay = function overlapsRay(ray) {
var direction = ray.direction,
from = ray.from;
var dirFracX = 1 / direction.x;
var dirFracY = 1 / direction.y;
var dirFracZ = 1 / direction.z; // this.lowerBound is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
var t1 = (this.lowerBound.x - from.x) * dirFracX;
var t2 = (this.upperBound.x - from.x) * dirFracX;
var t3 = (this.lowerBound.y - from.y) * dirFracY;
var t4 = (this.upperBound.y - from.y) * dirFracY;
var t5 = (this.lowerBound.z - from.z) * dirFracZ;
var t6 = (this.upperBound.z - from.z) * dirFracZ; // const tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)));
// const tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)));
var tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6));
var tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
if (tmax < 0) {
//t = tmax;
return false;
} // if tmin > tmax, ray doesn't intersect AABB
if (tmin > tmax) {
//t = tmax;
return false;
}
return true;
};
return AABB;
}();
var tmp = new Vec3();
var transformIntoFrame_corners = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
/**
* Collision "matrix". It's actually a triangular-shaped array of whether two bodies are touching this step, for reference next step
* @class ArrayCollisionMatrix
* @constructor
*/
var ArrayCollisionMatrix = /*#__PURE__*/function () {
// The matrix storage.
function ArrayCollisionMatrix() {
this.matrix = [];
}
/**
* Get an element
* @method get
* @param {Body} i
* @param {Body} j
* @return {Number}
*/
var _proto = ArrayCollisionMatrix.prototype;
_proto.get = function get(bi, bj) {
var i = bi.index;
var j = bj.index;
if (j > i) {
var temp = j;
j = i;
i = temp;
}
return this.matrix[(i * (i + 1) >> 1) + j - 1];
}
/**
* Set an element
* @method set
* @param {Body} i
* @param {Body} j
* @param {boolean} value
*/
;
_proto.set = function set(bi, bj, value) {
var i = bi.index;
var j = bj.index;
if (j > i) {
var temp = j;
j = i;
i = temp;
}
this.matrix[(i * (i + 1) >> 1) + j - 1] = value ? 1 : 0;
}
/**
* Sets all elements to zero
* @method reset
*/
;
_proto.reset = function reset() {
for (var i = 0, l = this.matrix.length; i !== l; i++) {
this.matrix[i] = 0;
}
}
/**
* Sets the max number of objects
* @method setNumObjects
* @param {Number} n
*/
;
_proto.setNumObjects = function setNumObjects(n) {
this.matrix.length = n * (n - 1) >> 1;
};
return ArrayCollisionMatrix;
}();
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
/**
* Base class for objects that dispatches events.
* @class EventTarget
* @constructor
*/
var EventTarget = /*#__PURE__*/function () {
function EventTarget() {}
/**
* Add an event listener
* @method addEventListener
* @param {String} type
* @param {Function} listener
* @return {EventTarget} The self object, for chainability.
*/
var _proto = EventTarget.prototype;
_proto.addEventListener = function addEventListener(type, listener) {
if (this._listeners === undefined) {
this._listeners = {};
}
var listeners = this._listeners;
if (listeners[type] === undefined) {
listeners[type] = [];
}
if (!listeners[type].includes(listener)) {
listeners[type].push(listener);
}
return this;
}
/**
* Check if an event listener is added
* @method hasEventListener
* @param {String} type
* @param {Function} listener
* @return {Boolean}
*/
;
_proto.hasEventListener = function hasEventListener(type, listener) {
if (this._listeners === undefined) {
return false;
}
var listeners = this._listeners;
if (listeners[type] !== undefined && listeners[type].includes(listener)) {
return true;
}
return false;
}
/**
* Check if any event listener of the given type is added
* @method hasAnyEventListener
* @param {String} type
* @return {Boolean}
*/
;
_proto.hasAnyEventListener = function hasAnyEventListener(type) {
if (this._listeners === undefined) {
return false;
}
var listeners = this._listeners;
return listeners[type] !== undefined;
}
/**
* Remove an event listener
* @method removeEventListener
* @param {String} type
* @param {Function} listener
* @return {EventTarget} The self object, for chainability.
*/
;
_proto.removeEventListener = function removeEventListener(type, listener) {
if (this._listeners === undefined) {
return this;
}
var listeners = this._listeners;
if (listeners[type] === undefined) {
return this;
}
var index = listeners[type].indexOf(listener);
if (index !== -1) {
listeners[type].splice(index, 1);
}
return this;
}
/**
* Emit an event.
* @method dispatchEvent
* @param {Object} event
* @param {String} event.type
* @return {EventTarget} The self object, for chainability.
*/
;
_proto.dispatchEvent = function dispatchEvent(event) {
if (this._listeners === undefined) {
return this;
}
var listeners = this._listeners;
var listenerArray = listeners[event.type];
if (listenerArray !== undefined) {
event.target = this;
for (var i = 0, l = listenerArray.length; i < l; i++) {
listenerArray[i].call(this, event);
}
}
return this;
};
return EventTarget;
}();
/**
* A Quaternion describes a rotation in 3D space. The Quaternion is mathematically defined as Q = x*i + y*j + z*k + w, where (i,j,k) are imaginary basis vectors. (x,y,z) can be seen as a vector related to the axis of rotation, while the real multiplier, w, is related to the amount of rotation.
* @param {Number} x Multiplier of the imaginary basis vector i.
* @param {Number} y Multiplier of the imaginary basis vector j.
* @param {Number} z Multiplier of t