diff --git a/dist/aframe-physics-system.js b/dist/aframe-physics-system.js index dc754d8..7294af5 100644 --- a/dist/aframe-physics-system.js +++ b/dist/aframe-physics-system.js @@ -1,197 +1,197 @@ (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 i) { - var temp = j; + const temp = j; j = i; i = temp; } - return i + "-" + j in this.matrix; } /** @@ -684,18 +685,19 @@ var ObjectCollisionMatrix = /*#__PURE__*/function () { * @param {Body} j * @param {boolean} value */ - ; - - _proto.set = function set(bi, bj, value) { - var i = bi.id; - var j = bj.id; + set(bi, bj, value) { + let { + id: i + } = bi; + let { + id: j + } = bj; if (j > i) { - var temp = j; + const temp = j; j = i; i = temp; } - if (value) { this.matrix[i + "-" + j] = true; } else { @@ -706,9 +708,8 @@ var ObjectCollisionMatrix = /*#__PURE__*/function () { * Empty the matrix * @method reset */ - ; - _proto.reset = function reset() { + reset() { this.matrix = {}; } /** @@ -716,12 +717,9 @@ var ObjectCollisionMatrix = /*#__PURE__*/function () { * @method setNumObjects * @param {Number} n */ - ; - _proto.setNumObjects = function setNumObjects(n) {}; - - return ObjectCollisionMatrix; -}(); + setNumObjects(n) {} +} /** * A 3x3 matrix. @@ -730,12 +728,9 @@ var ObjectCollisionMatrix = /*#__PURE__*/function () { * @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]; - } - +exports.ObjectCollisionMatrix = ObjectCollisionMatrix; +class Mat3 { + constructor(elements = [0, 0, 0, 0, 0, 0, 0, 0, 0]) { this.elements = elements; } /** @@ -745,11 +740,8 @@ var Mat3 = /*#__PURE__*/function () { * @todo Create another function that immediately creates an identity matrix eg. eye() */ - - var _proto = Mat3.prototype; - - _proto.identity = function identity() { - var e = this.elements; + identity() { + const e = this.elements; e[0] = 1; e[1] = 0; e[2] = 0; @@ -764,10 +756,9 @@ var Mat3 = /*#__PURE__*/function () { * Set all elements to zero * @method setZero */ - ; - _proto.setZero = function setZero() { - var e = this.elements; + setZero() { + const e = this.elements; e[0] = 0; e[1] = 0; e[2] = 0; @@ -783,10 +774,9 @@ var Mat3 = /*#__PURE__*/function () { * @method setTrace * @param {Vec3} vec3 */ - ; - _proto.setTrace = function setTrace(vector) { - var e = this.elements; + setTrace(vector) { + const e = this.elements; e[0] = vector.x; e[4] = vector.y; e[8] = vector.z; @@ -796,14 +786,9 @@ var Mat3 = /*#__PURE__*/function () { * @method getTrace * @return {Vec3} */ - ; - - _proto.getTrace = function getTrace(target) { - if (target === void 0) { - target = new Vec3(); - } - var e = this.elements; + getTrace(target = new Vec3()) { + const e = this.elements; target.x = e[0]; target.y = e[4]; target.z = e[8]; @@ -814,17 +799,12 @@ var Mat3 = /*#__PURE__*/function () { * @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; + vmult(v, target = new Vec3()) { + const e = this.elements; + const x = v.x; + const y = v.y; + const 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; @@ -835,10 +815,9 @@ var Mat3 = /*#__PURE__*/function () { * @method smult * @param {Number} s */ - ; - _proto.smult = function smult(s) { - for (var i = 0; i < this.elements.length; i++) { + smult(s) { + for (let i = 0; i < this.elements.length; i++) { this.elements[i] *= s; } } @@ -848,27 +827,20 @@ var Mat3 = /*#__PURE__*/function () { * @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++) { + mmult(matrix, target = new Mat3()) { + const { + elements + } = matrix; + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 3; j++) { + let sum = 0.0; + for (let k = 0; k < 3; k++) { sum += elements[i + k * 3] * this.elements[k + j * 3]; } - target.elements[i + j * 3] = sum; } } - return target; } /** @@ -877,22 +849,15 @@ var Mat3 = /*#__PURE__*/function () { * @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++) { + scale(vector, target = new Mat3()) { + const e = this.elements; + const t = target.elements; + for (let 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; } /** @@ -903,68 +868,54 @@ var Mat3 = /*#__PURE__*/function () { * @return {Vec3} The solution x * @todo should reuse arrays */ - ; - - _proto.solve = function solve(b, target) { - if (target === void 0) { - target = new Vec3(); - } + solve(b, target = new Vec3()) { // Construct equations - var nr = 3; // num rows + const nr = 3; // num rows - var nc = 4; // num cols - - var eqns = []; - var i; - var j; + const nc = 4; // num cols + const eqns = []; + let i; + let 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; + let n = 3; + const k = n; + let np; + const kp = 4; // num rows + let 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]; + const multiplier = eqns[i + nc * j] / eqns[i + nc * i]; np = kp; - do { // do ligne( k ) = ligne( k ) - multiplier * ligne( i ) p = kp - np; @@ -974,15 +925,12 @@ var Mat3 = /*#__PURE__*/function () { } } 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; } /** @@ -993,9 +941,8 @@ var Mat3 = /*#__PURE__*/function () { * @param {Number} value Optional. If provided, the matrix element will be set to this value. * @return {Number} */ - ; - _proto.e = function e(row, column, value) { + e(row, column, value) { if (value === undefined) { return this.elements[column + 3 * row]; } else { @@ -1009,13 +956,11 @@ var Mat3 = /*#__PURE__*/function () { * @param {Mat3} source * @return {Mat3} this */ - ; - _proto.copy = function copy(matrix) { - for (var i = 0; i < matrix.elements.length; i++) { + copy(matrix) { + for (let i = 0; i < matrix.elements.length; i++) { this.elements[i] = matrix.elements[i]; } - return this; } /** @@ -1023,16 +968,13 @@ var Mat3 = /*#__PURE__*/function () { * @method toString * @return string */ - ; - _proto.toString = function toString() { - var r = ''; - var sep = ','; - - for (var i = 0; i < 9; i++) { + toString() { + let r = ''; + const sep = ','; + for (let i = 0; i < 9; i++) { r += this.elements[i] + sep; } - return r; } /** @@ -1041,32 +983,24 @@ var Mat3 = /*#__PURE__*/function () { * @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(); - } + reverse(target = new Mat3()) { // Construct equations - var nr = 3; // num rows + const nr = 3; // num rows - var nc = 6; // num cols - - var eqns = []; - var i; - var j; + const nc = 6; // num cols + const eqns = []; + let i; + let 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; @@ -1077,38 +1011,32 @@ var Mat3 = /*#__PURE__*/function () { 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; + let n = 3; + const k = n; + let np; + const kp = nc; // num rows + let 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]; + const multiplier = eqns[i + nc * j] / eqns[i + nc * i]; np = kp; - do { // do line( k ) = line( k ) - multiplier * line( i ) p = kp - np; @@ -1118,54 +1046,39 @@ var Mat3 = /*#__PURE__*/function () { } } 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]; - + const 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; + 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]; - + const multiplier = 1 / eqns[i + nc * i]; np = nc; - do { p = nc - np; - eqns[p + nc * i] = eqns[p + nc * i] * _multiplier2; + eqns[p + nc * i] = eqns[p + nc * i] * multiplier; } 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; } /** @@ -1173,26 +1086,25 @@ var Mat3 = /*#__PURE__*/function () { * @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; + + setRotationFromQuaternion(q) { + const x = q.x; + const y = q.y; + const z = q.z; + const w = q.w; + const x2 = x + x; + const y2 = y + y; + const z2 = z + z; + const xx = x * x2; + const xy = x * y2; + const xz = x * z2; + const yy = y * y2; + const yz = y * z2; + const zz = z * z2; + const wx = w * x2; + const wy = w * y2; + const wz = w * z2; + const e = this.elements; e[3 * 0 + 0] = 1 - (yy + zz); e[3 * 0 + 1] = xy - wz; e[3 * 0 + 2] = xz + wy; @@ -1210,27 +1122,18 @@ var Mat3 = /*#__PURE__*/function () { * @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++) { + transpose(target = new Mat3()) { + const Mt = target.elements; + const M = this.elements; + for (let i = 0; i !== 3; i++) { + for (let j = 0; j !== 3; j++) { Mt[3 * i + j] = M[3 * j + i]; } } - return target; - }; - - return Mat3; -}(); + } +} /** * 3-dimensional vector @@ -1244,21 +1147,9 @@ var Mat3 = /*#__PURE__*/function () { * 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; - } - +exports.Mat3 = Mat3; +class Vec3 { + constructor(x = 0.0, y = 0.0, z = 0.0) { this.x = x; this.y = y; this.z = z; @@ -1271,20 +1162,13 @@ var Vec3 = /*#__PURE__*/function () { * @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; + cross(vector, target = new Vec3()) { + const vx = vector.x; + const vy = vector.y; + const vz = vector.z; + const x = this.x; + const y = this.y; + const z = this.z; target.x = y * vz - z * vy; target.y = z * vx - x * vz; target.z = x * vy - y * vx; @@ -1298,9 +1182,8 @@ var Vec3 = /*#__PURE__*/function () { * @param {Number} z * @return Vec3 */ - ; - _proto.set = function set(x, y, z) { + set(x, y, z) { this.x = x; this.y = y; this.z = z; @@ -1310,9 +1193,8 @@ var Vec3 = /*#__PURE__*/function () { * Set all components of the vector to zero. * @method setZero */ - ; - _proto.setZero = function setZero() { + setZero() { this.x = this.y = this.z = 0; } /** @@ -1322,9 +1204,8 @@ var Vec3 = /*#__PURE__*/function () { * @param {Vec3} target Optional. * @return {Vec3} */ - ; - _proto.vadd = function vadd(vector, target) { + vadd(vector, target) { if (target) { target.x = vector.x + this.x; target.y = vector.y + this.y; @@ -1340,9 +1221,8 @@ var Vec3 = /*#__PURE__*/function () { * @param {Vec3} target Optional. Target to save in. * @return {Vec3} */ - ; - _proto.vsub = function vsub(vector, target) { + vsub(vector, target) { if (target) { target.x = this.x - vector.x; target.y = this.y - vector.y; @@ -1357,9 +1237,8 @@ var Vec3 = /*#__PURE__*/function () { * @see http://www8.cs.umu.se/kurser/TDBD24/VT06/lectures/Lecture6.pdf * @return {Mat3} */ - ; - _proto.crossmat = function crossmat() { + crossmat() { return new Mat3([0, -this.z, this.y, this.z, 0, -this.x, -this.y, this.x, 0]); } /** @@ -1367,16 +1246,14 @@ var Vec3 = /*#__PURE__*/function () { * @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); + normalize() { + const x = this.x; + const y = this.y; + const z = this.z; + const n = Math.sqrt(x * x + y * y + z * z); if (n > 0.0) { - var invN = 1 / n; + const invN = 1 / n; this.x *= invN; this.y *= invN; this.z *= invN; @@ -1386,7 +1263,6 @@ var Vec3 = /*#__PURE__*/function () { this.y = 0; this.z = 0; } - return n; } /** @@ -1395,18 +1271,12 @@ var Vec3 = /*#__PURE__*/function () { * @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); + unit(target = new Vec3()) { + const x = this.x; + const y = this.y; + const z = this.z; + let ninv = Math.sqrt(x * x + y * y + z * z); if (ninv > 0.0) { ninv = 1.0 / ninv; target.x = x * ninv; @@ -1417,7 +1287,6 @@ var Vec3 = /*#__PURE__*/function () { target.y = 0; target.z = 0; } - return target; } /** @@ -1425,12 +1294,11 @@ var Vec3 = /*#__PURE__*/function () { * @method length * @return {Number} */ - ; - _proto.length = function length() { - var x = this.x; - var y = this.y; - var z = this.z; + length() { + const x = this.x; + const y = this.y; + const z = this.z; return Math.sqrt(x * x + y * y + z * z); } /** @@ -1438,9 +1306,8 @@ var Vec3 = /*#__PURE__*/function () { * @method lengthSquared * @return {Number} */ - ; - _proto.lengthSquared = function lengthSquared() { + lengthSquared() { return this.dot(this); } /** @@ -1449,15 +1316,14 @@ var Vec3 = /*#__PURE__*/function () { * @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; + distanceTo(p) { + const x = this.x; + const y = this.y; + const z = this.z; + const px = p.x; + const py = p.y; + const pz = p.z; return Math.sqrt((px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z)); } /** @@ -1466,15 +1332,14 @@ var Vec3 = /*#__PURE__*/function () { * @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; + distanceSquared(p) { + const x = this.x; + const y = this.y; + const z = this.z; + const px = p.x; + const py = p.y; + const pz = p.z; return (px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z); } /** @@ -1484,16 +1349,11 @@ var Vec3 = /*#__PURE__*/function () { * @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; + scale(scalar, target = new Vec3()) { + const x = this.x; + const y = this.y; + const z = this.z; target.x = scalar * x; target.y = scalar * y; target.z = scalar * z; @@ -1506,13 +1366,8 @@ var Vec3 = /*#__PURE__*/function () { * @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(); - } + vmul(vector, target = new Vec3()) { target.x = vector.x * this.x; target.y = vector.y * this.y; target.z = vector.z * this.z; @@ -1526,13 +1381,8 @@ var Vec3 = /*#__PURE__*/function () { * @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(); - } + addScaledVector(scalar, vector, target = new Vec3()) { target.x = this.x + scalar * vector.x; target.y = this.y + scalar * vector.y; target.z = this.z + scalar * vector.z; @@ -1544,18 +1394,16 @@ var Vec3 = /*#__PURE__*/function () { * @param {Vec3} v * @return {Number} */ - ; - _proto.dot = function dot(vector) { + dot(vector) { return this.x * vector.x + this.y * vector.y + this.z * vector.z; } /** * @method isZero * @return bool */ - ; - _proto.isZero = function isZero() { + isZero() { return this.x === 0 && this.y === 0 && this.z === 0; } /** @@ -1564,13 +1412,8 @@ var Vec3 = /*#__PURE__*/function () { * @param {Vec3} target Optional target to save in * @return {Vec3} */ - ; - - _proto.negate = function negate(target) { - if (target === void 0) { - target = new Vec3(); - } + negate(target = new Vec3()) { target.x = -this.x; target.y = -this.y; target.z = -this.z; @@ -1582,17 +1425,14 @@ var Vec3 = /*#__PURE__*/function () { * @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(); + tangents(t1, t2) { + const norm = this.length(); if (norm > 0.0) { - var n = Vec3_tangents_n; - var inorm = 1 / norm; + const n = Vec3_tangents_n; + const inorm = 1 / norm; n.set(this.x * inorm, this.y * inorm, this.z * inorm); - var randVec = Vec3_tangents_randVec; - + const randVec = Vec3_tangents_randVec; if (Math.abs(n.x) < 0.9) { randVec.set(1, 0, 0); n.cross(randVec, t1); @@ -1600,7 +1440,6 @@ var Vec3 = /*#__PURE__*/function () { randVec.set(0, 1, 0); n.cross(randVec, t1); } - n.cross(t1, t2); } else { // The normal length is zero, make something up @@ -1613,9 +1452,8 @@ var Vec3 = /*#__PURE__*/function () { * @method toString * @return string */ - ; - _proto.toString = function toString() { + toString() { return this.x + "," + this.y + "," + this.z; } /** @@ -1623,9 +1461,8 @@ var Vec3 = /*#__PURE__*/function () { * @method toArray * @return Array */ - ; - _proto.toArray = function toArray() { + toArray() { return [this.x, this.y, this.z]; } /** @@ -1634,9 +1471,8 @@ var Vec3 = /*#__PURE__*/function () { * @param {Vec3} source * @return {Vec3} this */ - ; - _proto.copy = function copy(vector) { + copy(vector) { this.x = vector.x; this.y = vector.y; this.z = vector.z; @@ -1649,12 +1485,11 @@ var Vec3 = /*#__PURE__*/function () { * @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; + lerp(vector, t, target) { + const x = this.x; + const y = this.y; + const z = this.z; target.x = x + (vector.x - x) * t; target.y = y + (vector.y - y) * t; target.z = z + (vector.z - z) * t; @@ -1666,17 +1501,11 @@ var Vec3 = /*#__PURE__*/function () { * @param {Number} precision * @return bool */ - ; - - _proto.almostEquals = function almostEquals(vector, precision) { - if (precision === void 0) { - precision = 1e-6; - } + almostEquals(vector, 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; } /** @@ -1684,17 +1513,11 @@ var Vec3 = /*#__PURE__*/function () { * @method almostZero * @param {Number} precision */ - ; - - _proto.almostZero = function almostZero(precision) { - if (precision === void 0) { - precision = 1e-6; - } + almostZero(precision = 1e-6) { if (Math.abs(this.x) > precision || Math.abs(this.y) > precision || Math.abs(this.z) > precision) { return false; } - return true; } /** @@ -1704,9 +1527,8 @@ var Vec3 = /*#__PURE__*/function () { * @param {Number} precision Set to zero for exact comparisons * @return {Boolean} */ - ; - _proto.isAntiparallelTo = function isAntiparallelTo(vector, precision) { + isAntiparallelTo(vector, precision) { this.negate(antip_neg); return antip_neg.almostEquals(vector, precision); } @@ -1715,14 +1537,12 @@ var Vec3 = /*#__PURE__*/function () { * @method clone * @return {Vec3} */ - ; - _proto.clone = function clone() { + clone() { return new Vec3(this.x, this.y, this.z); - }; - - return Vec3; -}(); + } +} +exports.Vec3 = Vec3; Vec3.ZERO = new Vec3(0, 0, 0); Vec3.UNIT_X = new Vec3(1, 0, 0); Vec3.UNIT_Y = new Vec3(0, 1, 0); @@ -1734,9 +1554,9 @@ Vec3.UNIT_Z = new Vec3(0, 0, 1); * @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(); +const Vec3_tangents_n = new Vec3(); +const Vec3_tangents_randVec = new Vec3(); +const antip_neg = new Vec3(); /** * Axis aligned bounding box class. @@ -1746,21 +1566,15 @@ var antip_neg = new Vec3(); * @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 () { +class AABB { // The lower bound of the bounding box // The upper bound of the bounding box - function AABB(options) { - if (options === void 0) { - options = {}; - } - + constructor(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); } @@ -1775,61 +1589,46 @@ var AABB = /*#__PURE__*/function () { * @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 + setFromPoints(points, position, quaternion, skinSize) { + const l = this.lowerBound; + const u = this.upperBound; + const 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]; - + for (let i = 1; i < points.length; i++) { + let 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; @@ -1838,7 +1637,6 @@ var AABB = /*#__PURE__*/function () { u.y += skinSize; u.z += skinSize; } - return this; } /** @@ -1847,9 +1645,8 @@ var AABB = /*#__PURE__*/function () { * @param {AABB} aabb Source to copy from * @return {AABB} The this object, for chainability */ - ; - _proto.copy = function copy(aabb) { + copy(aabb) { this.lowerBound.copy(aabb.lowerBound); this.upperBound.copy(aabb.upperBound); return this; @@ -1858,9 +1655,8 @@ var AABB = /*#__PURE__*/function () { * Clone an AABB * @method clone */ - ; - _proto.clone = function clone() { + clone() { return new AABB().copy(this); } /** @@ -1868,9 +1664,8 @@ var AABB = /*#__PURE__*/function () { * @method extend * @param {AABB} aabb */ - ; - _proto.extend = function extend(aabb) { + 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); @@ -1884,27 +1679,25 @@ var AABB = /*#__PURE__*/function () { * @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 + overlaps(aabb) { + const l1 = this.lowerBound; + const u1 = this.upperBound; + const l2 = aabb.lowerBound; + const 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; + const overlapsX = l2.x <= u1.x && u1.x <= u2.x || l1.x <= u2.x && u2.x <= u1.x; + const overlapsY = l2.y <= u1.y && u1.y <= u2.y || l1.y <= u2.y && u2.y <= u1.y; + const 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; + volume() { + const l = this.lowerBound; + const u = this.upperBound; return (u.x - l.x) * (u.y - l.y) * (u.z - l.z); } /** @@ -1913,13 +1706,12 @@ var AABB = /*#__PURE__*/function () { * @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 + contains(aabb) { + const l1 = this.lowerBound; + const u1 = this.upperBound; + const l2 = aabb.lowerBound; + const u2 = aabb.upperBound; // l2 u2 // |---------| // |---------------| // l1 u1 @@ -1937,11 +1729,10 @@ var AABB = /*#__PURE__*/function () { * @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; + getCorners(a, b, c, d, e, f, g, h) { + const l = this.lowerBound; + const u = this.upperBound; a.copy(l); b.set(u.x, l.y, l.z); c.set(u.x, u.y, l.z); @@ -1958,26 +1749,24 @@ var AABB = /*#__PURE__*/function () { * @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 + toLocalFrame(frame, target) { + const corners = transformIntoFrame_corners; + const a = corners[0]; + const b = corners[1]; + const c = corners[2]; + const d = corners[3]; + const e = corners[4]; + const f = corners[5]; + const g = corners[6]; + const 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]; + for (let i = 0; i !== 8; i++) { + const corner = corners[i]; frame.pointToLocal(corner, corner); } - return target.setFromPoints(corners); } /** @@ -1987,26 +1776,24 @@ var AABB = /*#__PURE__*/function () { * @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 + toWorldFrame(frame, target) { + const corners = transformIntoFrame_corners; + const a = corners[0]; + const b = corners[1]; + const c = corners[2]; + const d = corners[3]; + const e = corners[4]; + const f = corners[5]; + const g = corners[6]; + const 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]; + for (let i = 0; i !== 8; i++) { + const corner = corners[i]; frame.pointToWorld(corner, corner); } - return target.setFromPoints(corners); } /** @@ -2014,54 +1801,51 @@ var AABB = /*#__PURE__*/function () { * @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))); + overlapsRay(ray) { + const { + direction, + from + } = ray; + const dirFracX = 1 / direction.x; + const dirFracY = 1 / direction.y; + const dirFracZ = 1 / direction.z; // this.lowerBound is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner + + const t1 = (this.lowerBound.x - from.x) * dirFracX; + const t2 = (this.upperBound.x - from.x) * dirFracX; + const t3 = (this.lowerBound.y - from.y) * dirFracY; + const t4 = (this.upperBound.y - from.y) * dirFracY; + const t5 = (this.lowerBound.z - from.z) * dirFracZ; + const 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 + const tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6)); + const 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()]; + } +} +exports.AABB = AABB; +const tmp = new Vec3(); +const 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 () { +class ArrayCollisionMatrix { // The matrix storage. - function ArrayCollisionMatrix() { + constructor() { this.matrix = []; } /** @@ -2072,19 +1856,18 @@ var ArrayCollisionMatrix = /*#__PURE__*/function () { * @return {Number} */ - - var _proto = ArrayCollisionMatrix.prototype; - - _proto.get = function get(bi, bj) { - var i = bi.index; - var j = bj.index; - + get(bi, bj) { + let { + index: i + } = bi; + let { + index: j + } = bj; if (j > i) { - var temp = j; + const temp = j; j = i; i = temp; } - return this.matrix[(i * (i + 1) >> 1) + j - 1]; } /** @@ -2094,28 +1877,28 @@ var ArrayCollisionMatrix = /*#__PURE__*/function () { * @param {Body} j * @param {boolean} value */ - ; - - _proto.set = function set(bi, bj, value) { - var i = bi.index; - var j = bj.index; + set(bi, bj, value) { + let { + index: i + } = bi; + let { + index: j + } = bj; if (j > i) { - var temp = j; + const 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++) { + reset() { + for (let i = 0, l = this.matrix.length; i !== l; i++) { this.matrix[i] = 0; } } @@ -2124,27 +1907,10 @@ var ArrayCollisionMatrix = /*#__PURE__*/function () { * @method setNumObjects * @param {Number} n */ - ; - _proto.setNumObjects = function setNumObjects(n) { + 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; } /** @@ -2152,8 +1918,9 @@ function _assertThisInitialized(self) { * @class EventTarget * @constructor */ -var EventTarget = /*#__PURE__*/function () { - function EventTarget() {} +exports.ArrayCollisionMatrix = ArrayCollisionMatrix; +class EventTarget { + constructor() {} /** * Add an event listener * @method addEventListener @@ -2162,24 +1929,17 @@ var EventTarget = /*#__PURE__*/function () { * @return {EventTarget} The self object, for chainability. */ - - var _proto = EventTarget.prototype; - - _proto.addEventListener = function addEventListener(type, listener) { + addEventListener(type, listener) { if (this._listeners === undefined) { this._listeners = {}; } - - var listeners = this._listeners; - + const listeners = this._listeners; if (listeners[type] === undefined) { listeners[type] = []; } - if (!listeners[type].includes(listener)) { listeners[type].push(listener); } - return this; } /** @@ -2189,19 +1949,15 @@ var EventTarget = /*#__PURE__*/function () { * @param {Function} listener * @return {Boolean} */ - ; - _proto.hasEventListener = function hasEventListener(type, listener) { + hasEventListener(type, listener) { if (this._listeners === undefined) { return false; } - - var listeners = this._listeners; - + const listeners = this._listeners; if (listeners[type] !== undefined && listeners[type].includes(listener)) { return true; } - return false; } /** @@ -2210,14 +1966,12 @@ var EventTarget = /*#__PURE__*/function () { * @param {String} type * @return {Boolean} */ - ; - _proto.hasAnyEventListener = function hasAnyEventListener(type) { + hasAnyEventListener(type) { if (this._listeners === undefined) { return false; } - - var listeners = this._listeners; + const listeners = this._listeners; return listeners[type] !== undefined; } /** @@ -2227,25 +1981,19 @@ var EventTarget = /*#__PURE__*/function () { * @param {Function} listener * @return {EventTarget} The self object, for chainability. */ - ; - _proto.removeEventListener = function removeEventListener(type, listener) { + removeEventListener(type, listener) { if (this._listeners === undefined) { return this; } - - var listeners = this._listeners; - + const listeners = this._listeners; if (listeners[type] === undefined) { return this; } - - var index = listeners[type].indexOf(listener); - + const index = listeners[type].indexOf(listener); if (index !== -1) { listeners[type].splice(index, 1); } - return this; } /** @@ -2255,29 +2003,22 @@ var EventTarget = /*#__PURE__*/function () { * @param {String} event.type * @return {EventTarget} The self object, for chainability. */ - ; - _proto.dispatchEvent = function dispatchEvent(event) { + dispatchEvent(event) { if (this._listeners === undefined) { return this; } - - var listeners = this._listeners; - var listenerArray = listeners[event.type]; - + const listeners = this._listeners; + const listenerArray = listeners[event.type]; if (listenerArray !== undefined) { event.target = this; - - for (var i = 0, l = listenerArray.length; i < l; i++) { + for (let 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. @@ -2287,25 +2028,9 @@ var EventTarget = /*#__PURE__*/function () { * @param {Number} w Multiplier of the real part. * @see http://en.wikipedia.org/wiki/Quaternion */ - -var Quaternion = /*#__PURE__*/function () { - function Quaternion(x, y, z, w) { - if (x === void 0) { - x = 0; - } - - if (y === void 0) { - y = 0; - } - - if (z === void 0) { - z = 0; - } - - if (w === void 0) { - w = 1; - } - +exports.EventTarget = EventTarget; +class Quaternion { + constructor(x = 0, y = 0, z = 0, w = 1) { this.x = x; this.y = y; this.z = z; @@ -2315,10 +2040,7 @@ var Quaternion = /*#__PURE__*/function () { * Set the value of the quaternion. */ - - var _proto = Quaternion.prototype; - - _proto.set = function set(x, y, z, w) { + set(x, y, z, w) { this.x = x; this.y = y; this.z = z; @@ -2329,27 +2051,24 @@ var Quaternion = /*#__PURE__*/function () { * Convert to a readable format * @return {String} "x,y,z,w" */ - ; - _proto.toString = function toString() { + toString() { return this.x + "," + this.y + "," + this.z + "," + this.w; } /** * Convert to an Array * @return {Array} [x, y, z, w] */ - ; - _proto.toArray = function toArray() { + toArray() { return [this.x, this.y, this.z, this.w]; } /** * Set the quaternion components given an axis and an angle in radians. */ - ; - _proto.setFromAxisAngle = function setFromAxisAngle(vector, angle) { - var s = Math.sin(angle * 0.5); + setFromAxisAngle(vector, angle) { + const s = Math.sin(angle * 0.5); this.x = vector.x * s; this.y = vector.y * s; this.z = vector.z * s; @@ -2361,17 +2080,12 @@ var Quaternion = /*#__PURE__*/function () { * @param {Vec3} [targetAxis] A vector object to reuse for storing the axis. * @return {Array} An array, first element is the axis and the second is the angle in radians. */ - ; - - _proto.toAxisAngle = function toAxisAngle(targetAxis) { - if (targetAxis === void 0) { - targetAxis = new Vec3(); - } + toAxisAngle(targetAxis = new Vec3()) { this.normalize(); // if w>1 acos and sqrt will produce errors, this cant happen if quaternion is normalised - var angle = 2 * Math.acos(this.w); - var s = Math.sqrt(1 - this.w * this.w); // assuming quaternion normalised then w is less than 1, so term always positive. + const angle = 2 * Math.acos(this.w); + const s = Math.sqrt(1 - this.w * this.w); // assuming quaternion normalised then w is less than 1, so term always positive. if (s < 0.001) { // test to avoid divide by zero, s is always positive due to sqrt @@ -2386,49 +2100,41 @@ var Quaternion = /*#__PURE__*/function () { targetAxis.y = this.y / s; targetAxis.z = this.z / s; } - return [targetAxis, angle]; } /** * Set the quaternion value given two vectors. The resulting rotation will be the needed rotation to rotate u to v. */ - ; - _proto.setFromVectors = function setFromVectors(u, v) { + setFromVectors(u, v) { if (u.isAntiparallelTo(v)) { - var t1 = sfv_t1; - var t2 = sfv_t2; + const t1 = sfv_t1; + const t2 = sfv_t2; u.tangents(t1, t2); this.setFromAxisAngle(t1, Math.PI); } else { - var a = u.cross(v); + const a = u.cross(v); this.x = a.x; this.y = a.y; this.z = a.z; - this.w = Math.sqrt(Math.pow(u.length(), 2) * Math.pow(v.length(), 2)) + u.dot(v); + this.w = Math.sqrt(u.length() ** 2 * v.length() ** 2) + u.dot(v); this.normalize(); } - return this; } /** * Multiply the quaternion with an other quaternion. */ - ; - - _proto.mult = function mult(quat, target) { - if (target === void 0) { - target = new Quaternion(); - } - var ax = this.x; - var ay = this.y; - var az = this.z; - var aw = this.w; - var bx = quat.x; - var by = quat.y; - var bz = quat.z; - var bw = quat.w; + mult(quat, target = new Quaternion()) { + const ax = this.x; + const ay = this.y; + const az = this.z; + const aw = this.w; + const bx = quat.x; + const by = quat.y; + const bz = quat.z; + const bw = quat.w; target.x = ax * bw + aw * bx + ay * bz - az * by; target.y = ay * bw + aw * by + az * bx - ax * bz; target.z = az * bw + aw * bz + ax * by - ay * bx; @@ -2438,19 +2144,14 @@ var Quaternion = /*#__PURE__*/function () { /** * Get the inverse quaternion rotation. */ - ; - _proto.inverse = function inverse(target) { - if (target === void 0) { - target = new Quaternion(); - } - - var x = this.x; - var y = this.y; - var z = this.z; - var w = this.w; + inverse(target = new Quaternion()) { + const x = this.x; + const y = this.y; + const z = this.z; + const w = this.w; this.conjugate(target); - var inorm2 = 1 / (x * x + y * y + z * z + w * w); + const inorm2 = 1 / (x * x + y * y + z * z + w * w); target.x *= inorm2; target.y *= inorm2; target.z *= inorm2; @@ -2460,13 +2161,8 @@ var Quaternion = /*#__PURE__*/function () { /** * Get the quaternion conjugate */ - ; - - _proto.conjugate = function conjugate(target) { - if (target === void 0) { - target = new Quaternion(); - } + conjugate(target = new Quaternion()) { target.x = -this.x; target.y = -this.y; target.z = -this.z; @@ -2477,11 +2173,9 @@ var Quaternion = /*#__PURE__*/function () { * Normalize the quaternion. Note that this changes the values of the quaternion. * @method normalize */ - ; - - _proto.normalize = function normalize() { - var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); + normalize() { + let l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); if (l === 0) { this.x = 0; this.y = 0; @@ -2494,7 +2188,6 @@ var Quaternion = /*#__PURE__*/function () { this.z *= l; this.w *= l; } - return this; } /** @@ -2502,11 +2195,9 @@ var Quaternion = /*#__PURE__*/function () { * @see http://jsperf.com/fast-quaternion-normalization * @author unphased, https://github.com/unphased */ - ; - - _proto.normalizeFast = function normalizeFast() { - var f = (3.0 - (this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w)) / 2.0; + normalizeFast() { + const f = (3.0 - (this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w)) / 2.0; if (f === 0) { this.x = 0; this.y = 0; @@ -2518,31 +2209,25 @@ var Quaternion = /*#__PURE__*/function () { this.z *= f; this.w *= f; } - return this; } /** * Multiply the quaternion by a vector */ - ; - _proto.vmult = function vmult(v, target) { - if (target === void 0) { - target = new Vec3(); - } - - var x = v.x; - var y = v.y; - var z = v.z; - var qx = this.x; - var qy = this.y; - var qz = this.z; - var qw = this.w; // q*v + vmult(v, target = new Vec3()) { + const x = v.x; + const y = v.y; + const z = v.z; + const qx = this.x; + const qy = this.y; + const qz = this.z; + const qw = this.w; // q*v - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; + const ix = qw * x + qy * z - qz * y; + const iy = qw * y + qz * x - qx * z; + const iz = qw * z + qx * y - qy * x; + const iw = -qx * x - qy * y - qz * z; target.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; target.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; target.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; @@ -2554,9 +2239,8 @@ var Quaternion = /*#__PURE__*/function () { * @param {Quaternion} source * @return {Quaternion} this */ - ; - _proto.copy = function copy(quat) { + copy(quat) { this.x = quat.x; this.y = quat.y; this.z = quat.z; @@ -2569,43 +2253,34 @@ var Quaternion = /*#__PURE__*/function () { * @param {Vec3} target * @param {String} order Three-character string, defaults to "YZX" */ - ; - - _proto.toEuler = function toEuler(target, order) { - if (order === void 0) { - order = 'YZX'; - } - - var heading; - var attitude; - var bank; - var x = this.x; - var y = this.y; - var z = this.z; - var w = this.w; + toEuler(target, order = 'YZX') { + let heading; + let attitude; + let bank; + const x = this.x; + const y = this.y; + const z = this.z; + const w = this.w; switch (order) { case 'YZX': - var test = x * y + z * w; - + const test = x * y + z * w; if (test > 0.499) { // singularity at north pole heading = 2 * Math.atan2(x, w); attitude = Math.PI / 2; bank = 0; } - if (test < -0.499) { // singularity at south pole heading = -2 * Math.atan2(x, w); attitude = -Math.PI / 2; bank = 0; } - if (heading === undefined) { - var sqx = x * x; - var sqy = y * y; - var sqz = z * z; + const sqx = x * x; + const sqy = y * y; + const sqz = z * z; heading = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz); // Heading attitude = Math.asin(2 * test); // attitude @@ -2614,11 +2289,9 @@ var Quaternion = /*#__PURE__*/function () { } break; - default: throw new Error("Euler order " + order + " not supported yet."); } - target.y = heading; target.z = attitude; target.x = bank; @@ -2630,20 +2303,14 @@ var Quaternion = /*#__PURE__*/function () { * @param {String} order The order to apply angles: 'XYZ' or 'YXZ' or any other combination * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m */ - ; - - _proto.setFromEuler = function setFromEuler(x, y, z, order) { - if (order === void 0) { - order = 'XYZ'; - } - - var c1 = Math.cos(x / 2); - var c2 = Math.cos(y / 2); - var c3 = Math.cos(z / 2); - var s1 = Math.sin(x / 2); - var s2 = Math.sin(y / 2); - var s3 = Math.sin(z / 2); + setFromEuler(x, y, z, order = 'XYZ') { + const c1 = Math.cos(x / 2); + const c2 = Math.cos(y / 2); + const c3 = Math.cos(z / 2); + const s1 = Math.sin(x / 2); + const s2 = Math.sin(y / 2); + const s3 = Math.sin(z / 2); if (order === 'XYZ') { this.x = s1 * c2 * c3 + c1 * s2 * s3; this.y = c1 * s2 * c3 - s1 * c2 * s3; @@ -2675,16 +2342,14 @@ var Quaternion = /*#__PURE__*/function () { this.z = c1 * c2 * s3 + s1 * s2 * c3; this.w = c1 * c2 * c3 + s1 * s2 * s3; } - return this; } /** * @method clone * @return {Quaternion} */ - ; - _proto.clone = function clone() { + clone() { return new Quaternion(this.x, this.y, this.z, this.w); } /** @@ -2695,26 +2360,21 @@ var Quaternion = /*#__PURE__*/function () { * @param {Quaternion} [target] A quaternion to store the result in. If not provided, a new one will be created. * @returns {Quaternion} The "target" object */ - ; - - _proto.slerp = function slerp(toQuat, t, target) { - if (target === void 0) { - target = new Quaternion(); - } - var ax = this.x; - var ay = this.y; - var az = this.z; - var aw = this.w; - var bx = toQuat.x; - var by = toQuat.y; - var bz = toQuat.z; - var bw = toQuat.w; - var omega; - var cosom; - var sinom; - var scale0; - var scale1; // calc cosine + slerp(toQuat, t, target = new Quaternion()) { + const ax = this.x; + const ay = this.y; + const az = this.z; + const aw = this.w; + let bx = toQuat.x; + let by = toQuat.y; + let bz = toQuat.z; + let bw = toQuat.w; + let omega; + let cosom; + let sinom; + let scale0; + let scale1; // calc cosine cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary) @@ -2726,7 +2386,6 @@ var Quaternion = /*#__PURE__*/function () { bw = -bw; } // calculate coefficients - if (1.0 - cosom > 0.000001) { // standard case (slerp) omega = Math.acos(cosom); @@ -2740,7 +2399,6 @@ var Quaternion = /*#__PURE__*/function () { scale1 = t; } // calculate final values - target.x = scale0 * ax + scale1 * bx; target.y = scale0 * ay + scale1 * by; target.z = scale0 * az + scale1 * bz; @@ -2750,34 +2408,27 @@ var Quaternion = /*#__PURE__*/function () { /** * Rotate an absolute orientation quaternion given an angular velocity and a time step. */ - ; - - _proto.integrate = function integrate(angularVelocity, dt, angularFactor, target) { - if (target === void 0) { - target = new Quaternion(); - } - var ax = angularVelocity.x * angularFactor.x, - ay = angularVelocity.y * angularFactor.y, - az = angularVelocity.z * angularFactor.z, - bx = this.x, - by = this.y, - bz = this.z, - bw = this.w; - var half_dt = dt * 0.5; + integrate(angularVelocity, dt, angularFactor, target = new Quaternion()) { + const ax = angularVelocity.x * angularFactor.x, + ay = angularVelocity.y * angularFactor.y, + az = angularVelocity.z * angularFactor.z, + bx = this.x, + by = this.y, + bz = this.z, + bw = this.w; + const half_dt = dt * 0.5; target.x += half_dt * (ax * bw + ay * bz - az * by); target.y += half_dt * (ay * bw + az * bx - ax * bz); target.z += half_dt * (az * bw + ax * by - ay * bx); target.w += half_dt * (-ax * bx - ay * by - az * bz); return target; - }; - - return Quaternion; -}(); -var sfv_t1 = new Vec3(); -var sfv_t2 = new Vec3(); - -var SHAPE_TYPES = { + } +} +exports.Quaternion = Quaternion; +const sfv_t1 = new Vec3(); +const sfv_t2 = new Vec3(); +const SHAPE_TYPES = exports.SHAPE_TYPES = { SPHERE: 1, PLANE: 2, BOX: 4, @@ -2800,16 +2451,12 @@ var SHAPE_TYPES = { * @param {number} [options.material=null] * @author schteppe */ -var Shape = /*#__PURE__*/function () { +class Shape { // Identifyer of the Shape. // The type of this shape. Must be set to an int > 0 by subclasses. // The local bounding sphere radius of this shape. // Whether to produce contact forces when in contact with other bodies. Note that contacts will be generated, but they will be disabled. - function Shape(options) { - if (options === void 0) { - options = {}; - } - + constructor(options = {}) { this.id = Shape.idCounter++; this.type = options.type || 0; this.boundingSphereRadius = 0; @@ -2824,10 +2471,7 @@ var Shape = /*#__PURE__*/function () { * @method updateBoundingSphereRadius */ - - var _proto = Shape.prototype; - - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + updateBoundingSphereRadius() { throw "computeBoundingSphereRadius() not implemented for shape type " + this.type; } /** @@ -2835,9 +2479,8 @@ var Shape = /*#__PURE__*/function () { * @method volume * @return {Number} */ - ; - _proto.volume = function volume() { + volume() { throw "volume() not implemented for shape type " + this.type; } /** @@ -2847,18 +2490,15 @@ var Shape = /*#__PURE__*/function () { * @param {Vec3} target * @see http://en.wikipedia.org/wiki/List_of_moments_of_inertia */ - ; - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { + calculateLocalInertia(mass, target) { throw "calculateLocalInertia() not implemented for shape type " + this.type; - }; - - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { + } + calculateWorldAABB(pos, quat, min, max) { throw "calculateWorldAABB() not implemented for shape type " + this.type; - }; - - return Shape; -}(); + } +} +exports.Shape = Shape; Shape.idCounter = 0; /** * The available shape types. @@ -2868,20 +2508,13 @@ Shape.idCounter = 0; */ Shape.types = SHAPE_TYPES; - -var Transform = /*#__PURE__*/function () { - function Transform(options) { - if (options === void 0) { - options = {}; - } - +class Transform { + constructor(options = {}) { this.position = new Vec3(); this.quaternion = new Quaternion(); - if (options.position) { this.position.copy(options.position); } - if (options.quaternion) { this.quaternion.copy(options.quaternion); } @@ -2890,74 +2523,44 @@ var Transform = /*#__PURE__*/function () { * Get a global point in local transform coordinates. */ - - var _proto = Transform.prototype; - - _proto.pointToLocal = function pointToLocal(worldPoint, result) { + pointToLocal(worldPoint, result) { return Transform.pointToLocalFrame(this.position, this.quaternion, worldPoint, result); } /** * Get a local point in global transform coordinates. */ - ; - _proto.pointToWorld = function pointToWorld(localPoint, result) { + pointToWorld(localPoint, result) { return Transform.pointToWorldFrame(this.position, this.quaternion, localPoint, result); - }; - - _proto.vectorToWorldFrame = function vectorToWorldFrame(localVector, result) { - if (result === void 0) { - result = new Vec3(); - } - + } + vectorToWorldFrame(localVector, result = new Vec3()) { this.quaternion.vmult(localVector, result); return result; - }; - - Transform.pointToLocalFrame = function pointToLocalFrame(position, quaternion, worldPoint, result) { - if (result === void 0) { - result = new Vec3(); - } - + } + static pointToLocalFrame(position, quaternion, worldPoint, result = new Vec3()) { worldPoint.vsub(position, result); quaternion.conjugate(tmpQuat); tmpQuat.vmult(result, result); return result; - }; - - Transform.pointToWorldFrame = function pointToWorldFrame(position, quaternion, localPoint, result) { - if (result === void 0) { - result = new Vec3(); - } - + } + static pointToWorldFrame(position, quaternion, localPoint, result = new Vec3()) { quaternion.vmult(localPoint, result); result.vadd(position, result); return result; - }; - - Transform.vectorToWorldFrame = function vectorToWorldFrame(quaternion, localVector, result) { - if (result === void 0) { - result = new Vec3(); - } - + } + static vectorToWorldFrame(quaternion, localVector, result = new Vec3()) { quaternion.vmult(localVector, result); return result; - }; - - Transform.vectorToLocalFrame = function vectorToLocalFrame(position, quaternion, worldVector, result) { - if (result === void 0) { - result = new Vec3(); - } - + } + static vectorToLocalFrame(position, quaternion, worldVector, result = new Vec3()) { quaternion.w *= -1; quaternion.vmult(worldVector, result); quaternion.w *= -1; return result; - }; - - return Transform; -}(); -var tmpQuat = new Quaternion(); + } +} +exports.Transform = Transform; +const tmpQuat = new Quaternion(); /** * A set of polygons describing a convex shape. @@ -2977,89 +2580,66 @@ var tmpQuat = new Quaternion(); * @todo Move the clipping functions to ContactGenerator? * @todo Automatically merge coplanar polygons in constructor. */ -var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { - _inheritsLoose(ConvexPolyhedron, _Shape); - +class ConvexPolyhedron extends Shape { // Array of integer arrays, indicating which vertices each face consists of // If given, these locally defined, normalized axes are the only ones being checked when doing separating axis check. - function ConvexPolyhedron(props) { - var _this; - - if (props === void 0) { - props = {}; - } - - var _props = props, - _props$vertices = _props.vertices, - vertices = _props$vertices === void 0 ? [] : _props$vertices, - _props$faces = _props.faces, - faces = _props$faces === void 0 ? [] : _props$faces, - _props$normals = _props.normals, - normals = _props$normals === void 0 ? [] : _props$normals, - axes = _props.axes, - boundingSphereRadius = _props.boundingSphereRadius; - _this = _Shape.call(this, { + constructor(props = {}) { + const { + vertices = [], + faces = [], + normals = [], + axes, + boundingSphereRadius + } = props; + super({ type: Shape.types.CONVEXPOLYHEDRON - }) || this; - _this.vertices = vertices; - _this.faces = faces; - _this.faceNormals = normals; - - if (_this.faceNormals.length === 0) { - _this.computeNormals(); + }); + this.vertices = vertices; + this.faces = faces; + this.faceNormals = normals; + if (this.faceNormals.length === 0) { + this.computeNormals(); } - if (!boundingSphereRadius) { - _this.updateBoundingSphereRadius(); + this.updateBoundingSphereRadius(); } else { - _this.boundingSphereRadius = boundingSphereRadius; + this.boundingSphereRadius = boundingSphereRadius; } + this.worldVertices = []; // World transformed version of .vertices - _this.worldVertices = []; // World transformed version of .vertices + this.worldVerticesNeedsUpdate = true; + this.worldFaceNormals = []; // World transformed version of .faceNormals - _this.worldVerticesNeedsUpdate = true; - _this.worldFaceNormals = []; // World transformed version of .faceNormals - - _this.worldFaceNormalsNeedsUpdate = true; - _this.uniqueAxes = axes ? axes.slice() : null; - _this.uniqueEdges = []; - - _this.computeEdges(); - - return _this; + this.worldFaceNormalsNeedsUpdate = true; + this.uniqueAxes = axes ? axes.slice() : null; + this.uniqueEdges = []; + this.computeEdges(); } /** * Computes uniqueEdges * @method computeEdges */ - - var _proto = ConvexPolyhedron.prototype; - - _proto.computeEdges = function computeEdges() { - var faces = this.faces; - var vertices = this.vertices; - var edges = this.uniqueEdges; + computeEdges() { + const faces = this.faces; + const vertices = this.vertices; + const edges = this.uniqueEdges; edges.length = 0; - var edge = new Vec3(); - - for (var i = 0; i !== faces.length; i++) { - var face = faces[i]; - var numVertices = face.length; - - for (var j = 0; j !== numVertices; j++) { - var k = (j + 1) % numVertices; + const edge = new Vec3(); + for (let i = 0; i !== faces.length; i++) { + const face = faces[i]; + const numVertices = face.length; + for (let j = 0; j !== numVertices; j++) { + const k = (j + 1) % numVertices; vertices[face[j]].vsub(vertices[face[k]], edge); edge.normalize(); - var found = false; - - for (var p = 0; p !== edges.length; p++) { + let found = false; + for (let p = 0; p !== edges.length; p++) { if (edges[p].almostEquals(edge) || edges[p].almostEquals(edge)) { found = true; break; } } - if (!found) { edges.push(edge.clone()); } @@ -3070,30 +2650,26 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * Compute the normals of the faces. Will reuse existing Vec3 objects in the .faceNormals array if they exist. * @method computeNormals */ - ; - _proto.computeNormals = function computeNormals() { + computeNormals() { this.faceNormals.length = this.faces.length; // Generate normals - for (var i = 0; i < this.faces.length; i++) { + for (let i = 0; i < this.faces.length; i++) { // Check so all vertices exists for this face - for (var j = 0; j < this.faces[i].length; j++) { + for (let j = 0; j < this.faces[i].length; j++) { if (!this.vertices[this.faces[i][j]]) { throw new Error("Vertex " + this.faces[i][j] + " not found!"); } } - - var n = this.faceNormals[i] || new Vec3(); + const n = this.faceNormals[i] || new Vec3(); this.getFaceNormal(i, n); n.negate(n); this.faceNormals[i] = n; - var vertex = this.vertices[this.faces[i][0]]; - + const vertex = this.vertices[this.faces[i][0]]; if (n.dot(vertex) < 0) { console.error(".faceNormals[" + i + "] = Vec3(" + n.toString() + ") looks like it points into the shape? The vertices follow. Make sure they are ordered CCW around the normal, using the right hand rule."); - - for (var _j = 0; _j < this.faces[i].length; _j++) { - console.warn(".vertices[" + this.faces[i][_j] + "] = Vec3(" + this.vertices[this.faces[i][_j]].toString() + ")"); + for (let j = 0; j < this.faces[i].length; j++) { + console.warn(".vertices[" + this.faces[i][j] + "] = Vec3(" + this.vertices[this.faces[i][j]].toString() + ")"); } } } @@ -3104,13 +2680,12 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Number} i * @param {Vec3} target */ - ; - _proto.getFaceNormal = function getFaceNormal(i, target) { - var f = this.faces[i]; - var va = this.vertices[f[0]]; - var vb = this.vertices[f[1]]; - var vc = this.vertices[f[2]]; + getFaceNormal(i, target) { + const f = this.faces[i]; + const va = this.vertices[f[0]]; + const vb = this.vertices[f[1]]; + const vc = this.vertices[f[2]]; ConvexPolyhedron.computeNormal(va, vb, vc, target); } /** @@ -3125,35 +2700,29 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Number} maxDist * @param {array} result The an array of contact point objects, see clipFaceAgainstHull */ - ; - _proto.clipAgainstHull = function clipAgainstHull(posA, quatA, hullB, posB, quatB, separatingNormal, minDist, maxDist, result) { - var WorldNormal = new Vec3(); - var closestFaceB = -1; - var dmax = -Number.MAX_VALUE; - - for (var face = 0; face < hullB.faces.length; face++) { + clipAgainstHull(posA, quatA, hullB, posB, quatB, separatingNormal, minDist, maxDist, result) { + const WorldNormal = new Vec3(); + let closestFaceB = -1; + let dmax = -Number.MAX_VALUE; + for (let face = 0; face < hullB.faces.length; face++) { WorldNormal.copy(hullB.faceNormals[face]); quatB.vmult(WorldNormal, WorldNormal); - var d = WorldNormal.dot(separatingNormal); - + const d = WorldNormal.dot(separatingNormal); if (d > dmax) { dmax = d; closestFaceB = face; } } - - var worldVertsB1 = []; - - for (var i = 0; i < hullB.faces[closestFaceB].length; i++) { - var b = hullB.vertices[hullB.faces[closestFaceB][i]]; - var worldb = new Vec3(); + const worldVertsB1 = []; + for (let i = 0; i < hullB.faces[closestFaceB].length; i++) { + const b = hullB.vertices[hullB.faces[closestFaceB][i]]; + const worldb = new Vec3(); worldb.copy(b); quatB.vmult(worldb, worldb); posB.vadd(worldb, worldb); worldVertsB1.push(worldb); } - if (closestFaceB >= 0) { this.clipFaceAgainstHull(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result); } @@ -3169,32 +2738,28 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Vec3} target The target vector to save the axis in * @return {bool} Returns false if a separation is found, else true */ - ; - - _proto.findSeparatingAxis = function findSeparatingAxis(hullB, posA, quatA, posB, quatB, target, faceListA, faceListB) { - var faceANormalWS3 = new Vec3(); - var Worldnormal1 = new Vec3(); - var deltaC = new Vec3(); - var worldEdge0 = new Vec3(); - var worldEdge1 = new Vec3(); - var Cross = new Vec3(); - var dmin = Number.MAX_VALUE; - var hullA = this; + findSeparatingAxis(hullB, posA, quatA, posB, quatB, target, faceListA, faceListB) { + const faceANormalWS3 = new Vec3(); + const Worldnormal1 = new Vec3(); + const deltaC = new Vec3(); + const worldEdge0 = new Vec3(); + const worldEdge1 = new Vec3(); + const Cross = new Vec3(); + let dmin = Number.MAX_VALUE; + const hullA = this; if (!hullA.uniqueAxes) { - var numFacesA = faceListA ? faceListA.length : hullA.faces.length; // Test face normals from hullA + const numFacesA = faceListA ? faceListA.length : hullA.faces.length; // Test face normals from hullA - for (var i = 0; i < numFacesA; i++) { - var fi = faceListA ? faceListA[i] : i; // Get world face normal + for (let i = 0; i < numFacesA; i++) { + const fi = faceListA ? faceListA[i] : i; // Get world face normal faceANormalWS3.copy(hullA.faceNormals[fi]); quatA.vmult(faceANormalWS3, faceANormalWS3); - var d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB); - + const d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB); if (d === false) { return false; } - if (d < dmin) { dmin = d; target.copy(faceANormalWS3); @@ -3202,80 +2767,63 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { } } else { // Test unique axes - for (var _i = 0; _i !== hullA.uniqueAxes.length; _i++) { + for (let i = 0; i !== hullA.uniqueAxes.length; i++) { // Get world axis - quatA.vmult(hullA.uniqueAxes[_i], faceANormalWS3); - - var _d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB); - - if (_d === false) { + quatA.vmult(hullA.uniqueAxes[i], faceANormalWS3); + const d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB); + if (d === false) { return false; } - - if (_d < dmin) { - dmin = _d; + if (d < dmin) { + dmin = d; target.copy(faceANormalWS3); } } } - if (!hullB.uniqueAxes) { // Test face normals from hullB - var numFacesB = faceListB ? faceListB.length : hullB.faces.length; - - for (var _i2 = 0; _i2 < numFacesB; _i2++) { - var _fi = faceListB ? faceListB[_i2] : _i2; - - Worldnormal1.copy(hullB.faceNormals[_fi]); + const numFacesB = faceListB ? faceListB.length : hullB.faces.length; + for (let i = 0; i < numFacesB; i++) { + const fi = faceListB ? faceListB[i] : i; + Worldnormal1.copy(hullB.faceNormals[fi]); quatB.vmult(Worldnormal1, Worldnormal1); - - var _d2 = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB); - - if (_d2 === false) { + const d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB); + if (d === false) { return false; } - - if (_d2 < dmin) { - dmin = _d2; + if (d < dmin) { + dmin = d; target.copy(Worldnormal1); } } } else { // Test unique axes in B - for (var _i3 = 0; _i3 !== hullB.uniqueAxes.length; _i3++) { - quatB.vmult(hullB.uniqueAxes[_i3], Worldnormal1); - - var _d3 = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB); - - if (_d3 === false) { + for (let i = 0; i !== hullB.uniqueAxes.length; i++) { + quatB.vmult(hullB.uniqueAxes[i], Worldnormal1); + const d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB); + if (d === false) { return false; } - - if (_d3 < dmin) { - dmin = _d3; + if (d < dmin) { + dmin = d; target.copy(Worldnormal1); } } } // Test edges - - for (var e0 = 0; e0 !== hullA.uniqueEdges.length; e0++) { + for (let e0 = 0; e0 !== hullA.uniqueEdges.length; e0++) { // Get world edge quatA.vmult(hullA.uniqueEdges[e0], worldEdge0); - - for (var e1 = 0; e1 !== hullB.uniqueEdges.length; e1++) { + for (let e1 = 0; e1 !== hullB.uniqueEdges.length; e1++) { // Get world edge 2 quatB.vmult(hullB.uniqueEdges[e1], worldEdge1); worldEdge0.cross(worldEdge1, Cross); - if (!Cross.almostZero()) { Cross.normalize(); - var dist = hullA.testSepAxis(Cross, hullB, posA, quatA, posB, quatB); - + const dist = hullA.testSepAxis(Cross, hullB, posA, quatA, posB, quatB); if (dist === false) { return false; } - if (dist < dmin) { dmin = dist; target.copy(Cross); @@ -3283,13 +2831,10 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { } } } - posB.vsub(posA, deltaC); - if (deltaC.dot(target) > 0.0) { target.negate(target); } - return true; } /** @@ -3303,24 +2848,22 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Quaternion} quatB * @return {number} The overlap depth, or FALSE if no penetration. */ - ; - _proto.testSepAxis = function testSepAxis(axis, hullB, posA, quatA, posB, quatB) { - var hullA = this; + testSepAxis(axis, hullB, posA, quatA, posB, quatB) { + const hullA = this; ConvexPolyhedron.project(hullA, axis, posA, quatA, maxminA); ConvexPolyhedron.project(hullB, axis, posB, quatB, maxminB); - var maxA = maxminA[0]; - var minA = maxminA[1]; - var maxB = maxminB[0]; - var minB = maxminB[1]; - + const maxA = maxminA[0]; + const minA = maxminA[1]; + const maxB = maxminB[0]; + const minB = maxminB[1]; if (maxA < minB || maxB < minA) { return false; // Separated } - var d0 = maxA - minB; - var d1 = maxB - minA; - var depth = d0 < d1 ? d0 : d1; + const d0 = maxA - minB; + const d1 = maxB - minA; + const depth = d0 < d1 ? d0 : d1; return depth; } /** @@ -3328,17 +2871,16 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Number} mass * @param {Vec3} target */ - ; - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { + calculateLocalInertia(mass, target) { // Approximate with box inertia // Exact inertia calculation is overkill, but see http://geometrictools.com/Documentation/PolyhedralMassProperties.pdf for the correct way to do it - var aabbmax = new Vec3(); - var aabbmin = new Vec3(); + const aabbmax = new Vec3(); + const aabbmin = new Vec3(); this.computeLocalAABB(aabbmin, aabbmax); - var x = aabbmax.x - aabbmin.x; - var y = aabbmax.y - aabbmin.y; - var z = aabbmax.z - aabbmin.z; + const x = aabbmax.x - aabbmin.x; + const y = aabbmax.y - aabbmin.y; + const z = aabbmax.z - aabbmin.z; target.x = 1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * z * 2 * z); target.y = 1.0 / 12.0 * mass * (2 * x * 2 * x + 2 * z * 2 * z); target.z = 1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * x * 2 * x); @@ -3348,13 +2890,12 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Number} face_i Index of the face * @return {Number} */ - ; - _proto.getPlaneConstantOfFace = function getPlaneConstantOfFace(face_i) { - var f = this.faces[face_i]; - var n = this.faceNormals[face_i]; - var v = this.vertices[f[0]]; - var c = -n.dot(v); + getPlaneConstantOfFace(face_i) { + const f = this.faces[face_i]; + const n = this.faceNormals[face_i]; + const v = this.vertices[f[0]]; + const c = -n.dot(v); return c; } /** @@ -3368,51 +2909,43 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Number} maxDist * @param Array result Array to store resulting contact points in. Will be objects with properties: point, depth, normal. These are represented in world coordinates. */ - ; - - _proto.clipFaceAgainstHull = function clipFaceAgainstHull(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result) { - var faceANormalWS = new Vec3(); - var edge0 = new Vec3(); - var WorldEdge0 = new Vec3(); - var worldPlaneAnormal1 = new Vec3(); - var planeNormalWS1 = new Vec3(); - var worldA1 = new Vec3(); - var localPlaneNormal = new Vec3(); - var planeNormalWS = new Vec3(); - var hullA = this; - var worldVertsB2 = []; - var pVtxIn = worldVertsB1; - var pVtxOut = worldVertsB2; - var closestFaceA = -1; - var dmin = Number.MAX_VALUE; // Find the face with normal closest to the separating axis - - for (var face = 0; face < hullA.faces.length; face++) { + + clipFaceAgainstHull(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result) { + const faceANormalWS = new Vec3(); + const edge0 = new Vec3(); + const WorldEdge0 = new Vec3(); + const worldPlaneAnormal1 = new Vec3(); + const planeNormalWS1 = new Vec3(); + const worldA1 = new Vec3(); + const localPlaneNormal = new Vec3(); + const planeNormalWS = new Vec3(); + const hullA = this; + const worldVertsB2 = []; + const pVtxIn = worldVertsB1; + const pVtxOut = worldVertsB2; + let closestFaceA = -1; + let dmin = Number.MAX_VALUE; // Find the face with normal closest to the separating axis + + for (let face = 0; face < hullA.faces.length; face++) { faceANormalWS.copy(hullA.faceNormals[face]); quatA.vmult(faceANormalWS, faceANormalWS); - var d = faceANormalWS.dot(separatingNormal); - + const d = faceANormalWS.dot(separatingNormal); if (d < dmin) { dmin = d; closestFaceA = face; } } - if (closestFaceA < 0) { return; } // Get the face and construct connected faces - - var polyA = hullA.faces[closestFaceA]; + const polyA = hullA.faces[closestFaceA]; polyA.connectedFaces = []; - - for (var i = 0; i < hullA.faces.length; i++) { - for (var j = 0; j < hullA.faces[i].length; j++) { - if ( - /* Sharing a vertex*/ - polyA.indexOf(hullA.faces[i][j]) !== -1 && - /* Not the one we are looking for connections from */ - i !== closestFaceA && - /* Not already added */ + for (let i = 0; i < hullA.faces.length; i++) { + for (let j = 0; j < hullA.faces[i].length; j++) { + if ( /* Sharing a vertex*/ + polyA.indexOf(hullA.faces[i][j]) !== -1 && /* Not the one we are looking for connections from */ + i !== closestFaceA && /* Not already added */ polyA.connectedFaces.indexOf(i) === -1) { polyA.connectedFaces.push(i); } @@ -3420,12 +2953,10 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { } // Clip the polygon to the back of the planes of all faces of hull A, // that are adjacent to the witness face - - var numVerticesA = polyA.length; - - for (var _i4 = 0; _i4 < numVerticesA; _i4++) { - var a = hullA.vertices[polyA[_i4]]; - var b = hullA.vertices[polyA[(_i4 + 1) % numVerticesA]]; + const numVerticesA = polyA.length; + for (let i = 0; i < numVerticesA; i++) { + const a = hullA.vertices[polyA[i]]; + const b = hullA.vertices[polyA[(i + 1) % numVerticesA]]; a.vsub(b, edge0); WorldEdge0.copy(edge0); quatA.vmult(WorldEdge0, WorldEdge0); @@ -3438,51 +2969,42 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { worldA1.copy(a); quatA.vmult(worldA1, worldA1); posA.vadd(worldA1, worldA1); - var otherFace = polyA.connectedFaces[_i4]; + const otherFace = polyA.connectedFaces[i]; localPlaneNormal.copy(this.faceNormals[otherFace]); - - var _localPlaneEq = this.getPlaneConstantOfFace(otherFace); - + const localPlaneEq = this.getPlaneConstantOfFace(otherFace); planeNormalWS.copy(localPlaneNormal); quatA.vmult(planeNormalWS, planeNormalWS); + const planeEqWS = localPlaneEq - planeNormalWS.dot(posA); // Clip face against our constructed plane - var _planeEqWS = _localPlaneEq - planeNormalWS.dot(posA); // Clip face against our constructed plane - - - this.clipFaceAgainstPlane(pVtxIn, pVtxOut, planeNormalWS, _planeEqWS); // Throw away all clipped points, but save the remaining until next clip + this.clipFaceAgainstPlane(pVtxIn, pVtxOut, planeNormalWS, planeEqWS); // Throw away all clipped points, but save the remaining until next clip while (pVtxIn.length) { pVtxIn.shift(); } - while (pVtxOut.length) { pVtxIn.push(pVtxOut.shift()); } } // only keep contact points that are behind the witness face - localPlaneNormal.copy(this.faceNormals[closestFaceA]); - var localPlaneEq = this.getPlaneConstantOfFace(closestFaceA); + const localPlaneEq = this.getPlaneConstantOfFace(closestFaceA); planeNormalWS.copy(localPlaneNormal); quatA.vmult(planeNormalWS, planeNormalWS); - var planeEqWS = localPlaneEq - planeNormalWS.dot(posA); - - for (var _i5 = 0; _i5 < pVtxIn.length; _i5++) { - var depth = planeNormalWS.dot(pVtxIn[_i5]) + planeEqWS; // ??? + const planeEqWS = localPlaneEq - planeNormalWS.dot(posA); + for (let i = 0; i < pVtxIn.length; i++) { + let depth = planeNormalWS.dot(pVtxIn[i]) + planeEqWS; // ??? if (depth <= minDist) { console.log("clamped: depth=" + depth + " to minDist=" + minDist); depth = minDist; } - if (depth <= maxDist) { - var point = pVtxIn[_i5]; - + const point = pVtxIn[i]; if (depth <= 1e-6) { - var p = { - point: point, + const p = { + point, normal: planeNormalWS, - depth: depth + depth }; result.push(p); } @@ -3497,93 +3019,75 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Vec3} planeNormal * @param {Number} planeConstant The constant in the mathematical plane equation */ - ; - - _proto.clipFaceAgainstPlane = function clipFaceAgainstPlane(inVertices, outVertices, planeNormal, planeConstant) { - var n_dot_first; - var n_dot_last; - var numVerts = inVertices.length; + clipFaceAgainstPlane(inVertices, outVertices, planeNormal, planeConstant) { + let n_dot_first; + let n_dot_last; + const numVerts = inVertices.length; if (numVerts < 2) { return outVertices; } - - var firstVertex = inVertices[inVertices.length - 1]; - var lastVertex = inVertices[0]; + let firstVertex = inVertices[inVertices.length - 1]; + let lastVertex = inVertices[0]; n_dot_first = planeNormal.dot(firstVertex) + planeConstant; - - for (var vi = 0; vi < numVerts; vi++) { + for (let vi = 0; vi < numVerts; vi++) { lastVertex = inVertices[vi]; n_dot_last = planeNormal.dot(lastVertex) + planeConstant; - if (n_dot_first < 0) { if (n_dot_last < 0) { // Start < 0, end < 0, so output lastVertex - var newv = new Vec3(); + const newv = new Vec3(); newv.copy(lastVertex); outVertices.push(newv); } else { // Start < 0, end >= 0, so output intersection - var _newv = new Vec3(); - - firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), _newv); - outVertices.push(_newv); + const newv = new Vec3(); + firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv); + outVertices.push(newv); } } else { if (n_dot_last < 0) { // Start >= 0, end < 0 so output intersection and end - var _newv2 = new Vec3(); - - firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), _newv2); - outVertices.push(_newv2); + const newv = new Vec3(); + firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv); + outVertices.push(newv); outVertices.push(lastVertex); } } - firstVertex = lastVertex; n_dot_first = n_dot_last; } - return outVertices; } // Updates .worldVertices and sets .worldVerticesNeedsUpdate to false. - ; - _proto.computeWorldVertices = function computeWorldVertices(position, quat) { + computeWorldVertices(position, quat) { while (this.worldVertices.length < this.vertices.length) { this.worldVertices.push(new Vec3()); } - - var verts = this.vertices; - var worldVerts = this.worldVertices; - - for (var i = 0; i !== this.vertices.length; i++) { + const verts = this.vertices; + const worldVerts = this.worldVertices; + for (let i = 0; i !== this.vertices.length; i++) { quat.vmult(verts[i], worldVerts[i]); position.vadd(worldVerts[i], worldVerts[i]); } - this.worldVerticesNeedsUpdate = false; - }; - - _proto.computeLocalAABB = function computeLocalAABB(aabbmin, aabbmax) { - var vertices = this.vertices; + } + computeLocalAABB(aabbmin, aabbmax) { + const vertices = this.vertices; aabbmin.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE); aabbmax.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE); - - for (var i = 0; i < this.vertices.length; i++) { - var v = vertices[i]; - + for (let i = 0; i < this.vertices.length; i++) { + const v = vertices[i]; if (v.x < aabbmin.x) { aabbmin.x = v.x; } else if (v.x > aabbmax.x) { aabbmax.x = v.x; } - if (v.y < aabbmin.y) { aabbmin.y = v.y; } else if (v.y > aabbmax.y) { aabbmax.y = v.y; } - if (v.z < aabbmin.z) { aabbmin.z = v.z; } else if (v.z > aabbmax.z) { @@ -3596,42 +3100,33 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @method computeWorldFaceNormals * @param {Quaternion} quat */ - ; - - _proto.computeWorldFaceNormals = function computeWorldFaceNormals(quat) { - var N = this.faceNormals.length; + computeWorldFaceNormals(quat) { + const N = this.faceNormals.length; while (this.worldFaceNormals.length < N) { this.worldFaceNormals.push(new Vec3()); } - - var normals = this.faceNormals; - var worldNormals = this.worldFaceNormals; - - for (var i = 0; i !== N; i++) { + const normals = this.faceNormals; + const worldNormals = this.worldFaceNormals; + for (let i = 0; i !== N; i++) { quat.vmult(normals[i], worldNormals[i]); } - this.worldFaceNormalsNeedsUpdate = false; } /** * @method updateBoundingSphereRadius */ - ; - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + updateBoundingSphereRadius() { // Assume points are distributed with local (0,0,0) as center - var max2 = 0; - var verts = this.vertices; - - for (var i = 0; i !== verts.length; i++) { - var norm2 = verts[i].lengthSquared(); - + let max2 = 0; + const verts = this.vertices; + for (let i = 0; i !== verts.length; i++) { + const norm2 = verts[i].lengthSquared(); if (norm2 > max2) { max2 = norm2; } } - this.boundingSphereRadius = Math.sqrt(max2); } /** @@ -3641,49 +3136,40 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Vec3} min * @param {Vec3} max */ - ; - - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { - var verts = this.vertices; - var minx; - var miny; - var minz; - var maxx; - var maxy; - var maxz; - var tempWorldVertex = new Vec3(); - for (var i = 0; i < verts.length; i++) { + calculateWorldAABB(pos, quat, min, max) { + const verts = this.vertices; + let minx; + let miny; + let minz; + let maxx; + let maxy; + let maxz; + let tempWorldVertex = new Vec3(); + for (let i = 0; i < verts.length; i++) { tempWorldVertex.copy(verts[i]); quat.vmult(tempWorldVertex, tempWorldVertex); pos.vadd(tempWorldVertex, tempWorldVertex); - var v = tempWorldVertex; - + const v = tempWorldVertex; if (minx === undefined || v.x < minx) { minx = v.x; } - if (maxx === undefined || v.x > maxx) { maxx = v.x; } - if (miny === undefined || v.y < miny) { miny = v.y; } - if (maxy === undefined || v.y > maxy) { maxy = v.y; } - if (minz === undefined || v.z < minz) { minz = v.z; } - if (maxz === undefined || v.z > maxz) { maxz = v.z; } } - min.set(minx, miny, minz); max.set(maxx, maxy, maxz); } @@ -3692,9 +3178,8 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @method volume * @return {Number} */ - ; - _proto.volume = function volume() { + volume() { return 4.0 * Math.PI * this.boundingSphereRadius / 3.0; } /** @@ -3703,19 +3188,12 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Vec3} target * @return {Vec3} */ - ; - - _proto.getAveragePointLocal = function getAveragePointLocal(target) { - if (target === void 0) { - target = new Vec3(); - } - - var verts = this.vertices; - for (var i = 0; i < verts.length; i++) { + getAveragePointLocal(target = new Vec3()) { + const verts = this.vertices; + for (let i = 0; i < verts.length; i++) { target.vadd(verts[i], target); } - target.scale(1 / verts.length, target); return target; } @@ -3725,23 +3203,21 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Vec3} offset * @param {Quaternion} quat */ - ; - _proto.transformAllPoints = function transformAllPoints(offset, quat) { - var n = this.vertices.length; - var verts = this.vertices; // Apply rotation + transformAllPoints(offset, quat) { + const n = this.vertices.length; + const verts = this.vertices; // Apply rotation if (quat) { // Rotate vertices - for (var i = 0; i < n; i++) { - var v = verts[i]; + for (let i = 0; i < n; i++) { + const v = verts[i]; quat.vmult(v, v); } // Rotate face normals - - for (var _i6 = 0; _i6 < this.faceNormals.length; _i6++) { - var _v = this.faceNormals[_i6]; - quat.vmult(_v, _v); + for (let i = 0; i < this.faceNormals.length; i++) { + const v = this.faceNormals[i]; + quat.vmult(v, v); } /* // Rotate edges @@ -3749,15 +3225,12 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { const v = this.uniqueEdges[i]; quat.vmult(v,v); }*/ - } // Apply offset - if (offset) { - for (var _i7 = 0; _i7 < n; _i7++) { - var _v2 = verts[_i7]; - - _v2.vadd(offset, _v2); + for (let i = 0; i < n; i++) { + const v = verts[i]; + v.vadd(offset, v); } } } @@ -3769,39 +3242,33 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Vec3} p A point given in local coordinates * @return {Boolean} */ - ; - _proto.pointIsInside = function pointIsInside(p) { - var verts = this.vertices; - var faces = this.faces; - var normals = this.faceNormals; - var pointInside = new Vec3(); + pointIsInside(p) { + const verts = this.vertices; + const faces = this.faces; + const normals = this.faceNormals; + const pointInside = new Vec3(); this.getAveragePointLocal(pointInside); - - for (var i = 0; i < this.faces.length; i++) { - var n = normals[i]; - var v = verts[faces[i][0]]; // We only need one point in the face + for (let i = 0; i < this.faces.length; i++) { + let n = normals[i]; + const v = verts[faces[i][0]]; // We only need one point in the face // This dot product determines which side of the edge the point is - var vToP = new Vec3(); + const vToP = new Vec3(); p.vsub(v, vToP); - var r1 = n.dot(vToP); - var vToPointInside = new Vec3(); + const r1 = n.dot(vToP); + const vToPointInside = new Vec3(); pointInside.vsub(v, vToPointInside); - var r2 = n.dot(vToPointInside); - + const r2 = n.dot(vToPointInside); if (r1 < 0 && r2 > 0 || r1 > 0 && r2 < 0) { return false; // Encountered some other sign. Exit. } } // If we got here, all dot products were of the same sign. - - return -1; - }; - - return ConvexPolyhedron; -}(Shape); -/** + return -1; + } +} +/** * Get face normal given 3 vertices * @static * @method computeNormal @@ -3810,21 +3277,19 @@ var ConvexPolyhedron = /*#__PURE__*/function (_Shape) { * @param {Vec3} vc * @param {Vec3} target */ - -ConvexPolyhedron.computeNormal = function (va, vb, vc, target) { - var cb = new Vec3(); - var ab = new Vec3(); +exports.ConvexPolyhedron = ConvexPolyhedron; +ConvexPolyhedron.computeNormal = (va, vb, vc, target) => { + const cb = new Vec3(); + const ab = new Vec3(); vb.vsub(va, ab); vc.vsub(vb, cb); cb.cross(ab, target); - if (!target.isZero()) { target.normalize(); } }; - -var maxminA = []; -var maxminB = []; +const maxminA = []; +const maxminB = []; /** * Get max and min dot product of a convex hull at position (pos,quat) projected onto an axis. * Results are saved in the array maxmin. @@ -3837,43 +3302,37 @@ var maxminB = []; * @param {array} result result[0] and result[1] will be set to maximum and minimum, respectively. */ -ConvexPolyhedron.project = function (shape, axis, pos, quat, result) { - var n = shape.vertices.length; - var localAxis = new Vec3(); - var max = 0; - var min = 0; - var localOrigin = new Vec3(); - var vs = shape.vertices; +ConvexPolyhedron.project = (shape, axis, pos, quat, result) => { + const n = shape.vertices.length; + const localAxis = new Vec3(); + let max = 0; + let min = 0; + const localOrigin = new Vec3(); + const vs = shape.vertices; localOrigin.setZero(); // Transform the axis to local Transform.vectorToLocalFrame(pos, quat, axis, localAxis); Transform.pointToLocalFrame(pos, quat, localOrigin, localOrigin); - var add = localOrigin.dot(localAxis); + const add = localOrigin.dot(localAxis); min = max = vs[0].dot(localAxis); - - for (var i = 1; i < n; i++) { - var val = vs[i].dot(localAxis); - + for (let i = 1; i < n; i++) { + const val = vs[i].dot(localAxis); if (val > max) { max = val; } - if (val < min) { min = val; } } - min -= add; max -= add; - if (min > max) { // Inconsistent - swap - var temp = min; + const temp = min; min = max; max = temp; } // Output - result[0] = max; result[1] = min; }; @@ -3886,51 +3345,46 @@ ConvexPolyhedron.project = function (shape, axis, pos, quat, result) { * @author schteppe * @extends Shape */ -var Box = /*#__PURE__*/function (_Shape) { - _inheritsLoose(Box, _Shape); - +class Box extends Shape { // Used by the contact generator to make contacts with other convex polyhedra for example. - function Box(halfExtents) { - var _this; - - _this = _Shape.call(this, { + constructor(halfExtents) { + super({ type: Shape.types.BOX - }) || this; - _this.halfExtents = halfExtents; - _this.convexPolyhedronRepresentation = null; - - _this.updateConvexPolyhedronRepresentation(); - - _this.updateBoundingSphereRadius(); - - return _this; + }); + this.halfExtents = halfExtents; + this.convexPolyhedronRepresentation = null; + this.updateConvexPolyhedronRepresentation(); + this.updateBoundingSphereRadius(); } /** * Updates the local convex polyhedron representation used for some collisions. * @method updateConvexPolyhedronRepresentation */ - - var _proto = Box.prototype; - - _proto.updateConvexPolyhedronRepresentation = function updateConvexPolyhedronRepresentation() { - var sx = this.halfExtents.x; - var sy = this.halfExtents.y; - var sz = this.halfExtents.z; - var V = Vec3; - var vertices = [new V(-sx, -sy, -sz), new V(sx, -sy, -sz), new V(sx, sy, -sz), new V(-sx, sy, -sz), new V(-sx, -sy, sz), new V(sx, -sy, sz), new V(sx, sy, sz), new V(-sx, sy, sz)]; - var faces = [[3, 2, 1, 0], // -z - [4, 5, 6, 7], // +z - [5, 4, 0, 1], // -y - [2, 3, 7, 6], // +y - [0, 4, 7, 3], // -x + updateConvexPolyhedronRepresentation() { + const sx = this.halfExtents.x; + const sy = this.halfExtents.y; + const sz = this.halfExtents.z; + const V = Vec3; + const vertices = [new V(-sx, -sy, -sz), new V(sx, -sy, -sz), new V(sx, sy, -sz), new V(-sx, sy, -sz), new V(-sx, -sy, sz), new V(sx, -sy, sz), new V(sx, sy, sz), new V(-sx, sy, sz)]; + const faces = [[3, 2, 1, 0], + // -z + [4, 5, 6, 7], + // +z + [5, 4, 0, 1], + // -y + [2, 3, 7, 6], + // +y + [0, 4, 7, 3], + // -x [1, 2, 6, 5] // +x ]; - var axes = [new V(0, 0, 1), new V(0, 1, 0), new V(1, 0, 0)]; - var h = new ConvexPolyhedron({ - vertices: vertices, - faces: faces, - axes: axes + + const axes = [new V(0, 0, 1), new V(0, 1, 0), new V(1, 0, 0)]; + const h = new ConvexPolyhedron({ + vertices, + faces, + axes }); this.convexPolyhedronRepresentation = h; h.material = this.material; @@ -3941,13 +3395,8 @@ var Box = /*#__PURE__*/function (_Shape) { * @param {Vec3} target * @return {Vec3} */ - ; - - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { - if (target === void 0) { - target = new Vec3(); - } + calculateLocalInertia(mass, target = new Vec3()) { Box.calculateInertia(this.halfExtents, mass, target); return target; } @@ -3958,49 +3407,41 @@ var Box = /*#__PURE__*/function (_Shape) { * @param {Quaternion} quat Orientation to apply to the normal vectors. If not provided, the vectors will be in respect to the local frame. * @return {array} */ - ; - _proto.getSideNormals = function getSideNormals(sixTargetVectors, quat) { - var sides = sixTargetVectors; - var ex = this.halfExtents; + getSideNormals(sixTargetVectors, quat) { + const sides = sixTargetVectors; + const ex = this.halfExtents; sides[0].set(ex.x, 0, 0); sides[1].set(0, ex.y, 0); sides[2].set(0, 0, ex.z); sides[3].set(-ex.x, 0, 0); sides[4].set(0, -ex.y, 0); sides[5].set(0, 0, -ex.z); - if (quat !== undefined) { - for (var i = 0; i !== sides.length; i++) { + for (let i = 0; i !== sides.length; i++) { quat.vmult(sides[i], sides[i]); } } - return sides; - }; - - _proto.volume = function volume() { + } + volume() { return 8.0 * this.halfExtents.x * this.halfExtents.y * this.halfExtents.z; - }; - - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + } + updateBoundingSphereRadius() { this.boundingSphereRadius = this.halfExtents.length(); - }; - - _proto.forEachWorldCorner = function forEachWorldCorner(pos, quat, callback) { - var e = this.halfExtents; - var corners = [[e.x, e.y, e.z], [-e.x, e.y, e.z], [-e.x, -e.y, e.z], [-e.x, -e.y, -e.z], [e.x, -e.y, -e.z], [e.x, e.y, -e.z], [-e.x, e.y, -e.z], [e.x, -e.y, e.z]]; - - for (var i = 0; i < corners.length; i++) { + } + forEachWorldCorner(pos, quat, callback) { + const e = this.halfExtents; + const corners = [[e.x, e.y, e.z], [-e.x, e.y, e.z], [-e.x, -e.y, e.z], [-e.x, -e.y, -e.z], [e.x, -e.y, -e.z], [e.x, e.y, -e.z], [-e.x, e.y, -e.z], [e.x, -e.y, e.z]]; + for (let i = 0; i < corners.length; i++) { worldCornerTempPos.set(corners[i][0], corners[i][1], corners[i][2]); quat.vmult(worldCornerTempPos, worldCornerTempPos); pos.vadd(worldCornerTempPos, worldCornerTempPos); callback(worldCornerTempPos.x, worldCornerTempPos.y, worldCornerTempPos.z); } - }; - - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { - var e = this.halfExtents; + } + calculateWorldAABB(pos, quat, min, max) { + const e = this.halfExtents; worldCornersTemp[0].set(e.x, e.y, e.z); worldCornersTemp[1].set(-e.x, e.y, e.z); worldCornersTemp[2].set(-e.x, -e.y, e.z); @@ -4009,42 +3450,35 @@ var Box = /*#__PURE__*/function (_Shape) { worldCornersTemp[5].set(e.x, e.y, -e.z); worldCornersTemp[6].set(-e.x, e.y, -e.z); worldCornersTemp[7].set(e.x, -e.y, e.z); - var wc = worldCornersTemp[0]; + const wc = worldCornersTemp[0]; quat.vmult(wc, wc); pos.vadd(wc, wc); max.copy(wc); min.copy(wc); - - for (var i = 1; i < 8; i++) { - var _wc = worldCornersTemp[i]; - quat.vmult(_wc, _wc); - pos.vadd(_wc, _wc); - var _x = _wc.x; - var _y = _wc.y; - var _z = _wc.z; - - if (_x > max.x) { - max.x = _x; + for (let i = 1; i < 8; i++) { + const wc = worldCornersTemp[i]; + quat.vmult(wc, wc); + pos.vadd(wc, wc); + const x = wc.x; + const y = wc.y; + const z = wc.z; + if (x > max.x) { + max.x = x; } - - if (_y > max.y) { - max.y = _y; + if (y > max.y) { + max.y = y; } - - if (_z > max.z) { - max.z = _z; + if (z > max.z) { + max.z = z; } - - if (_x < min.x) { - min.x = _x; + if (x < min.x) { + min.x = x; } - - if (_y < min.y) { - min.y = _y; + if (y < min.y) { + min.y = y; } - - if (_z < min.z) { - min.z = _z; + if (z < min.z) { + min.z = z; } } // Get each axis max // min.set(Infinity,Infinity,Infinity); @@ -4069,28 +3503,23 @@ var Box = /*#__PURE__*/function (_Shape) { // min.z = z; // } // }); - - }; - - return Box; -}(Shape); - -Box.calculateInertia = function (halfExtents, mass, target) { - var e = halfExtents; + } +} +exports.Box = Box; +Box.calculateInertia = (halfExtents, mass, target) => { + const e = halfExtents; target.x = 1.0 / 12.0 * mass * (2 * e.y * 2 * e.y + 2 * e.z * 2 * e.z); target.y = 1.0 / 12.0 * mass * (2 * e.x * 2 * e.x + 2 * e.z * 2 * e.z); target.z = 1.0 / 12.0 * mass * (2 * e.y * 2 * e.y + 2 * e.x * 2 * e.x); }; - -var worldCornerTempPos = new Vec3(); -var worldCornersTemp = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()]; - -var BODY_TYPES = { +const worldCornerTempPos = new Vec3(); +const worldCornersTemp = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()]; +const BODY_TYPES = exports.BODY_TYPES = { DYNAMIC: 1, STATIC: 2, KINEMATIC: 4 }; -var BODY_SLEEP_STATES = { +const BODY_SLEEP_STATES = exports.BODY_SLEEP_STATES = { AWAKE: 0, SLEEPY: 1, SLEEPING: 2 @@ -4128,9 +3557,7 @@ var BODY_SLEEP_STATES = { * body.addShape(shape); * world.addBody(body); */ -var Body = /*#__PURE__*/function (_EventTarget) { - _inheritsLoose(Body, _EventTarget); - +class Body extends EventTarget { // Position of body in World.bodies. Updated by World and used in ArrayCollisionMatrix. // Reference to the world the body is living in. // Callback function that is used BEFORE stepping the system. Use it to apply forces, for example. Inside the function, "this" will refer to this Body object. Deprecated - use World events instead. @@ -4158,135 +3585,101 @@ var Body = /*#__PURE__*/function (_EventTarget) { // World space bounding box of the body and its shapes. // Indicates if the AABB needs to be updated before use. // Total bounding radius of the Body including its shapes, relative to body.position. - function Body(options) { - var _this; - - if (options === void 0) { - options = {}; - } - - _this = _EventTarget.call(this) || this; - _this.id = Body.idCounter++; - _this.index = -1; - _this.world = null; - _this.preStep = null; - _this.postStep = null; - _this.vlambda = new Vec3(); - _this.collisionFilterGroup = typeof options.collisionFilterGroup === 'number' ? options.collisionFilterGroup : 1; - _this.collisionFilterMask = typeof options.collisionFilterMask === 'number' ? options.collisionFilterMask : -1; - _this.collisionResponse = typeof options.collisionResponse === 'boolean' ? options.collisionResponse : true; - _this.position = new Vec3(); - _this.previousPosition = new Vec3(); - _this.interpolatedPosition = new Vec3(); - _this.initPosition = new Vec3(); - + constructor(options = {}) { + super(); + this.id = Body.idCounter++; + this.index = -1; + this.world = null; + this.preStep = null; + this.postStep = null; + this.vlambda = new Vec3(); + this.collisionFilterGroup = typeof options.collisionFilterGroup === 'number' ? options.collisionFilterGroup : 1; + this.collisionFilterMask = typeof options.collisionFilterMask === 'number' ? options.collisionFilterMask : -1; + this.collisionResponse = typeof options.collisionResponse === 'boolean' ? options.collisionResponse : true; + this.position = new Vec3(); + this.previousPosition = new Vec3(); + this.interpolatedPosition = new Vec3(); + this.initPosition = new Vec3(); if (options.position) { - _this.position.copy(options.position); - - _this.previousPosition.copy(options.position); - - _this.interpolatedPosition.copy(options.position); - - _this.initPosition.copy(options.position); + this.position.copy(options.position); + this.previousPosition.copy(options.position); + this.interpolatedPosition.copy(options.position); + this.initPosition.copy(options.position); } - - _this.velocity = new Vec3(); - + this.velocity = new Vec3(); if (options.velocity) { - _this.velocity.copy(options.velocity); - } - - _this.initVelocity = new Vec3(); - _this.force = new Vec3(); - var mass = typeof options.mass === 'number' ? options.mass : 0; - _this.mass = mass; - _this.invMass = mass > 0 ? 1.0 / mass : 0; - _this.material = options.material || null; - _this.linearDamping = typeof options.linearDamping === 'number' ? options.linearDamping : 0.01; - _this.type = mass <= 0.0 ? Body.STATIC : Body.DYNAMIC; - + this.velocity.copy(options.velocity); + } + this.initVelocity = new Vec3(); + this.force = new Vec3(); + const mass = typeof options.mass === 'number' ? options.mass : 0; + this.mass = mass; + this.invMass = mass > 0 ? 1.0 / mass : 0; + this.material = options.material || null; + this.linearDamping = typeof options.linearDamping === 'number' ? options.linearDamping : 0.01; + this.type = mass <= 0.0 ? Body.STATIC : Body.DYNAMIC; if (typeof options.type === typeof Body.STATIC) { - _this.type = options.type; + this.type = options.type; } - - _this.allowSleep = typeof options.allowSleep !== 'undefined' ? options.allowSleep : true; - _this.sleepState = 0; - _this.sleepSpeedLimit = typeof options.sleepSpeedLimit !== 'undefined' ? options.sleepSpeedLimit : 0.1; - _this.sleepTimeLimit = typeof options.sleepTimeLimit !== 'undefined' ? options.sleepTimeLimit : 1; - _this.timeLastSleepy = 0; - _this.wakeUpAfterNarrowphase = false; - _this.torque = new Vec3(); - _this.quaternion = new Quaternion(); - _this.initQuaternion = new Quaternion(); - _this.previousQuaternion = new Quaternion(); - _this.interpolatedQuaternion = new Quaternion(); - + this.allowSleep = typeof options.allowSleep !== 'undefined' ? options.allowSleep : true; + this.sleepState = 0; + this.sleepSpeedLimit = typeof options.sleepSpeedLimit !== 'undefined' ? options.sleepSpeedLimit : 0.1; + this.sleepTimeLimit = typeof options.sleepTimeLimit !== 'undefined' ? options.sleepTimeLimit : 1; + this.timeLastSleepy = 0; + this.wakeUpAfterNarrowphase = false; + this.torque = new Vec3(); + this.quaternion = new Quaternion(); + this.initQuaternion = new Quaternion(); + this.previousQuaternion = new Quaternion(); + this.interpolatedQuaternion = new Quaternion(); if (options.quaternion) { - _this.quaternion.copy(options.quaternion); - - _this.initQuaternion.copy(options.quaternion); - - _this.previousQuaternion.copy(options.quaternion); - - _this.interpolatedQuaternion.copy(options.quaternion); + this.quaternion.copy(options.quaternion); + this.initQuaternion.copy(options.quaternion); + this.previousQuaternion.copy(options.quaternion); + this.interpolatedQuaternion.copy(options.quaternion); } - - _this.angularVelocity = new Vec3(); - + this.angularVelocity = new Vec3(); if (options.angularVelocity) { - _this.angularVelocity.copy(options.angularVelocity); - } - - _this.initAngularVelocity = new Vec3(); - _this.shapes = []; - _this.shapeOffsets = []; - _this.shapeOrientations = []; - _this.inertia = new Vec3(); - _this.invInertia = new Vec3(); - _this.invInertiaWorld = new Mat3(); - _this.invMassSolve = 0; - _this.invInertiaSolve = new Vec3(); - _this.invInertiaWorldSolve = new Mat3(); - _this.fixedRotation = typeof options.fixedRotation !== 'undefined' ? options.fixedRotation : false; - _this.angularDamping = typeof options.angularDamping !== 'undefined' ? options.angularDamping : 0.01; - _this.linearFactor = new Vec3(1, 1, 1); - + this.angularVelocity.copy(options.angularVelocity); + } + this.initAngularVelocity = new Vec3(); + this.shapes = []; + this.shapeOffsets = []; + this.shapeOrientations = []; + this.inertia = new Vec3(); + this.invInertia = new Vec3(); + this.invInertiaWorld = new Mat3(); + this.invMassSolve = 0; + this.invInertiaSolve = new Vec3(); + this.invInertiaWorldSolve = new Mat3(); + this.fixedRotation = typeof options.fixedRotation !== 'undefined' ? options.fixedRotation : false; + this.angularDamping = typeof options.angularDamping !== 'undefined' ? options.angularDamping : 0.01; + this.linearFactor = new Vec3(1, 1, 1); if (options.linearFactor) { - _this.linearFactor.copy(options.linearFactor); + this.linearFactor.copy(options.linearFactor); } - - _this.angularFactor = new Vec3(1, 1, 1); - + this.angularFactor = new Vec3(1, 1, 1); if (options.angularFactor) { - _this.angularFactor.copy(options.angularFactor); + this.angularFactor.copy(options.angularFactor); } - - _this.aabb = new AABB(); - _this.aabbNeedsUpdate = true; - _this.boundingRadius = 0; - _this.wlambda = new Vec3(); - + this.aabb = new AABB(); + this.aabbNeedsUpdate = true; + this.boundingRadius = 0; + this.wlambda = new Vec3(); if (options.shape) { - _this.addShape(options.shape); + this.addShape(options.shape); } - - _this.updateMassProperties(); - - return _this; + this.updateMassProperties(); } /** * Wake the body up. * @method wakeUp */ - - var _proto = Body.prototype; - - _proto.wakeUp = function wakeUp() { - var prevState = this.sleepState; + wakeUp() { + const prevState = this.sleepState; this.sleepState = 0; this.wakeUpAfterNarrowphase = false; - if (prevState === Body.SLEEPING) { this.dispatchEvent(Body.wakeupEvent); } @@ -4295,9 +3688,8 @@ var Body = /*#__PURE__*/function (_EventTarget) { * Force body sleep * @method sleep */ - ; - _proto.sleep = function sleep() { + sleep() { this.sleepState = Body.SLEEPING; this.velocity.set(0, 0, 0); this.angularVelocity.set(0, 0, 0); @@ -4308,14 +3700,12 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @method sleepTick * @param {Number} time The world time in seconds */ - ; - _proto.sleepTick = function sleepTick(time) { + sleepTick(time) { if (this.allowSleep) { - var sleepState = this.sleepState; - var speedSquared = this.velocity.lengthSquared() + this.angularVelocity.lengthSquared(); - var speedLimitSquared = Math.pow(this.sleepSpeedLimit, 2); - + const sleepState = this.sleepState; + const speedSquared = this.velocity.lengthSquared() + this.angularVelocity.lengthSquared(); + const speedLimitSquared = this.sleepSpeedLimit ** 2; if (sleepState === Body.AWAKE && speedSquared < speedLimitSquared) { this.sleepState = Body.SLEEPY; // Sleepy @@ -4334,9 +3724,8 @@ var Body = /*#__PURE__*/function (_EventTarget) { * If the body is sleeping, it should be immovable / have infinite mass during solve. We solve it by having a separate "solve mass". * @method updateSolveMassProperties */ - ; - _proto.updateSolveMassProperties = function updateSolveMassProperties() { + updateSolveMassProperties() { if (this.sleepState === Body.SLEEPING || this.type === Body.KINEMATIC) { this.invMassSolve = 0; this.invInertiaSolve.setZero(); @@ -4354,13 +3743,8 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {Vec3} result * @return {Vec3} */ - ; - - _proto.pointToLocalFrame = function pointToLocalFrame(worldPoint, result) { - if (result === void 0) { - result = new Vec3(); - } + pointToLocalFrame(worldPoint, result = new Vec3()) { worldPoint.vsub(this.position, result); this.quaternion.conjugate().vmult(result, result); return result; @@ -4372,13 +3756,8 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {Vec3} result * @return {Vec3} */ - ; - - _proto.vectorToLocalFrame = function vectorToLocalFrame(worldVector, result) { - if (result === void 0) { - result = new Vec3(); - } + vectorToLocalFrame(worldVector, result = new Vec3()) { this.quaternion.conjugate().vmult(worldVector, result); return result; } @@ -4389,13 +3768,8 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {Vec3} result * @return {Vec3} */ - ; - - _proto.pointToWorldFrame = function pointToWorldFrame(localPoint, result) { - if (result === void 0) { - result = new Vec3(); - } + pointToWorldFrame(localPoint, result = new Vec3()) { this.quaternion.vmult(localPoint, result); result.vadd(this.position, result); return result; @@ -4407,13 +3781,8 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {Vec3} result * @return {Vec3} */ - ; - - _proto.vectorToWorldFrame = function vectorToWorldFrame(localVector, result) { - if (result === void 0) { - result = new Vec3(); - } + vectorToWorldFrame(localVector, result = new Vec3()) { this.quaternion.vmult(localVector, result); return result; } @@ -4425,20 +3794,16 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {Quaternion} [_orientation] * @return {Body} The body object, for chainability. */ - ; - - _proto.addShape = function addShape(shape, _offset, _orientation) { - var offset = new Vec3(); - var orientation = new Quaternion(); + addShape(shape, _offset, _orientation) { + const offset = new Vec3(); + const orientation = new Quaternion(); if (_offset) { offset.copy(_offset); } - if (_orientation) { orientation.copy(_orientation); } - this.shapes.push(shape); this.shapeOffsets.push(offset); this.shapeOrientations.push(orientation); @@ -4452,25 +3817,21 @@ var Body = /*#__PURE__*/function (_EventTarget) { * Update the bounding radius of the body. Should be done if any of the shapes are changed. * @method updateBoundingRadius */ - ; - - _proto.updateBoundingRadius = function updateBoundingRadius() { - var shapes = this.shapes; - var shapeOffsets = this.shapeOffsets; - var N = shapes.length; - var radius = 0; - for (var i = 0; i !== N; i++) { - var shape = shapes[i]; + updateBoundingRadius() { + const shapes = this.shapes; + const shapeOffsets = this.shapeOffsets; + const N = shapes.length; + let radius = 0; + for (let i = 0; i !== N; i++) { + const shape = shapes[i]; shape.updateBoundingSphereRadius(); - var offset = shapeOffsets[i].length(); - var r = shape.boundingSphereRadius; - + const offset = shapeOffsets[i].length(); + const r = shape.boundingSphereRadius; if (offset + r > radius) { radius = offset + r; } } - this.boundingRadius = radius; } /** @@ -4478,21 +3839,19 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @method computeAABB * @todo rename to updateAABB() */ - ; - _proto.computeAABB = function computeAABB() { - var shapes = this.shapes; - var shapeOffsets = this.shapeOffsets; - var shapeOrientations = this.shapeOrientations; - var N = shapes.length; - var offset = tmpVec; - var orientation = tmpQuat$1; - var bodyQuat = this.quaternion; - var aabb = this.aabb; - var shapeAABB = computeAABB_shapeAABB; - - for (var i = 0; i !== N; i++) { - var shape = shapes[i]; // Get shape world position + computeAABB() { + const shapes = this.shapes; + const shapeOffsets = this.shapeOffsets; + const shapeOrientations = this.shapeOrientations; + const N = shapes.length; + const offset = tmpVec; + const orientation = tmpQuat$1; + const bodyQuat = this.quaternion; + const aabb = this.aabb; + const shapeAABB = computeAABB_shapeAABB; + for (let i = 0; i !== N; i++) { + const shape = shapes[i]; // Get shape world position bodyQuat.vmult(shapeOffsets[i], offset); offset.vadd(this.position, offset); // Get shape world quaternion @@ -4500,78 +3859,68 @@ var Body = /*#__PURE__*/function (_EventTarget) { bodyQuat.mult(shapeOrientations[i], orientation); // Get shape AABB shape.calculateWorldAABB(offset, orientation, shapeAABB.lowerBound, shapeAABB.upperBound); - if (i === 0) { aabb.copy(shapeAABB); } else { aabb.extend(shapeAABB); } } - this.aabbNeedsUpdate = false; } /** * Update .inertiaWorld and .invInertiaWorld * @method updateInertiaWorld */ - ; - - _proto.updateInertiaWorld = function updateInertiaWorld(force) { - var I = this.invInertia; - if (I.x === I.y && I.y === I.z && !force) ; else { - var m1 = uiw_m1; - var m2 = uiw_m2; + updateInertiaWorld(force) { + const I = this.invInertia; + if (I.x === I.y && I.y === I.z && !force) ;else { + const m1 = uiw_m1; + const m2 = uiw_m2; m1.setRotationFromQuaternion(this.quaternion); m1.transpose(m2); m1.scale(I, m1); m1.mmult(m2, this.invInertiaWorld); } - }; - - _proto.applyForce = function applyForce(force, relativePoint) { + } + applyForce(force, relativePoint) { if (this.type !== Body.DYNAMIC) { // Needed? return; } // Compute produced rotational force - - var rotForce = Body_applyForce_rotForce; + const rotForce = Body_applyForce_rotForce; relativePoint.cross(force, rotForce); // Add linear force this.force.vadd(force, this.force); // Add rotational force this.torque.vadd(rotForce, this.torque); - }; - - _proto.applyLocalForce = function applyLocalForce(localForce, localPoint) { + } + applyLocalForce(localForce, localPoint) { if (this.type !== Body.DYNAMIC) { return; } - - var worldForce = Body_applyLocalForce_worldForce; - var relativePointWorld = Body_applyLocalForce_relativePointWorld; // Transform the force vector to world space + const worldForce = Body_applyLocalForce_worldForce; + const relativePointWorld = Body_applyLocalForce_relativePointWorld; // Transform the force vector to world space this.vectorToWorldFrame(localForce, worldForce); this.vectorToWorldFrame(localPoint, relativePointWorld); this.applyForce(worldForce, relativePointWorld); - }; - - _proto.applyImpulse = function applyImpulse(impulse, relativePoint) { + } + applyImpulse(impulse, relativePoint) { if (this.type !== Body.DYNAMIC) { return; } // Compute point position relative to the body center + const r = relativePoint; // Compute produced central impulse velocity - var r = relativePoint; // Compute produced central impulse velocity - - var velo = Body_applyImpulse_velo; + const velo = Body_applyImpulse_velo; velo.copy(impulse); velo.scale(this.invMass, velo); // Add linear impulse this.velocity.vadd(velo, this.velocity); // Compute produced rotational impulse velocity - var rotVelo = Body_applyImpulse_rotVelo; + const rotVelo = Body_applyImpulse_rotVelo; r.cross(impulse, rotVelo); /* rotVelo.x *= this.invInertia.x; @@ -4582,15 +3931,13 @@ var Body = /*#__PURE__*/function (_EventTarget) { this.invInertiaWorld.vmult(rotVelo, rotVelo); // Add rotational Impulse this.angularVelocity.vadd(rotVelo, this.angularVelocity); - }; - - _proto.applyLocalImpulse = function applyLocalImpulse(localImpulse, localPoint) { + } + applyLocalImpulse(localImpulse, localPoint) { if (this.type !== Body.DYNAMIC) { return; } - - var worldImpulse = Body_applyLocalImpulse_worldImpulse; - var relativePointWorld = Body_applyLocalImpulse_relativePoint; // Transform the force vector to world space + const worldImpulse = Body_applyLocalImpulse_worldImpulse; + const relativePointWorld = Body_applyLocalImpulse_relativePoint; // Transform the force vector to world space this.vectorToWorldFrame(localImpulse, worldImpulse); this.vectorToWorldFrame(localPoint, relativePointWorld); @@ -4600,13 +3947,12 @@ var Body = /*#__PURE__*/function (_EventTarget) { * Should be called whenever you change the body shape or mass. * @method updateMassProperties */ - ; - _proto.updateMassProperties = function updateMassProperties() { - var halfExtents = Body_updateMassProperties_halfExtents; + updateMassProperties() { + const halfExtents = Body_updateMassProperties_halfExtents; this.invMass = this.mass > 0 ? 1.0 / this.mass : 0; - var I = this.inertia; - var fixed = this.fixedRotation; // Approximate with AABB box + const I = this.inertia; + const fixed = this.fixedRotation; // Approximate with AABB box this.computeAABB(); halfExtents.set((this.aabb.upperBound.x - this.aabb.lowerBound.x) / 2, (this.aabb.upperBound.y - this.aabb.lowerBound.y) / 2, (this.aabb.upperBound.z - this.aabb.lowerBound.z) / 2); @@ -4621,10 +3967,9 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {Vec3} result * @return {Vec3} The result vector. */ - ; - _proto.getVelocityAtWorldPoint = function getVelocityAtWorldPoint(worldPoint, result) { - var r = new Vec3(); + getVelocityAtWorldPoint(worldPoint, result) { + const r = new Vec3(); worldPoint.vsub(this.position, r); this.angularVelocity.cross(r, result); this.velocity.vadd(result, result); @@ -4636,36 +3981,33 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {boolean} quatNormalize Set to true to normalize the body quaternion * @param {boolean} quatNormalizeFast If the quaternion should be normalized using "fast" quaternion normalization */ - ; - _proto.integrate = function integrate(dt, quatNormalize, quatNormalizeFast) { + integrate(dt, quatNormalize, quatNormalizeFast) { // Save previous position this.previousPosition.copy(this.position); this.previousQuaternion.copy(this.quaternion); - if (!(this.type === Body.DYNAMIC || this.type === Body.KINEMATIC) || this.sleepState === Body.SLEEPING) { // Only for dynamic return; } - - var velo = this.velocity; - var angularVelo = this.angularVelocity; - var pos = this.position; - var force = this.force; - var torque = this.torque; - var quat = this.quaternion; - var invMass = this.invMass; - var invInertia = this.invInertiaWorld; - var linearFactor = this.linearFactor; - var iMdt = invMass * dt; + const velo = this.velocity; + const angularVelo = this.angularVelocity; + const pos = this.position; + const force = this.force; + const torque = this.torque; + const quat = this.quaternion; + const invMass = this.invMass; + const invInertia = this.invInertiaWorld; + const linearFactor = this.linearFactor; + const iMdt = invMass * dt; velo.x += force.x * iMdt * linearFactor.x; velo.y += force.y * iMdt * linearFactor.y; velo.z += force.z * iMdt * linearFactor.z; - var e = invInertia.elements; - var angularFactor = this.angularFactor; - var tx = torque.x * angularFactor.x; - var ty = torque.y * angularFactor.y; - var tz = torque.z * angularFactor.z; + const e = invInertia.elements; + const angularFactor = this.angularFactor; + const tx = torque.x * angularFactor.x; + const ty = torque.y * angularFactor.y; + const tz = torque.z * angularFactor.z; angularVelo.x += dt * (e[0] * tx + e[1] * ty + e[2] * tz); angularVelo.y += dt * (e[3] * tx + e[4] * ty + e[5] * tz); angularVelo.z += dt * (e[6] * tx + e[7] * ty + e[8] * tz); // Use new velocity - leap frog @@ -4674,7 +4016,6 @@ var Body = /*#__PURE__*/function (_EventTarget) { pos.y += velo.y * dt; pos.z += velo.z * dt; quat.integrate(this.angularVelocity, dt, this.angularFactor, quat); - if (quatNormalize) { if (quatNormalizeFast) { quat.normalizeFast(); @@ -4682,14 +4023,11 @@ var Body = /*#__PURE__*/function (_EventTarget) { quat.normalize(); } } - this.aabbNeedsUpdate = true; // Update world inertia this.updateInertiaWorld(); - }; - - return Body; -}(EventTarget); + } +} /** * Dispatched after two bodies collide. This event is dispatched on each * of the two bodies involved in the collision. @@ -4697,7 +4035,7 @@ var Body = /*#__PURE__*/function (_EventTarget) { * @param {Body} body The body that was involved in the collision. * @param {ContactEquation} contact The details of the collision. */ - +exports.Body = Body; Body.COLLIDE_EVENT_NAME = 'collide'; /** * A dynamic body is fully simulated. Can be moved manually by the user, but normally they move according to forces. A dynamic body can collide with all body types. A dynamic body always has finite, non-zero mass. @@ -4757,12 +4095,11 @@ Body.sleepyEvent = { Body.sleepEvent = { type: 'sleep' }; -var tmpVec = new Vec3(); -var tmpQuat$1 = new Quaternion(); -var computeAABB_shapeAABB = new AABB(); -var uiw_m1 = new Mat3(); -var uiw_m2 = new Mat3(); -var uiw_m3 = new Mat3(); +const tmpVec = new Vec3(); +const tmpQuat$1 = new Quaternion(); +const computeAABB_shapeAABB = new AABB(); +const uiw_m1 = new Mat3(); +const uiw_m2 = new Mat3(); /** * Apply force to a world point. This could for example be a point on the Body surface. Applying force this way will add to Body.force and Body.torque. * @method applyForce @@ -4770,7 +4107,7 @@ var uiw_m3 = new Mat3(); * @param {Vec3} relativePoint A point relative to the center of mass to apply the force on. */ -var Body_applyForce_rotForce = new Vec3(); +const Body_applyForce_rotForce = new Vec3(); /** * Apply force to a local point in the body. * @method applyLocalForce @@ -4778,8 +4115,8 @@ var Body_applyForce_rotForce = new Vec3(); * @param {Vec3} localPoint A local point in the body to apply the force on. */ -var Body_applyLocalForce_worldForce = new Vec3(); -var Body_applyLocalForce_relativePointWorld = new Vec3(); +const Body_applyLocalForce_worldForce = new Vec3(); +const Body_applyLocalForce_relativePointWorld = new Vec3(); /** * Apply impulse to a world point. This could for example be a point on the Body surface. An impulse is a force added to a body during a short period of time (impulse = force * time). Impulses will be added to Body.velocity and Body.angularVelocity. * @method applyImpulse @@ -4787,8 +4124,8 @@ var Body_applyLocalForce_relativePointWorld = new Vec3(); * @param {Vec3} relativePoint A point relative to the center of mass to apply the force on. */ -var Body_applyImpulse_velo = new Vec3(); -var Body_applyImpulse_rotVelo = new Vec3(); +const Body_applyImpulse_velo = new Vec3(); +const Body_applyImpulse_rotVelo = new Vec3(); /** * Apply locally-defined impulse to a local point in the body. * @method applyLocalImpulse @@ -4796,9 +4133,9 @@ var Body_applyImpulse_rotVelo = new Vec3(); * @param {Vec3} localPoint A local point in the body to apply the force on. */ -var Body_applyLocalImpulse_worldImpulse = new Vec3(); -var Body_applyLocalImpulse_relativePoint = new Vec3(); -var Body_updateMassProperties_halfExtents = new Vec3(); +const Body_applyLocalImpulse_worldImpulse = new Vec3(); +const Body_applyLocalImpulse_relativePoint = new Vec3(); +const Body_updateMassProperties_halfExtents = new Vec3(); /** * Base class for broadphase implementations @@ -4806,11 +4143,11 @@ var Body_updateMassProperties_halfExtents = new Vec3(); * @constructor * @author schteppe */ -var Broadphase = /*#__PURE__*/function () { +class Broadphase { // The world to search for collisions in. // If set to true, the broadphase uses bounding boxes for intersection test, else it uses bounding spheres. // Set to true if the objects in the world moved. - function Broadphase() { + constructor() { this.world = null; this.useBoundingBoxes = false; this.dirty = true; @@ -4823,10 +4160,7 @@ var Broadphase = /*#__PURE__*/function () { * @param {Array} p2 Empty array to be filled with body objects */ - - var _proto = Broadphase.prototype; - - _proto.collisionPairs = function collisionPairs(world, p1, p2) { + collisionPairs(world, p1, p2) { throw new Error('collisionPairs not implemented for this BroadPhase class!'); } /** @@ -4836,20 +4170,17 @@ var Broadphase = /*#__PURE__*/function () { * @param {Body} bodyB * @return {bool} */ - ; - _proto.needBroadphaseCollision = function needBroadphaseCollision(bodyA, bodyB) { + needBroadphaseCollision(bodyA, bodyB) { // Check collision filter masks if ((bodyA.collisionFilterGroup & bodyB.collisionFilterMask) === 0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask) === 0) { return false; } // Check types - if (((bodyA.type & Body.STATIC) !== 0 || bodyA.sleepState === Body.SLEEPING) && ((bodyB.type & Body.STATIC) !== 0 || bodyB.sleepState === Body.SLEEPING)) { // Both bodies are static or sleeping. Skip. return false; } - return true; } /** @@ -4860,22 +4191,19 @@ var Broadphase = /*#__PURE__*/function () { * @param {array} pairs1 * @param {array} pairs2 */ - ; - _proto.intersectionTest = function intersectionTest(bodyA, bodyB, pairs1, pairs2) { + intersectionTest(bodyA, bodyB, pairs1, pairs2) { if (this.useBoundingBoxes) { this.doBoundingBoxBroadphase(bodyA, bodyB, pairs1, pairs2); } else { this.doBoundingSphereBroadphase(bodyA, bodyB, pairs1, pairs2); } - }; - - _proto.doBoundingSphereBroadphase = function doBoundingSphereBroadphase(bodyA, bodyB, pairs1, pairs2) { - var r = Broadphase_collisionPairs_r; + } + doBoundingSphereBroadphase(bodyA, bodyB, pairs1, pairs2) { + const r = Broadphase_collisionPairs_r; bodyB.position.vsub(bodyA.position, r); - var boundingRadiusSum2 = Math.pow(bodyA.boundingRadius + bodyB.boundingRadius, 2); - var norm2 = r.lengthSquared(); - + const boundingRadiusSum2 = (bodyA.boundingRadius + bodyB.boundingRadius) ** 2; + const norm2 = r.lengthSquared(); if (norm2 < boundingRadiusSum2) { pairs1.push(bodyA); pairs2.push(bodyB); @@ -4889,53 +4217,44 @@ var Broadphase = /*#__PURE__*/function () { * @param {Array} pairs1 * @param {Array} pairs2 */ - ; - _proto.doBoundingBoxBroadphase = function doBoundingBoxBroadphase(bodyA, bodyB, pairs1, pairs2) { + doBoundingBoxBroadphase(bodyA, bodyB, pairs1, pairs2) { if (bodyA.aabbNeedsUpdate) { bodyA.computeAABB(); } - if (bodyB.aabbNeedsUpdate) { bodyB.computeAABB(); } // Check AABB / AABB - if (bodyA.aabb.overlaps(bodyB.aabb)) { pairs1.push(bodyA); pairs2.push(bodyB); } - }; - - _proto.makePairsUnique = function makePairsUnique(pairs1, pairs2) { - var t = Broadphase_makePairsUnique_temp; - var p1 = Broadphase_makePairsUnique_p1; - var p2 = Broadphase_makePairsUnique_p2; - var N = pairs1.length; - - for (var i = 0; i !== N; i++) { + } + makePairsUnique(pairs1, pairs2) { + const t = Broadphase_makePairsUnique_temp; + const p1 = Broadphase_makePairsUnique_p1; + const p2 = Broadphase_makePairsUnique_p2; + const N = pairs1.length; + for (let i = 0; i !== N; i++) { p1[i] = pairs1[i]; p2[i] = pairs2[i]; } - pairs1.length = 0; pairs2.length = 0; - - for (var _i = 0; _i !== N; _i++) { - var id1 = p1[_i].id; - var id2 = p2[_i].id; - var key = id1 < id2 ? id1 + "," + id2 : id2 + "," + id1; - t[key] = _i; + for (let i = 0; i !== N; i++) { + const id1 = p1[i].id; + const id2 = p2[i].id; + const key = id1 < id2 ? id1 + "," + id2 : id2 + "," + id1; + t[key] = i; t.keys.push(key); } - - for (var _i2 = 0; _i2 !== t.keys.length; _i2++) { - var _key = t.keys.pop(); - - var pairIndex = t[_key]; + for (let i = 0; i !== t.keys.length; i++) { + const key = t.keys.pop(); + const pairIndex = t[key]; pairs1.push(p1[pairIndex]); pairs2.push(p2[pairIndex]); - delete t[_key]; + delete t[key]; } } /** @@ -4943,9 +4262,8 @@ var Broadphase = /*#__PURE__*/function () { * @method setWorld * @param {World} world */ - ; - _proto.setWorld = function setWorld(world) {} + setWorld(world) {} /** * Returns all the bodies within the AABB. * @method aabbQuery @@ -4954,15 +4272,12 @@ var Broadphase = /*#__PURE__*/function () { * @param {array} result An array to store resulting bodies in. * @return {array} */ - ; - _proto.aabbQuery = function aabbQuery(world, aabb, result) { + aabbQuery(world, aabb, result) { console.warn('.aabbQuery is not implemented in this Broadphase subclass.'); return []; - }; - - return Broadphase; -}(); + } +} /** * Check if the bounding spheres of two bodies are intersecting. * @method doBoundingSphereBroadphase @@ -4971,12 +4286,10 @@ var Broadphase = /*#__PURE__*/function () { * @param {Array} pairs1 bodyA is appended to this array if intersection * @param {Array} pairs2 bodyB is appended to this array if intersection */ - -var // Temp objects +exports.Broadphase = Broadphase; +const +// Temp objects Broadphase_collisionPairs_r = new Vec3(); -var Broadphase_collisionPairs_normal = new Vec3(); -var Broadphase_collisionPairs_quat = new Quaternion(); -var Broadphase_collisionPairs_relpos = new Vec3(); /** * Removes duplicate pairs from the pair arrays. * @method makePairsUnique @@ -4984,27 +4297,17 @@ var Broadphase_collisionPairs_relpos = new Vec3(); * @param {Array} pairs2 */ -var Broadphase_makePairsUnique_temp = { +const Broadphase_makePairsUnique_temp = { keys: [] }; -var Broadphase_makePairsUnique_p1 = []; -var Broadphase_makePairsUnique_p2 = []; -/** - * Check if the bounding spheres of two bodies overlap. - * @method boundingSphereCheck - * @param {Body} bodyA - * @param {Body} bodyB - * @return {boolean} - */ - -var bsc_dist = new Vec3(); - -Broadphase.boundingSphereCheck = function (bodyA, bodyB) { - var dist = new Vec3(); // bsc_dist; +const Broadphase_makePairsUnique_p1 = []; +const Broadphase_makePairsUnique_p2 = []; +Broadphase.boundingSphereCheck = (bodyA, bodyB) => { + const dist = new Vec3(); // bsc_dist; bodyA.position.vsub(bodyB.position, dist); - var sa = bodyA.shapes[0]; - var sb = bodyB.shapes[0]; + const sa = bodyA.shapes[0]; + const sb = bodyB.shapes[0]; return Math.pow(sa.boundingSphereRadius + sb.boundingSphereRadius, 2) > dist.lengthSquared(); }; @@ -5020,238 +4323,184 @@ Broadphase.boundingSphereCheck = function (bodyA, bodyB) { * @param {Number} ny Number of boxes along y * @param {Number} nz Number of boxes along z */ -var GridBroadphase = /*#__PURE__*/function (_Broadphase) { - _inheritsLoose(GridBroadphase, _Broadphase); - - function GridBroadphase(aabbMin, aabbMax, nx, ny, nz) { - var _this; - - if (aabbMin === void 0) { - aabbMin = new Vec3(100, 100, 100); - } - - if (aabbMax === void 0) { - aabbMax = new Vec3(-100, -100, -100); - } - - if (nx === void 0) { - nx = 10; - } - - if (ny === void 0) { - ny = 10; - } - - if (nz === void 0) { - nz = 10; - } - - _this = _Broadphase.call(this) || this; - _this.nx = nx; - _this.ny = ny; - _this.nz = nz; - _this.aabbMin = aabbMin; - _this.aabbMax = aabbMax; - var nbins = _this.nx * _this.ny * _this.nz; - +class GridBroadphase extends Broadphase { + constructor(aabbMin = new Vec3(100, 100, 100), aabbMax = new Vec3(-100, -100, -100), nx = 10, ny = 10, nz = 10) { + super(); + this.nx = nx; + this.ny = ny; + this.nz = nz; + this.aabbMin = aabbMin; + this.aabbMax = aabbMax; + const nbins = this.nx * this.ny * this.nz; if (nbins <= 0) { throw "GridBroadphase: Each dimension's n must be >0"; } - - _this.bins = []; - _this.binLengths = []; //Rather than continually resizing arrays (thrashing the memory), just record length and allow them to grow - - _this.bins.length = nbins; - _this.binLengths.length = nbins; - - for (var i = 0; i < nbins; i++) { - _this.bins[i] = []; - _this.binLengths[i] = 0; - } - - return _this; - } - - var _proto = GridBroadphase.prototype; - - _proto.collisionPairs = function collisionPairs(world, pairs1, pairs2) { - var N = world.numObjects(); - var bodies = world.bodies; - var max = this.aabbMax; - var min = this.aabbMin; - var nx = this.nx; - var ny = this.ny; - var nz = this.nz; - var xstep = ny * nz; - var ystep = nz; - var zstep = 1; - var xmax = max.x; - var ymax = max.y; - var zmax = max.z; - var xmin = min.x; - var ymin = min.y; - var zmin = min.z; - var xmult = nx / (xmax - xmin); - var ymult = ny / (ymax - ymin); - var zmult = nz / (zmax - zmin); - var binsizeX = (xmax - xmin) / nx; - var binsizeY = (ymax - ymin) / ny; - var binsizeZ = (zmax - zmin) / nz; - var binRadius = Math.sqrt(binsizeX * binsizeX + binsizeY * binsizeY + binsizeZ * binsizeZ) * 0.5; - var types = Shape.types; - var SPHERE = types.SPHERE; - var PLANE = types.PLANE; - var BOX = types.BOX; - var COMPOUND = types.COMPOUND; - var CONVEXPOLYHEDRON = types.CONVEXPOLYHEDRON; - var bins = this.bins; - var binLengths = this.binLengths; - var Nbins = this.bins.length; // Reset bins - - for (var i = 0; i !== Nbins; i++) { + this.bins = []; + this.binLengths = []; //Rather than continually resizing arrays (thrashing the memory), just record length and allow them to grow + + this.bins.length = nbins; + this.binLengths.length = nbins; + for (let i = 0; i < nbins; i++) { + this.bins[i] = []; + this.binLengths[i] = 0; + } + } + collisionPairs(world, pairs1, pairs2) { + const N = world.numObjects(); + const bodies = world.bodies; + const max = this.aabbMax; + const min = this.aabbMin; + const nx = this.nx; + const ny = this.ny; + const nz = this.nz; + const xstep = ny * nz; + const ystep = nz; + const zstep = 1; + const xmax = max.x; + const ymax = max.y; + const zmax = max.z; + const xmin = min.x; + const ymin = min.y; + const zmin = min.z; + const xmult = nx / (xmax - xmin); + const ymult = ny / (ymax - ymin); + const zmult = nz / (zmax - zmin); + const binsizeX = (xmax - xmin) / nx; + const binsizeY = (ymax - ymin) / ny; + const binsizeZ = (zmax - zmin) / nz; + const binRadius = Math.sqrt(binsizeX * binsizeX + binsizeY * binsizeY + binsizeZ * binsizeZ) * 0.5; + const types = Shape.types; + const SPHERE = types.SPHERE; + const PLANE = types.PLANE; + const BOX = types.BOX; + const COMPOUND = types.COMPOUND; + const CONVEXPOLYHEDRON = types.CONVEXPOLYHEDRON; + const bins = this.bins; + const binLengths = this.binLengths; + const Nbins = this.bins.length; // Reset bins + + for (let i = 0; i !== Nbins; i++) { binLengths[i] = 0; } - - var ceil = Math.ceil; - + const ceil = Math.ceil; function addBoxToBins(x0, y0, z0, x1, y1, z1, bi) { - var xoff0 = (x0 - xmin) * xmult | 0; - var yoff0 = (y0 - ymin) * ymult | 0; - var zoff0 = (z0 - zmin) * zmult | 0; - var xoff1 = ceil((x1 - xmin) * xmult); - var yoff1 = ceil((y1 - ymin) * ymult); - var zoff1 = ceil((z1 - zmin) * zmult); - + let xoff0 = (x0 - xmin) * xmult | 0; + let yoff0 = (y0 - ymin) * ymult | 0; + let zoff0 = (z0 - zmin) * zmult | 0; + let xoff1 = ceil((x1 - xmin) * xmult); + let yoff1 = ceil((y1 - ymin) * ymult); + let zoff1 = ceil((z1 - zmin) * zmult); if (xoff0 < 0) { xoff0 = 0; } else if (xoff0 >= nx) { xoff0 = nx - 1; } - if (yoff0 < 0) { yoff0 = 0; } else if (yoff0 >= ny) { yoff0 = ny - 1; } - if (zoff0 < 0) { zoff0 = 0; } else if (zoff0 >= nz) { zoff0 = nz - 1; } - if (xoff1 < 0) { xoff1 = 0; } else if (xoff1 >= nx) { xoff1 = nx - 1; } - if (yoff1 < 0) { yoff1 = 0; } else if (yoff1 >= ny) { yoff1 = ny - 1; } - if (zoff1 < 0) { zoff1 = 0; } else if (zoff1 >= nz) { zoff1 = nz - 1; } - xoff0 *= xstep; yoff0 *= ystep; zoff0 *= zstep; xoff1 *= xstep; yoff1 *= ystep; zoff1 *= zstep; - - for (var xoff = xoff0; xoff <= xoff1; xoff += xstep) { - for (var yoff = yoff0; yoff <= yoff1; yoff += ystep) { - for (var zoff = zoff0; zoff <= zoff1; zoff += zstep) { - var idx = xoff + yoff + zoff; + for (let xoff = xoff0; xoff <= xoff1; xoff += xstep) { + for (let yoff = yoff0; yoff <= yoff1; yoff += ystep) { + for (let zoff = zoff0; zoff <= zoff1; zoff += zstep) { + const idx = xoff + yoff + zoff; bins[idx][binLengths[idx]++] = bi; } } } } // Put all bodies into the bins - - for (var _i = 0; _i !== N; _i++) { - var bi = bodies[_i]; - var si = bi.shapes[0]; - + for (let i = 0; i !== N; i++) { + const bi = bodies[i]; + const si = bi.shapes[0]; switch (si.type) { case SPHERE: { - var shape = si; // Put in bin + const shape = si; // Put in bin // check if overlap with other bins - var x = bi.position.x; - var y = bi.position.y; - var z = bi.position.z; - var r = shape.radius; + const x = bi.position.x; + const y = bi.position.y; + const z = bi.position.z; + const r = shape.radius; addBoxToBins(x - r, y - r, z - r, x + r, y + r, z + r, bi); break; } - case PLANE: { - var _shape = si; - - if (_shape.worldNormalNeedsUpdate) { - _shape.computeWorldNormal(bi.quaternion); + const shape = si; + if (shape.worldNormalNeedsUpdate) { + shape.computeWorldNormal(bi.quaternion); } - - var planeNormal = _shape.worldNormal; //Relative position from origin of plane object to the first bin + const planeNormal = shape.worldNormal; //Relative position from origin of plane object to the first bin //Incremented as we iterate through the bins - var xreset = xmin + binsizeX * 0.5 - bi.position.x; - var yreset = ymin + binsizeY * 0.5 - bi.position.y; - var zreset = zmin + binsizeZ * 0.5 - bi.position.z; - var d = GridBroadphase_collisionPairs_d; + const xreset = xmin + binsizeX * 0.5 - bi.position.x; + const yreset = ymin + binsizeY * 0.5 - bi.position.y; + const zreset = zmin + binsizeZ * 0.5 - bi.position.z; + const d = GridBroadphase_collisionPairs_d; d.set(xreset, yreset, zreset); - - for (var xi = 0, xoff = 0; xi !== nx; xi++, xoff += xstep, d.y = yreset, d.x += binsizeX) { - for (var yi = 0, yoff = 0; yi !== ny; yi++, yoff += ystep, d.z = zreset, d.y += binsizeY) { - for (var zi = 0, zoff = 0; zi !== nz; zi++, zoff += zstep, d.z += binsizeZ) { + for (let xi = 0, xoff = 0; xi !== nx; xi++, xoff += xstep, d.y = yreset, d.x += binsizeX) { + for (let yi = 0, yoff = 0; yi !== ny; yi++, yoff += ystep, d.z = zreset, d.y += binsizeY) { + for (let zi = 0, zoff = 0; zi !== nz; zi++, zoff += zstep, d.z += binsizeZ) { if (d.dot(planeNormal) < binRadius) { - var idx = xoff + yoff + zoff; + const idx = xoff + yoff + zoff; bins[idx][binLengths[idx]++] = bi; } } } } - break; } - default: { if (bi.aabbNeedsUpdate) { bi.computeAABB(); } - addBoxToBins(bi.aabb.lowerBound.x, bi.aabb.lowerBound.y, bi.aabb.lowerBound.z, bi.aabb.upperBound.x, bi.aabb.upperBound.y, bi.aabb.upperBound.z, bi); break; } } } // Check each bin - - for (var _i2 = 0; _i2 !== Nbins; _i2++) { - var binLength = binLengths[_i2]; //Skip bins with no potential collisions + for (let i = 0; i !== Nbins; i++) { + const binLength = binLengths[i]; //Skip bins with no potential collisions if (binLength > 1) { - var bin = bins[_i2]; // Do N^2 broadphase inside - - for (var _xi = 0; _xi !== binLength; _xi++) { - var _bi = bin[_xi]; - - for (var _yi = 0; _yi !== _xi; _yi++) { - var bj = bin[_yi]; - - if (this.needBroadphaseCollision(_bi, bj)) { - this.intersectionTest(_bi, bj, pairs1, pairs2); + const bin = bins[i]; // Do N^2 broadphase inside + + for (let xi = 0; xi !== binLength; xi++) { + const bi = bin[xi]; + for (let yi = 0; yi !== xi; yi++) { + const bj = bin[yi]; + if (this.needBroadphaseCollision(bi, bj)) { + this.intersectionTest(bi, bj, pairs1, pairs2); } } } @@ -5268,12 +4517,9 @@ var GridBroadphase = /*#__PURE__*/function (_Broadphase) { // } // } - this.makePairsUnique(pairs1, pairs2); - }; - - return GridBroadphase; -}(Broadphase); + } +} /** * Get all the collision pairs in the physics world * @method collisionPairs @@ -5281,9 +4527,8 @@ var GridBroadphase = /*#__PURE__*/function (_Broadphase) { * @param {Array} pairs1 * @param {Array} pairs2 */ - -var GridBroadphase_collisionPairs_d = new Vec3(); -var GridBroadphase_collisionPairs_binPos = new Vec3(); +exports.GridBroadphase = GridBroadphase; +const GridBroadphase_collisionPairs_d = new Vec3(); /** * Naive broadphase implementation, used in lack of better ones. @@ -5292,11 +4537,9 @@ var GridBroadphase_collisionPairs_binPos = new Vec3(); * @description The naive broadphase looks at all possible pairs without restriction, therefore it has complexity N^2 (which is bad) * @extends Broadphase */ -var NaiveBroadphase = /*#__PURE__*/function (_Broadphase) { - _inheritsLoose(NaiveBroadphase, _Broadphase); - - function NaiveBroadphase() { - return _Broadphase.call(this) || this; +class NaiveBroadphase extends Broadphase { + constructor() { + super(); } /** * Get all the collision pairs in the physics world @@ -5306,24 +4549,19 @@ var NaiveBroadphase = /*#__PURE__*/function (_Broadphase) { * @param {Array} pairs2 */ + collisionPairs(world, pairs1, pairs2) { + const bodies = world.bodies; + const n = bodies.length; + let bi; + let bj; // Naive N^2 ftw! - var _proto = NaiveBroadphase.prototype; - - _proto.collisionPairs = function collisionPairs(world, pairs1, pairs2) { - var bodies = world.bodies; - var n = bodies.length; - var bi; - var bj; // Naive N^2 ftw! - - for (var i = 0; i !== n; i++) { - for (var j = 0; j !== i; j++) { + for (let i = 0; i !== n; i++) { + for (let j = 0; j !== i; j++) { bi = bodies[i]; bj = bodies[j]; - if (!this.needBroadphaseCollision(bi, bj)) { continue; } - this.intersectionTest(bi, bj, pairs1, pairs2); } } @@ -5336,42 +4574,33 @@ var NaiveBroadphase = /*#__PURE__*/function (_Broadphase) { * @param {array} result An array to store resulting bodies in. * @return {array} */ - ; - - _proto.aabbQuery = function aabbQuery(world, aabb, result) { - if (result === void 0) { - result = []; - } - - for (var i = 0; i < world.bodies.length; i++) { - var b = world.bodies[i]; + aabbQuery(world, aabb, result = []) { + for (let i = 0; i < world.bodies.length; i++) { + const b = world.bodies[i]; if (b.aabbNeedsUpdate) { b.computeAABB(); } // Ugly hack until Body gets aabb - if (b.aabb.overlaps(aabb)) { result.push(b); } } - return result; - }; - - return NaiveBroadphase; -}(Broadphase); + } +} /** * Storage for Ray casting data. * @class RaycastResult * @constructor */ -var RaycastResult = /*#__PURE__*/function () { +exports.NaiveBroadphase = NaiveBroadphase; +class RaycastResult { // The index of the hit triangle, if the hit shape was a trimesh. // Distance to the hit. Will be set to -1 if there was no hit. // If the ray should stop traversing the bodies. - function RaycastResult() { + constructor() { this.rayFromWorld = new Vec3(); this.rayToWorld = new Vec3(); this.hitNormalWorld = new Vec3(); @@ -5388,10 +4617,7 @@ var RaycastResult = /*#__PURE__*/function () { * @method reset */ - - var _proto = RaycastResult.prototype; - - _proto.reset = function reset() { + reset() { this.rayFromWorld.setZero(); this.rayToWorld.setZero(); this.hitNormalWorld.setZero(); @@ -5406,9 +4632,8 @@ var RaycastResult = /*#__PURE__*/function () { /** * @method abort */ - ; - _proto.abort = function abort() { + abort() { this.shouldStop = true; } /** @@ -5421,9 +4646,8 @@ var RaycastResult = /*#__PURE__*/function () { * @param {Body} body * @param {number} distance */ - ; - _proto.set = function set(rayFromWorld, rayToWorld, hitNormalWorld, hitPointWorld, shape, body, distance) { + set(rayFromWorld, rayToWorld, hitNormalWorld, hitPointWorld, shape, body, distance) { this.rayFromWorld.copy(rayFromWorld); this.rayToWorld.copy(rayToWorld); this.hitNormalWorld.copy(hitNormalWorld); @@ -5431,12 +4655,10 @@ var RaycastResult = /*#__PURE__*/function () { this.shape = shape; this.body = body; this.distance = distance; - }; - - return RaycastResult; -}(); - -var RAY_MODES = { + } +} +exports.RaycastResult = RaycastResult; +const RAY_MODES = exports.RAY_MODES = { CLOSEST: 1, ANY: 2, ALL: 4 @@ -5449,7 +4671,7 @@ var RAY_MODES = { * @param {Vec3} from * @param {Vec3} to */ -var Ray = /*#__PURE__*/function () { +class Ray { // The precision of the ray. Used when checking parallelity etc. // Set to true if you want the Ray to take .collisionResponse flags into account on bodies and shapes. // If set to true, the ray skips any hits with normal.dot(rayDirection) < 0. @@ -5457,15 +4679,7 @@ var Ray = /*#__PURE__*/function () { // Current result object. // Will be set to true during intersectWorld() if the ray hit anything. // User-provided result callback. Will be used if mode is Ray.ALL. - function Ray(from, to) { - if (from === void 0) { - from = new Vec3(); - } - - if (to === void 0) { - to = new Vec3(); - } - + constructor(from = new Vec3(), to = new Vec3()) { this.from = from.clone(); this.to = to.clone(); this.direction = new Vec3(); @@ -5477,8 +4691,7 @@ var Ray = /*#__PURE__*/function () { this.mode = Ray.ANY; this.result = new RaycastResult(); this.hasHit = false; - - this.callback = function (result) {}; + this.callback = result => {}; } /** * Do itersection against all bodies in the given World. @@ -5488,27 +4701,20 @@ var Ray = /*#__PURE__*/function () { * @return {Boolean} True if the ray hit anything, otherwise false. */ - - var _proto = Ray.prototype; - - _proto.intersectWorld = function intersectWorld(world, options) { + intersectWorld(world, options) { this.mode = options.mode || Ray.ANY; this.result = options.result || new RaycastResult(); this.skipBackfaces = !!options.skipBackfaces; this.collisionFilterMask = typeof options.collisionFilterMask !== 'undefined' ? options.collisionFilterMask : -1; this.collisionFilterGroup = typeof options.collisionFilterGroup !== 'undefined' ? options.collisionFilterGroup : -1; this.checkCollisionResponse = typeof options.checkCollisionResponse !== 'undefined' ? options.checkCollisionResponse : true; - if (options.from) { this.from.copy(options.from); } - if (options.to) { this.to.copy(options.to); } - - this.callback = options.callback || function () {}; - + this.callback = options.callback || (() => {}); this.hasHit = false; this.result.reset(); this.updateDirection(); @@ -5523,30 +4729,23 @@ var Ray = /*#__PURE__*/function () { * @param {Body} body * @param {RaycastResult} [result] Deprecated - set the result property of the Ray instead. */ - ; - _proto.intersectBody = function intersectBody(body, result) { + intersectBody(body, result) { if (result) { this.result = result; this.updateDirection(); } - - var checkCollisionResponse = this.checkCollisionResponse; - + const checkCollisionResponse = this.checkCollisionResponse; if (checkCollisionResponse && !body.collisionResponse) { return; } - if ((this.collisionFilterGroup & body.collisionFilterMask) === 0 || (body.collisionFilterGroup & this.collisionFilterMask) === 0) { return; } - - var xi = intersectBody_xi; - var qi = intersectBody_qi; - - for (var i = 0, N = body.shapes.length; i < N; i++) { - var shape = body.shapes[i]; - + const xi = intersectBody_xi; + const qi = intersectBody_qi; + for (let i = 0, N = body.shapes.length; i < N; i++) { + const shape = body.shapes[i]; if (checkCollisionResponse && !shape.collisionResponse) { continue; // Skip } @@ -5555,7 +4754,6 @@ var Ray = /*#__PURE__*/function () { body.quaternion.vmult(body.shapeOffsets[i], xi); xi.vadd(body.position, xi); this.intersectShape(shape, qi, xi, body); - if (this.result.shouldStop) { break; } @@ -5566,82 +4764,68 @@ var Ray = /*#__PURE__*/function () { * @param {Array} bodies An array of Body objects. * @param {RaycastResult} [result] Deprecated */ - ; - _proto.intersectBodies = function intersectBodies(bodies, result) { + intersectBodies(bodies, result) { if (result) { this.result = result; this.updateDirection(); } - - for (var i = 0, l = bodies.length; !this.result.shouldStop && i < l; i++) { + for (let i = 0, l = bodies.length; !this.result.shouldStop && i < l; i++) { this.intersectBody(bodies[i]); } } /** * Updates the direction vector. */ - ; - _proto.updateDirection = function updateDirection() { + updateDirection() { this.to.vsub(this.from, this.direction); this.direction.normalize(); - }; - - _proto.intersectShape = function intersectShape(shape, quat, position, body) { - var from = this.from; // Checking boundingSphere - - var distance = distanceFromIntersection(from, this.direction, position); + } + intersectShape(shape, quat, position, body) { + const from = this.from; // Checking boundingSphere + const distance = distanceFromIntersection(from, this.direction, position); if (distance > shape.boundingSphereRadius) { return; } - - var intersectMethod = this[shape.type]; - + const intersectMethod = this[shape.type]; if (intersectMethod) { intersectMethod.call(this, shape, quat, position, body, shape); } - }; - - _proto._intersectBox = function _intersectBox(box, quat, position, body, reportedShape) { + } + _intersectBox(box, quat, position, body, reportedShape) { return this._intersectConvex(box.convexPolyhedronRepresentation, quat, position, body, reportedShape); - }; - - _proto._intersectPlane = function _intersectPlane(shape, quat, position, body, reportedShape) { - var from = this.from; - var to = this.to; - var direction = this.direction; // Get plane normal + } + _intersectPlane(shape, quat, position, body, reportedShape) { + const from = this.from; + const to = this.to; + const direction = this.direction; // Get plane normal - var worldNormal = new Vec3(0, 0, 1); + const worldNormal = new Vec3(0, 0, 1); quat.vmult(worldNormal, worldNormal); - var len = new Vec3(); + const len = new Vec3(); from.vsub(position, len); - var planeToFrom = len.dot(worldNormal); + const planeToFrom = len.dot(worldNormal); to.vsub(position, len); - var planeToTo = len.dot(worldNormal); - + const planeToTo = len.dot(worldNormal); if (planeToFrom * planeToTo > 0) { // "from" and "to" are on the same side of the plane... bail out return; } - if (from.distanceTo(to) < planeToFrom) { return; } - - var n_dot_dir = worldNormal.dot(direction); - + const n_dot_dir = worldNormal.dot(direction); if (Math.abs(n_dot_dir) < this.precision) { // No intersection return; } - - var planePointToFrom = new Vec3(); - var dir_scaled_with_t = new Vec3(); - var hitPointWorld = new Vec3(); + const planePointToFrom = new Vec3(); + const dir_scaled_with_t = new Vec3(); + const hitPointWorld = new Vec3(); from.vsub(position, planePointToFrom); - var t = -worldNormal.dot(planePointToFrom) / n_dot_dir; + const t = -worldNormal.dot(planePointToFrom) / n_dot_dir; direction.scale(t, dir_scaled_with_t); from.vadd(dir_scaled_with_t, hitPointWorld); this.reportIntersection(worldNormal, hitPointWorld, reportedShape, body, -1); @@ -5649,26 +4833,26 @@ var Ray = /*#__PURE__*/function () { /** * Get the world AABB of the ray. */ - ; - _proto.getAABB = function getAABB(aabb) { - var lowerBound = aabb.lowerBound, - upperBound = aabb.upperBound; - var to = this.to; - var from = this.from; + getAABB(aabb) { + const { + lowerBound, + upperBound + } = aabb; + const to = this.to; + const from = this.from; lowerBound.x = Math.min(to.x, from.x); lowerBound.y = Math.min(to.y, from.y); lowerBound.z = Math.min(to.z, from.z); upperBound.x = Math.max(to.x, from.x); upperBound.y = Math.max(to.y, from.y); upperBound.z = Math.max(to.z, from.z); - }; - - _proto._intersectHeightfield = function _intersectHeightfield(shape, quat, position, body, reportedShape) { - var data = shape.data; - var w = shape.elementSize; // Convert the ray to local heightfield coordinates + } + _intersectHeightfield(shape, quat, position, body, reportedShape) { + const data = shape.data; + const w = shape.elementSize; // Convert the ray to local heightfield coordinates - var localRay = intersectHeightfield_localRay; //new Ray(this.from, this.to); + const localRay = intersectHeightfield_localRay; //new Ray(this.from, this.to); localRay.from.copy(this.from); localRay.to.copy(this.to); @@ -5676,15 +4860,15 @@ var Ray = /*#__PURE__*/function () { Transform.pointToLocalFrame(position, quat, localRay.to, localRay.to); localRay.updateDirection(); // Get the index of the data points to test against - var index = intersectHeightfield_index; - var iMinX; - var iMinY; - var iMaxX; - var iMaxY; // Set to max + const index = intersectHeightfield_index; + let iMinX; + let iMinY; + let iMaxX; + let iMaxY; // Set to max iMinX = iMinY = 0; iMaxX = iMaxY = shape.data.length - 1; - var aabb = new AABB(); + const aabb = new AABB(); localRay.getAABB(aabb); shape.getIndexOfPosition(aabb.lowerBound.x, aabb.lowerBound.y, index, true); iMinX = Math.max(iMinX, index[0]); @@ -5692,49 +4876,39 @@ var Ray = /*#__PURE__*/function () { shape.getIndexOfPosition(aabb.upperBound.x, aabb.upperBound.y, index, true); iMaxX = Math.min(iMaxX, index[0] + 1); iMaxY = Math.min(iMaxY, index[1] + 1); - - for (var i = iMinX; i < iMaxX; i++) { - for (var j = iMinY; j < iMaxY; j++) { + for (let i = iMinX; i < iMaxX; i++) { + for (let j = iMinY; j < iMaxY; j++) { if (this.result.shouldStop) { return; } - shape.getAabbAtIndex(i, j, aabb); - if (!aabb.overlapsRay(localRay)) { continue; } // Lower triangle - shape.getConvexTrianglePillar(i, j, false); Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset); - this._intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, reportedShape, intersectConvexOptions); - if (this.result.shouldStop) { return; } // Upper triangle - shape.getConvexTrianglePillar(i, j, true); Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset); - this._intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, reportedShape, intersectConvexOptions); } } - }; - - _proto._intersectSphere = function _intersectSphere(sphere, quat, position, body, reportedShape) { - var from = this.from; - var to = this.to; - var r = sphere.radius; - var a = Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2) + Math.pow(to.z - from.z, 2); - var b = 2 * ((to.x - from.x) * (from.x - position.x) + (to.y - from.y) * (from.y - position.y) + (to.z - from.z) * (from.z - position.z)); - var c = Math.pow(from.x - position.x, 2) + Math.pow(from.y - position.y, 2) + Math.pow(from.z - position.z, 2) - Math.pow(r, 2); - var delta = Math.pow(b, 2) - 4 * a * c; - var intersectionPoint = Ray_intersectSphere_intersectionPoint; - var normal = Ray_intersectSphere_normal; - + } + _intersectSphere(sphere, quat, position, body, reportedShape) { + const from = this.from; + const to = this.to; + const r = sphere.radius; + const a = (to.x - from.x) ** 2 + (to.y - from.y) ** 2 + (to.z - from.z) ** 2; + const b = 2 * ((to.x - from.x) * (from.x - position.x) + (to.y - from.y) * (from.y - position.y) + (to.z - from.z) * (from.z - position.z)); + const c = (from.x - position.x) ** 2 + (from.y - position.y) ** 2 + (from.z - position.z) ** 2 - r ** 2; + const delta = b ** 2 - 4 * a * c; + const intersectionPoint = Ray_intersectSphere_intersectionPoint; + const normal = Ray_intersectSphere_normal; if (delta < 0) { // No intersection return; @@ -5745,20 +4919,17 @@ var Ray = /*#__PURE__*/function () { normal.normalize(); this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1); } else { - var d1 = (-b - Math.sqrt(delta)) / (2 * a); - var d2 = (-b + Math.sqrt(delta)) / (2 * a); - + const d1 = (-b - Math.sqrt(delta)) / (2 * a); + const d2 = (-b + Math.sqrt(delta)) / (2 * a); if (d1 >= 0 && d1 <= 1) { from.lerp(to, d1, intersectionPoint); intersectionPoint.vsub(position, normal); normal.normalize(); this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1); } - if (this.result.shouldStop) { return; } - if (d2 >= 0 && d2 <= 1) { from.lerp(to, d2, intersectionPoint); intersectionPoint.vsub(position, normal); @@ -5766,29 +4937,27 @@ var Ray = /*#__PURE__*/function () { this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1); } } - }; - - _proto._intersectConvex = function _intersectConvex(shape, quat, position, body, reportedShape, options) { - var normal = intersectConvex_normal; - var vector = intersectConvex_vector; - var faceList = options && options.faceList || null; // Checking faces - - var faces = shape.faces; - var vertices = shape.vertices; - var normals = shape.faceNormals; - var direction = this.direction; - var from = this.from; - var to = this.to; - var fromToDistance = from.distanceTo(to); - var Nfaces = faceList ? faceList.length : faces.length; - var result = this.result; - - for (var j = 0; !result.shouldStop && j < Nfaces; j++) { - var fi = faceList ? faceList[j] : j; - var face = faces[fi]; - var faceNormal = normals[fi]; - var q = quat; - var x = position; // determine if ray intersects the plane of the face + } + _intersectConvex(shape, quat, position, body, reportedShape, options) { + const normal = intersectConvex_normal; + const vector = intersectConvex_vector; + const faceList = options && options.faceList || null; // Checking faces + + const faces = shape.faces; + const vertices = shape.vertices; + const normals = shape.faceNormals; + const direction = this.direction; + const from = this.from; + const to = this.to; + const fromToDistance = from.distanceTo(to); + const Nfaces = faceList ? faceList.length : faces.length; + const result = this.result; + for (let j = 0; !result.shouldStop && j < Nfaces; j++) { + const fi = faceList ? faceList[j] : j; + const face = faces[fi]; + const faceNormal = normals[fi]; + const q = quat; + const x = position; // determine if ray intersects the plane of the face // note: this works regardless of the direction of the face normal // Get plane point in world coordinates... @@ -5800,29 +4969,26 @@ var Ray = /*#__PURE__*/function () { q.vmult(faceNormal, normal); // If this dot product is negative, we have something interesting - var dot = direction.dot(normal); // Bail out if ray and plane are parallel + const dot = direction.dot(normal); // Bail out if ray and plane are parallel if (Math.abs(dot) < this.precision) { continue; } // calc distance to plane - - var scalar = normal.dot(vector) / dot; // if negative distance, then plane is behind ray + const scalar = normal.dot(vector) / dot; // if negative distance, then plane is behind ray if (scalar < 0) { continue; } // if (dot < 0) { // Intersection point is from + direction * scalar - direction.scale(scalar, intersectPoint); intersectPoint.vadd(from, intersectPoint); // a is the point we compare points b and c with. a.copy(vertices[face[0]]); q.vmult(a, a); x.vadd(a, a); - - for (var i = 1; !result.shouldStop && i < face.length - 1; i++) { + for (let i = 1; !result.shouldStop && i < face.length - 1; i++) { // Transform 3 vertices to world coords b.copy(vertices[face[i]]); c.copy(vertices[face[i + 1]]); @@ -5830,41 +4996,37 @@ var Ray = /*#__PURE__*/function () { q.vmult(c, c); x.vadd(b, b); x.vadd(c, c); - var distance = intersectPoint.distanceTo(from); - + const distance = intersectPoint.distanceTo(from); if (!(pointInTriangle(intersectPoint, a, b, c) || pointInTriangle(intersectPoint, b, a, c)) || distance > fromToDistance) { continue; } - this.reportIntersection(normal, intersectPoint, reportedShape, body, fi); } // } - } } /** * @todo Optimize by transforming the world to local space first. * @todo Use Octree lookup */ - ; - - _proto._intersectTrimesh = function _intersectTrimesh(mesh, quat, position, body, reportedShape, options) { - var normal = intersectTrimesh_normal; - var triangles = intersectTrimesh_triangles; - var treeTransform = intersectTrimesh_treeTransform; - var vector = intersectConvex_vector; - var localDirection = intersectTrimesh_localDirection; - var localFrom = intersectTrimesh_localFrom; - var localTo = intersectTrimesh_localTo; - var worldIntersectPoint = intersectTrimesh_worldIntersectPoint; - var worldNormal = intersectTrimesh_worldNormal; - var faceList = options && options.faceList || null; // Checking faces - - var indices = mesh.indices; - var vertices = mesh.vertices; // const normals = mesh.faceNormals - - var from = this.from; - var to = this.to; - var direction = this.direction; + + _intersectTrimesh(mesh, quat, position, body, reportedShape, options) { + const normal = intersectTrimesh_normal; + const triangles = intersectTrimesh_triangles; + const treeTransform = intersectTrimesh_treeTransform; + const vector = intersectConvex_vector; + const localDirection = intersectTrimesh_localDirection; + const localFrom = intersectTrimesh_localFrom; + const localTo = intersectTrimesh_localTo; + const worldIntersectPoint = intersectTrimesh_worldIntersectPoint; + const worldNormal = intersectTrimesh_worldNormal; + const faceList = options && options.faceList || null; // Checking faces + + const indices = mesh.indices; + const vertices = mesh.vertices; // const normals = mesh.faceNormals + + const from = this.from; + const to = this.to; + const direction = this.direction; treeTransform.position.copy(position); treeTransform.quaternion.copy(quat); // Transform ray to local space! @@ -5879,11 +5041,10 @@ var Ray = /*#__PURE__*/function () { localFrom.z *= mesh.scale.z; localTo.vsub(localFrom, localDirection); localDirection.normalize(); - var fromToDistanceSquared = localFrom.distanceSquared(localTo); + const fromToDistanceSquared = localFrom.distanceSquared(localTo); mesh.tree.rayQuery(this, treeTransform, triangles); - - for (var i = 0, N = triangles.length; !this.result.shouldStop && i !== N; i++) { - var trianglesIndex = triangles[i]; + for (let i = 0, N = triangles.length; !this.result.shouldStop && i !== N; i++) { + const trianglesIndex = triangles[i]; mesh.getNormal(trianglesIndex, normal); // determine if ray intersects the plane of the face // note: this works regardless of the direction of the face normal // Get plane point in world coordinates... @@ -5892,55 +5053,48 @@ var Ray = /*#__PURE__*/function () { a.vsub(localFrom, vector); // If this dot product is negative, we have something interesting - var dot = localDirection.dot(normal); // Bail out if ray and plane are parallel + const dot = localDirection.dot(normal); // Bail out if ray and plane are parallel // if (Math.abs( dot ) < this.precision){ // continue; // } // calc distance to plane - var scalar = normal.dot(vector) / dot; // if negative distance, then plane is behind ray + const scalar = normal.dot(vector) / dot; // if negative distance, then plane is behind ray if (scalar < 0) { continue; } // Intersection point is from + direction * scalar - localDirection.scale(scalar, intersectPoint); intersectPoint.vadd(localFrom, intersectPoint); // Get triangle vertices mesh.getVertex(indices[trianglesIndex * 3 + 1], b); mesh.getVertex(indices[trianglesIndex * 3 + 2], c); - var squaredDistance = intersectPoint.distanceSquared(localFrom); - + const squaredDistance = intersectPoint.distanceSquared(localFrom); if (!(pointInTriangle(intersectPoint, b, a, c) || pointInTriangle(intersectPoint, a, b, c)) || squaredDistance > fromToDistanceSquared) { continue; } // transform intersectpoint and normal to world - Transform.vectorToWorldFrame(quat, normal, worldNormal); Transform.pointToWorldFrame(position, quat, intersectPoint, worldIntersectPoint); this.reportIntersection(worldNormal, worldIntersectPoint, reportedShape, body, trianglesIndex); } - triangles.length = 0; } /** * @return {boolean} True if the intersections should continue */ - ; - _proto.reportIntersection = function reportIntersection(normal, hitPointWorld, shape, body, hitFaceIndex) { - var from = this.from; - var to = this.to; - var distance = from.distanceTo(hitPointWorld); - var result = this.result; // Skip back faces? + reportIntersection(normal, hitPointWorld, shape, body, hitFaceIndex) { + const from = this.from; + const to = this.to; + const distance = from.distanceTo(hitPointWorld); + const result = this.result; // Skip back faces? if (this.skipBackfaces && normal.dot(this.direction) > 0) { return; } - result.hitFaceIndex = typeof hitFaceIndex !== 'undefined' ? hitFaceIndex : -1; - switch (this.mode) { case Ray.ALL: this.hasHit = true; @@ -5948,7 +5102,6 @@ var Ray = /*#__PURE__*/function () { result.hasHit = true; this.callback(result); break; - case Ray.CLOSEST: // Store if closer than current closest if (distance < result.distance || !result.hasHit) { @@ -5956,9 +5109,7 @@ var Ray = /*#__PURE__*/function () { result.hasHit = true; result.set(from, to, normal, hitPointWorld, shape, body, distance); } - break; - case Ray.ANY: // Report and stop. this.hasHit = true; @@ -5967,85 +5118,75 @@ var Ray = /*#__PURE__*/function () { result.shouldStop = true; break; } - }; - - return Ray; -}(); + } +} +exports.Ray = Ray; Ray.CLOSEST = 1; Ray.ANY = 2; Ray.ALL = 4; -var tmpAABB = new AABB(); -var tmpArray = []; -var v1 = new Vec3(); -var v2 = new Vec3(); +const tmpAABB = new AABB(); +const tmpArray = []; +const v1 = new Vec3(); +const v2 = new Vec3(); /* * As per "Barycentric Technique" as named here http://www.blackpawn.com/texts/pointinpoly/default.html But without the division */ Ray.pointInTriangle = pointInTriangle; - function pointInTriangle(p, a, b, c) { c.vsub(a, v0); b.vsub(a, v1); p.vsub(a, v2); - var dot00 = v0.dot(v0); - var dot01 = v0.dot(v1); - var dot02 = v0.dot(v2); - var dot11 = v1.dot(v1); - var dot12 = v1.dot(v2); - var u; - var v; + const dot00 = v0.dot(v0); + const dot01 = v0.dot(v1); + const dot02 = v0.dot(v2); + const dot11 = v1.dot(v1); + const dot12 = v1.dot(v2); + let u; + let v; return (u = dot11 * dot02 - dot01 * dot12) >= 0 && (v = dot00 * dot12 - dot01 * dot02) >= 0 && u + v < dot00 * dot11 - dot01 * dot01; } - -var intersectBody_xi = new Vec3(); -var intersectBody_qi = new Quaternion(); -var vector = new Vec3(); -var normal = new Vec3(); -var intersectPoint = new Vec3(); -var a = new Vec3(); -var b = new Vec3(); -var c = new Vec3(); -var d = new Vec3(); -var tmpRaycastResult = new RaycastResult(); +const intersectBody_xi = new Vec3(); +const intersectBody_qi = new Quaternion(); +const intersectPoint = new Vec3(); +const a = new Vec3(); +const b = new Vec3(); +const c = new Vec3(); Ray.prototype[Shape.types.BOX] = Ray.prototype._intersectBox; Ray.prototype[Shape.types.PLANE] = Ray.prototype._intersectPlane; -var intersectConvexOptions = { +const intersectConvexOptions = { faceList: [0] }; -var worldPillarOffset = new Vec3(); -var intersectHeightfield_localRay = new Ray(); -var intersectHeightfield_index = []; +const worldPillarOffset = new Vec3(); +const intersectHeightfield_localRay = new Ray(); +const intersectHeightfield_index = []; Ray.prototype[Shape.types.HEIGHTFIELD] = Ray.prototype._intersectHeightfield; -var Ray_intersectSphere_intersectionPoint = new Vec3(); -var Ray_intersectSphere_normal = new Vec3(); +const Ray_intersectSphere_intersectionPoint = new Vec3(); +const Ray_intersectSphere_normal = new Vec3(); Ray.prototype[Shape.types.SPHERE] = Ray.prototype._intersectSphere; -var intersectConvex_normal = new Vec3(); -var intersectConvex_minDistNormal = new Vec3(); -var intersectConvex_minDistIntersect = new Vec3(); -var intersectConvex_vector = new Vec3(); +const intersectConvex_normal = new Vec3(); +const intersectConvex_vector = new Vec3(); Ray.prototype[Shape.types.CONVEXPOLYHEDRON] = Ray.prototype._intersectConvex; -var intersectTrimesh_normal = new Vec3(); -var intersectTrimesh_localDirection = new Vec3(); -var intersectTrimesh_localFrom = new Vec3(); -var intersectTrimesh_localTo = new Vec3(); -var intersectTrimesh_worldNormal = new Vec3(); -var intersectTrimesh_worldIntersectPoint = new Vec3(); -var intersectTrimesh_localAABB = new AABB(); -var intersectTrimesh_triangles = []; -var intersectTrimesh_treeTransform = new Transform(); +const intersectTrimesh_normal = new Vec3(); +const intersectTrimesh_localDirection = new Vec3(); +const intersectTrimesh_localFrom = new Vec3(); +const intersectTrimesh_localTo = new Vec3(); +const intersectTrimesh_worldNormal = new Vec3(); +const intersectTrimesh_worldIntersectPoint = new Vec3(); +const intersectTrimesh_localAABB = new AABB(); +const intersectTrimesh_triangles = []; +const intersectTrimesh_treeTransform = new Transform(); Ray.prototype[Shape.types.TRIMESH] = Ray.prototype._intersectTrimesh; -var v0 = new Vec3(); -var intersect = new Vec3(); - +const v0 = new Vec3(); +const intersect = new Vec3(); function distanceFromIntersection(from, direction, position) { // v0 is vector from from to position position.vsub(from, v0); - var dot = v0.dot(direction); // intersect = direction*dot + from + const dot = v0.dot(direction); // intersect = direction*dot + from direction.scale(dot, intersect); intersect.vadd(from, intersect); - var distance = position.distanceTo(intersect); + const distance = position.distanceTo(intersect); return distance; } @@ -6057,38 +5198,28 @@ function distanceFromIntersection(from, direction, position) { * @param {World} [world] * @extends Broadphase */ -var SAPBroadphase = /*#__PURE__*/function (_Broadphase) { - _inheritsLoose(SAPBroadphase, _Broadphase); - +class SAPBroadphase extends Broadphase { // List of bodies currently in the broadphase. // The world to search in. // Axis to sort the bodies along. Set to 0 for x axis, and 1 for y axis. For best performance, choose an axis that the bodies are spread out more on. - function SAPBroadphase(world) { - var _this; - - _this = _Broadphase.call(this) || this; - _this.axisList = []; - _this.world = null; - _this.axisIndex = 0; - var axisList = _this.axisList; - - _this._addBodyHandler = function (event) { + constructor(world) { + super(); + this.axisList = []; + this.world = null; + this.axisIndex = 0; + const axisList = this.axisList; + this._addBodyHandler = event => { axisList.push(event.body); }; - - _this._removeBodyHandler = function (event) { - var idx = axisList.indexOf(event.body); - + this._removeBodyHandler = event => { + const idx = axisList.indexOf(event.body); if (idx !== -1) { axisList.splice(idx, 1); } }; - if (world) { - _this.setWorld(world); + this.setWorld(world); } - - return _this; } /** * Change the world @@ -6096,18 +5227,14 @@ var SAPBroadphase = /*#__PURE__*/function (_Broadphase) { * @param {World} world */ - - var _proto = SAPBroadphase.prototype; - - _proto.setWorld = function setWorld(world) { + setWorld(world) { // Clear the old axis array this.axisList.length = 0; // Add all bodies from the new world - for (var i = 0; i < world.bodies.length; i++) { + for (let i = 0; i < world.bodies.length; i++) { this.axisList.push(world.bodies[i]); } // Remove old handlers, if any - world.removeEventListener('addBody', this._addBodyHandler); world.removeEventListener('removeBody', this._removeBodyHandler); // Add handlers to update the list of bodies. @@ -6123,54 +5250,44 @@ var SAPBroadphase = /*#__PURE__*/function (_Broadphase) { * @param {Array} p1 * @param {Array} p2 */ - ; - - _proto.collisionPairs = function collisionPairs(world, p1, p2) { - var bodies = this.axisList; - var N = bodies.length; - var axisIndex = this.axisIndex; - var i; - var j; + collisionPairs(world, p1, p2) { + const bodies = this.axisList; + const N = bodies.length; + const axisIndex = this.axisIndex; + let i; + let j; if (this.dirty) { this.sortList(); this.dirty = false; } // Look through the list - for (i = 0; i !== N; i++) { - var _bi = bodies[i]; - + const bi = bodies[i]; for (j = i + 1; j < N; j++) { - var _bj = bodies[j]; - - if (!this.needBroadphaseCollision(_bi, _bj)) { + const bj = bodies[j]; + if (!this.needBroadphaseCollision(bi, bj)) { continue; } - - if (!SAPBroadphase.checkBounds(_bi, _bj, axisIndex)) { + if (!SAPBroadphase.checkBounds(bi, bj, axisIndex)) { break; } - - this.intersectionTest(_bi, _bj, p1, p2); + this.intersectionTest(bi, bj, p1, p2); } } - }; - - _proto.sortList = function sortList() { - var axisList = this.axisList; - var axisIndex = this.axisIndex; - var N = axisList.length; // Update AABBs - - for (var i = 0; i !== N; i++) { - var _bi2 = axisList[i]; + } + sortList() { + const axisList = this.axisList; + const axisIndex = this.axisIndex; + const N = axisList.length; // Update AABBs - if (_bi2.aabbNeedsUpdate) { - _bi2.computeAABB(); + for (let i = 0; i !== N; i++) { + const bi = axisList[i]; + if (bi.aabbNeedsUpdate) { + bi.computeAABB(); } } // Sort the list - if (axisIndex === 0) { SAPBroadphase.insertionSortX(axisList); } else if (axisIndex === 1) { @@ -6184,36 +5301,32 @@ var SAPBroadphase = /*#__PURE__*/function (_Broadphase) { * axis to use. Will automatically set property .axisIndex. * @method autoDetectAxis */ - ; - - _proto.autoDetectAxis = function autoDetectAxis() { - var sumX = 0; - var sumX2 = 0; - var sumY = 0; - var sumY2 = 0; - var sumZ = 0; - var sumZ2 = 0; - var bodies = this.axisList; - var N = bodies.length; - var invN = 1 / N; - - for (var i = 0; i !== N; i++) { - var b = bodies[i]; - var centerX = b.position.x; + + autoDetectAxis() { + let sumX = 0; + let sumX2 = 0; + let sumY = 0; + let sumY2 = 0; + let sumZ = 0; + let sumZ2 = 0; + const bodies = this.axisList; + const N = bodies.length; + const invN = 1 / N; + for (let i = 0; i !== N; i++) { + const b = bodies[i]; + const centerX = b.position.x; sumX += centerX; sumX2 += centerX * centerX; - var centerY = b.position.y; + const centerY = b.position.y; sumY += centerY; sumY2 += centerY * centerY; - var centerZ = b.position.z; + const centerZ = b.position.z; sumZ += centerZ; sumZ2 += centerZ * centerZ; } - - var varianceX = sumX2 - sumX * sumX * invN; - var varianceY = sumY2 - sumY * sumY * invN; - var varianceZ = sumZ2 - sumZ * sumZ * invN; - + const varianceX = sumX2 - sumX * sumX * invN; + const varianceY = sumY2 - sumY * sumY * invN; + const varianceZ = sumZ2 - sumZ * sumZ * invN; if (varianceX > varianceY) { if (varianceX > varianceZ) { this.axisIndex = 0; @@ -6234,73 +5347,54 @@ var SAPBroadphase = /*#__PURE__*/function (_Broadphase) { * @param {array} result An array to store resulting bodies in. * @return {array} */ - ; - - _proto.aabbQuery = function aabbQuery(world, aabb, result) { - if (result === void 0) { - result = []; - } + aabbQuery(world, aabb, result = []) { if (this.dirty) { this.sortList(); this.dirty = false; } - - var axisIndex = this.axisIndex; - var axis = 'x'; - + const axisIndex = this.axisIndex; + let axis = 'x'; if (axisIndex === 1) { axis = 'y'; } - if (axisIndex === 2) { axis = 'z'; } - - var axisList = this.axisList; - var lower = aabb.lowerBound[axis]; - var upper = aabb.upperBound[axis]; - - for (var i = 0; i < axisList.length; i++) { - var b = axisList[i]; - + const axisList = this.axisList; + const lower = aabb.lowerBound[axis]; + const upper = aabb.upperBound[axis]; + for (let i = 0; i < axisList.length; i++) { + const b = axisList[i]; if (b.aabbNeedsUpdate) { b.computeAABB(); } - if (b.aabb.overlaps(aabb)) { result.push(b); } } - return result; - }; - - return SAPBroadphase; -}(Broadphase); + } +} /** * @static * @method insertionSortX * @param {Array} a * @return {Array} */ - -SAPBroadphase.insertionSortX = function (a) { - for (var i = 1, l = a.length; i < l; i++) { - var v = a[i]; - var j = void 0; - +exports.SAPBroadphase = SAPBroadphase; +SAPBroadphase.insertionSortX = a => { + for (let i = 1, l = a.length; i < l; i++) { + const v = a[i]; + let j; for (j = i - 1; j >= 0; j--) { if (a[j].aabb.lowerBound.x <= v.aabb.lowerBound.x) { break; } - a[j + 1] = a[j]; } - a[j + 1] = v; } - return a; }; /** @@ -6310,23 +5404,18 @@ SAPBroadphase.insertionSortX = function (a) { * @return {Array} */ - -SAPBroadphase.insertionSortY = function (a) { - for (var i = 1, l = a.length; i < l; i++) { - var v = a[i]; - var j = void 0; - +SAPBroadphase.insertionSortY = a => { + for (let i = 1, l = a.length; i < l; i++) { + const v = a[i]; + let j; for (j = i - 1; j >= 0; j--) { if (a[j].aabb.lowerBound.y <= v.aabb.lowerBound.y) { break; } - a[j + 1] = a[j]; } - a[j + 1] = v; } - return a; }; /** @@ -6336,23 +5425,18 @@ SAPBroadphase.insertionSortY = function (a) { * @return {Array} */ - -SAPBroadphase.insertionSortZ = function (a) { - for (var i = 1, l = a.length; i < l; i++) { - var v = a[i]; - var j = void 0; - +SAPBroadphase.insertionSortZ = a => { + for (let i = 1, l = a.length; i < l; i++) { + const v = a[i]; + let j; for (j = i - 1; j >= 0; j--) { if (a[j].aabb.lowerBound.z <= v.aabb.lowerBound.z) { break; } - a[j + 1] = a[j]; } - a[j + 1] = v; } - return a; }; /** @@ -6365,11 +5449,9 @@ SAPBroadphase.insertionSortZ = function (a) { * @return {Boolean} */ - -SAPBroadphase.checkBounds = function (bi, bj, axisIndex) { - var biPos; - var bjPos; - +SAPBroadphase.checkBounds = (bi, bj, axisIndex) => { + let biPos; + let bjPos; if (axisIndex === 0) { biPos = bi.position.x; bjPos = bj.position.x; @@ -6380,16 +5462,14 @@ SAPBroadphase.checkBounds = function (bi, bj, axisIndex) { biPos = bi.position.z; bjPos = bj.position.z; } - - var ri = bi.boundingRadius, - rj = bj.boundingRadius, - // boundA1 = biPos - ri, - boundA2 = biPos + ri, - boundB1 = bjPos - rj; // boundB2 = bjPos + rj; + const ri = bi.boundingRadius, + rj = bj.boundingRadius, + // boundA1 = biPos - ri, + boundA2 = biPos + ri, + boundB1 = bjPos - rj; // boundB2 = bjPos + rj; return boundB1 < boundA2; }; - function Utils() {} /** * Extend an options object with default values. @@ -6400,17 +5480,12 @@ function Utils() {} * @return {object} The modified options object. */ -Utils.defaults = function (options, defaults) { - if (options === void 0) { - options = {}; - } - - for (var key in defaults) { +Utils.defaults = (options = {}, defaults) => { + for (let key in defaults) { if (!(key in options)) { options[key] = defaults[key]; } } - return options; }; @@ -6425,14 +5500,10 @@ Utils.defaults = function (options, defaults) { * @param {boolean} [options.collideConnected=true] * @param {boolean} [options.wakeUpBodies=true] */ -var Constraint = /*#__PURE__*/function () { +class Constraint { // Equations to be solved in this constraint. // Set to true if you want the bodies to collide when they are connected. - function Constraint(bodyA, bodyB, options) { - if (options === void 0) { - options = {}; - } - + constructor(bodyA, bodyB, options = {}) { options = Utils.defaults(options, { collideConnected: true, wakeUpBodies: true @@ -6442,12 +5513,10 @@ var Constraint = /*#__PURE__*/function () { this.bodyB = bodyB; this.id = Constraint.idCounter++; this.collideConnected = options.collideConnected; - if (options.wakeUpBodies) { if (bodyA) { bodyA.wakeUp(); } - if (bodyB) { bodyB.wakeUp(); } @@ -6458,22 +5527,17 @@ var Constraint = /*#__PURE__*/function () { * @method update */ - - var _proto = Constraint.prototype; - - _proto.update = function update() { + update() { throw new Error('method update() not implmemented in this Constraint subclass!'); } /** * Enables all equations in the constraint. * @method enable */ - ; - - _proto.enable = function enable() { - var eqs = this.equations; - for (var i = 0; i < eqs.length; i++) { + enable() { + const eqs = this.equations; + for (let i = 0; i < eqs.length; i++) { eqs[i].enabled = true; } } @@ -6481,26 +5545,23 @@ var Constraint = /*#__PURE__*/function () { * Disables all equations in the constraint. * @method disable */ - ; - _proto.disable = function disable() { - var eqs = this.equations; - - for (var i = 0; i < eqs.length; i++) { + disable() { + const eqs = this.equations; + for (let i = 0; i < eqs.length; i++) { eqs[i].enabled = false; } - }; - - return Constraint; -}(); + } +} +exports.Constraint = Constraint; Constraint.idCounter = 0; /** * An element containing 6 entries, 3 spatial and 3 rotational degrees of freedom. */ -var JacobianElement = /*#__PURE__*/function () { - function JacobianElement() { +class JacobianElement { + constructor() { this.spatial = new Vec3(); this.rotational = new Vec3(); } @@ -6508,23 +5569,17 @@ var JacobianElement = /*#__PURE__*/function () { * Multiply with other JacobianElement */ - - var _proto = JacobianElement.prototype; - - _proto.multiplyElement = function multiplyElement(element) { + multiplyElement(element) { return element.spatial.dot(this.spatial) + element.rotational.dot(this.rotational); } /** * Multiply with two vectors */ - ; - _proto.multiplyVectors = function multiplyVectors(spatial, rotational) { + multiplyVectors(spatial, rotational) { return spatial.dot(this.spatial) + rotational.dot(this.rotational); - }; - - return JacobianElement; -}(); + } +} /** * Equation base class @@ -6536,20 +5591,13 @@ var JacobianElement = /*#__PURE__*/function () { * @param {Number} minForce Minimum (read: negative max) force to be applied by the constraint. * @param {Number} maxForce Maximum (read: positive max) force to be applied by the constraint. */ -var Equation = /*#__PURE__*/function () { +exports.JacobianElement = JacobianElement; +class Equation { // SPOOK parameter // SPOOK parameter // SPOOK parameter // A number, proportional to the force added to the bodies. - function Equation(bi, bj, minForce, maxForce) { - if (minForce === void 0) { - minForce = -1e6; - } - - if (maxForce === void 0) { - maxForce = 1e6; - } - + constructor(bi, bj, minForce = -1e6, maxForce = 1e6) { this.id = Equation.id++; this.minForce = minForce; this.maxForce = maxForce; @@ -6572,13 +5620,10 @@ var Equation = /*#__PURE__*/function () { * @method setSpookParams */ - - var _proto = Equation.prototype; - - _proto.setSpookParams = function setSpookParams(stiffness, relaxation, timeStep) { - var d = relaxation; - var k = stiffness; - var h = timeStep; + setSpookParams(stiffness, relaxation, timeStep) { + const d = relaxation; + const k = stiffness; + const h = timeStep; this.a = 4.0 / (h * (1 + 4 * d)); this.b = 4.0 * d / (1 + 4 * d); this.eps = 4.0 / (h * h * k * (1 + 4 * d)); @@ -6588,12 +5633,11 @@ var Equation = /*#__PURE__*/function () { * @method computeB * @return {Number} */ - ; - _proto.computeB = function computeB(a, b, h) { - var GW = this.computeGW(); - var Gq = this.computeGq(); - var GiMf = this.computeGiMf(); + computeB(a, b, h) { + const GW = this.computeGW(); + const Gq = this.computeGq(); + const GiMf = this.computeGiMf(); return -Gq * a - GW * b - GiMf * h; } /** @@ -6601,15 +5645,14 @@ var Equation = /*#__PURE__*/function () { * @method computeGq * @return {Number} */ - ; - _proto.computeGq = function computeGq() { - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; - var bi = this.bi; - var bj = this.bj; - var xi = bi.position; - var xj = bj.position; + computeGq() { + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; + const bi = this.bi; + const bj = this.bj; + const xi = bi.position; + const xj = bj.position; return GA.spatial.dot(xi) + GB.spatial.dot(xj); } /** @@ -6617,17 +5660,16 @@ var Equation = /*#__PURE__*/function () { * @method computeGW * @return {Number} */ - ; - - _proto.computeGW = function computeGW() { - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; - var bi = this.bi; - var bj = this.bj; - var vi = bi.velocity; - var vj = bj.velocity; - var wi = bi.angularVelocity; - var wj = bj.angularVelocity; + + computeGW() { + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; + const bi = this.bi; + const bj = this.bj; + const vi = bi.velocity; + const vj = bj.velocity; + const wi = bi.angularVelocity; + const wj = bj.angularVelocity; return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj); } /** @@ -6635,48 +5677,45 @@ var Equation = /*#__PURE__*/function () { * @method computeGWlambda * @return {Number} */ - ; - - _proto.computeGWlambda = function computeGWlambda() { - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; - var bi = this.bi; - var bj = this.bj; - var vi = bi.vlambda; - var vj = bj.vlambda; - var wi = bi.wlambda; - var wj = bj.wlambda; - return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj); - }; - _proto.computeGiMf = function computeGiMf() { - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; - var bi = this.bi; - var bj = this.bj; - var fi = bi.force; - var ti = bi.torque; - var fj = bj.force; - var tj = bj.torque; - var invMassi = bi.invMassSolve; - var invMassj = bj.invMassSolve; + computeGWlambda() { + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; + const bi = this.bi; + const bj = this.bj; + const vi = bi.vlambda; + const vj = bj.vlambda; + const wi = bi.wlambda; + const wj = bj.wlambda; + return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj); + } + computeGiMf() { + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; + const bi = this.bi; + const bj = this.bj; + const fi = bi.force; + const ti = bi.torque; + const fj = bj.force; + const tj = bj.torque; + const invMassi = bi.invMassSolve; + const invMassj = bj.invMassSolve; fi.scale(invMassi, iMfi); fj.scale(invMassj, iMfj); bi.invInertiaWorldSolve.vmult(ti, invIi_vmult_taui); bj.invInertiaWorldSolve.vmult(tj, invIj_vmult_tauj); return GA.multiplyVectors(iMfi, invIi_vmult_taui) + GB.multiplyVectors(iMfj, invIj_vmult_tauj); - }; - - _proto.computeGiMGt = function computeGiMGt() { - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; - var bi = this.bi; - var bj = this.bj; - var invMassi = bi.invMassSolve; - var invMassj = bj.invMassSolve; - var invIi = bi.invInertiaWorldSolve; - var invIj = bj.invInertiaWorldSolve; - var result = invMassi + invMassj; + } + computeGiMGt() { + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; + const bi = this.bi; + const bj = this.bj; + const invMassi = bi.invMassSolve; + const invMassj = bj.invMassSolve; + const invIi = bi.invInertiaWorldSolve; + const invIj = bj.invInertiaWorldSolve; + let result = invMassi + invMassj; invIi.vmult(GA.rotational, tmp$1); result += tmp$1.dot(GA.rotational); invIj.vmult(GB.rotational, tmp$1); @@ -6688,14 +5727,13 @@ var Equation = /*#__PURE__*/function () { * @method addToWlambda * @param {Number} deltalambda */ - ; - _proto.addToWlambda = function addToWlambda(deltalambda) { - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; - var bi = this.bi; - var bj = this.bj; - var temp = addToWlambda_temp; // Add to linear velocity + addToWlambda(deltalambda) { + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; + const bi = this.bi; + const bj = this.bj; + const temp = addToWlambda_temp; // Add to linear velocity // v_lambda += inv(M) * delta_lamba * G bi.vlambda.addScaledVector(bi.invMassSolve * deltalambda, GA.spatial, bi.vlambda); @@ -6712,14 +5750,12 @@ var Equation = /*#__PURE__*/function () { * @param {Number} eps * @return {Number} */ - ; - _proto.computeC = function computeC() { + computeC() { return this.computeGiMGt() + this.eps; - }; - - return Equation; -}(); + } +} +exports.Equation = Equation; Equation.id = 0; /** * Computes G*inv(M)*f, where M is the mass matrix with diagonal blocks for each body, and f are the forces on the bodies. @@ -6727,18 +5763,18 @@ Equation.id = 0; * @return {Number} */ -var iMfi = new Vec3(); -var iMfj = new Vec3(); -var invIi_vmult_taui = new Vec3(); -var invIj_vmult_tauj = new Vec3(); +const iMfi = new Vec3(); +const iMfj = new Vec3(); +const invIi_vmult_taui = new Vec3(); +const invIj_vmult_tauj = new Vec3(); /** * Computes G*inv(M)*G' * @method computeGiMGt * @return {Number} */ -var tmp$1 = new Vec3(); -var addToWlambda_temp = new Vec3(); +const tmp$1 = new Vec3(); +const addToWlambda_temp = new Vec3(); /** * Contact/non-penetration constraint equation @@ -6749,51 +5785,39 @@ var addToWlambda_temp = new Vec3(); * @param {Body} bodyB * @extends Equation */ -var ContactEquation = /*#__PURE__*/function (_Equation) { - _inheritsLoose(ContactEquation, _Equation); - +class ContactEquation extends Equation { // "bounciness": u1 = -e*u0 // World-oriented vector that goes from the center of bi to the contact point. // World-oriented vector that starts in body j position and goes to the contact point. // Contact normal, pointing out of body i. - function ContactEquation(bodyA, bodyB, maxForce) { - var _this; - - if (maxForce === void 0) { - maxForce = 1e6; - } - - _this = _Equation.call(this, bodyA, bodyB, 0, maxForce) || this; - _this.restitution = 0.0; - _this.ri = new Vec3(); - _this.rj = new Vec3(); - _this.ni = new Vec3(); - return _this; - } - - var _proto = ContactEquation.prototype; - - _proto.computeB = function computeB(h) { - var a = this.a; - var b = this.b; - var bi = this.bi; - var bj = this.bj; - var ri = this.ri; - var rj = this.rj; - var rixn = ContactEquation_computeB_temp1; - var rjxn = ContactEquation_computeB_temp2; - var vi = bi.velocity; - var wi = bi.angularVelocity; - var fi = bi.force; - var taui = bi.torque; - var vj = bj.velocity; - var wj = bj.angularVelocity; - var fj = bj.force; - var tauj = bj.torque; - var penetrationVec = ContactEquation_computeB_temp3; - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; - var n = this.ni; // Caluclate cross products + constructor(bodyA, bodyB, maxForce = 1e6) { + super(bodyA, bodyB, 0, maxForce); + this.restitution = 0.0; + this.ri = new Vec3(); + this.rj = new Vec3(); + this.ni = new Vec3(); + } + computeB(h) { + const a = this.a; + const b = this.b; + const bi = this.bi; + const bj = this.bj; + const ri = this.ri; + const rj = this.rj; + const rixn = ContactEquation_computeB_temp1; + const rjxn = ContactEquation_computeB_temp2; + const vi = bi.velocity; + const wi = bi.angularVelocity; + const fi = bi.force; + const taui = bi.torque; + const vj = bj.velocity; + const wj = bj.angularVelocity; + const fj = bj.force; + const tauj = bj.torque; + const penetrationVec = ContactEquation_computeB_temp3; + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; + const n = this.ni; // Caluclate cross products ri.cross(n, rixn); rj.cross(n, rjxn); // g = xj+rj -(xi+ri) @@ -6808,12 +5832,12 @@ var ContactEquation = /*#__PURE__*/function (_Equation) { penetrationVec.vadd(rj, penetrationVec); penetrationVec.vsub(bi.position, penetrationVec); penetrationVec.vsub(ri, penetrationVec); - var g = n.dot(penetrationVec); // Compute iteration + const g = n.dot(penetrationVec); // Compute iteration - var ePlusOne = this.restitution + 1; - var GW = ePlusOne * vj.dot(n) - ePlusOne * vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn); - var GiMf = this.computeGiMf(); - var B = -g * a - GW * b - h * GiMf; + const ePlusOne = this.restitution + 1; + const GW = ePlusOne * vj.dot(n) - ePlusOne * vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn); + const GiMf = this.computeGiMf(); + const B = -g * a - GW * b - h * GiMf; return B; } /** @@ -6821,33 +5845,31 @@ var ContactEquation = /*#__PURE__*/function (_Equation) { * @method getImpactVelocityAlongNormal * @return {number} */ - ; - _proto.getImpactVelocityAlongNormal = function getImpactVelocityAlongNormal() { - var vi = ContactEquation_getImpactVelocityAlongNormal_vi; - var vj = ContactEquation_getImpactVelocityAlongNormal_vj; - var xi = ContactEquation_getImpactVelocityAlongNormal_xi; - var xj = ContactEquation_getImpactVelocityAlongNormal_xj; - var relVel = ContactEquation_getImpactVelocityAlongNormal_relVel; + getImpactVelocityAlongNormal() { + const vi = ContactEquation_getImpactVelocityAlongNormal_vi; + const vj = ContactEquation_getImpactVelocityAlongNormal_vj; + const xi = ContactEquation_getImpactVelocityAlongNormal_xi; + const xj = ContactEquation_getImpactVelocityAlongNormal_xj; + const relVel = ContactEquation_getImpactVelocityAlongNormal_relVel; this.bi.position.vadd(this.ri, xi); this.bj.position.vadd(this.rj, xj); this.bi.getVelocityAtWorldPoint(xi, vi); this.bj.getVelocityAtWorldPoint(xj, vj); vi.vsub(vj, relVel); return this.ni.dot(relVel); - }; - - return ContactEquation; -}(Equation); -var ContactEquation_computeB_temp1 = new Vec3(); // Temp vectors + } +} +exports.ContactEquation = ContactEquation; +const ContactEquation_computeB_temp1 = new Vec3(); // Temp vectors -var ContactEquation_computeB_temp2 = new Vec3(); -var ContactEquation_computeB_temp3 = new Vec3(); -var ContactEquation_getImpactVelocityAlongNormal_vi = new Vec3(); -var ContactEquation_getImpactVelocityAlongNormal_vj = new Vec3(); -var ContactEquation_getImpactVelocityAlongNormal_xi = new Vec3(); -var ContactEquation_getImpactVelocityAlongNormal_xj = new Vec3(); -var ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3(); +const ContactEquation_computeB_temp2 = new Vec3(); +const ContactEquation_computeB_temp3 = new Vec3(); +const ContactEquation_getImpactVelocityAlongNormal_vi = new Vec3(); +const ContactEquation_getImpactVelocityAlongNormal_vj = new Vec3(); +const ContactEquation_getImpactVelocityAlongNormal_xi = new Vec3(); +const ContactEquation_getImpactVelocityAlongNormal_xj = new Vec3(); +const ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3(); /** * Connects two bodies at given offset points. @@ -6874,52 +5896,31 @@ var ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3(); * const constraint = new PointToPointConstraint(bodyA, localPivotA, bodyB, localPivotB); * world.addConstraint(constraint); */ -var PointToPointConstraint = /*#__PURE__*/function (_Constraint) { - _inheritsLoose(PointToPointConstraint, _Constraint); - +class PointToPointConstraint extends Constraint { // Pivot, defined locally in bodyA. // Pivot, defined locally in bodyB. - function PointToPointConstraint(bodyA, pivotA, bodyB, pivotB, maxForce) { - var _this; - - if (pivotA === void 0) { - pivotA = new Vec3(); - } - - if (pivotB === void 0) { - pivotB = new Vec3(); - } - - if (maxForce === void 0) { - maxForce = 1e6; - } - - _this = _Constraint.call(this, bodyA, bodyB) || this; - _this.pivotA = pivotA.clone(); - _this.pivotB = pivotB.clone(); - var x = _this.equationX = new ContactEquation(bodyA, bodyB); - var y = _this.equationY = new ContactEquation(bodyA, bodyB); - var z = _this.equationZ = new ContactEquation(bodyA, bodyB); // Equations to be fed to the solver - - _this.equations.push(x, y, z); // Make the equations bidirectional + constructor(bodyA, pivotA = new Vec3(), bodyB, pivotB = new Vec3(), maxForce = 1e6) { + super(bodyA, bodyB); + this.pivotA = pivotA.clone(); + this.pivotB = pivotB.clone(); + const x = this.equationX = new ContactEquation(bodyA, bodyB); + const y = this.equationY = new ContactEquation(bodyA, bodyB); + const z = this.equationZ = new ContactEquation(bodyA, bodyB); // Equations to be fed to the solver + this.equations.push(x, y, z); // Make the equations bidirectional x.minForce = y.minForce = z.minForce = -maxForce; x.maxForce = y.maxForce = z.maxForce = maxForce; x.ni.set(1, 0, 0); y.ni.set(0, 1, 0); z.ni.set(0, 0, 1); - return _this; } - - var _proto = PointToPointConstraint.prototype; - - _proto.update = function update() { - var bodyA = this.bodyA; - var bodyB = this.bodyB; - var x = this.equationX; - var y = this.equationY; - var z = this.equationZ; // Rotate the pivots to world space + update() { + const bodyA = this.bodyA; + const bodyB = this.bodyB; + const x = this.equationX; + const y = this.equationY; + const z = this.equationZ; // Rotate the pivots to world space bodyA.quaternion.vmult(this.pivotA, x.ri); bodyB.quaternion.vmult(this.pivotB, x.rj); @@ -6927,10 +5928,8 @@ var PointToPointConstraint = /*#__PURE__*/function (_Constraint) { y.rj.copy(x.rj); z.ri.copy(x.ri); z.rj.copy(x.rj); - }; - - return PointToPointConstraint; -}(Constraint); + } +} /** * Cone equation. Works to keep the given body world vectors aligned, or tilted within a given angle from each other. @@ -6945,36 +5944,25 @@ var PointToPointConstraint = /*#__PURE__*/function (_Constraint) { * @param {number} [options.maxForce=1e6] * @extends Equation */ -var ConeEquation = /*#__PURE__*/function (_Equation) { - _inheritsLoose(ConeEquation, _Equation); - +exports.PointToPointConstraint = PointToPointConstraint; +class ConeEquation extends Equation { // The cone angle to keep. - function ConeEquation(bodyA, bodyB, options) { - var _this; - - if (options === void 0) { - options = {}; - } - - var maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; - _this = _Equation.call(this, bodyA, bodyB, -maxForce, maxForce) || this; - _this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0); - _this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0); - _this.angle = typeof options.angle !== 'undefined' ? options.angle : 0; - return _this; - } - - var _proto = ConeEquation.prototype; - - _proto.computeB = function computeB(h) { - var a = this.a; - var b = this.b; - var ni = this.axisA; - var nj = this.axisB; - var nixnj = tmpVec1; - var njxni = tmpVec2; - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; // Caluclate cross products + constructor(bodyA, bodyB, options = {}) { + const maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; + super(bodyA, bodyB, -maxForce, maxForce); + this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0); + this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0); + this.angle = typeof options.angle !== 'undefined' ? options.angle : 0; + } + computeB(h) { + const a = this.a; + const b = this.b; + const ni = this.axisA; + const nj = this.axisB; + const nixnj = tmpVec1; + const njxni = tmpVec2; + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; // Caluclate cross products ni.cross(nj, nixnj); nj.cross(ni, njxni); // The angle between two vector is: @@ -6986,17 +5974,15 @@ var ConeEquation = /*#__PURE__*/function (_Equation) { GA.rotational.copy(njxni); GB.rotational.copy(nixnj); - var g = Math.cos(this.angle) - ni.dot(nj); - var GW = this.computeGW(); - var GiMf = this.computeGiMf(); - var B = -g * a - GW * b - h * GiMf; + const g = Math.cos(this.angle) - ni.dot(nj); + const GW = this.computeGW(); + const GiMf = this.computeGiMf(); + const B = -g * a - GW * b - h * GiMf; return B; - }; - - return ConeEquation; -}(Equation); -var tmpVec1 = new Vec3(); -var tmpVec2 = new Vec3(); + } +} +const tmpVec1 = new Vec3(); +const tmpVec2 = new Vec3(); /** * Rotational constraint. Works to keep the local vectors orthogonal to each other in world space. @@ -7010,35 +5996,23 @@ var tmpVec2 = new Vec3(); * @param {number} [options.maxForce] * @extends Equation */ -var RotationalEquation = /*#__PURE__*/function (_Equation) { - _inheritsLoose(RotationalEquation, _Equation); - - function RotationalEquation(bodyA, bodyB, options) { - var _this; - - if (options === void 0) { - options = {}; - } - - var maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; - _this = _Equation.call(this, bodyA, bodyB, -maxForce, maxForce) || this; - _this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0); - _this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0); - _this.maxAngle = Math.PI / 2; - return _this; - } - - var _proto = RotationalEquation.prototype; - - _proto.computeB = function computeB(h) { - var a = this.a; - var b = this.b; - var ni = this.axisA; - var nj = this.axisB; - var nixnj = tmpVec1$1; - var njxni = tmpVec2$1; - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; // Caluclate cross products +class RotationalEquation extends Equation { + constructor(bodyA, bodyB, options = {}) { + const maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; + super(bodyA, bodyB, -maxForce, maxForce); + this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0); + this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0); + this.maxAngle = Math.PI / 2; + } + computeB(h) { + const a = this.a; + const b = this.b; + const ni = this.axisA; + const nj = this.axisB; + const nixnj = tmpVec1$1; + const njxni = tmpVec2$1; + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; // Caluclate cross products ni.cross(nj, nixnj); nj.cross(ni, njxni); // g = ni * nj @@ -7048,17 +6022,16 @@ var RotationalEquation = /*#__PURE__*/function (_Equation) { GA.rotational.copy(njxni); GB.rotational.copy(nixnj); - var g = Math.cos(this.maxAngle) - ni.dot(nj); - var GW = this.computeGW(); - var GiMf = this.computeGiMf(); - var B = -g * a - GW * b - h * GiMf; + const g = Math.cos(this.maxAngle) - ni.dot(nj); + const GW = this.computeGW(); + const GiMf = this.computeGiMf(); + const B = -g * a - GW * b - h * GiMf; return B; - }; - - return RotationalEquation; -}(Equation); -var tmpVec1$1 = new Vec3(); -var tmpVec2$1 = new Vec3(); + } +} +exports.RotationalEquation = RotationalEquation; +const tmpVec1$1 = new Vec3(); +const tmpVec2$1 = new Vec3(); /** * @class ConeTwistConstraint @@ -7074,50 +6047,34 @@ var tmpVec2$1 = new Vec3(); * @param {Number} [options.maxForce=1e6] * @extends PointToPointConstraint */ -var ConeTwistConstraint = /*#__PURE__*/function (_PointToPointConstrai) { - _inheritsLoose(ConeTwistConstraint, _PointToPointConstrai); - - function ConeTwistConstraint(bodyA, bodyB, options) { - var _this; - - if (options === void 0) { - options = {}; - } - - var maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; // Set pivot point in between - - var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3(); - var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3(); - _this = _PointToPointConstrai.call(this, bodyA, pivotA, bodyB, pivotB, maxForce) || this; - _this.axisA = options.axisA ? options.axisA.clone() : new Vec3(); - _this.axisB = options.axisB ? options.axisB.clone() : new Vec3(); - _this.collideConnected = !!options.collideConnected; - _this.angle = typeof options.angle !== 'undefined' ? options.angle : 0; - var c = _this.coneEquation = new ConeEquation(bodyA, bodyB, options); - var t = _this.twistEquation = new RotationalEquation(bodyA, bodyB, options); - _this.twistAngle = typeof options.twistAngle !== 'undefined' ? options.twistAngle : 0; // Make the cone equation push the bodies toward the cone axis, not outward +class ConeTwistConstraint extends PointToPointConstraint { + constructor(bodyA, bodyB, options = {}) { + const maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; // Set pivot point in between + + const pivotA = options.pivotA ? options.pivotA.clone() : new Vec3(); + const pivotB = options.pivotB ? options.pivotB.clone() : new Vec3(); + super(bodyA, pivotA, bodyB, pivotB, maxForce); + this.axisA = options.axisA ? options.axisA.clone() : new Vec3(); + this.axisB = options.axisB ? options.axisB.clone() : new Vec3(); + this.collideConnected = !!options.collideConnected; + this.angle = typeof options.angle !== 'undefined' ? options.angle : 0; + const c = this.coneEquation = new ConeEquation(bodyA, bodyB, options); + const t = this.twistEquation = new RotationalEquation(bodyA, bodyB, options); + this.twistAngle = typeof options.twistAngle !== 'undefined' ? options.twistAngle : 0; // Make the cone equation push the bodies toward the cone axis, not outward c.maxForce = 0; c.minForce = -maxForce; // Make the twist equation add torque toward the initial position t.maxForce = 0; t.minForce = -maxForce; - - _this.equations.push(c, t); - - return _this; + this.equations.push(c, t); } - - var _proto = ConeTwistConstraint.prototype; - - _proto.update = function update() { - var bodyA = this.bodyA; - var bodyB = this.bodyB; - var cone = this.coneEquation; - var twist = this.twistEquation; - - _PointToPointConstrai.prototype.update.call(this); // Update the axes to the cone constraint - + update() { + const bodyA = this.bodyA; + const bodyB = this.bodyB; + const cone = this.coneEquation; + const twist = this.twistEquation; + super.update(); // Update the axes to the cone constraint bodyA.vectorToWorldFrame(this.axisA, cone.axisA); bodyB.vectorToWorldFrame(this.axisB, cone.axisB); // Update the world axes in the twist constraint @@ -7128,12 +6085,8 @@ var ConeTwistConstraint = /*#__PURE__*/function (_PointToPointConstrai) { bodyB.vectorToWorldFrame(twist.axisB, twist.axisB); cone.angle = this.angle; twist.maxAngle = this.twistAngle; - }; - - return ConeTwistConstraint; -}(PointToPointConstraint); -var ConeTwistConstraint_update_tmpVec1 = new Vec3(); -var ConeTwistConstraint_update_tmpVec2 = new Vec3(); + } +} /** * Constrains two bodies to be at a constant distance from each others center of mass. @@ -7146,49 +6099,32 @@ var ConeTwistConstraint_update_tmpVec2 = new Vec3(); * @param {Number} [maxForce=1e6] * @extends Constraint */ -var DistanceConstraint = /*#__PURE__*/function (_Constraint) { - _inheritsLoose(DistanceConstraint, _Constraint); - - function DistanceConstraint(bodyA, bodyB, distance, maxForce) { - var _this; - - if (maxForce === void 0) { - maxForce = 1e6; - } - - _this = _Constraint.call(this, bodyA, bodyB) || this; - +exports.ConeTwistConstraint = ConeTwistConstraint; +class DistanceConstraint extends Constraint { + constructor(bodyA, bodyB, distance, maxForce = 1e6) { + super(bodyA, bodyB); if (typeof distance === 'undefined') { distance = bodyA.position.distanceTo(bodyB.position); } - - _this.distance = distance; - var eq = _this.distanceEquation = new ContactEquation(bodyA, bodyB); - - _this.equations.push(eq); // Make it bidirectional - + this.distance = distance; + const eq = this.distanceEquation = new ContactEquation(bodyA, bodyB); + this.equations.push(eq); // Make it bidirectional eq.minForce = -maxForce; eq.maxForce = maxForce; - return _this; } - - var _proto = DistanceConstraint.prototype; - - _proto.update = function update() { - var bodyA = this.bodyA; - var bodyB = this.bodyB; - var eq = this.distanceEquation; - var halfDist = this.distance * 0.5; - var normal = eq.ni; + update() { + const bodyA = this.bodyA; + const bodyB = this.bodyB; + const eq = this.distanceEquation; + const halfDist = this.distance * 0.5; + const normal = eq.ni; bodyB.position.vsub(bodyA.position, normal); normal.normalize(); normal.scale(halfDist, eq.ri); normal.scale(-halfDist, eq.rj); - }; - - return DistanceConstraint; -}(Constraint); + } +} /** * Lock constraint. Will remove all degrees of freedom between the bodies. @@ -7201,56 +6137,41 @@ var DistanceConstraint = /*#__PURE__*/function (_Constraint) { * @param {Number} [options.maxForce=1e6] * @extends PointToPointConstraint */ -var LockConstraint = /*#__PURE__*/function (_PointToPointConstrai) { - _inheritsLoose(LockConstraint, _PointToPointConstrai); - - function LockConstraint(bodyA, bodyB, options) { - var _this; +exports.DistanceConstraint = DistanceConstraint; +class LockConstraint extends PointToPointConstraint { + constructor(bodyA, bodyB, options = {}) { + const maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; // Set pivot point in between - if (options === void 0) { - options = {}; - } - - var maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; // Set pivot point in between - - var pivotA = new Vec3(); - var pivotB = new Vec3(); - var halfWay = new Vec3(); + const pivotA = new Vec3(); + const pivotB = new Vec3(); + const halfWay = new Vec3(); bodyA.position.vadd(bodyB.position, halfWay); halfWay.scale(0.5, halfWay); bodyB.pointToLocalFrame(halfWay, pivotB); bodyA.pointToLocalFrame(halfWay, pivotA); // The point-to-point constraint will keep a point shared between the bodies - _this = _PointToPointConstrai.call(this, bodyA, pivotA, bodyB, pivotB, maxForce) || this; // Store initial rotation of the bodies as unit vectors in the local body spaces - - _this.xA = bodyA.vectorToLocalFrame(Vec3.UNIT_X); - _this.xB = bodyB.vectorToLocalFrame(Vec3.UNIT_X); - _this.yA = bodyA.vectorToLocalFrame(Vec3.UNIT_Y); - _this.yB = bodyB.vectorToLocalFrame(Vec3.UNIT_Y); - _this.zA = bodyA.vectorToLocalFrame(Vec3.UNIT_Z); - _this.zB = bodyB.vectorToLocalFrame(Vec3.UNIT_Z); // ...and the following rotational equations will keep all rotational DOF's in place - - var r1 = _this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options); - var r2 = _this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options); - var r3 = _this.rotationalEquation3 = new RotationalEquation(bodyA, bodyB, options); - - _this.equations.push(r1, r2, r3); - - return _this; - } - - var _proto = LockConstraint.prototype; - - _proto.update = function update() { - var bodyA = this.bodyA; - var bodyB = this.bodyB; - var motor = this.motorEquation; - var r1 = this.rotationalEquation1; - var r2 = this.rotationalEquation2; - var r3 = this.rotationalEquation3; - - _PointToPointConstrai.prototype.update.call(this); // These vector pairs must be orthogonal - + super(bodyA, pivotA, bodyB, pivotB, maxForce); // Store initial rotation of the bodies as unit vectors in the local body spaces + + this.xA = bodyA.vectorToLocalFrame(Vec3.UNIT_X); + this.xB = bodyB.vectorToLocalFrame(Vec3.UNIT_X); + this.yA = bodyA.vectorToLocalFrame(Vec3.UNIT_Y); + this.yB = bodyB.vectorToLocalFrame(Vec3.UNIT_Y); + this.zA = bodyA.vectorToLocalFrame(Vec3.UNIT_Z); + this.zB = bodyB.vectorToLocalFrame(Vec3.UNIT_Z); // ...and the following rotational equations will keep all rotational DOF's in place + + const r1 = this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options); + const r2 = this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options); + const r3 = this.rotationalEquation3 = new RotationalEquation(bodyA, bodyB, options); + this.equations.push(r1, r2, r3); + } + update() { + const bodyA = this.bodyA; + const bodyB = this.bodyB; + const motor = this.motorEquation; + const r1 = this.rotationalEquation1; + const r2 = this.rotationalEquation2; + const r3 = this.rotationalEquation3; + super.update(); // These vector pairs must be orthogonal bodyA.vectorToWorldFrame(this.xA, r1.axisA); bodyB.vectorToWorldFrame(this.yB, r1.axisB); @@ -7258,12 +6179,8 @@ var LockConstraint = /*#__PURE__*/function (_PointToPointConstrai) { bodyB.vectorToWorldFrame(this.zB, r2.axisB); bodyA.vectorToWorldFrame(this.zA, r3.axisA); bodyB.vectorToWorldFrame(this.xB, r3.axisB); - }; - - return LockConstraint; -}(PointToPointConstraint); -var LockConstraint_update_tmpVec1 = new Vec3(); -var LockConstraint_update_tmpVec2 = new Vec3(); + } +} /** * Rotational motor constraint. Tries to keep the relative angular velocity of the bodies to a given value. @@ -7275,37 +6192,26 @@ var LockConstraint_update_tmpVec2 = new Vec3(); * @param {Number} maxForce * @extends Equation */ -var RotationalMotorEquation = /*#__PURE__*/function (_Equation) { - _inheritsLoose(RotationalMotorEquation, _Equation); - +exports.LockConstraint = LockConstraint; +class RotationalMotorEquation extends Equation { // World oriented rotational axis. // World oriented rotational axis. // Motor velocity. - function RotationalMotorEquation(bodyA, bodyB, maxForce) { - var _this; - - if (maxForce === void 0) { - maxForce = 1e6; - } - - _this = _Equation.call(this, bodyA, bodyB, -maxForce, maxForce) || this; - _this.axisA = new Vec3(); - _this.axisB = new Vec3(); - _this.targetVelocity = 0; - return _this; - } - - var _proto = RotationalMotorEquation.prototype; - - _proto.computeB = function computeB(h) { - var a = this.a; - var b = this.b; - var bi = this.bi; - var bj = this.bj; - var axisA = this.axisA; - var axisB = this.axisB; - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; // g = 0 + constructor(bodyA, bodyB, maxForce = 1e6) { + super(bodyA, bodyB, -maxForce, maxForce); + this.axisA = new Vec3(); + this.axisB = new Vec3(); + this.targetVelocity = 0; + } + computeB(h) { + const a = this.a; + const b = this.b; + const bi = this.bi; + const bj = this.bj; + const axisA = this.axisA; + const axisB = this.axisB; + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; // g = 0 // gdot = axisA * wi - axisB * wj // gdot = G * W = G * [vi wi vj wj] // => @@ -7313,14 +6219,12 @@ var RotationalMotorEquation = /*#__PURE__*/function (_Equation) { GA.rotational.copy(axisA); axisB.negate(GB.rotational); - var GW = this.computeGW() - this.targetVelocity; - var GiMf = this.computeGiMf(); - var B = -GW * b - h * GiMf; + const GW = this.computeGW() - this.targetVelocity; + const GiMf = this.computeGiMf(); + const B = -GW * b - h * GiMf; return B; - }; - - return RotationalMotorEquation; -}(Equation); + } +} /** * Hinge constraint. Think of it as a door hinge. It tries to keep the door in the correct place and with the correct orientation. @@ -7337,105 +6241,85 @@ var RotationalMotorEquation = /*#__PURE__*/function (_Equation) { * @param {Number} [options.maxForce=1e6] * @extends PointToPointConstraint */ -var HingeConstraint = /*#__PURE__*/function (_PointToPointConstrai) { - _inheritsLoose(HingeConstraint, _PointToPointConstrai); - +exports.RotationalMotorEquation = RotationalMotorEquation; +class HingeConstraint extends PointToPointConstraint { // Rotation axis, defined locally in bodyA. // Rotation axis, defined locally in bodyB. - function HingeConstraint(bodyA, bodyB, options) { - var _this; - - if (options === void 0) { - options = {}; - } - - var maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; - var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3(); - var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3(); - _this = _PointToPointConstrai.call(this, bodyA, pivotA, bodyB, pivotB, maxForce) || this; - var axisA = _this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0); + constructor(bodyA, bodyB, options = {}) { + const maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6; + const pivotA = options.pivotA ? options.pivotA.clone() : new Vec3(); + const pivotB = options.pivotB ? options.pivotB.clone() : new Vec3(); + super(bodyA, pivotA, bodyB, pivotB, maxForce); + const axisA = this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0); axisA.normalize(); - var axisB = _this.axisB = options.axisB ? options.axisB.clone() : new Vec3(1, 0, 0); + const axisB = this.axisB = options.axisB ? options.axisB.clone() : new Vec3(1, 0, 0); axisB.normalize(); - _this.collideConnected = !!options.collideConnected; - var rotational1 = _this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options); - var rotational2 = _this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options); - var motor = _this.motorEquation = new RotationalMotorEquation(bodyA, bodyB, maxForce); + this.collideConnected = !!options.collideConnected; + const rotational1 = this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options); + const rotational2 = this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options); + const motor = this.motorEquation = new RotationalMotorEquation(bodyA, bodyB, maxForce); motor.enabled = false; // Not enabled by default // Equations to be fed to the solver - _this.equations.push(rotational1, rotational2, motor); - - return _this; + this.equations.push(rotational1, rotational2, motor); } /** * @method enableMotor */ - - var _proto = HingeConstraint.prototype; - - _proto.enableMotor = function enableMotor() { + enableMotor() { this.motorEquation.enabled = true; } /** * @method disableMotor */ - ; - _proto.disableMotor = function disableMotor() { + disableMotor() { this.motorEquation.enabled = false; } /** * @method setMotorSpeed * @param {number} speed */ - ; - _proto.setMotorSpeed = function setMotorSpeed(speed) { + setMotorSpeed(speed) { this.motorEquation.targetVelocity = speed; } /** * @method setMotorMaxForce * @param {number} maxForce */ - ; - _proto.setMotorMaxForce = function setMotorMaxForce(maxForce) { + setMotorMaxForce(maxForce) { this.motorEquation.maxForce = maxForce; this.motorEquation.minForce = -maxForce; - }; - - _proto.update = function update() { - var bodyA = this.bodyA; - var bodyB = this.bodyB; - var motor = this.motorEquation; - var r1 = this.rotationalEquation1; - var r2 = this.rotationalEquation2; - var worldAxisA = HingeConstraint_update_tmpVec1; - var worldAxisB = HingeConstraint_update_tmpVec2; - var axisA = this.axisA; - var axisB = this.axisB; - - _PointToPointConstrai.prototype.update.call(this); // Get world axes - + } + update() { + const bodyA = this.bodyA; + const bodyB = this.bodyB; + const motor = this.motorEquation; + const r1 = this.rotationalEquation1; + const r2 = this.rotationalEquation2; + const worldAxisA = HingeConstraint_update_tmpVec1; + const worldAxisB = HingeConstraint_update_tmpVec2; + const axisA = this.axisA; + const axisB = this.axisB; + super.update(); // Get world axes bodyA.quaternion.vmult(axisA, worldAxisA); bodyB.quaternion.vmult(axisB, worldAxisB); worldAxisA.tangents(r1.axisA, r2.axisA); r1.axisB.copy(worldAxisB); r2.axisB.copy(worldAxisB); - if (this.motorEquation.enabled) { bodyA.quaternion.vmult(this.axisA, motor.axisA); bodyB.quaternion.vmult(this.axisB, motor.axisB); } - }; - - return HingeConstraint; -}(PointToPointConstraint); -var HingeConstraint_update_tmpVec1 = new Vec3(); -var HingeConstraint_update_tmpVec2 = new Vec3(); + } +} +exports.HingeConstraint = HingeConstraint; +const HingeConstraint_update_tmpVec1 = new Vec3(); +const HingeConstraint_update_tmpVec2 = new Vec3(); /** * Constrains the slipping in a contact along a tangent @@ -7447,53 +6331,44 @@ var HingeConstraint_update_tmpVec2 = new Vec3(); * @param {Number} slipForce should be +-F_friction = +-mu * F_normal = +-mu * m * g * @extends Equation */ -var FrictionEquation = /*#__PURE__*/function (_Equation) { - _inheritsLoose(FrictionEquation, _Equation); - +class FrictionEquation extends Equation { // Tangent. - function FrictionEquation(bodyA, bodyB, slipForce) { - var _this; - - _this = _Equation.call(this, bodyA, bodyB, -slipForce, slipForce) || this; - _this.ri = new Vec3(); - _this.rj = new Vec3(); - _this.t = new Vec3(); - return _this; - } - - var _proto = FrictionEquation.prototype; - - _proto.computeB = function computeB(h) { - var a = this.a; - var b = this.b; - var bi = this.bi; - var bj = this.bj; - var ri = this.ri; - var rj = this.rj; - var rixt = FrictionEquation_computeB_temp1; - var rjxt = FrictionEquation_computeB_temp2; - var t = this.t; // Caluclate cross products + constructor(bodyA, bodyB, slipForce) { + super(bodyA, bodyB, -slipForce, slipForce); + this.ri = new Vec3(); + this.rj = new Vec3(); + this.t = new Vec3(); + } + computeB(h) { + const a = this.a; + const b = this.b; + const bi = this.bi; + const bj = this.bj; + const ri = this.ri; + const rj = this.rj; + const rixt = FrictionEquation_computeB_temp1; + const rjxt = FrictionEquation_computeB_temp2; + const t = this.t; // Caluclate cross products ri.cross(t, rixt); rj.cross(t, rjxt); // G = [-t -rixt t rjxt] // And remember, this is a pure velocity constraint, g is always zero! - var GA = this.jacobianElementA; - var GB = this.jacobianElementB; + const GA = this.jacobianElementA; + const GB = this.jacobianElementB; t.negate(GA.spatial); rixt.negate(GA.rotational); GB.spatial.copy(t); GB.rotational.copy(rjxt); - var GW = this.computeGW(); - var GiMf = this.computeGiMf(); - var B = -GW * b - h * GiMf; + const GW = this.computeGW(); + const GiMf = this.computeGiMf(); + const B = -GW * b - h * GiMf; return B; - }; - - return FrictionEquation; -}(Equation); -var FrictionEquation_computeB_temp1 = new Vec3(); -var FrictionEquation_computeB_temp2 = new Vec3(); + } +} +exports.FrictionEquation = FrictionEquation; +const FrictionEquation_computeB_temp1 = new Vec3(); +const FrictionEquation_computeB_temp2 = new Vec3(); /** * Defines what happens when two materials meet. @@ -7510,32 +6385,35 @@ var FrictionEquation_computeB_temp2 = new Vec3(); * @param {Number} [options.frictionEquationRelaxation=3] * @todo Refactor materials to materialA and materialB */ -var ContactMaterial = // Identifier of this material. -// Participating materials. -// Friction coefficient. -// Restitution coefficient. -// Stiffness of the produced contact equations. -// Relaxation time of the produced contact equations. -// Stiffness of the produced friction equations. -// Relaxation time of the produced friction equations -function ContactMaterial(m1, m2, options) { - options = Utils.defaults(options, { - friction: 0.3, - restitution: 0.3, - contactEquationStiffness: 1e7, - contactEquationRelaxation: 3, - frictionEquationStiffness: 1e7, - frictionEquationRelaxation: 3 - }); - this.id = ContactMaterial.idCounter++; - this.materials = [m1, m2]; - this.friction = options.friction; - this.restitution = options.restitution; - this.contactEquationStiffness = options.contactEquationStiffness; - this.contactEquationRelaxation = options.contactEquationRelaxation; - this.frictionEquationStiffness = options.frictionEquationStiffness; - this.frictionEquationRelaxation = options.frictionEquationRelaxation; -}; +class ContactMaterial { + // Identifier of this material. + // Participating materials. + // Friction coefficient. + // Restitution coefficient. + // Stiffness of the produced contact equations. + // Relaxation time of the produced contact equations. + // Stiffness of the produced friction equations. + // Relaxation time of the produced friction equations + constructor(m1, m2, options) { + options = Utils.defaults(options, { + friction: 0.3, + restitution: 0.3, + contactEquationStiffness: 1e7, + contactEquationRelaxation: 3, + frictionEquationStiffness: 1e7, + frictionEquationRelaxation: 3 + }); + this.id = ContactMaterial.idCounter++; + this.materials = [m1, m2]; + this.friction = options.friction; + this.restitution = options.restitution; + this.contactEquationStiffness = options.contactEquationStiffness; + this.contactEquationRelaxation = options.contactEquationRelaxation; + this.frictionEquationStiffness = options.frictionEquationStiffness; + this.frictionEquationRelaxation = options.frictionEquationRelaxation; + } +} +exports.ContactMaterial = ContactMaterial; ContactMaterial.idCounter = 0; /** @@ -7545,27 +6423,25 @@ ContactMaterial.idCounter = 0; * @param {object} [options] * @author schteppe */ -var Material = // Material name. -// Material id. -// Friction for this material. If non-negative, it will be used instead of the friction given by ContactMaterials. If there's no matching ContactMaterial, the value from .defaultContactMaterial in the World will be used. -// Restitution for this material. If non-negative, it will be used instead of the restitution given by ContactMaterials. If there's no matching ContactMaterial, the value from .defaultContactMaterial in the World will be used. -function Material(options) { - if (options === void 0) { - options = {}; - } - - var name = ''; // Backwards compatibility fix - - if (typeof options === 'string') { - name = options; - options = {}; +class Material { + // Material name. + // Material id. + // Friction for this material. If non-negative, it will be used instead of the friction given by ContactMaterials. If there's no matching ContactMaterial, the value from .defaultContactMaterial in the World will be used. + // Restitution for this material. If non-negative, it will be used instead of the restitution given by ContactMaterials. If there's no matching ContactMaterial, the value from .defaultContactMaterial in the World will be used. + constructor(options = {}) { + let name = ''; // Backwards compatibility fix + + if (typeof options === 'string') { + name = options; + options = {}; + } + this.name = name; + this.id = Material.idCounter++; + this.friction = typeof options.friction !== 'undefined' ? options.friction : -1; + this.restitution = typeof options.restitution !== 'undefined' ? options.restitution : -1; } - - this.name = name; - this.id = Material.idCounter++; - this.friction = typeof options.friction !== 'undefined' ? options.friction : -1; - this.restitution = typeof options.restitution !== 'undefined' ? options.restitution : -1; -}; +} +exports.Material = Material; Material.idCounter = 0; /** @@ -7584,7 +6460,7 @@ Material.idCounter = 0; * @param {Vec3} [options.localAnchorA] Where to hook the spring to body A, in local body coordinates. * @param {Vec3} [options.localAnchorB] */ -var Spring = /*#__PURE__*/function () { +class Spring { // Rest length of the spring. // Stiffness of the spring. // Damping of the spring. @@ -7592,11 +6468,7 @@ var Spring = /*#__PURE__*/function () { // Second connected body. // Anchor for bodyA in local bodyA coordinates. // Anchor for bodyB in local bodyB coordinates. - function Spring(bodyA, bodyB, options) { - if (options === void 0) { - options = {}; - } - + constructor(bodyA, bodyB, options = {}) { this.restLength = typeof options.restLength === 'number' ? options.restLength : 1; this.stiffness = options.stiffness || 100; this.damping = options.damping || 1; @@ -7604,19 +6476,15 @@ var Spring = /*#__PURE__*/function () { this.bodyB = bodyB; this.localAnchorA = new Vec3(); this.localAnchorB = new Vec3(); - if (options.localAnchorA) { this.localAnchorA.copy(options.localAnchorA); } - if (options.localAnchorB) { this.localAnchorB.copy(options.localAnchorB); } - if (options.worldAnchorA) { this.setWorldAnchorA(options.worldAnchorA); } - if (options.worldAnchorB) { this.setWorldAnchorB(options.worldAnchorB); } @@ -7627,10 +6495,7 @@ var Spring = /*#__PURE__*/function () { * @param {Vec3} worldAnchorA */ - - var _proto = Spring.prototype; - - _proto.setWorldAnchorA = function setWorldAnchorA(worldAnchorA) { + setWorldAnchorA(worldAnchorA) { this.bodyA.pointToLocalFrame(worldAnchorA, this.localAnchorA); } /** @@ -7638,9 +6503,8 @@ var Spring = /*#__PURE__*/function () { * @method setWorldAnchorB * @param {Vec3} worldAnchorB */ - ; - _proto.setWorldAnchorB = function setWorldAnchorB(worldAnchorB) { + setWorldAnchorB(worldAnchorB) { this.bodyB.pointToLocalFrame(worldAnchorB, this.localAnchorB); } /** @@ -7648,9 +6512,8 @@ var Spring = /*#__PURE__*/function () { * @method getWorldAnchorA * @param {Vec3} result The vector to store the result in. */ - ; - _proto.getWorldAnchorA = function getWorldAnchorA(result) { + getWorldAnchorA(result) { this.bodyA.pointToWorldFrame(this.localAnchorA, result); } /** @@ -7658,34 +6521,32 @@ var Spring = /*#__PURE__*/function () { * @method getWorldAnchorB * @param {Vec3} result The vector to store the result in. */ - ; - _proto.getWorldAnchorB = function getWorldAnchorB(result) { + getWorldAnchorB(result) { this.bodyB.pointToWorldFrame(this.localAnchorB, result); } /** * Apply the spring force to the connected bodies. * @method applyForce */ - ; - - _proto.applyForce = function applyForce() { - var k = this.stiffness; - var d = this.damping; - var l = this.restLength; - var bodyA = this.bodyA; - var bodyB = this.bodyB; - var r = applyForce_r; - var r_unit = applyForce_r_unit; - var u = applyForce_u; - var f = applyForce_f; - var tmp = applyForce_tmp; - var worldAnchorA = applyForce_worldAnchorA; - var worldAnchorB = applyForce_worldAnchorB; - var ri = applyForce_ri; - var rj = applyForce_rj; - var ri_x_f = applyForce_ri_x_f; - var rj_x_f = applyForce_rj_x_f; // Get world anchors + + applyForce() { + const k = this.stiffness; + const d = this.damping; + const l = this.restLength; + const bodyA = this.bodyA; + const bodyB = this.bodyB; + const r = applyForce_r; + const r_unit = applyForce_r_unit; + const u = applyForce_u; + const f = applyForce_f; + const tmp = applyForce_tmp; + const worldAnchorA = applyForce_worldAnchorA; + const worldAnchorB = applyForce_worldAnchorB; + const ri = applyForce_ri; + const rj = applyForce_rj; + const ri_x_f = applyForce_ri_x_f; + const rj_x_f = applyForce_rj_x_f; // Get world anchors this.getWorldAnchorA(worldAnchorA); this.getWorldAnchorB(worldAnchorB); // Get offset points @@ -7694,7 +6555,7 @@ var Spring = /*#__PURE__*/function () { worldAnchorB.vsub(bodyB.position, rj); // Compute distance vector between world anchor points worldAnchorB.vsub(worldAnchorA, r); - var rlen = r.length(); + const rlen = r.length(); r_unit.copy(r); r_unit.normalize(); // Compute relative velocity of the anchor points, u @@ -7714,21 +6575,20 @@ var Spring = /*#__PURE__*/function () { rj.cross(f, rj_x_f); bodyA.torque.vsub(ri_x_f, bodyA.torque); bodyB.torque.vadd(rj_x_f, bodyB.torque); - }; - - return Spring; -}(); -var applyForce_r = new Vec3(); -var applyForce_r_unit = new Vec3(); -var applyForce_u = new Vec3(); -var applyForce_f = new Vec3(); -var applyForce_worldAnchorA = new Vec3(); -var applyForce_worldAnchorB = new Vec3(); -var applyForce_ri = new Vec3(); -var applyForce_rj = new Vec3(); -var applyForce_ri_x_f = new Vec3(); -var applyForce_rj_x_f = new Vec3(); -var applyForce_tmp = new Vec3(); + } +} +exports.Spring = Spring; +const applyForce_r = new Vec3(); +const applyForce_r_unit = new Vec3(); +const applyForce_u = new Vec3(); +const applyForce_f = new Vec3(); +const applyForce_worldAnchorA = new Vec3(); +const applyForce_worldAnchorB = new Vec3(); +const applyForce_ri = new Vec3(); +const applyForce_rj = new Vec3(); +const applyForce_ri_x_f = new Vec3(); +const applyForce_rj_x_f = new Vec3(); +const applyForce_tmp = new Vec3(); /** * @class WheelInfo @@ -7763,7 +6623,7 @@ var applyForce_tmp = new Vec3(); * @param {boolean} [options.useCustomSlidingRotationalSpeed=false] * @param {number} [options.customSlidingRotationalSpeed=-0.1] */ -var WheelInfo = /*#__PURE__*/function () { +class WheelInfo { // Max travel distance of the suspension, in meters. // Speed to apply to the wheel rotation when the wheel is sliding. // If the customSlidingRotationalSpeed should be used. @@ -7771,11 +6631,7 @@ var WheelInfo = /*#__PURE__*/function () { // Rotation value, in radians. // The result from raycasting. // Wheel world transform. - function WheelInfo(options) { - if (options === void 0) { - options = {}; - } - + constructor(options = {}) { options = Utils.defaults(options, { chassisConnectionPointLocal: new Vec3(), chassisConnectionPointWorld: new Vec3(), @@ -7843,23 +6699,18 @@ var WheelInfo = /*#__PURE__*/function () { this.worldTransform = new Transform(); this.isInContact = false; } - - var _proto = WheelInfo.prototype; - - _proto.updateWheel = function updateWheel(chassis) { - var raycastResult = this.raycastResult; - + updateWheel(chassis) { + const raycastResult = this.raycastResult; if (this.isInContact) { - var project = raycastResult.hitNormalWorld.dot(raycastResult.directionWorld); + const project = raycastResult.hitNormalWorld.dot(raycastResult.directionWorld); raycastResult.hitPointWorld.vsub(chassis.position, relpos); chassis.getVelocityAtWorldPoint(relpos, chassis_velocity_at_contactPoint); - var projVel = raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint); - + const projVel = raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint); if (project >= -0.1) { this.suspensionRelativeVelocity = 0.0; this.clippedInvContactDotSuspension = 1.0 / 0.1; } else { - var inv = -1 / project; + const inv = -1 / project; this.suspensionRelativeVelocity = projVel * inv; this.clippedInvContactDotSuspension = inv; } @@ -7870,12 +6721,10 @@ var WheelInfo = /*#__PURE__*/function () { raycastResult.directionWorld.scale(-1, raycastResult.hitNormalWorld); this.clippedInvContactDotSuspension = 1.0; } - }; - - return WheelInfo; -}(); -var chassis_velocity_at_contactPoint = new Vec3(); -var relpos = new Vec3(); + } +} +const chassis_velocity_at_contactPoint = new Vec3(); +const relpos = new Vec3(); /** * Vehicle helper class that casts rays from the wheel positions towards the ground and applies forces. @@ -7887,12 +6736,12 @@ var relpos = new Vec3(); * @param {integer} [options.indexLeftAxis] * @param {integer} [options.indexUpAxis] */ -var RaycastVehicle = /*#__PURE__*/function () { +class RaycastVehicle { // Will be set to true if the car is sliding. // Index of the right axis, 0=x, 1=y, 2=z // Index of the forward axis, 0=x, 1=y, 2=z // Index of the up axis, 0=x, 1=y, 2=z - function RaycastVehicle(options) { + constructor(options) { this.chassisBody = options.chassisBody; this.wheelInfos = []; this.sliding = false; @@ -7901,9 +6750,7 @@ var RaycastVehicle = /*#__PURE__*/function () { this.indexForwardAxis = typeof options.indexForwardAxis !== 'undefined' ? options.indexForwardAxis : 0; this.indexUpAxis = typeof options.indexUpAxis !== 'undefined' ? options.indexUpAxis : 2; this.constraints = []; - - this.preStepCallback = function () {}; - + this.preStepCallback = () => {}; this.currentVehicleSpeedKmHour = 0; } /** @@ -7912,16 +6759,9 @@ var RaycastVehicle = /*#__PURE__*/function () { * @param {object} [options] */ - - var _proto = RaycastVehicle.prototype; - - _proto.addWheel = function addWheel(options) { - if (options === void 0) { - options = {}; - } - - var info = new WheelInfo(options); - var index = this.wheelInfos.length; + addWheel(options = {}) { + const info = new WheelInfo(options); + const index = this.wheelInfos.length; this.wheelInfos.push(info); return index; } @@ -7931,10 +6771,9 @@ var RaycastVehicle = /*#__PURE__*/function () { * @param {number} value * @param {integer} wheelIndex */ - ; - _proto.setSteeringValue = function setSteeringValue(value, wheelIndex) { - var wheel = this.wheelInfos[wheelIndex]; + setSteeringValue(value, wheelIndex) { + const wheel = this.wheelInfos[wheelIndex]; wheel.steering = value; } /** @@ -7943,9 +6782,8 @@ var RaycastVehicle = /*#__PURE__*/function () { * @param {number} value * @param {integer} wheelIndex */ - ; - _proto.applyEngineForce = function applyEngineForce(value, wheelIndex) { + applyEngineForce(value, wheelIndex) { this.wheelInfos[wheelIndex].engineForce = value; } /** @@ -7954,9 +6792,8 @@ var RaycastVehicle = /*#__PURE__*/function () { * @param {number} brake * @param {integer} wheelIndex */ - ; - _proto.setBrake = function setBrake(brake, wheelIndex) { + setBrake(brake, wheelIndex) { this.wheelInfos[wheelIndex].brake = brake; } /** @@ -7964,17 +6801,14 @@ var RaycastVehicle = /*#__PURE__*/function () { * @method addToWorld * @param {World} world */ - ; - _proto.addToWorld = function addToWorld(world) { - var constraints = this.constraints; + addToWorld(world) { + const constraints = this.constraints; world.addBody(this.chassisBody); - var that = this; - - this.preStepCallback = function () { + const that = this; + this.preStepCallback = () => { that.updateVehicle(world.dt); }; - world.addEventListener('preStep', this.preStepCallback); this.world = world; } @@ -7985,128 +6819,104 @@ var RaycastVehicle = /*#__PURE__*/function () { * @param {integer} axisIndex * @param {Vec3} result */ - ; - _proto.getVehicleAxisWorld = function getVehicleAxisWorld(axisIndex, result) { + getVehicleAxisWorld(axisIndex, result) { result.set(axisIndex === 0 ? 1 : 0, axisIndex === 1 ? 1 : 0, axisIndex === 2 ? 1 : 0); this.chassisBody.vectorToWorldFrame(result, result); - }; - - _proto.updateVehicle = function updateVehicle(timeStep) { - var wheelInfos = this.wheelInfos; - var numWheels = wheelInfos.length; - var chassisBody = this.chassisBody; - - for (var i = 0; i < numWheels; i++) { + } + updateVehicle(timeStep) { + const wheelInfos = this.wheelInfos; + const numWheels = wheelInfos.length; + const chassisBody = this.chassisBody; + for (let i = 0; i < numWheels; i++) { this.updateWheelTransform(i); } - this.currentVehicleSpeedKmHour = 3.6 * chassisBody.velocity.length(); - var forwardWorld = new Vec3(); + const forwardWorld = new Vec3(); this.getVehicleAxisWorld(this.indexForwardAxis, forwardWorld); - if (forwardWorld.dot(chassisBody.velocity) < 0) { this.currentVehicleSpeedKmHour *= -1; } // simulate suspension - - for (var _i = 0; _i < numWheels; _i++) { - this.castRay(wheelInfos[_i]); + for (let i = 0; i < numWheels; i++) { + this.castRay(wheelInfos[i]); } - this.updateSuspension(timeStep); - var impulse = new Vec3(); - var relpos = new Vec3(); - - for (var _i2 = 0; _i2 < numWheels; _i2++) { + const impulse = new Vec3(); + const relpos = new Vec3(); + for (let i = 0; i < numWheels; i++) { //apply suspension force - var wheel = wheelInfos[_i2]; - var suspensionForce = wheel.suspensionForce; - + const wheel = wheelInfos[i]; + let suspensionForce = wheel.suspensionForce; if (suspensionForce > wheel.maxSuspensionForce) { suspensionForce = wheel.maxSuspensionForce; } - wheel.raycastResult.hitNormalWorld.scale(suspensionForce * timeStep, impulse); wheel.raycastResult.hitPointWorld.vsub(chassisBody.position, relpos); chassisBody.applyImpulse(impulse, relpos); } - this.updateFriction(timeStep); - var hitNormalWorldScaledWithProj = new Vec3(); - var fwd = new Vec3(); - var vel = new Vec3(); - - for (var _i3 = 0; _i3 < numWheels; _i3++) { - var _wheel = wheelInfos[_i3]; //const relpos = new Vec3(); + const hitNormalWorldScaledWithProj = new Vec3(); + const fwd = new Vec3(); + const vel = new Vec3(); + for (let i = 0; i < numWheels; i++) { + const wheel = wheelInfos[i]; //const relpos = new Vec3(); //wheel.chassisConnectionPointWorld.vsub(chassisBody.position, relpos); - chassisBody.getVelocityAtWorldPoint(_wheel.chassisConnectionPointWorld, vel); // Hack to get the rotation in the correct direction - - var m = 1; + chassisBody.getVelocityAtWorldPoint(wheel.chassisConnectionPointWorld, vel); // Hack to get the rotation in the correct direction + let m = 1; switch (this.indexUpAxis) { case 1: m = -1; break; } - - if (_wheel.isInContact) { + if (wheel.isInContact) { this.getVehicleAxisWorld(this.indexForwardAxis, fwd); - var proj = fwd.dot(_wheel.raycastResult.hitNormalWorld); - - _wheel.raycastResult.hitNormalWorld.scale(proj, hitNormalWorldScaledWithProj); - + const proj = fwd.dot(wheel.raycastResult.hitNormalWorld); + wheel.raycastResult.hitNormalWorld.scale(proj, hitNormalWorldScaledWithProj); fwd.vsub(hitNormalWorldScaledWithProj, fwd); - var proj2 = fwd.dot(vel); - _wheel.deltaRotation = m * proj2 * timeStep / _wheel.radius; + const proj2 = fwd.dot(vel); + wheel.deltaRotation = m * proj2 * timeStep / wheel.radius; } - - if ((_wheel.sliding || !_wheel.isInContact) && _wheel.engineForce !== 0 && _wheel.useCustomSlidingRotationalSpeed) { + if ((wheel.sliding || !wheel.isInContact) && wheel.engineForce !== 0 && wheel.useCustomSlidingRotationalSpeed) { // Apply custom rotation when accelerating and sliding - _wheel.deltaRotation = (_wheel.engineForce > 0 ? 1 : -1) * _wheel.customSlidingRotationalSpeed * timeStep; + wheel.deltaRotation = (wheel.engineForce > 0 ? 1 : -1) * wheel.customSlidingRotationalSpeed * timeStep; } // Lock wheels - - if (Math.abs(_wheel.brake) > Math.abs(_wheel.engineForce)) { - _wheel.deltaRotation = 0; + if (Math.abs(wheel.brake) > Math.abs(wheel.engineForce)) { + wheel.deltaRotation = 0; } + wheel.rotation += wheel.deltaRotation; // Use the old value - _wheel.rotation += _wheel.deltaRotation; // Use the old value - - _wheel.deltaRotation *= 0.99; // damping of rotation when not in contact + wheel.deltaRotation *= 0.99; // damping of rotation when not in contact } - }; - - _proto.updateSuspension = function updateSuspension(deltaTime) { - var chassisBody = this.chassisBody; - var chassisMass = chassisBody.mass; - var wheelInfos = this.wheelInfos; - var numWheels = wheelInfos.length; - - for (var w_it = 0; w_it < numWheels; w_it++) { - var wheel = wheelInfos[w_it]; + } + updateSuspension(deltaTime) { + const chassisBody = this.chassisBody; + const chassisMass = chassisBody.mass; + const wheelInfos = this.wheelInfos; + const numWheels = wheelInfos.length; + for (let w_it = 0; w_it < numWheels; w_it++) { + const wheel = wheelInfos[w_it]; if (wheel.isInContact) { - var force = void 0; // Spring + let force; // Spring - var susp_length = wheel.suspensionRestLength; - var current_length = wheel.suspensionLength; - var length_diff = susp_length - current_length; + const susp_length = wheel.suspensionRestLength; + const current_length = wheel.suspensionLength; + const length_diff = susp_length - current_length; force = wheel.suspensionStiffness * length_diff * wheel.clippedInvContactDotSuspension; // Damper - var projected_rel_vel = wheel.suspensionRelativeVelocity; - var susp_damping = void 0; - + const projected_rel_vel = wheel.suspensionRelativeVelocity; + let susp_damping; if (projected_rel_vel < 0) { susp_damping = wheel.dampingCompression; } else { susp_damping = wheel.dampingRelaxation; } - force -= susp_damping * projected_rel_vel; wheel.suspensionForce = force * chassisMass; - if (wheel.suspensionForce < 0) { wheel.suspensionForce = 0; } @@ -8120,65 +6930,58 @@ var RaycastVehicle = /*#__PURE__*/function () { * @method removeFromWorld * @param {World} world */ - ; - _proto.removeFromWorld = function removeFromWorld(world) { - var constraints = this.constraints; + removeFromWorld(world) { + const constraints = this.constraints; world.removeBody(this.chassisBody); world.removeEventListener('preStep', this.preStepCallback); this.world = null; - }; - - _proto.castRay = function castRay(wheel) { - var rayvector = castRay_rayvector; - var target = castRay_target; + } + castRay(wheel) { + const rayvector = castRay_rayvector; + const target = castRay_target; this.updateWheelTransformWorld(wheel); - var chassisBody = this.chassisBody; - var depth = -1; - var raylen = wheel.suspensionRestLength + wheel.radius; + const chassisBody = this.chassisBody; + let depth = -1; + const raylen = wheel.suspensionRestLength + wheel.radius; wheel.directionWorld.scale(raylen, rayvector); - var source = wheel.chassisConnectionPointWorld; + const source = wheel.chassisConnectionPointWorld; source.vadd(rayvector, target); - var raycastResult = wheel.raycastResult; + const raycastResult = wheel.raycastResult; raycastResult.reset(); // Turn off ray collision with the chassis temporarily - var oldState = chassisBody.collisionResponse; + const oldState = chassisBody.collisionResponse; chassisBody.collisionResponse = false; // Cast ray against world this.world.rayTest(source, target, raycastResult); chassisBody.collisionResponse = oldState; - var object = raycastResult.body; + const object = raycastResult.body; wheel.raycastResult.groundObject = 0; - if (object) { depth = raycastResult.distance; wheel.raycastResult.hitNormalWorld = raycastResult.hitNormalWorld; wheel.isInContact = true; - var hitDistance = raycastResult.distance; + const hitDistance = raycastResult.distance; wheel.suspensionLength = hitDistance - wheel.radius; // clamp on max suspension travel - var minSuspensionLength = wheel.suspensionRestLength - wheel.maxSuspensionTravel; - var maxSuspensionLength = wheel.suspensionRestLength + wheel.maxSuspensionTravel; - + const minSuspensionLength = wheel.suspensionRestLength - wheel.maxSuspensionTravel; + const maxSuspensionLength = wheel.suspensionRestLength + wheel.maxSuspensionTravel; if (wheel.suspensionLength < minSuspensionLength) { wheel.suspensionLength = minSuspensionLength; } - if (wheel.suspensionLength > maxSuspensionLength) { wheel.suspensionLength = maxSuspensionLength; wheel.raycastResult.reset(); } - - var denominator = wheel.raycastResult.hitNormalWorld.dot(wheel.directionWorld); - var chassis_velocity_at_contactPoint = new Vec3(); + const denominator = wheel.raycastResult.hitNormalWorld.dot(wheel.directionWorld); + const chassis_velocity_at_contactPoint = new Vec3(); chassisBody.getVelocityAtWorldPoint(wheel.raycastResult.hitPointWorld, chassis_velocity_at_contactPoint); - var projVel = wheel.raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint); - + const projVel = wheel.raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint); if (denominator >= -0.1) { wheel.suspensionRelativeVelocity = 0; wheel.clippedInvContactDotSuspension = 1 / 0.1; } else { - var inv = -1 / denominator; + const inv = -1 / denominator; wheel.suspensionRelativeVelocity = projVel * inv; wheel.clippedInvContactDotSuspension = inv; } @@ -8189,13 +6992,11 @@ var RaycastVehicle = /*#__PURE__*/function () { wheel.directionWorld.scale(-1, wheel.raycastResult.hitNormalWorld); wheel.clippedInvContactDotSuspension = 1.0; } - return depth; - }; - - _proto.updateWheelTransformWorld = function updateWheelTransformWorld(wheel) { + } + updateWheelTransformWorld(wheel) { wheel.isInContact = false; - var chassisBody = this.chassisBody; + const chassisBody = this.chassisBody; chassisBody.pointToWorldFrame(wheel.chassisConnectionPointLocal, wheel.chassisConnectionPointWorld); chassisBody.vectorToWorldFrame(wheel.directionLocal, wheel.directionWorld); chassisBody.vectorToWorldFrame(wheel.axleLocal, wheel.axleWorld); @@ -8206,13 +7007,12 @@ var RaycastVehicle = /*#__PURE__*/function () { * @method updateWheelTransform * @param {integer} wheelIndex The wheel index to update. */ - ; - _proto.updateWheelTransform = function updateWheelTransform(wheelIndex) { - var up = tmpVec4; - var right = tmpVec5; - var fwd = tmpVec6; - var wheel = this.wheelInfos[wheelIndex]; + updateWheelTransform(wheelIndex) { + const up = tmpVec4; + const right = tmpVec5; + const fwd = tmpVec6; + const wheel = this.wheelInfos[wheelIndex]; this.updateWheelTransformWorld(wheel); wheel.directionLocal.scale(-1, up); right.copy(wheel.axleLocal); @@ -8220,18 +7020,18 @@ var RaycastVehicle = /*#__PURE__*/function () { fwd.normalize(); right.normalize(); // Rotate around steering over the wheelAxle - var steering = wheel.steering; - var steeringOrn = new Quaternion(); + const steering = wheel.steering; + const steeringOrn = new Quaternion(); steeringOrn.setFromAxisAngle(up, steering); - var rotatingOrn = new Quaternion(); + const rotatingOrn = new Quaternion(); rotatingOrn.setFromAxisAngle(right, wheel.rotation); // World rotation of the wheel - var q = wheel.worldTransform.quaternion; + const q = wheel.worldTransform.quaternion; this.chassisBody.quaternion.mult(steeringOrn, q); q.mult(rotatingOrn, q); q.normalize(); // world position of the wheel - var p = wheel.worldTransform.position; + const p = wheel.worldTransform.position; p.copy(wheel.directionWorld); p.scale(wheel.suspensionLength, p); p.vadd(wheel.chassisConnectionPointWorld, p); @@ -8242,241 +7042,197 @@ var RaycastVehicle = /*#__PURE__*/function () { * @param {integer} wheelIndex * @return {Transform} */ - ; - _proto.getWheelTransformWorld = function getWheelTransformWorld(wheelIndex) { + getWheelTransformWorld(wheelIndex) { return this.wheelInfos[wheelIndex].worldTransform; - }; - - _proto.updateFriction = function updateFriction(timeStep) { - var surfNormalWS_scaled_proj = updateFriction_surfNormalWS_scaled_proj; //calculate the impulse, so that the wheels don't move sidewards - - var wheelInfos = this.wheelInfos; - var numWheels = wheelInfos.length; - var chassisBody = this.chassisBody; - var forwardWS = updateFriction_forwardWS; - var axle = updateFriction_axle; - - for (var i = 0; i < numWheels; i++) { - var wheel = wheelInfos[i]; - var groundObject = wheel.raycastResult.body; - + } + updateFriction(timeStep) { + const surfNormalWS_scaled_proj = updateFriction_surfNormalWS_scaled_proj; //calculate the impulse, so that the wheels don't move sidewards + + const wheelInfos = this.wheelInfos; + const numWheels = wheelInfos.length; + const chassisBody = this.chassisBody; + const forwardWS = updateFriction_forwardWS; + const axle = updateFriction_axle; + for (let i = 0; i < numWheels; i++) { + const wheel = wheelInfos[i]; + const groundObject = wheel.raycastResult.body; wheel.sideImpulse = 0; wheel.forwardImpulse = 0; - if (!forwardWS[i]) { forwardWS[i] = new Vec3(); } - if (!axle[i]) { axle[i] = new Vec3(); } } - - for (var _i4 = 0; _i4 < numWheels; _i4++) { - var _wheel2 = wheelInfos[_i4]; - var _groundObject = _wheel2.raycastResult.body; - - if (_groundObject) { - var axlei = axle[_i4]; - var wheelTrans = this.getWheelTransformWorld(_i4); // Get world axle + for (let i = 0; i < numWheels; i++) { + const wheel = wheelInfos[i]; + const groundObject = wheel.raycastResult.body; + if (groundObject) { + const axlei = axle[i]; + const wheelTrans = this.getWheelTransformWorld(i); // Get world axle wheelTrans.vectorToWorldFrame(directions[this.indexRightAxis], axlei); - var surfNormalWS = _wheel2.raycastResult.hitNormalWorld; - var proj = axlei.dot(surfNormalWS); + const surfNormalWS = wheel.raycastResult.hitNormalWorld; + const proj = axlei.dot(surfNormalWS); surfNormalWS.scale(proj, surfNormalWS_scaled_proj); axlei.vsub(surfNormalWS_scaled_proj, axlei); axlei.normalize(); - surfNormalWS.cross(axlei, forwardWS[_i4]); - - forwardWS[_i4].normalize(); - - _wheel2.sideImpulse = resolveSingleBilateral(chassisBody, _wheel2.raycastResult.hitPointWorld, _groundObject, _wheel2.raycastResult.hitPointWorld, axlei); - _wheel2.sideImpulse *= sideFrictionStiffness2; + surfNormalWS.cross(axlei, forwardWS[i]); + forwardWS[i].normalize(); + wheel.sideImpulse = resolveSingleBilateral(chassisBody, wheel.raycastResult.hitPointWorld, groundObject, wheel.raycastResult.hitPointWorld, axlei); + wheel.sideImpulse *= sideFrictionStiffness2; } } - - var sideFactor = 1; - var fwdFactor = 0.5; + const sideFactor = 1; + const fwdFactor = 0.5; this.sliding = false; - - for (var _i5 = 0; _i5 < numWheels; _i5++) { - var _wheel3 = wheelInfos[_i5]; - var _groundObject2 = _wheel3.raycastResult.body; - var rollingFriction = 0; - _wheel3.slipInfo = 1; - - if (_groundObject2) { - var defaultRollingFrictionImpulse = 0; - var maxImpulse = _wheel3.brake ? _wheel3.brake : defaultRollingFrictionImpulse; // btWheelContactPoint contactPt(chassisBody,groundObject,wheelInfraycastInfo.hitPointWorld,forwardWS[wheel],maxImpulse); + for (let i = 0; i < numWheels; i++) { + const wheel = wheelInfos[i]; + const groundObject = wheel.raycastResult.body; + let rollingFriction = 0; + wheel.slipInfo = 1; + if (groundObject) { + const defaultRollingFrictionImpulse = 0; + const maxImpulse = wheel.brake ? wheel.brake : defaultRollingFrictionImpulse; // btWheelContactPoint contactPt(chassisBody,groundObject,wheelInfraycastInfo.hitPointWorld,forwardWS[wheel],maxImpulse); // rollingFriction = calcRollingFriction(contactPt); - rollingFriction = calcRollingFriction(chassisBody, _groundObject2, _wheel3.raycastResult.hitPointWorld, forwardWS[_i5], maxImpulse); - rollingFriction += _wheel3.engineForce * timeStep; // rollingFriction = 0; + rollingFriction = calcRollingFriction(chassisBody, groundObject, wheel.raycastResult.hitPointWorld, forwardWS[i], maxImpulse); + rollingFriction += wheel.engineForce * timeStep; // rollingFriction = 0; - var factor = maxImpulse / rollingFriction; - _wheel3.slipInfo *= factor; + const factor = maxImpulse / rollingFriction; + wheel.slipInfo *= factor; } //switch between active rolling (throttle), braking and non-active rolling friction (nthrottle/break) - - _wheel3.forwardImpulse = 0; - _wheel3.skidInfo = 1; - - if (_groundObject2) { - _wheel3.skidInfo = 1; - var maximp = _wheel3.suspensionForce * timeStep * _wheel3.frictionSlip; - var maximpSide = maximp; - var maximpSquared = maximp * maximpSide; - _wheel3.forwardImpulse = rollingFriction; //wheelInfo.engineForce* timeStep; - - var x = _wheel3.forwardImpulse * fwdFactor; - var y = _wheel3.sideImpulse * sideFactor; - var impulseSquared = x * x + y * y; - _wheel3.sliding = false; - + wheel.forwardImpulse = 0; + wheel.skidInfo = 1; + if (groundObject) { + wheel.skidInfo = 1; + const maximp = wheel.suspensionForce * timeStep * wheel.frictionSlip; + const maximpSide = maximp; + const maximpSquared = maximp * maximpSide; + wheel.forwardImpulse = rollingFriction; //wheelInfo.engineForce* timeStep; + + const x = wheel.forwardImpulse * fwdFactor; + const y = wheel.sideImpulse * sideFactor; + const impulseSquared = x * x + y * y; + wheel.sliding = false; if (impulseSquared > maximpSquared) { this.sliding = true; - _wheel3.sliding = true; - - var _factor = maximp / Math.sqrt(impulseSquared); - - _wheel3.skidInfo *= _factor; + wheel.sliding = true; + const factor = maximp / Math.sqrt(impulseSquared); + wheel.skidInfo *= factor; } } } - if (this.sliding) { - for (var _i6 = 0; _i6 < numWheels; _i6++) { - var _wheel4 = wheelInfos[_i6]; - - if (_wheel4.sideImpulse !== 0) { - if (_wheel4.skidInfo < 1) { - _wheel4.forwardImpulse *= _wheel4.skidInfo; - _wheel4.sideImpulse *= _wheel4.skidInfo; + for (let i = 0; i < numWheels; i++) { + const wheel = wheelInfos[i]; + if (wheel.sideImpulse !== 0) { + if (wheel.skidInfo < 1) { + wheel.forwardImpulse *= wheel.skidInfo; + wheel.sideImpulse *= wheel.skidInfo; } } } } // apply the impulses - - for (var _i7 = 0; _i7 < numWheels; _i7++) { - var _wheel5 = wheelInfos[_i7]; - var rel_pos = new Vec3(); - - _wheel5.raycastResult.hitPointWorld.vsub(chassisBody.position, rel_pos); // cannons applyimpulse is using world coord for the position + for (let i = 0; i < numWheels; i++) { + const wheel = wheelInfos[i]; + const rel_pos = new Vec3(); + wheel.raycastResult.hitPointWorld.vsub(chassisBody.position, rel_pos); // cannons applyimpulse is using world coord for the position //rel_pos.copy(wheel.raycastResult.hitPointWorld); - - if (_wheel5.forwardImpulse !== 0) { - var impulse = new Vec3(); - - forwardWS[_i7].scale(_wheel5.forwardImpulse, impulse); - + if (wheel.forwardImpulse !== 0) { + const impulse = new Vec3(); + forwardWS[i].scale(wheel.forwardImpulse, impulse); chassisBody.applyImpulse(impulse, rel_pos); } + if (wheel.sideImpulse !== 0) { + const groundObject = wheel.raycastResult.body; + const rel_pos2 = new Vec3(); + wheel.raycastResult.hitPointWorld.vsub(groundObject.position, rel_pos2); //rel_pos2.copy(wheel.raycastResult.hitPointWorld); - if (_wheel5.sideImpulse !== 0) { - var _groundObject3 = _wheel5.raycastResult.body; - var rel_pos2 = new Vec3(); - - _wheel5.raycastResult.hitPointWorld.vsub(_groundObject3.position, rel_pos2); //rel_pos2.copy(wheel.raycastResult.hitPointWorld); - - - var sideImp = new Vec3(); - - axle[_i7].scale(_wheel5.sideImpulse, sideImp); // Scale the relative position in the up direction with rollInfluence. + const sideImp = new Vec3(); + axle[i].scale(wheel.sideImpulse, sideImp); // Scale the relative position in the up direction with rollInfluence. // If rollInfluence is 1, the impulse will be applied on the hitPoint (easy to roll over), if it is zero it will be applied in the same plane as the center of mass (not easy to roll over). - chassisBody.vectorToLocalFrame(rel_pos, rel_pos); - rel_pos['xyz'[this.indexUpAxis]] *= _wheel5.rollInfluence; + rel_pos['xyz'[this.indexUpAxis]] *= wheel.rollInfluence; chassisBody.vectorToWorldFrame(rel_pos, rel_pos); chassisBody.applyImpulse(sideImp, rel_pos); //apply friction impulse on the ground sideImp.scale(-1, sideImp); - - _groundObject3.applyImpulse(sideImp, rel_pos2); + groundObject.applyImpulse(sideImp, rel_pos2); } } - }; - - return RaycastVehicle; -}(); -var tmpVec1$2 = new Vec3(); -var tmpVec2$2 = new Vec3(); -var tmpVec3 = new Vec3(); -var tmpVec4 = new Vec3(); -var tmpVec5 = new Vec3(); -var tmpVec6 = new Vec3(); -var tmpRay = new Ray(); -var torque = new Vec3(); -var castRay_rayvector = new Vec3(); -var castRay_target = new Vec3(); -var directions = [new Vec3(1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, 0, 1)]; -var updateFriction_surfNormalWS_scaled_proj = new Vec3(); -var updateFriction_axle = []; -var updateFriction_forwardWS = []; -var sideFrictionStiffness2 = 1; -var calcRollingFriction_vel1 = new Vec3(); -var calcRollingFriction_vel2 = new Vec3(); -var calcRollingFriction_vel = new Vec3(); - + } +} +exports.RaycastVehicle = RaycastVehicle; +const tmpVec4 = new Vec3(); +const tmpVec5 = new Vec3(); +const tmpVec6 = new Vec3(); +const tmpRay = new Ray(); +const castRay_rayvector = new Vec3(); +const castRay_target = new Vec3(); +const directions = [new Vec3(1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, 0, 1)]; +const updateFriction_surfNormalWS_scaled_proj = new Vec3(); +const updateFriction_axle = []; +const updateFriction_forwardWS = []; +const sideFrictionStiffness2 = 1; +const calcRollingFriction_vel1 = new Vec3(); +const calcRollingFriction_vel2 = new Vec3(); +const calcRollingFriction_vel = new Vec3(); function calcRollingFriction(body0, body1, frictionPosWorld, frictionDirectionWorld, maxImpulse) { - var j1 = 0; - var contactPosWorld = frictionPosWorld; // const rel_pos1 = new Vec3(); + let j1 = 0; + const contactPosWorld = frictionPosWorld; // const rel_pos1 = new Vec3(); // const rel_pos2 = new Vec3(); - var vel1 = calcRollingFriction_vel1; - var vel2 = calcRollingFriction_vel2; - var vel = calcRollingFriction_vel; // contactPosWorld.vsub(body0.position, rel_pos1); + const vel1 = calcRollingFriction_vel1; + const vel2 = calcRollingFriction_vel2; + const vel = calcRollingFriction_vel; // contactPosWorld.vsub(body0.position, rel_pos1); // contactPosWorld.vsub(body1.position, rel_pos2); body0.getVelocityAtWorldPoint(contactPosWorld, vel1); body1.getVelocityAtWorldPoint(contactPosWorld, vel2); vel1.vsub(vel2, vel); - var vrel = frictionDirectionWorld.dot(vel); - var denom0 = computeImpulseDenominator(body0, frictionPosWorld, frictionDirectionWorld); - var denom1 = computeImpulseDenominator(body1, frictionPosWorld, frictionDirectionWorld); - var relaxation = 1; - var jacDiagABInv = relaxation / (denom0 + denom1); // calculate j that moves us to zero relative velocity + const vrel = frictionDirectionWorld.dot(vel); + const denom0 = computeImpulseDenominator(body0, frictionPosWorld, frictionDirectionWorld); + const denom1 = computeImpulseDenominator(body1, frictionPosWorld, frictionDirectionWorld); + const relaxation = 1; + const jacDiagABInv = relaxation / (denom0 + denom1); // calculate j that moves us to zero relative velocity j1 = -vrel * jacDiagABInv; - if (maxImpulse < j1) { j1 = maxImpulse; } - if (j1 < -maxImpulse) { j1 = -maxImpulse; } - return j1; } - -var computeImpulseDenominator_r0 = new Vec3(); -var computeImpulseDenominator_c0 = new Vec3(); -var computeImpulseDenominator_vec = new Vec3(); -var computeImpulseDenominator_m = new Vec3(); - +const computeImpulseDenominator_r0 = new Vec3(); +const computeImpulseDenominator_c0 = new Vec3(); +const computeImpulseDenominator_vec = new Vec3(); +const computeImpulseDenominator_m = new Vec3(); function computeImpulseDenominator(body, pos, normal) { - var r0 = computeImpulseDenominator_r0; - var c0 = computeImpulseDenominator_c0; - var vec = computeImpulseDenominator_vec; - var m = computeImpulseDenominator_m; + const r0 = computeImpulseDenominator_r0; + const c0 = computeImpulseDenominator_c0; + const vec = computeImpulseDenominator_vec; + const m = computeImpulseDenominator_m; pos.vsub(body.position, r0); r0.cross(normal, c0); body.invInertiaWorld.vmult(c0, m); m.cross(r0, vec); return body.invMass + normal.dot(vec); } - -var resolveSingleBilateral_vel1 = new Vec3(); -var resolveSingleBilateral_vel2 = new Vec3(); -var resolveSingleBilateral_vel = new Vec3(); //bilateral constraint between two dynamic objects +const resolveSingleBilateral_vel1 = new Vec3(); +const resolveSingleBilateral_vel2 = new Vec3(); +const resolveSingleBilateral_vel = new Vec3(); //bilateral constraint between two dynamic objects function resolveSingleBilateral(body1, pos1, body2, pos2, normal) { - var normalLenSqr = normal.lengthSquared(); - + const normalLenSqr = normal.lengthSquared(); if (normalLenSqr > 1.1) { return 0; // no impulse } // const rel_pos1 = new Vec3(); @@ -8484,17 +7240,16 @@ function resolveSingleBilateral(body1, pos1, body2, pos2, normal) { // pos1.vsub(body1.position, rel_pos1); // pos2.vsub(body2.position, rel_pos2); - - var vel1 = resolveSingleBilateral_vel1; - var vel2 = resolveSingleBilateral_vel2; - var vel = resolveSingleBilateral_vel; + const vel1 = resolveSingleBilateral_vel1; + const vel2 = resolveSingleBilateral_vel2; + const vel = resolveSingleBilateral_vel; body1.getVelocityAtWorldPoint(pos1, vel1); body2.getVelocityAtWorldPoint(pos2, vel2); vel1.vsub(vel2, vel); - var rel_vel = normal.dot(vel); - var contactDamping = 0.2; - var massTerm = 1 / (body1.invMass + body2.invMass); - var impulse = -contactDamping * rel_vel * massTerm; + const rel_vel = normal.dot(vel); + const contactDamping = 0.2; + const massTerm = 1 / (body1.invMass + body2.invMass); + const impulse = -contactDamping * rel_vel * massTerm; return impulse; } @@ -8506,61 +7261,40 @@ function resolveSingleBilateral(body1, pos1, body2, pos2, normal) { * @param {Number} radius The radius of the sphere, a non-negative number. * @author schteppe / http://github.com/schteppe */ -var Sphere = /*#__PURE__*/function (_Shape) { - _inheritsLoose(Sphere, _Shape); - - function Sphere(radius) { - var _this; - - _this = _Shape.call(this, { +class Sphere extends Shape { + constructor(radius) { + super({ type: Shape.types.SPHERE - }) || this; - _this.radius = radius !== undefined ? radius : 1.0; - - if (_this.radius < 0) { + }); + this.radius = radius !== undefined ? radius : 1.0; + if (this.radius < 0) { throw new Error('The sphere radius cannot be negative.'); } - - _this.updateBoundingSphereRadius(); - - return _this; + this.updateBoundingSphereRadius(); } - - var _proto = Sphere.prototype; - - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { - if (target === void 0) { - target = new Vec3(); - } - - var I = 2.0 * mass * this.radius * this.radius / 5.0; + calculateLocalInertia(mass, target = new Vec3()) { + const I = 2.0 * mass * this.radius * this.radius / 5.0; target.x = I; target.y = I; target.z = I; return target; - }; - - _proto.volume = function volume() { + } + volume() { return 4.0 * Math.PI * Math.pow(this.radius, 3) / 3.0; - }; - - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + } + updateBoundingSphereRadius() { this.boundingSphereRadius = this.radius; - }; - - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { - var r = this.radius; - var axes = ['x', 'y', 'z']; - - for (var i = 0; i < axes.length; i++) { - var ax = axes[i]; + } + calculateWorldAABB(pos, quat, min, max) { + const r = this.radius; + const axes = ['x', 'y', 'z']; + for (let i = 0; i < axes.length; i++) { + const ax = axes[i]; min[ax] = pos[ax] - r; max[ax] = pos[ax] + r; } - }; - - return Sphere; -}(Shape); + } +} /** * Simple vehicle helper class with spherical rigid body wheels. @@ -8568,15 +7302,11 @@ var Sphere = /*#__PURE__*/function (_Shape) { * @constructor * @param {Body} [options.chassisBody] */ -var RigidVehicle = /*#__PURE__*/function () { - function RigidVehicle(options) { - if (options === void 0) { - options = {}; - } - +exports.Sphere = Sphere; +class RigidVehicle { + constructor(options = {}) { this.wheelBodies = []; this.coordinateSystem = typeof options.coordinateSystem !== 'undefined' ? options.coordinateSystem.clone() : new Vec3(1, 2, 3); - if (options.chassisBody) { this.chassisBody = options.chassisBody; } else { @@ -8586,7 +7316,6 @@ var RigidVehicle = /*#__PURE__*/function () { shape: new Box(new Vec3(5, 2, 0.5)) }); } - this.constraints = []; this.wheelAxes = []; this.wheelForces = []; @@ -8602,16 +7331,8 @@ var RigidVehicle = /*#__PURE__*/function () { * @param {Body} [options.body] The wheel body. */ - - var _proto = RigidVehicle.prototype; - - _proto.addWheel = function addWheel(options) { - if (options === void 0) { - options = {}; - } - - var wheelBody; - + addWheel(options = {}) { + let wheelBody; if (options.body) { wheelBody = options.body; } else { @@ -8621,20 +7342,17 @@ var RigidVehicle = /*#__PURE__*/function () { shape: new Sphere(1.2) }); } - this.wheelBodies.push(wheelBody); this.wheelForces.push(0); // Position constrain wheels + const position = typeof options.position !== 'undefined' ? options.position.clone() : new Vec3(); // Set position locally to the chassis - var zero = new Vec3(); - var position = typeof options.position !== 'undefined' ? options.position.clone() : new Vec3(); // Set position locally to the chassis - - var worldPosition = new Vec3(); + const worldPosition = new Vec3(); this.chassisBody.pointToWorldFrame(position, worldPosition); wheelBody.position.set(worldPosition.x, worldPosition.y, worldPosition.z); // Constrain wheel - var axis = typeof options.axis !== 'undefined' ? options.axis.clone() : new Vec3(0, 1, 0); + const axis = typeof options.axis !== 'undefined' ? options.axis.clone() : new Vec3(0, 1, 0); this.wheelAxes.push(axis); - var hingeConstraint = new HingeConstraint(this.chassisBody, wheelBody, { + const hingeConstraint = new HingeConstraint(this.chassisBody, wheelBody, { pivotA: position, axisA: axis, pivotB: Vec3.ZERO, @@ -8651,15 +7369,14 @@ var RigidVehicle = /*#__PURE__*/function () { * @param {integer} wheelIndex * @todo check coordinateSystem */ - ; - _proto.setSteeringValue = function setSteeringValue(value, wheelIndex) { + setSteeringValue(value, wheelIndex) { // Set angle of the hinge axis - var axis = this.wheelAxes[wheelIndex]; - var c = Math.cos(value); - var s = Math.sin(value); - var x = axis.x; - var y = axis.y; + const axis = this.wheelAxes[wheelIndex]; + const c = Math.cos(value); + const s = Math.sin(value); + const x = axis.x; + const y = axis.y; this.constraints[wheelIndex].axisA.set(c * x - s * y, s * x + c * y, 0); } /** @@ -8668,10 +7385,9 @@ var RigidVehicle = /*#__PURE__*/function () { * @param {number} value * @param {integer} wheelIndex */ - ; - _proto.setMotorSpeed = function setMotorSpeed(value, wheelIndex) { - var hingeConstraint = this.constraints[wheelIndex]; + setMotorSpeed(value, wheelIndex) { + const hingeConstraint = this.constraints[wheelIndex]; hingeConstraint.enableMotor(); hingeConstraint.motorTargetVelocity = value; } @@ -8681,10 +7397,9 @@ var RigidVehicle = /*#__PURE__*/function () { * @param {number} value * @param {integer} wheelIndex */ - ; - _proto.disableMotor = function disableMotor(wheelIndex) { - var hingeConstraint = this.constraints[wheelIndex]; + disableMotor(wheelIndex) { + const hingeConstraint = this.constraints[wheelIndex]; hingeConstraint.disableMotor(); } /** @@ -8693,9 +7408,8 @@ var RigidVehicle = /*#__PURE__*/function () { * @param {number} value * @param {integer} wheelIndex */ - ; - _proto.setWheelForce = function setWheelForce(value, wheelIndex) { + setWheelForce(value, wheelIndex) { this.wheelForces[wheelIndex] = value; } /** @@ -8704,42 +7418,35 @@ var RigidVehicle = /*#__PURE__*/function () { * @param {number} value * @param {integer} wheelIndex */ - ; - _proto.applyWheelForce = function applyWheelForce(value, wheelIndex) { - var axis = this.wheelAxes[wheelIndex]; - var wheelBody = this.wheelBodies[wheelIndex]; - var bodyTorque = wheelBody.torque; - axis.scale(value, torque$1); - wheelBody.vectorToWorldFrame(torque$1, torque$1); - bodyTorque.vadd(torque$1, bodyTorque); + applyWheelForce(value, wheelIndex) { + const axis = this.wheelAxes[wheelIndex]; + const wheelBody = this.wheelBodies[wheelIndex]; + const bodyTorque = wheelBody.torque; + axis.scale(value, torque); + wheelBody.vectorToWorldFrame(torque, torque); + bodyTorque.vadd(torque, bodyTorque); } /** * Add the vehicle including its constraints to the world. * @method addToWorld * @param {World} world */ - ; - _proto.addToWorld = function addToWorld(world) { - var constraints = this.constraints; - var bodies = this.wheelBodies.concat([this.chassisBody]); - - for (var i = 0; i < bodies.length; i++) { + addToWorld(world) { + const constraints = this.constraints; + const bodies = this.wheelBodies.concat([this.chassisBody]); + for (let i = 0; i < bodies.length; i++) { world.addBody(bodies[i]); } - - for (var _i = 0; _i < constraints.length; _i++) { - world.addConstraint(constraints[_i]); + for (let i = 0; i < constraints.length; i++) { + world.addConstraint(constraints[i]); } - world.addEventListener('preStep', this._update.bind(this)); - }; - - _proto._update = function _update() { - var wheelForces = this.wheelForces; - - for (var i = 0; i < wheelForces.length; i++) { + } + _update() { + const wheelForces = this.wheelForces; + for (let i = 0; i < wheelForces.length; i++) { this.applyWheelForce(wheelForces[i], i); } } @@ -8748,18 +7455,15 @@ var RigidVehicle = /*#__PURE__*/function () { * @method removeFromWorld * @param {World} world */ - ; - - _proto.removeFromWorld = function removeFromWorld(world) { - var constraints = this.constraints; - var bodies = this.wheelBodies.concat([this.chassisBody]); - for (var i = 0; i < bodies.length; i++) { + removeFromWorld(world) { + const constraints = this.constraints; + const bodies = this.wheelBodies.concat([this.chassisBody]); + for (let i = 0; i < bodies.length; i++) { world.removeBody(bodies[i]); } - - for (var _i2 = 0; _i2 < constraints.length; _i2++) { - world.removeConstraint(constraints[_i2]); + for (let i = 0; i < constraints.length; i++) { + world.removeConstraint(constraints[i]); } } /** @@ -8767,31 +7471,29 @@ var RigidVehicle = /*#__PURE__*/function () { * @method getWheelSpeed * @param {integer} wheelIndex */ - ; - _proto.getWheelSpeed = function getWheelSpeed(wheelIndex) { - var axis = this.wheelAxes[wheelIndex]; - var wheelBody = this.wheelBodies[wheelIndex]; - var w = wheelBody.angularVelocity; + getWheelSpeed(wheelIndex) { + const axis = this.wheelAxes[wheelIndex]; + const wheelBody = this.wheelBodies[wheelIndex]; + const w = wheelBody.angularVelocity; this.chassisBody.vectorToWorldFrame(axis, worldAxis); return w.dot(worldAxis); - }; - - return RigidVehicle; -}(); -var torque$1 = new Vec3(); -var worldAxis = new Vec3(); + } +} +exports.RigidVehicle = RigidVehicle; +const torque = new Vec3(); +const worldAxis = new Vec3(); /** * Smoothed-particle hydrodynamics system * @class SPHSystem * @constructor */ -var SPHSystem = /*#__PURE__*/function () { +class SPHSystem { // Density of the system (kg/m3). // Distance below which two particles are considered to be neighbors. It should be adjusted so there are about 15-20 neighbor particles within this radius. // Viscosity of the system. - function SPHSystem() { + constructor() { this.particles = []; this.density = 1; this.smoothingRadius = 1; @@ -8809,12 +7511,8 @@ var SPHSystem = /*#__PURE__*/function () { * @param {Body} particle */ - - var _proto = SPHSystem.prototype; - - _proto.add = function add(particle) { + add(particle) { this.particles.push(particle); - if (this.neighbors.length < this.particles.length) { this.neighbors.push([]); } @@ -8824,109 +7522,95 @@ var SPHSystem = /*#__PURE__*/function () { * @method remove * @param {Body} particle */ - ; - - _proto.remove = function remove(particle) { - var idx = this.particles.indexOf(particle); + remove(particle) { + const idx = this.particles.indexOf(particle); if (idx !== -1) { this.particles.splice(idx, 1); - if (this.neighbors.length > this.particles.length) { this.neighbors.pop(); } } - }; - - _proto.getNeighbors = function getNeighbors(particle, neighbors) { - var N = this.particles.length; - var id = particle.id; - var R2 = this.smoothingRadius * this.smoothingRadius; - var dist = SPHSystem_getNeighbors_dist; - - for (var i = 0; i !== N; i++) { - var p = this.particles[i]; + } + getNeighbors(particle, neighbors) { + const N = this.particles.length; + const id = particle.id; + const R2 = this.smoothingRadius * this.smoothingRadius; + const dist = SPHSystem_getNeighbors_dist; + for (let i = 0; i !== N; i++) { + const p = this.particles[i]; p.position.vsub(particle.position, dist); - if (id !== p.id && dist.lengthSquared() < R2) { neighbors.push(p); } } - }; - - _proto.update = function update() { - var N = this.particles.length; - var dist = SPHSystem_update_dist; - var cs = this.speedOfSound; - var eps = this.eps; - - for (var i = 0; i !== N; i++) { - var p = this.particles[i]; // Current particle + } + update() { + const N = this.particles.length; + const dist = SPHSystem_update_dist; + const cs = this.speedOfSound; + const eps = this.eps; + for (let i = 0; i !== N; i++) { + const p = this.particles[i]; // Current particle - var neighbors = this.neighbors[i]; // Get neighbors + const neighbors = this.neighbors[i]; // Get neighbors neighbors.length = 0; this.getNeighbors(p, neighbors); neighbors.push(this.particles[i]); // Add current too - var numNeighbors = neighbors.length; // Accumulate density for the particle - - var sum = 0.0; + const numNeighbors = neighbors.length; // Accumulate density for the particle - for (var j = 0; j !== numNeighbors; j++) { + let sum = 0.0; + for (let j = 0; j !== numNeighbors; j++) { //printf("Current particle has position %f %f %f\n",objects[id].pos.x(),objects[id].pos.y(),objects[id].pos.z()); p.position.vsub(neighbors[j].position, dist); - var len = dist.length(); - var weight = this.w(len); + const len = dist.length(); + const weight = this.w(len); sum += neighbors[j].mass * weight; } // Save - this.densities[i] = sum; this.pressures[i] = cs * cs * (this.densities[i] - this.density); } // Add forces // Sum to these accelerations - - var a_pressure = SPHSystem_update_a_pressure; - var a_visc = SPHSystem_update_a_visc; - var gradW = SPHSystem_update_gradW; - var r_vec = SPHSystem_update_r_vec; - var u = SPHSystem_update_u; - - for (var _i = 0; _i !== N; _i++) { - var particle = this.particles[_i]; + const a_pressure = SPHSystem_update_a_pressure; + const a_visc = SPHSystem_update_a_visc; + const gradW = SPHSystem_update_gradW; + const r_vec = SPHSystem_update_r_vec; + const u = SPHSystem_update_u; + for (let i = 0; i !== N; i++) { + const particle = this.particles[i]; a_pressure.set(0, 0, 0); a_visc.set(0, 0, 0); // Init vars - var Pij = void 0; - var nabla = void 0; - - var _neighbors = this.neighbors[_i]; - var _numNeighbors = _neighbors.length; //printf("Neighbors: "); + let Pij; + let nabla; + const neighbors = this.neighbors[i]; + const numNeighbors = neighbors.length; //printf("Neighbors: "); - for (var _j = 0; _j !== _numNeighbors; _j++) { - var neighbor = _neighbors[_j]; //printf("%d ",nj); + for (let j = 0; j !== numNeighbors; j++) { + const neighbor = neighbors[j]; //printf("%d ",nj); // Get r once for all.. particle.position.vsub(neighbor.position, r_vec); - var r = r_vec.length(); // Pressure contribution + const r = r_vec.length(); // Pressure contribution - Pij = -neighbor.mass * (this.pressures[_i] / (this.densities[_i] * this.densities[_i] + eps) + this.pressures[_j] / (this.densities[_j] * this.densities[_j] + eps)); + Pij = -neighbor.mass * (this.pressures[i] / (this.densities[i] * this.densities[i] + eps) + this.pressures[j] / (this.densities[j] * this.densities[j] + eps)); this.gradw(r_vec, gradW); // Add to pressure acceleration gradW.scale(Pij, gradW); a_pressure.vadd(gradW, a_pressure); // Viscosity contribution neighbor.velocity.vsub(particle.velocity, u); - u.scale(1.0 / (0.0001 + this.densities[_i] * this.densities[_j]) * this.viscosity * neighbor.mass, u); + u.scale(1.0 / (0.0001 + this.densities[i] * this.densities[j]) * this.viscosity * neighbor.mass, u); nabla = this.nablaw(r); u.scale(nabla, u); // Add to viscosity acceleration a_visc.vadd(u, a_visc); } // Calculate force - a_visc.scale(particle.mass, a_visc); a_pressure.scale(particle.mass, a_pressure); // Add force to particles @@ -8934,46 +7618,41 @@ var SPHSystem = /*#__PURE__*/function () { particle.force.vadd(a_pressure, particle.force); } } // Calculate the weight using the W(r) weightfunction - ; - _proto.w = function w(r) { + w(r) { // 315 - var h = this.smoothingRadius; - return 315.0 / (64.0 * Math.PI * Math.pow(h, 9)) * Math.pow(h * h - r * r, 3); + const h = this.smoothingRadius; + return 315.0 / (64.0 * Math.PI * h ** 9) * (h * h - r * r) ** 3; } // calculate gradient of the weight function - ; - _proto.gradw = function gradw(rVec, resultVec) { - var r = rVec.length(); - var h = this.smoothingRadius; - rVec.scale(945.0 / (32.0 * Math.PI * Math.pow(h, 9)) * Math.pow(h * h - r * r, 2), resultVec); + gradw(rVec, resultVec) { + const r = rVec.length(); + const h = this.smoothingRadius; + rVec.scale(945.0 / (32.0 * Math.PI * h ** 9) * (h * h - r * r) ** 2, resultVec); } // Calculate nabla(W) - ; - _proto.nablaw = function nablaw(r) { - var h = this.smoothingRadius; - var nabla = 945.0 / (32.0 * Math.PI * Math.pow(h, 9)) * (h * h - r * r) * (7 * r * r - 3 * h * h); + nablaw(r) { + const h = this.smoothingRadius; + const nabla = 945.0 / (32.0 * Math.PI * h ** 9) * (h * h - r * r) * (7 * r * r - 3 * h * h); return nabla; - }; - - return SPHSystem; -}(); + } +} /** * Get neighbors within smoothing volume, save in the array neighbors * @method getNeighbors * @param {Body} particle * @param {Array} neighbors */ +exports.SPHSystem = SPHSystem; +const SPHSystem_getNeighbors_dist = new Vec3(); // Temp vectors for calculation -var SPHSystem_getNeighbors_dist = new Vec3(); // Temp vectors for calculation - -var SPHSystem_update_dist = new Vec3(); // Relative velocity +const SPHSystem_update_dist = new Vec3(); // Relative velocity -var SPHSystem_update_a_pressure = new Vec3(); -var SPHSystem_update_a_visc = new Vec3(); -var SPHSystem_update_gradW = new Vec3(); -var SPHSystem_update_r_vec = new Vec3(); -var SPHSystem_update_u = new Vec3(); +const SPHSystem_update_a_pressure = new Vec3(); +const SPHSystem_update_a_visc = new Vec3(); +const SPHSystem_update_gradW = new Vec3(); +const SPHSystem_update_r_vec = new Vec3(); +const SPHSystem_update_u = new Vec3(); /** * @class Cylinder @@ -8986,29 +7665,25 @@ var SPHSystem_update_u = new Vec3(); * @param {Number} numSegments The number of segments to build the cylinder out of */ -var Cylinder = /*#__PURE__*/function (_ConvexPolyhedron) { - _inheritsLoose(Cylinder, _ConvexPolyhedron); - - function Cylinder(radiusTop, radiusBottom, height, numSegments) { - var N = numSegments; - var vertices = []; - var axes = []; - var faces = []; - var bottomface = []; - var topface = []; - var cos = Math.cos; - var sin = Math.sin; // First bottom point +class Cylinder extends ConvexPolyhedron { + constructor(radiusTop, radiusBottom, height, numSegments) { + const N = numSegments; + const vertices = []; + const axes = []; + const faces = []; + const bottomface = []; + const topface = []; + const cos = Math.cos; + const sin = Math.sin; // First bottom point vertices.push(new Vec3(radiusBottom * cos(0), radiusBottom * sin(0), -height * 0.5)); bottomface.push(0); // First top point vertices.push(new Vec3(radiusTop * cos(0), radiusTop * sin(0), height * 0.5)); topface.push(1); - - for (var i = 0; i < N; i++) { - var theta = 2 * Math.PI / N * (i + 1); - var thetaN = 2 * Math.PI / N * (i + 0.5); - + for (let i = 0; i < N; i++) { + const theta = 2 * Math.PI / N * (i + 1); + const thetaN = 2 * Math.PI / N * (i + 0.5); if (i < N - 1) { // Bottom vertices.push(new Vec3(radiusBottom * cos(theta), radiusBottom * sin(theta), -height * 0.5)); @@ -9022,31 +7697,25 @@ var Cylinder = /*#__PURE__*/function (_ConvexPolyhedron) { faces.push([0, 1, 2 * i + 1, 2 * i]); // Connect } // Axis: we can cut off half of them if we have even number of segments - if (N % 2 === 1 || i < N / 2) { axes.push(new Vec3(cos(thetaN), sin(thetaN), 0)); } } - faces.push(topface); axes.push(new Vec3(0, 0, 1)); // Reorder bottom face - var temp = []; - - for (var _i = 0; _i < bottomface.length; _i++) { - temp.push(bottomface[bottomface.length - _i - 1]); + const temp = []; + for (let i = 0; i < bottomface.length; i++) { + temp.push(bottomface[bottomface.length - i - 1]); } - faces.push(temp); - return _ConvexPolyhedron.call(this, { - vertices: vertices, - faces: faces, - axes: axes - }) || this; + super({ + vertices, + faces, + axes + }); } - - return Cylinder; -}(ConvexPolyhedron); +} /** * Particle shape. @@ -9055,13 +7724,12 @@ var Cylinder = /*#__PURE__*/function (_ConvexPolyhedron) { * @author schteppe * @extends Shape */ -var Particle = /*#__PURE__*/function (_Shape) { - _inheritsLoose(Particle, _Shape); - - function Particle() { - return _Shape.call(this, { +exports.Cylinder = Cylinder; +class Particle extends Shape { + constructor() { + super({ type: Shape.types.PARTICLE - }) || this; + }); } /** * @method calculateLocalInertia @@ -9070,34 +7738,22 @@ var Particle = /*#__PURE__*/function (_Shape) { * @return {Vec3} */ - - var _proto = Particle.prototype; - - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { - if (target === void 0) { - target = new Vec3(); - } - + calculateLocalInertia(mass, target = new Vec3()) { target.set(0, 0, 0); return target; - }; - - _proto.volume = function volume() { + } + volume() { return 0; - }; - - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + } + updateBoundingSphereRadius() { this.boundingSphereRadius = 0; - }; - - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { + } + calculateWorldAABB(pos, quat, min, max) { // Get each axis max min.copy(pos); max.copy(pos); - }; - - return Particle; -}(Shape); + } +} /** * A plane, facing in the Z direction. The plane has its surface at z=0 and everything below z=0 is assumed to be solid plane. To make the plane face in some other direction than z, you must put it inside a Body and rotate that body. See the demos. @@ -9106,80 +7762,62 @@ var Particle = /*#__PURE__*/function (_Shape) { * @extends Shape * @author schteppe */ -var Plane = /*#__PURE__*/function (_Shape) { - _inheritsLoose(Plane, _Shape); - - function Plane() { - var _this; - - _this = _Shape.call(this, { +exports.Particle = Particle; +class Plane extends Shape { + constructor() { + super({ type: Shape.types.PLANE - }) || this; // World oriented normal + }); // World oriented normal - _this.worldNormal = new Vec3(); - _this.worldNormalNeedsUpdate = true; - _this.boundingSphereRadius = Number.MAX_VALUE; - return _this; + this.worldNormal = new Vec3(); + this.worldNormalNeedsUpdate = true; + this.boundingSphereRadius = Number.MAX_VALUE; } - - var _proto = Plane.prototype; - - _proto.computeWorldNormal = function computeWorldNormal(quat) { - var n = this.worldNormal; + computeWorldNormal(quat) { + const n = this.worldNormal; n.set(0, 0, 1); quat.vmult(n, n); this.worldNormalNeedsUpdate = false; - }; - - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { - if (target === void 0) { - target = new Vec3(); - } - + } + calculateLocalInertia(mass, target = new Vec3()) { return target; - }; - - _proto.volume = function volume() { - return (// The plane is infinite... + } + volume() { + return ( + // The plane is infinite... Number.MAX_VALUE ); - }; - - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { + } + calculateWorldAABB(pos, quat, min, max) { // The plane AABB is infinite, except if the normal is pointing along any axis tempNormal.set(0, 0, 1); // Default plane normal is z quat.vmult(tempNormal, tempNormal); - var maxVal = Number.MAX_VALUE; + const maxVal = Number.MAX_VALUE; min.set(-maxVal, -maxVal, -maxVal); max.set(maxVal, maxVal, maxVal); - if (tempNormal.x === 1) { max.x = pos.x; } else if (tempNormal.x === -1) { min.x = pos.x; } - if (tempNormal.y === 1) { max.y = pos.y; } else if (tempNormal.y === -1) { min.y = pos.y; } - if (tempNormal.z === 1) { max.z = pos.z; } else if (tempNormal.z === -1) { min.z = pos.z; } - }; - - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + } + updateBoundingSphereRadius() { this.boundingSphereRadius = Number.MAX_VALUE; - }; - - return Plane; -}(Shape); -var tempNormal = new Vec3(); + } +} +exports.Plane = Plane; +const tempNormal = new Vec3(); /** * Heightfield shape class. Height data is given as an array. These data points are spread out evenly with a given distance. @@ -9211,106 +7849,81 @@ var tempNormal = new Vec3(); * heightfieldBody.addShape(heightfieldShape); * world.addBody(heightfieldBody); */ -var Heightfield = /*#__PURE__*/function (_Shape) { - _inheritsLoose(Heightfield, _Shape); - +class Heightfield extends Shape { // An array of numbers, or height values, that are spread out along the x axis. // Max value of the data. // Max value of the data. // The width of each element. To do: elementSizeX and Y - function Heightfield(data, options) { - var _this; - - if (options === void 0) { - options = {}; - } - + constructor(data, options = {}) { options = Utils.defaults(options, { maxValue: null, minValue: null, elementSize: 1 }); - _this = _Shape.call(this, { + super({ type: Shape.types.HEIGHTFIELD - }) || this; - _this.data = data; - _this.maxValue = options.maxValue; - _this.minValue = options.minValue; - _this.elementSize = options.elementSize; - + }); + this.data = data; + this.maxValue = options.maxValue; + this.minValue = options.minValue; + this.elementSize = options.elementSize; if (options.minValue === null) { - _this.updateMinValue(); + this.updateMinValue(); } - if (options.maxValue === null) { - _this.updateMaxValue(); + this.updateMaxValue(); } - - _this.cacheEnabled = true; - _this.pillarConvex = new ConvexPolyhedron(); - _this.pillarOffset = new Vec3(); - - _this.updateBoundingSphereRadius(); // "i_j_isUpper" => { convex: ..., offset: ... } + this.cacheEnabled = true; + this.pillarConvex = new ConvexPolyhedron(); + this.pillarOffset = new Vec3(); + this.updateBoundingSphereRadius(); // "i_j_isUpper" => { convex: ..., offset: ... } // for example: // _cachedPillars["0_2_1"] - - _this._cachedPillars = {}; - return _this; + this._cachedPillars = {}; } /** * Call whenever you change the data array. * @method update */ - - var _proto = Heightfield.prototype; - - _proto.update = function update() { + update() { this._cachedPillars = {}; } /** * Update the .minValue property * @method updateMinValue */ - ; - - _proto.updateMinValue = function updateMinValue() { - var data = this.data; - var minValue = data[0][0]; - - for (var i = 0; i !== data.length; i++) { - for (var j = 0; j !== data[i].length; j++) { - var v = data[i][j]; + updateMinValue() { + const data = this.data; + let minValue = data[0][0]; + for (let i = 0; i !== data.length; i++) { + for (let j = 0; j !== data[i].length; j++) { + const v = data[i][j]; if (v < minValue) { minValue = v; } } } - this.minValue = minValue; } /** * Update the .maxValue property * @method updateMaxValue */ - ; - - _proto.updateMaxValue = function updateMaxValue() { - var data = this.data; - var maxValue = data[0][0]; - - for (var i = 0; i !== data.length; i++) { - for (var j = 0; j !== data[i].length; j++) { - var v = data[i][j]; + updateMaxValue() { + const data = this.data; + let maxValue = data[0][0]; + for (let i = 0; i !== data.length; i++) { + for (let j = 0; j !== data[i].length; j++) { + const v = data[i][j]; if (v > maxValue) { maxValue = v; } } } - this.maxValue = maxValue; } /** @@ -9320,24 +7933,20 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {integer} yi * @param {number} value */ - ; - _proto.setHeightValueAtIndex = function setHeightValueAtIndex(xi, yi, value) { - var data = this.data; + setHeightValueAtIndex(xi, yi, value) { + const data = this.data; data[xi][yi] = value; // Invalidate cache this.clearCachedConvexTrianglePillar(xi, yi, false); - if (xi > 0) { this.clearCachedConvexTrianglePillar(xi - 1, yi, true); this.clearCachedConvexTrianglePillar(xi - 1, yi, false); } - if (yi > 0) { this.clearCachedConvexTrianglePillar(xi, yi - 1, true); this.clearCachedConvexTrianglePillar(xi, yi - 1, false); } - if (yi > 0 && xi > 0) { this.clearCachedConvexTrianglePillar(xi - 1, yi - 1, true); } @@ -9352,28 +7961,20 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {array} [result] An array to store the results in. * @return {array} The result array, if it was passed in. Minimum will be at position 0 and max at 1. */ - ; - - _proto.getRectMinMax = function getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, result) { - if (result === void 0) { - result = []; - } + getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, result = []) { // Get max and min of the data - var data = this.data; // Set first value - - var max = this.minValue; - - for (var i = iMinX; i <= iMaxX; i++) { - for (var j = iMinY; j <= iMaxY; j++) { - var height = data[i][j]; + const data = this.data; // Set first value + let max = this.minValue; + for (let i = iMinX; i <= iMaxX; i++) { + for (let j = iMinY; j <= iMaxY; j++) { + const height = data[i][j]; if (height > max) { max = height; } } } - result[0] = this.minValue; result[1] = max; } @@ -9386,70 +7987,59 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {boolean} clamp If the position should be clamped to the heightfield edge. * @return {boolean} */ - ; - _proto.getIndexOfPosition = function getIndexOfPosition(x, y, result, clamp) { + getIndexOfPosition(x, y, result, clamp) { // Get the index of the data points to test against - var w = this.elementSize; - var data = this.data; - var xi = Math.floor(x / w); - var yi = Math.floor(y / w); + const w = this.elementSize; + const data = this.data; + let xi = Math.floor(x / w); + let yi = Math.floor(y / w); result[0] = xi; result[1] = yi; - if (clamp) { // Clamp index to edges if (xi < 0) { xi = 0; } - if (yi < 0) { yi = 0; } - if (xi >= data.length - 1) { xi = data.length - 1; } - if (yi >= data[0].length - 1) { yi = data[0].length - 1; } } // Bail out if we are out of the terrain - if (xi < 0 || yi < 0 || xi >= data.length - 1 || yi >= data[0].length - 1) { return false; } - return true; - }; - - _proto.getTriangleAt = function getTriangleAt(x, y, edgeClamp, a, b, c) { - var idx = getHeightAt_idx; + } + getTriangleAt(x, y, edgeClamp, a, b, c) { + const idx = getHeightAt_idx; this.getIndexOfPosition(x, y, idx, edgeClamp); - var xi = idx[0]; - var yi = idx[1]; - var data = this.data; - + let xi = idx[0]; + let yi = idx[1]; + const data = this.data; if (edgeClamp) { xi = Math.min(data.length - 2, Math.max(0, xi)); yi = Math.min(data[0].length - 2, Math.max(0, yi)); } - - var elementSize = this.elementSize; - var lowerDist2 = Math.pow(x / elementSize - xi, 2) + Math.pow(y / elementSize - yi, 2); - var upperDist2 = Math.pow(x / elementSize - (xi + 1), 2) + Math.pow(y / elementSize - (yi + 1), 2); - var upper = lowerDist2 > upperDist2; + const elementSize = this.elementSize; + const lowerDist2 = (x / elementSize - xi) ** 2 + (y / elementSize - yi) ** 2; + const upperDist2 = (x / elementSize - (xi + 1)) ** 2 + (y / elementSize - (yi + 1)) ** 2; + const upper = lowerDist2 > upperDist2; this.getTriangle(xi, yi, upper, a, b, c); return upper; - }; - - _proto.getNormalAt = function getNormalAt(x, y, edgeClamp, result) { - var a = getNormalAt_a; - var b = getNormalAt_b; - var c = getNormalAt_c; - var e0 = getNormalAt_e0; - var e1 = getNormalAt_e1; + } + getNormalAt(x, y, edgeClamp, result) { + const a = getNormalAt_a; + const b = getNormalAt_b; + const c = getNormalAt_c; + const e0 = getNormalAt_e0; + const e1 = getNormalAt_e1; this.getTriangleAt(x, y, edgeClamp, a, b, c); b.vsub(a, e0); c.vsub(a, e1); @@ -9462,13 +8052,13 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {number} yi * @param {AABB} result */ - ; - _proto.getAabbAtIndex = function getAabbAtIndex(xi, yi, _ref) { - var lowerBound = _ref.lowerBound, - upperBound = _ref.upperBound; - var data = this.data; - var elementSize = this.elementSize; + getAabbAtIndex(xi, yi, { + lowerBound, + upperBound + }) { + const data = this.data; + const elementSize = this.elementSize; lowerBound.set(xi * elementSize, yi * elementSize, data[xi][yi]); upperBound.set((xi + 1) * elementSize, (yi + 1) * elementSize, data[xi + 1][yi + 1]); } @@ -9479,27 +8069,23 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {boolean} edgeClamp * @return {number} */ - ; - _proto.getHeightAt = function getHeightAt(x, y, edgeClamp) { - var data = this.data; - var a = getHeightAt_a; - var b = getHeightAt_b; - var c = getHeightAt_c; - var idx = getHeightAt_idx; + getHeightAt(x, y, edgeClamp) { + const data = this.data; + const a = getHeightAt_a; + const b = getHeightAt_b; + const c = getHeightAt_c; + const idx = getHeightAt_idx; this.getIndexOfPosition(x, y, idx, edgeClamp); - var xi = idx[0]; - var yi = idx[1]; - + let xi = idx[0]; + let yi = idx[1]; if (edgeClamp) { xi = Math.min(data.length - 2, Math.max(0, xi)); yi = Math.min(data[0].length - 2, Math.max(0, yi)); } - - var upper = this.getTriangleAt(x, y, edgeClamp, a, b, c); + const upper = this.getTriangleAt(x, y, edgeClamp, a, b, c); barycentricWeights(x, y, a.x, a.y, b.x, b.y, c.x, c.y, getHeightAt_weights); - var w = getHeightAt_weights; - + const w = getHeightAt_weights; if (upper) { // Top triangle verts return data[xi + 1][yi + 1] * w.x + data[xi][yi + 1] * w.y + data[xi + 1][yi] * w.z; @@ -9507,24 +8093,20 @@ var Heightfield = /*#__PURE__*/function (_Shape) { // Top triangle verts return data[xi][yi] * w.x + data[xi + 1][yi] * w.y + data[xi][yi + 1] * w.z; } - }; - - _proto.getCacheConvexTrianglePillarKey = function getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle) { + } + getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle) { return xi + "_" + yi + "_" + (getUpperTriangle ? 1 : 0); - }; - - _proto.getCachedConvexTrianglePillar = function getCachedConvexTrianglePillar(xi, yi, getUpperTriangle) { + } + getCachedConvexTrianglePillar(xi, yi, getUpperTriangle) { return this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)]; - }; - - _proto.setCachedConvexTrianglePillar = function setCachedConvexTrianglePillar(xi, yi, getUpperTriangle, convex, offset) { + } + setCachedConvexTrianglePillar(xi, yi, getUpperTriangle, convex, offset) { this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)] = { - convex: convex, - offset: offset + convex, + offset }; - }; - - _proto.clearCachedConvexTrianglePillar = function clearCachedConvexTrianglePillar(xi, yi, getUpperTriangle) { + } + clearCachedConvexTrianglePillar(xi, yi, getUpperTriangle) { delete this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)]; } /** @@ -9536,12 +8118,10 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {Vec3} b * @param {Vec3} c */ - ; - - _proto.getTriangle = function getTriangle(xi, yi, upper, a, b, c) { - var data = this.data; - var elementSize = this.elementSize; + getTriangle(xi, yi, upper, a, b, c) { + const data = this.data; + const elementSize = this.elementSize; if (upper) { // Top triangle verts a.set((xi + 1) * elementSize, (yi + 1) * elementSize, data[xi + 1][yi + 1]); @@ -9561,54 +8141,45 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {integer} j * @param {boolean} getUpperTriangle */ - ; - - _proto.getConvexTrianglePillar = function getConvexTrianglePillar(xi, yi, getUpperTriangle) { - var result = this.pillarConvex; - var offsetResult = this.pillarOffset; + getConvexTrianglePillar(xi, yi, getUpperTriangle) { + let result = this.pillarConvex; + let offsetResult = this.pillarOffset; if (this.cacheEnabled) { - var _data = this.getCachedConvexTrianglePillar(xi, yi, getUpperTriangle); - - if (_data) { - this.pillarConvex = _data.convex; - this.pillarOffset = _data.offset; + const data = this.getCachedConvexTrianglePillar(xi, yi, getUpperTriangle); + if (data) { + this.pillarConvex = data.convex; + this.pillarOffset = data.offset; return; } - result = new ConvexPolyhedron(); offsetResult = new Vec3(); this.pillarConvex = result; this.pillarOffset = offsetResult; } - - var data = this.data; - var elementSize = this.elementSize; - var faces = result.faces; // Reuse verts if possible + const data = this.data; + const elementSize = this.elementSize; + const faces = result.faces; // Reuse verts if possible result.vertices.length = 6; - - for (var i = 0; i < 6; i++) { + for (let i = 0; i < 6; i++) { if (!result.vertices[i]) { result.vertices[i] = new Vec3(); } } // Reuse faces if possible - faces.length = 5; - - for (var _i = 0; _i < 5; _i++) { - if (!faces[_i]) { - faces[_i] = []; + for (let i = 0; i < 5; i++) { + if (!faces[i]) { + faces[i] = []; } } - - var verts = result.vertices; - var h = (Math.min(data[xi][yi], data[xi + 1][yi], data[xi][yi + 1], data[xi + 1][yi + 1]) - this.minValue) / 2 + this.minValue; - + const verts = result.vertices; + const h = (Math.min(data[xi][yi], data[xi + 1][yi], data[xi][yi + 1], data[xi + 1][yi + 1]) - this.minValue) / 2 + this.minValue; if (!getUpperTriangle) { // Center of the triangle pillar - all polygons are given relative to this one - offsetResult.set((xi + 0.25) * elementSize, // sort of center of a triangle + offsetResult.set((xi + 0.25) * elementSize, + // sort of center of a triangle (yi + 0.25) * elementSize, h // vertical center ); // Top triangle verts @@ -9644,7 +8215,8 @@ var Heightfield = /*#__PURE__*/function (_Shape) { faces[4][3] = 1; } else { // Center of the triangle pillar - all polygons are given relative to this one - offsetResult.set((xi + 0.75) * elementSize, // sort of center of a triangle + offsetResult.set((xi + 0.75) * elementSize, + // sort of center of a triangle (yi + 0.75) * elementSize, h // vertical center ); // Top triangle verts @@ -9679,38 +8251,30 @@ var Heightfield = /*#__PURE__*/function (_Shape) { faces[4][2] = 5; faces[4][3] = 2; } - result.computeNormals(); result.computeEdges(); result.updateBoundingSphereRadius(); this.setCachedConvexTrianglePillar(xi, yi, getUpperTriangle, result, offsetResult); - }; - - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { - if (target === void 0) { - target = new Vec3(); - } - + } + calculateLocalInertia(mass, target = new Vec3()) { target.set(0, 0, 0); return target; - }; - - _proto.volume = function volume() { - return (// The terrain is infinite + } + volume() { + return ( + // The terrain is infinite Number.MAX_VALUE ); - }; - - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { + } + calculateWorldAABB(pos, quat, min, max) { // TODO: do it properly min.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE); max.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE); - }; - - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + } + updateBoundingSphereRadius() { // Use the bounding box of the min/max values - var data = this.data; - var s = this.elementSize; + const data = this.data; + const s = this.elementSize; this.boundingSphereRadius = new Vec3(data.length * s, data[0].length * s, Math.max(Math.abs(this.maxValue), Math.abs(this.minValue))).length(); } /** @@ -9719,62 +8283,57 @@ var Heightfield = /*#__PURE__*/function (_Shape) { * @param {Image} image * @param {Vec3} scale */ - ; - _proto.setHeightsFromImage = function setHeightsFromImage(image, scale) { - var x = scale.x, - z = scale.z, - y = scale.y; - var canvas = document.createElement('canvas'); + setHeightsFromImage(image, scale) { + const { + x, + z, + y + } = scale; + const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; - var context = canvas.getContext('2d'); + const context = canvas.getContext('2d'); context.drawImage(image, 0, 0); - var imageData = context.getImageData(0, 0, image.width, image.height); - var matrix = this.data; + const imageData = context.getImageData(0, 0, image.width, image.height); + const matrix = this.data; matrix.length = 0; this.elementSize = Math.abs(x) / imageData.width; - - for (var i = 0; i < imageData.height; i++) { - var row = []; - - for (var j = 0; j < imageData.width; j++) { - var a = imageData.data[(i * imageData.height + j) * 4]; - var b = imageData.data[(i * imageData.height + j) * 4 + 1]; - var c = imageData.data[(i * imageData.height + j) * 4 + 2]; - var height = (a + b + c) / 4 / 255 * z; - + for (let i = 0; i < imageData.height; i++) { + const row = []; + for (let j = 0; j < imageData.width; j++) { + const a = imageData.data[(i * imageData.height + j) * 4]; + const b = imageData.data[(i * imageData.height + j) * 4 + 1]; + const c = imageData.data[(i * imageData.height + j) * 4 + 2]; + const height = (a + b + c) / 4 / 255 * z; if (x < 0) { row.push(height); } else { row.unshift(height); } } - if (y < 0) { matrix.unshift(row); } else { matrix.push(row); } } - this.updateMaxValue(); this.updateMinValue(); this.update(); - }; - - return Heightfield; -}(Shape); -var getHeightAt_idx = []; -var getHeightAt_weights = new Vec3(); -var getHeightAt_a = new Vec3(); -var getHeightAt_b = new Vec3(); -var getHeightAt_c = new Vec3(); -var getNormalAt_a = new Vec3(); -var getNormalAt_b = new Vec3(); -var getNormalAt_c = new Vec3(); -var getNormalAt_e0 = new Vec3(); -var getNormalAt_e1 = new Vec3(); // from https://en.wikipedia.org/wiki/Barycentric_coordinate_system + } +} +exports.Heightfield = Heightfield; +const getHeightAt_idx = []; +const getHeightAt_weights = new Vec3(); +const getHeightAt_a = new Vec3(); +const getHeightAt_b = new Vec3(); +const getHeightAt_c = new Vec3(); +const getNormalAt_a = new Vec3(); +const getNormalAt_b = new Vec3(); +const getNormalAt_c = new Vec3(); +const getNormalAt_e0 = new Vec3(); +const getNormalAt_e1 = new Vec3(); // from https://en.wikipedia.org/wiki/Barycentric_coordinate_system function barycentricWeights(x, y, ax, ay, bx, by, cx, cy, result) { result.x = ((by - cy) * (x - cx) + (cx - bx) * (y - cy)) / ((by - cy) * (ax - cx) + (cx - bx) * (ay - cy)); @@ -9789,25 +8348,18 @@ function barycentricWeights(x, y, ax, ay, bx, by, cx, cy, result) { * @param {Octree} [options.root] * @param {AABB} [options.aabb] */ -var OctreeNode = /*#__PURE__*/function () { +class OctreeNode { // The root node // Boundary of this node // Contained data at the current node level // Children to this node - function OctreeNode(options) { - if (options === void 0) { - options = {}; - } - + constructor(options = {}) { this.root = options.root || null; this.aabb = options.aabb ? options.aabb.clone() : new AABB(); this.data = []; this.children = []; } - - var _proto = OctreeNode.prototype; - - _proto.reset = function reset() { + reset() { this.children.length = this.data.length = 0; } /** @@ -9817,45 +8369,35 @@ var OctreeNode = /*#__PURE__*/function () { * @param {object} elementData * @return {boolean} True if successful, otherwise false */ - ; - _proto.insert = function insert(aabb, elementData, level) { - if (level === void 0) { - level = 0; - } - - var nodeData = this.data; // Ignore objects that do not belong in this node + insert(aabb, elementData, level = 0) { + const nodeData = this.data; // Ignore objects that do not belong in this node if (!this.aabb.contains(aabb)) { return false; // object cannot be added } - var children = this.children; - var maxDepth = this.maxDepth || this.root.maxDepth; - + const children = this.children; + const maxDepth = this.maxDepth || this.root.maxDepth; if (level < maxDepth) { // Subdivide if there are no children yet - var subdivided = false; - + let subdivided = false; if (!children.length) { this.subdivide(); subdivided = true; } // add to whichever node will accept it - - for (var i = 0; i !== 8; i++) { + for (let i = 0; i !== 8; i++) { if (children[i].insert(aabb, elementData, level + 1)) { return true; } } - if (subdivided) { // No children accepted! Might as well just remove em since they contain none children.length = 0; } } // Too deep, or children didnt want it. add it in current node - nodeData.push(elementData); return true; } @@ -9863,13 +8405,12 @@ var OctreeNode = /*#__PURE__*/function () { * Create 8 equally sized children nodes and put them in the .children array. * @method subdivide */ - ; - _proto.subdivide = function subdivide() { - var aabb = this.aabb; - var l = aabb.lowerBound; - var u = aabb.upperBound; - var children = this.children; + subdivide() { + const aabb = this.aabb; + const l = aabb.lowerBound; + const u = aabb.upperBound; + const children = this.children; children.push(new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(0, 0, 0) @@ -9905,14 +8446,13 @@ var OctreeNode = /*#__PURE__*/function () { })); u.vsub(l, halfDiagonal); halfDiagonal.scale(0.5, halfDiagonal); - var root = this.root || this; - - for (var i = 0; i !== 8; i++) { - var child = children[i]; // Set current node as root + const root = this.root || this; + for (let i = 0; i !== 8; i++) { + const child = children[i]; // Set current node as root child.root = root; // Compute bounds - var lowerBound = child.aabb.lowerBound; + const lowerBound = child.aabb.lowerBound; lowerBound.x *= halfDiagonal.x; lowerBound.y *= halfDiagonal.y; lowerBound.z *= halfDiagonal.z; @@ -9928,10 +8468,9 @@ var OctreeNode = /*#__PURE__*/function () { * @param {array} result * @return {array} The "result" object */ - ; - _proto.aabbQuery = function aabbQuery(aabb, result) { - var nodeData = this.data; // abort if the range does not intersect this node + aabbQuery(aabb, result) { + const nodeData = this.data; // abort if the range does not intersect this node // if (!this.aabb.overlaps(aabb)){ // return result; // } @@ -9940,22 +8479,18 @@ var OctreeNode = /*#__PURE__*/function () { // Add child data // @todo unwrap recursion into a queue / loop, that's faster in JS - var children = this.children; // for (let i = 0, N = this.children.length; i !== N; i++) { + const children = this.children; // for (let i = 0, N = this.children.length; i !== N; i++) { // children[i].aabbQuery(aabb, result); // } - var queue = [this]; - + const queue = [this]; while (queue.length) { - var node = queue.pop(); - + const node = queue.pop(); if (node.aabb.overlaps(aabb)) { Array.prototype.push.apply(result, node.data); } - Array.prototype.push.apply(queue, node.children); } - return result; } /** @@ -9966,9 +8501,8 @@ var OctreeNode = /*#__PURE__*/function () { * @param {array} result * @return {array} The "result" object */ - ; - _proto.rayQuery = function rayQuery(ray, treeTransform, result) { + rayQuery(ray, treeTransform, result) { // Use aabb query for now. // @todo implement real ray query which needs less lookups ray.getAABB(tmpAABB$1); @@ -9979,20 +8513,16 @@ var OctreeNode = /*#__PURE__*/function () { /** * @method removeEmptyNodes */ - ; - _proto.removeEmptyNodes = function removeEmptyNodes() { - for (var i = this.children.length - 1; i >= 0; i--) { + removeEmptyNodes() { + for (let i = this.children.length - 1; i >= 0; i--) { this.children[i].removeEmptyNodes(); - if (!this.children[i].children.length && !this.children[i].data.length) { this.children.splice(i, 1); } } - }; - - return OctreeNode; -}(); + } +} /** * @class Octree * @param {AABB} aabb The total AABB of the tree @@ -10001,30 +8531,18 @@ var OctreeNode = /*#__PURE__*/function () { * @extends OctreeNode */ - -var Octree = /*#__PURE__*/function (_OctreeNode) { - _inheritsLoose(Octree, _OctreeNode); - +class Octree extends OctreeNode { // Maximum subdivision depth - function Octree(aabb, options) { - var _this; - - if (options === void 0) { - options = {}; - } - - _this = _OctreeNode.call(this, { + constructor(aabb, options = {}) { + super({ root: null, - aabb: aabb - }) || this; - _this.maxDepth = typeof options.maxDepth !== 'undefined' ? options.maxDepth : 8; - return _this; + aabb + }); + this.maxDepth = typeof options.maxDepth !== 'undefined' ? options.maxDepth : 8; } - - return Octree; -}(OctreeNode); -var halfDiagonal = new Vec3(); -var tmpAABB$1 = new AABB(); +} +const halfDiagonal = new Vec3(); +const tmpAABB$1 = new AABB(); /** * @class Trimesh @@ -10044,53 +8562,39 @@ var tmpAABB$1 = new AABB(); * ]; * const trimeshShape = new Trimesh(vertices, indices); */ -var Trimesh = /*#__PURE__*/function (_Shape) { - _inheritsLoose(Trimesh, _Shape); - +class Trimesh extends Shape { // Array of integers, indicating which vertices each triangle consists of. The length of this array is thus 3 times the number of triangles. // The normals data. // The local AABB of the mesh. // References to vertex pairs, making up all unique edges in the trimesh. // Local scaling of the mesh. Use .setScale() to set it. // The indexed triangles. Use .updateTree() to update it. - function Trimesh(vertices, indices) { - var _this; - - _this = _Shape.call(this, { + constructor(vertices, indices) { + super({ type: Shape.types.TRIMESH - }) || this; - _this.vertices = new Float32Array(vertices); - _this.indices = new Int16Array(indices); - _this.normals = new Float32Array(indices.length); - _this.aabb = new AABB(); - _this.edges = null; - _this.scale = new Vec3(1, 1, 1); - _this.tree = new Octree(); - - _this.updateEdges(); - - _this.updateNormals(); - - _this.updateAABB(); - - _this.updateBoundingSphereRadius(); - - _this.updateTree(); - - return _this; + }); + this.vertices = new Float32Array(vertices); + this.indices = new Int16Array(indices); + this.normals = new Float32Array(indices.length); + this.aabb = new AABB(); + this.edges = null; + this.scale = new Vec3(1, 1, 1); + this.tree = new Octree(); + this.updateEdges(); + this.updateNormals(); + this.updateAABB(); + this.updateBoundingSphereRadius(); + this.updateTree(); } /** * @method updateTree */ - - var _proto = Trimesh.prototype; - - _proto.updateTree = function updateTree() { - var tree = this.tree; + updateTree() { + const tree = this.tree; tree.reset(); tree.aabb.copy(this.aabb); - var scale = this.scale; // The local mesh AABB is scaled, but the octree AABB should be unscaled + const scale = this.scale; // The local mesh AABB is scaled, but the octree AABB should be unscaled tree.aabb.lowerBound.x *= 1 / scale.x; tree.aabb.lowerBound.y *= 1 / scale.y; @@ -10099,27 +8603,21 @@ var Trimesh = /*#__PURE__*/function (_Shape) { tree.aabb.upperBound.y *= 1 / scale.y; tree.aabb.upperBound.z *= 1 / scale.z; // Insert all triangles - var triangleAABB = new AABB(); - var a = new Vec3(); - var b = new Vec3(); - var c = new Vec3(); - var points = [a, b, c]; - - for (var i = 0; i < this.indices.length / 3; i++) { + const triangleAABB = new AABB(); + const a = new Vec3(); + const b = new Vec3(); + const c = new Vec3(); + const points = [a, b, c]; + for (let i = 0; i < this.indices.length / 3; i++) { //this.getTriangleVertices(i, a, b, c); // Get unscaled triangle verts - var i3 = i * 3; - + const i3 = i * 3; this._getUnscaledVertex(this.indices[i3], a); - this._getUnscaledVertex(this.indices[i3 + 1], b); - this._getUnscaledVertex(this.indices[i3 + 2], c); - triangleAABB.setFromPoints(points); tree.insert(triangleAABB, i); } - tree.removeEmptyNodes(); } /** @@ -10128,17 +8626,16 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {AABB} aabb * @param {array} result An array of integers, referencing the queried triangles. */ - ; - _proto.getTrianglesInAABB = function getTrianglesInAABB(aabb, result) { + getTrianglesInAABB(aabb, result) { unscaledAABB.copy(aabb); // Scale it to local - var scale = this.scale; - var isx = scale.x; - var isy = scale.y; - var isz = scale.z; - var l = unscaledAABB.lowerBound; - var u = unscaledAABB.upperBound; + const scale = this.scale; + const isx = scale.x; + const isy = scale.y; + const isz = scale.z; + const l = unscaledAABB.lowerBound; + const u = unscaledAABB.upperBound; l.x /= isx; l.y /= isy; l.z /= isz; @@ -10151,17 +8648,14 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @method setScale * @param {Vec3} scale */ - ; - - _proto.setScale = function setScale(scale) { - var wasUniform = this.scale.x === this.scale.y && this.scale.y === this.scale.z; - var isUniform = scale.x === scale.y && scale.y === scale.z; + setScale(scale) { + const wasUniform = this.scale.x === this.scale.y && this.scale.y === this.scale.z; + const isUniform = scale.x === scale.y && scale.y === scale.z; if (!(wasUniform && isUniform)) { // Non-uniform scaling. Need to update normals. this.updateNormals(); } - this.scale.copy(scale); this.updateAABB(); this.updateBoundingSphereRadius(); @@ -10170,18 +8664,16 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * Compute the normals of the faces. Will save in the .normals array. * @method updateNormals */ - ; - _proto.updateNormals = function updateNormals() { - var n = computeNormals_n; // Generate normals + updateNormals() { + const n = computeNormals_n; // Generate normals - var normals = this.normals; - - for (var i = 0; i < this.indices.length / 3; i++) { - var i3 = i * 3; - var a = this.indices[i3]; - var b = this.indices[i3 + 1]; - var c = this.indices[i3 + 2]; + const normals = this.normals; + for (let i = 0; i < this.indices.length / 3; i++) { + const i3 = i * 3; + const a = this.indices[i3]; + const b = this.indices[i3 + 1]; + const c = this.indices[i3 + 2]; this.getVertex(a, va); this.getVertex(b, vb); this.getVertex(c, vc); @@ -10195,34 +8687,28 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * Update the .edges property * @method updateEdges */ - ; - - _proto.updateEdges = function updateEdges() { - var edges = {}; - var add = function add(a, b) { - var key = a < b ? a + "_" + b : b + "_" + a; + updateEdges() { + const edges = {}; + const add = (a, b) => { + const key = a < b ? a + "_" + b : b + "_" + a; edges[key] = true; }; - - for (var i = 0; i < this.indices.length / 3; i++) { - var i3 = i * 3; - var a = this.indices[i3]; - var b = this.indices[i3 + 1]; - var c = this.indices[i3 + 2]; + for (let i = 0; i < this.indices.length / 3; i++) { + const i3 = i * 3; + const a = this.indices[i3]; + const b = this.indices[i3 + 1]; + const c = this.indices[i3 + 2]; add(a, b); add(b, c); add(c, a); } - - var keys = Object.keys(edges); + const keys = Object.keys(edges); this.edges = new Int16Array(keys.length * 2); - - for (var _i = 0; _i < keys.length; _i++) { - var indices = keys[_i].split('_'); - - this.edges[2 * _i] = parseInt(indices[0], 10); - this.edges[2 * _i + 1] = parseInt(indices[1], 10); + for (let i = 0; i < keys.length; i++) { + const indices = keys[i].split('_'); + this.edges[2 * i] = parseInt(indices[0], 10); + this.edges[2 * i + 1] = parseInt(indices[1], 10); } } /** @@ -10232,10 +8718,9 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {number} firstOrSecond 0 or 1, depending on which one of the vertices you need. * @param {Vec3} vertexStore Where to store the result */ - ; - _proto.getEdgeVertex = function getEdgeVertex(edgeIndex, firstOrSecond, vertexStore) { - var vertexIndex = this.edges[edgeIndex * 2 + (firstOrSecond ? 1 : 0)]; + getEdgeVertex(edgeIndex, firstOrSecond, vertexStore) { + const vertexIndex = this.edges[edgeIndex * 2 + (firstOrSecond ? 1 : 0)]; this.getVertex(vertexIndex, vertexStore); } /** @@ -10244,11 +8729,10 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {number} edgeIndex * @param {Vec3} vectorStore */ - ; - _proto.getEdgeVector = function getEdgeVector(edgeIndex, vectorStore) { - var va = getEdgeVector_va; - var vb = getEdgeVector_vb; + getEdgeVector(edgeIndex, vectorStore) { + const va = getEdgeVector_va; + const vb = getEdgeVector_vb; this.getEdgeVertex(edgeIndex, 0, va); this.getEdgeVertex(edgeIndex, 1, vb); vb.vsub(va, vectorStore); @@ -10260,13 +8744,10 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {Vec3} out * @return {Vec3} The "out" vector object */ - ; - - _proto.getVertex = function getVertex(i, out) { - var scale = this.scale; + getVertex(i, out) { + const scale = this.scale; this._getUnscaledVertex(i, out); - out.x *= scale.x; out.y *= scale.y; out.z *= scale.z; @@ -10280,11 +8761,10 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {Vec3} out * @return {Vec3} The "out" vector object */ - ; - _proto._getUnscaledVertex = function _getUnscaledVertex(i, out) { - var i3 = i * 3; - var vertices = this.vertices; + _getUnscaledVertex(i, out) { + const i3 = i * 3; + const vertices = this.vertices; return out.set(vertices[i3], vertices[i3 + 1], vertices[i3 + 2]); } /** @@ -10296,9 +8776,8 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {Vec3} out * @return {Vec3} The "out" vector object */ - ; - _proto.getWorldVertex = function getWorldVertex(i, pos, quat, out) { + getWorldVertex(i, pos, quat, out) { this.getVertex(i, out); Transform.pointToWorldFrame(pos, quat, out, out); return out; @@ -10311,10 +8790,9 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {Vec3} b * @param {Vec3} c */ - ; - _proto.getTriangleVertices = function getTriangleVertices(i, a, b, c) { - var i3 = i * 3; + getTriangleVertices(i, a, b, c) { + const i3 = i * 3; this.getVertex(this.indices[i3], a); this.getVertex(this.indices[i3 + 1], b); this.getVertex(this.indices[i3 + 2], c); @@ -10326,10 +8804,9 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {Vec3} target * @return {Vec3} The "target" vector object */ - ; - _proto.getNormal = function getNormal(i, target) { - var i3 = i * 3; + getNormal(i, target) { + const i3 = i * 3; return target.set(this.normals[i3], this.normals[i3 + 1], this.normals[i3 + 2]); } /** @@ -10338,15 +8815,14 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {Vec3} target * @return {Vec3} The "target" vector object */ - ; - _proto.calculateLocalInertia = function calculateLocalInertia(mass, target) { + calculateLocalInertia(mass, target) { // Approximate with box inertia // Exact inertia calculation is overkill, but see http://geometrictools.com/Documentation/PolyhedralMassProperties.pdf for the correct way to do it this.computeLocalAABB(cli_aabb); - var x = cli_aabb.upperBound.x - cli_aabb.lowerBound.x; - var y = cli_aabb.upperBound.y - cli_aabb.lowerBound.y; - var z = cli_aabb.upperBound.z - cli_aabb.lowerBound.z; + const x = cli_aabb.upperBound.x - cli_aabb.lowerBound.x; + const y = cli_aabb.upperBound.y - cli_aabb.lowerBound.y; + const z = cli_aabb.upperBound.z - cli_aabb.lowerBound.z; return target.set(1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * z * 2 * z), 1.0 / 12.0 * mass * (2 * x * 2 * x + 2 * z * 2 * z), 1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * x * 2 * x)); } /** @@ -10354,33 +8830,28 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @method computeLocalAABB * @param {AABB} aabb */ - ; - _proto.computeLocalAABB = function computeLocalAABB(aabb) { - var l = aabb.lowerBound; - var u = aabb.upperBound; - var n = this.vertices.length; - var vertices = this.vertices; - var v = computeLocalAABB_worldVert; + computeLocalAABB(aabb) { + const l = aabb.lowerBound; + const u = aabb.upperBound; + const n = this.vertices.length; + const vertices = this.vertices; + const v = computeLocalAABB_worldVert; this.getVertex(0, v); l.copy(v); u.copy(v); - - for (var i = 0; i !== n; i++) { + for (let i = 0; i !== n; i++) { this.getVertex(i, v); - if (v.x < l.x) { l.x = v.x; } else if (v.x > u.x) { u.x = v.x; } - if (v.y < l.y) { l.y = v.y; } else if (v.y > u.y) { u.y = v.y; } - if (v.z < l.z) { l.z = v.z; } else if (v.z > u.z) { @@ -10392,32 +8863,27 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * Update the .aabb property * @method updateAABB */ - ; - _proto.updateAABB = function updateAABB() { + updateAABB() { this.computeLocalAABB(this.aabb); } /** * Will update the .boundingSphereRadius property * @method updateBoundingSphereRadius */ - ; - _proto.updateBoundingSphereRadius = function updateBoundingSphereRadius() { + updateBoundingSphereRadius() { // Assume points are distributed with local (0,0,0) as center - var max2 = 0; - var vertices = this.vertices; - var v = new Vec3(); - - for (var i = 0, N = vertices.length / 3; i !== N; i++) { + let max2 = 0; + const vertices = this.vertices; + const v = new Vec3(); + for (let i = 0, N = vertices.length / 3; i !== N; i++) { this.getVertex(i, v); - var norm2 = v.lengthSquared(); - + const norm2 = v.lengthSquared(); if (norm2 > max2) { max2 = norm2; } } - this.boundingSphereRadius = Math.sqrt(max2); } /** @@ -10427,9 +8893,8 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @param {Vec3} min * @param {Vec3} max */ - ; - _proto.calculateWorldAABB = function calculateWorldAABB(pos, quat, min, max) { + calculateWorldAABB(pos, quat, min, max) { /* const n = this.vertices.length / 3, verts = this.vertices; @@ -10459,8 +8924,8 @@ var Trimesh = /*#__PURE__*/function (_Shape) { max.set(maxx,maxy,maxz); */ // Faster approximation using local AABB - var frame = calculateWorldAABB_frame; - var result = calculateWorldAABB_aabb; + const frame = calculateWorldAABB_frame; + const result = calculateWorldAABB_aabb; frame.position = pos; frame.quaternion = quat; this.aabb.toWorldFrame(frame, result); @@ -10472,18 +8937,16 @@ var Trimesh = /*#__PURE__*/function (_Shape) { * @method volume * @return {Number} */ - ; - _proto.volume = function volume() { + volume() { return 4.0 * Math.PI * this.boundingSphereRadius / 3.0; - }; - - return Trimesh; -}(Shape); -var computeNormals_n = new Vec3(); -var unscaledAABB = new AABB(); -var getEdgeVector_va = new Vec3(); -var getEdgeVector_vb = new Vec3(); + } +} +exports.Trimesh = Trimesh; +const computeNormals_n = new Vec3(); +const unscaledAABB = new AABB(); +const getEdgeVector_va = new Vec3(); +const getEdgeVector_vb = new Vec3(); /** * Get face normal given 3 vertices * @static @@ -10494,26 +8957,23 @@ var getEdgeVector_vb = new Vec3(); * @param {Vec3} target */ -var cb = new Vec3(); -var ab = new Vec3(); - -Trimesh.computeNormal = function (va, vb, vc, target) { +const cb = new Vec3(); +const ab = new Vec3(); +Trimesh.computeNormal = (va, vb, vc, target) => { vb.vsub(va, ab); vc.vsub(vb, cb); cb.cross(ab, target); - if (!target.isZero()) { target.normalize(); } }; - -var va = new Vec3(); -var vb = new Vec3(); -var vc = new Vec3(); -var cli_aabb = new AABB(); -var computeLocalAABB_worldVert = new Vec3(); -var calculateWorldAABB_frame = new Transform(); -var calculateWorldAABB_aabb = new AABB(); +const va = new Vec3(); +const vb = new Vec3(); +const vc = new Vec3(); +const cli_aabb = new AABB(); +const computeLocalAABB_worldVert = new Vec3(); +const calculateWorldAABB_frame = new Transform(); +const calculateWorldAABB_aabb = new AABB(); /** * Create a Trimesh instance, shaped as a torus. * @static @@ -10526,52 +8986,29 @@ var calculateWorldAABB_aabb = new AABB(); * @return {Trimesh} A torus */ -Trimesh.createTorus = function (radius, tube, radialSegments, tubularSegments, arc) { - if (radius === void 0) { - radius = 1; - } - - if (tube === void 0) { - tube = 0.5; - } - - if (radialSegments === void 0) { - radialSegments = 8; - } - - if (tubularSegments === void 0) { - tubularSegments = 6; - } - - if (arc === void 0) { - arc = Math.PI * 2; - } - - var vertices = []; - var indices = []; - - for (var j = 0; j <= radialSegments; j++) { - for (var i = 0; i <= tubularSegments; i++) { - var u = i / tubularSegments * arc; - var v = j / radialSegments * Math.PI * 2; - var x = (radius + tube * Math.cos(v)) * Math.cos(u); - var y = (radius + tube * Math.cos(v)) * Math.sin(u); - var z = tube * Math.sin(v); +Trimesh.createTorus = (radius = 1, tube = 0.5, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2) => { + const vertices = []; + const indices = []; + for (let j = 0; j <= radialSegments; j++) { + for (let i = 0; i <= tubularSegments; i++) { + const u = i / tubularSegments * arc; + const v = j / radialSegments * Math.PI * 2; + const x = (radius + tube * Math.cos(v)) * Math.cos(u); + const y = (radius + tube * Math.cos(v)) * Math.sin(u); + const z = tube * Math.sin(v); vertices.push(x, y, z); } } - - for (var _j = 1; _j <= radialSegments; _j++) { - for (var _i2 = 1; _i2 <= tubularSegments; _i2++) { - var a = (tubularSegments + 1) * _j + _i2 - 1; - var b = (tubularSegments + 1) * (_j - 1) + _i2 - 1; - var c = (tubularSegments + 1) * (_j - 1) + _i2; - var d = (tubularSegments + 1) * _j + _i2; + for (let j = 1; j <= radialSegments; j++) { + for (let i = 1; i <= tubularSegments; i++) { + const a = (tubularSegments + 1) * j + i - 1; + const b = (tubularSegments + 1) * (j - 1) + i - 1; + const c = (tubularSegments + 1) * (j - 1) + i; + const d = (tubularSegments + 1) * j + i; indices.push(a, b, d); indices.push(b, c, d); } } - return new Trimesh(vertices, indices); }; @@ -10581,9 +9018,9 @@ Trimesh.createTorus = function (radius, tube, radialSegments, tubularSegments, a * @constructor * @author schteppe / https://github.com/schteppe */ -var Solver = /*#__PURE__*/function () { +class Solver { // All equations to be solved - function Solver() { + constructor() { this.equations = []; } /** @@ -10594,11 +9031,9 @@ var Solver = /*#__PURE__*/function () { * @return {Number} number of iterations performed */ - - var _proto = Solver.prototype; - - _proto.solve = function solve(dt, world) { - return (// Should return the number of iterations done! + solve(dt, world) { + return ( + // Should return the number of iterations done! 0 ); } @@ -10607,9 +9042,8 @@ var Solver = /*#__PURE__*/function () { * @method addEquation * @param {Equation} eq */ - ; - _proto.addEquation = function addEquation(eq) { + addEquation(eq) { if (eq.enabled) { this.equations.push(eq); } @@ -10619,12 +9053,10 @@ var Solver = /*#__PURE__*/function () { * @method removeEquation * @param {Equation} eq */ - ; - - _proto.removeEquation = function removeEquation(eq) { - var eqs = this.equations; - var i = eqs.indexOf(eq); + removeEquation(eq) { + const eqs = this.equations; + const i = eqs.indexOf(eq); if (i !== -1) { eqs.splice(i, 1); } @@ -10633,14 +9065,11 @@ var Solver = /*#__PURE__*/function () { * Add all equations * @method removeAllEquations */ - ; - _proto.removeAllEquations = function removeAllEquations() { + removeAllEquations() { this.equations.length = 0; - }; - - return Solver; -}(); + } +} /** * Constraint equation Gauss-Seidel solver. @@ -10651,18 +9080,14 @@ var Solver = /*#__PURE__*/function () { * @see https://www8.cs.umu.se/kurser/5DV058/VT09/lectures/spooknotes.pdf * @extends Solver */ -var GSSolver = /*#__PURE__*/function (_Solver) { - _inheritsLoose(GSSolver, _Solver); - +exports.Solver = Solver; +class GSSolver extends Solver { // The number of solver iterations determines quality of the constraints in the world. The more iterations, the more correct simulation. More iterations need more computations though. If you have a large gravity force in your world, you will need more iterations. // When tolerance is reached, the system is assumed to be converged. - function GSSolver() { - var _this; - - _this = _Solver.call(this) || this; - _this.iterations = 10; - _this.tolerance = 1e-7; - return _this; + constructor() { + super(); + this.iterations = 10; + this.tolerance = 1e-7; } /** * Solve @@ -10672,121 +9097,102 @@ var GSSolver = /*#__PURE__*/function (_Solver) { * @return {Number} number of iterations performed */ - - var _proto = GSSolver.prototype; - - _proto.solve = function solve(dt, world) { - var iter = 0; - var maxIter = this.iterations; - var tolSquared = this.tolerance * this.tolerance; - var equations = this.equations; - var Neq = equations.length; - var bodies = world.bodies; - var Nbodies = bodies.length; - var h = dt; - var B; - var invC; - var deltalambda; - var deltalambdaTot; - var GWlambda; - var lambdaj; // Update solve mass + solve(dt, world) { + let iter = 0; + const maxIter = this.iterations; + const tolSquared = this.tolerance * this.tolerance; + const equations = this.equations; + const Neq = equations.length; + const bodies = world.bodies; + const Nbodies = bodies.length; + const h = dt; + let B; + let invC; + let deltalambda; + let deltalambdaTot; + let GWlambda; + let lambdaj; // Update solve mass if (Neq !== 0) { - for (var i = 0; i !== Nbodies; i++) { + for (let i = 0; i !== Nbodies; i++) { bodies[i].updateSolveMassProperties(); } } // Things that does not change during iteration can be computed once - - var invCs = GSSolver_solve_invCs; - var Bs = GSSolver_solve_Bs; - var lambda = GSSolver_solve_lambda; + const invCs = GSSolver_solve_invCs; + const Bs = GSSolver_solve_Bs; + const lambda = GSSolver_solve_lambda; invCs.length = Neq; Bs.length = Neq; lambda.length = Neq; - - for (var _i = 0; _i !== Neq; _i++) { - var c = equations[_i]; - lambda[_i] = 0.0; - Bs[_i] = c.computeB(h); - invCs[_i] = 1.0 / c.computeC(); + for (let i = 0; i !== Neq; i++) { + const c = equations[i]; + lambda[i] = 0.0; + Bs[i] = c.computeB(h); + invCs[i] = 1.0 / c.computeC(); } - if (Neq !== 0) { // Reset vlambda - for (var _i2 = 0; _i2 !== Nbodies; _i2++) { - var b = bodies[_i2]; - var vlambda = b.vlambda; - var wlambda = b.wlambda; + for (let i = 0; i !== Nbodies; i++) { + const b = bodies[i]; + const vlambda = b.vlambda; + const wlambda = b.wlambda; vlambda.set(0, 0, 0); wlambda.set(0, 0, 0); } // Iterate over equations - for (iter = 0; iter !== maxIter; iter++) { // Accumulate the total error for each iteration. deltalambdaTot = 0.0; - - for (var j = 0; j !== Neq; j++) { - var _c = equations[j]; // Compute iteration + for (let j = 0; j !== Neq; j++) { + const c = equations[j]; // Compute iteration B = Bs[j]; invC = invCs[j]; lambdaj = lambda[j]; - GWlambda = _c.computeGWlambda(); - deltalambda = invC * (B - GWlambda - _c.eps * lambdaj); // Clamp if we are not within the min/max interval + GWlambda = c.computeGWlambda(); + deltalambda = invC * (B - GWlambda - c.eps * lambdaj); // Clamp if we are not within the min/max interval - if (lambdaj + deltalambda < _c.minForce) { - deltalambda = _c.minForce - lambdaj; - } else if (lambdaj + deltalambda > _c.maxForce) { - deltalambda = _c.maxForce - lambdaj; + if (lambdaj + deltalambda < c.minForce) { + deltalambda = c.minForce - lambdaj; + } else if (lambdaj + deltalambda > c.maxForce) { + deltalambda = c.maxForce - lambdaj; } - lambda[j] += deltalambda; deltalambdaTot += deltalambda > 0.0 ? deltalambda : -deltalambda; // abs(deltalambda) - _c.addToWlambda(deltalambda); + c.addToWlambda(deltalambda); } // If the total error is small enough - stop iterate - if (deltalambdaTot * deltalambdaTot < tolSquared) { break; } } // Add result to velocity - - for (var _i3 = 0; _i3 !== Nbodies; _i3++) { - var _b = bodies[_i3]; - var v = _b.velocity; - var w = _b.angularVelocity; - - _b.vlambda.vmul(_b.linearFactor, _b.vlambda); - - v.vadd(_b.vlambda, v); - - _b.wlambda.vmul(_b.angularFactor, _b.wlambda); - - w.vadd(_b.wlambda, w); + for (let i = 0; i !== Nbodies; i++) { + const b = bodies[i]; + const v = b.velocity; + const w = b.angularVelocity; + b.vlambda.vmul(b.linearFactor, b.vlambda); + v.vadd(b.vlambda, v); + b.wlambda.vmul(b.angularFactor, b.wlambda); + w.vadd(b.wlambda, w); } // Set the .multiplier property of each equation - - var l = equations.length; - var invDt = 1 / h; - + let l = equations.length; + const invDt = 1 / h; while (l--) { equations[l].multiplier = lambda[l] * invDt; } } - return iter; - }; - - return GSSolver; -}(Solver); -var GSSolver_solve_lambda = []; // Just temporary number holders that we want to reuse each solve. + } +} +exports.GSSolver = GSSolver; +const GSSolver_solve_lambda = []; // Just temporary number holders that we want to reuse each solve. -var GSSolver_solve_invCs = []; -var GSSolver_solve_Bs = []; +const GSSolver_solve_invCs = []; +const GSSolver_solve_Bs = []; /** * Splits the equations into islands and solves them independently. Can improve performance. @@ -10795,31 +9201,22 @@ var GSSolver_solve_Bs = []; * @extends Solver * @param {Solver} subsolver */ -var SplitSolver = /*#__PURE__*/function (_Solver) { - _inheritsLoose(SplitSolver, _Solver); - +class SplitSolver extends Solver { // The number of solver iterations determines quality of the constraints in the world. The more iterations, the more correct simulation. More iterations need more computations though. If you have a large gravity force in your world, you will need more iterations. // When tolerance is reached, the system is assumed to be converged. - function SplitSolver(subsolver) { - var _this; - - _this = _Solver.call(this) || this; - _this.iterations = 10; - _this.tolerance = 1e-7; - _this.subsolver = subsolver; - _this.nodes = []; - _this.nodePool = []; // Create needed nodes, reuse if possible + constructor(subsolver) { + super(); + this.iterations = 10; + this.tolerance = 1e-7; + this.subsolver = subsolver; + this.nodes = []; + this.nodePool = []; // Create needed nodes, reuse if possible - while (_this.nodePool.length < 128) { - _this.nodePool.push(_this.createNode()); + while (this.nodePool.length < 128) { + this.nodePool.push(this.createNode()); } - - return _this; } - - var _proto = SplitSolver.prototype; - - _proto.createNode = function createNode() { + createNode() { return { body: null, children: [], @@ -10834,137 +9231,110 @@ var SplitSolver = /*#__PURE__*/function (_Solver) { * @param {World} world * @return {Number} number of iterations performed */ - ; - _proto.solve = function solve(dt, world) { - var nodes = SplitSolver_solve_nodes; - var nodePool = this.nodePool; - var bodies = world.bodies; - var equations = this.equations; - var Neq = equations.length; - var Nbodies = bodies.length; - var subsolver = this.subsolver; // Create needed nodes, reuse if possible + solve(dt, world) { + const nodes = SplitSolver_solve_nodes; + const nodePool = this.nodePool; + const bodies = world.bodies; + const equations = this.equations; + const Neq = equations.length; + const Nbodies = bodies.length; + const subsolver = this.subsolver; // Create needed nodes, reuse if possible while (nodePool.length < Nbodies) { nodePool.push(this.createNode()); } - nodes.length = Nbodies; - - for (var i = 0; i < Nbodies; i++) { + for (let i = 0; i < Nbodies; i++) { nodes[i] = nodePool[i]; } // Reset node values - - for (var _i = 0; _i !== Nbodies; _i++) { - var _node = nodes[_i]; - _node.body = bodies[_i]; - _node.children.length = 0; - _node.eqs.length = 0; - _node.visited = false; - } - - for (var k = 0; k !== Neq; k++) { - var eq = equations[k]; - - var _i2 = bodies.indexOf(eq.bi); - - var j = bodies.indexOf(eq.bj); - var ni = nodes[_i2]; - var nj = nodes[j]; + for (let i = 0; i !== Nbodies; i++) { + const node = nodes[i]; + node.body = bodies[i]; + node.children.length = 0; + node.eqs.length = 0; + node.visited = false; + } + for (let k = 0; k !== Neq; k++) { + const eq = equations[k]; + const i = bodies.indexOf(eq.bi); + const j = bodies.indexOf(eq.bj); + const ni = nodes[i]; + const nj = nodes[j]; ni.children.push(nj); ni.eqs.push(eq); nj.children.push(ni); nj.eqs.push(eq); } - - var child; - var n = 0; - var eqs = SplitSolver_solve_eqs; + let child; + let n = 0; + let eqs = SplitSolver_solve_eqs; subsolver.tolerance = this.tolerance; subsolver.iterations = this.iterations; - var dummyWorld = SplitSolver_solve_dummyWorld; - + const dummyWorld = SplitSolver_solve_dummyWorld; while (child = getUnvisitedNode(nodes)) { eqs.length = 0; dummyWorld.bodies.length = 0; bfs(child, visitFunc, dummyWorld.bodies, eqs); - var Neqs = eqs.length; + const Neqs = eqs.length; eqs = eqs.sort(sortById); - - for (var _i3 = 0; _i3 !== Neqs; _i3++) { - subsolver.addEquation(eqs[_i3]); + for (let i = 0; i !== Neqs; i++) { + subsolver.addEquation(eqs[i]); } - - var iter = subsolver.solve(dt, dummyWorld); + const iter = subsolver.solve(dt, dummyWorld); subsolver.removeAllEquations(); n++; } - return n; - }; - - return SplitSolver; -}(Solver); // Returns the number of subsystems - -var SplitSolver_solve_nodes = []; // All allocated node objects + } +} // Returns the number of subsystems +exports.SplitSolver = SplitSolver; +const SplitSolver_solve_nodes = []; // All allocated node objects -var SplitSolver_solve_eqs = []; // Temp array +const SplitSolver_solve_eqs = []; // Temp array -var SplitSolver_solve_dummyWorld = { +const SplitSolver_solve_dummyWorld = { bodies: [] }; // Temp object -var STATIC = Body.STATIC; - +const STATIC = Body.STATIC; function getUnvisitedNode(nodes) { - var Nnodes = nodes.length; - - for (var i = 0; i !== Nnodes; i++) { - var _node2 = nodes[i]; - - if (!_node2.visited && !(_node2.body.type & STATIC)) { - return _node2; + const Nnodes = nodes.length; + for (let i = 0; i !== Nnodes; i++) { + const node = nodes[i]; + if (!node.visited && !(node.body.type & STATIC)) { + return node; } } - return false; } - -var queue = []; - +const queue = []; function bfs(root, visitFunc, bds, eqs) { queue.push(root); root.visited = true; visitFunc(root, bds, eqs); - while (queue.length) { - var _node3 = queue.pop(); // Loop over unvisited child nodes - + const node = queue.pop(); // Loop over unvisited child nodes - var child = void 0; - - while (child = getUnvisitedNode(_node3.children)) { + let child; + while (child = getUnvisitedNode(node.children)) { child.visited = true; visitFunc(child, bds, eqs); queue.push(child); } } } - function visitFunc(node, bds, eqs) { bds.push(node.body); - var Neqs = node.eqs.length; - - for (var i = 0; i !== Neqs; i++) { - var eq = node.eqs[i]; - + const Neqs = node.eqs.length; + for (let i = 0; i !== Neqs; i++) { + const eq = node.eqs[i]; if (!eqs.includes(eq)) { eqs.push(eq); } } } - function sortById(a, b) { return b.id - a.id; } @@ -10974,8 +9344,8 @@ function sortById(a, b) { * @class Pool * @constructor */ -var Pool = /*#__PURE__*/function () { - function Pool() { +class Pool { + constructor() { this.objects = []; this.type = Object; } @@ -10985,16 +9355,11 @@ var Pool = /*#__PURE__*/function () { * @param {Object} obj */ - - var _proto = Pool.prototype; - - _proto.release = function release() { - var Nargs = arguments.length; - - for (var i = 0; i !== Nargs; i++) { - this.objects.push(i < 0 || arguments.length <= i ? undefined : arguments[i]); + release(...args) { + const Nargs = args.length; + for (let i = 0; i !== Nargs; i++) { + this.objects.push(args[i]); } - return this; } /** @@ -11002,9 +9367,8 @@ var Pool = /*#__PURE__*/function () { * @method get * @return {mixed} */ - ; - _proto.get = function get() { + get() { if (this.objects.length === 0) { return this.constructObject(); } else { @@ -11016,9 +9380,8 @@ var Pool = /*#__PURE__*/function () { * @method constructObject * @return {mixed} */ - ; - _proto.constructObject = function constructObject() { + constructObject() { throw new Error('constructObject() not implemented in this Pool subclass yet!'); } /** @@ -11026,40 +9389,29 @@ var Pool = /*#__PURE__*/function () { * @param {number} size * @return {Pool} Self, for chaining */ - ; - - _proto.resize = function resize(size) { - var objects = this.objects; + resize(size) { + const objects = this.objects; while (objects.length > size) { objects.pop(); } - while (objects.length < size) { objects.push(this.constructObject()); } - return this; - }; - - return Pool; -}(); + } +} /** * @class Vec3Pool * @constructor * @extends Pool */ - -var Vec3Pool = /*#__PURE__*/function (_Pool) { - _inheritsLoose(Vec3Pool, _Pool); - - function Vec3Pool() { - var _this; - - _this = _Pool.call(this) || this; - _this.type = Vec3; - return _this; +exports.Pool = Pool; +class Vec3Pool extends Pool { + constructor() { + super(); + this.type = Vec3; } /** * Construct a vector @@ -11067,17 +9419,12 @@ var Vec3Pool = /*#__PURE__*/function (_Pool) { * @return {Vec3} */ - - var _proto = Vec3Pool.prototype; - - _proto.constructObject = function constructObject() { + constructObject() { return new Vec3(); - }; - - return Vec3Pool; -}(Pool); - -var COLLISION_TYPES = { + } +} +exports.Vec3Pool = Vec3Pool; +const COLLISION_TYPES = exports.COLLISION_TYPES = { sphereSphere: Shape.types.SPHERE, spherePlane: Shape.types.SPHERE | Shape.types.PLANE, boxBox: Shape.types.BOX | Shape.types.BOX, @@ -11106,10 +9453,10 @@ var COLLISION_TYPES = { * @todo Contact reduction * @todo should move methods to prototype */ -var Narrowphase = /*#__PURE__*/function () { +class Narrowphase { // Internal storage of pooled contact points. // Pooled vectors. - function Narrowphase(world) { + constructor(world) { this.contactPointPool = []; this.frictionEquationPool = []; this.result = []; @@ -11131,12 +9478,8 @@ var Narrowphase = /*#__PURE__*/function () { * @return {ContactEquation} */ - - var _proto = Narrowphase.prototype; - - _proto.createContactEquation = function createContactEquation(bi, bj, si, sj, overrideShapeA, overrideShapeB) { - var c; - + createContactEquation(bi, bj, si, sj, overrideShapeA, overrideShapeB) { + let c; if (this.contactPointPool.length) { c = this.contactPointPool.pop(); c.bi = bi; @@ -11144,51 +9487,43 @@ var Narrowphase = /*#__PURE__*/function () { } else { c = new ContactEquation(bi, bj); } - c.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse; - var cm = this.currentContactMaterial; + const cm = this.currentContactMaterial; c.restitution = cm.restitution; c.setSpookParams(cm.contactEquationStiffness, cm.contactEquationRelaxation, this.world.dt); - var matA = si.material || bi.material; - var matB = sj.material || bj.material; - + const matA = si.material || bi.material; + const matB = sj.material || bj.material; if (matA && matB && matA.restitution >= 0 && matB.restitution >= 0) { c.restitution = matA.restitution * matB.restitution; } - c.si = overrideShapeA || si; c.sj = overrideShapeB || sj; return c; - }; - - _proto.createFrictionEquationsFromContact = function createFrictionEquationsFromContact(contactEquation, outArray) { - var bodyA = contactEquation.bi; - var bodyB = contactEquation.bj; - var shapeA = contactEquation.si; - var shapeB = contactEquation.sj; - var world = this.world; - var cm = this.currentContactMaterial; // If friction or restitution were specified in the material, use them - - var friction = cm.friction; - var matA = shapeA.material || bodyA.material; - var matB = shapeB.material || bodyB.material; - + } + createFrictionEquationsFromContact(contactEquation, outArray) { + const bodyA = contactEquation.bi; + const bodyB = contactEquation.bj; + const shapeA = contactEquation.si; + const shapeB = contactEquation.sj; + const world = this.world; + const cm = this.currentContactMaterial; // If friction or restitution were specified in the material, use them + + let friction = cm.friction; + const matA = shapeA.material || bodyA.material; + const matB = shapeB.material || bodyB.material; if (matA && matB && matA.friction >= 0 && matB.friction >= 0) { friction = matA.friction * matB.friction; } - if (friction > 0) { // Create 2 tangent equations - var mug = friction * world.gravity.length(); - var reducedMass = bodyA.invMass + bodyB.invMass; - + const mug = friction * world.gravity.length(); + let reducedMass = bodyA.invMass + bodyB.invMass; if (reducedMass > 0) { reducedMass = 1 / reducedMass; } - - var pool = this.frictionEquationPool; - var c1 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass); - var c2 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass); + const pool = this.frictionEquationPool; + const c1 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass); + const c2 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass); c1.bi = c2.bi = bodyA; c1.bj = c2.bj = bodyB; c1.minForce = c2.minForce = -mug * reducedMass; @@ -11207,30 +9542,25 @@ var Narrowphase = /*#__PURE__*/function () { outArray.push(c1, c2); return true; } - return false; } // Take the average N latest contact point on the plane. - ; - _proto.createFrictionFromAverage = function createFrictionFromAverage(numContacts) { + createFrictionFromAverage(numContacts) { // The last contactEquation - var c = this.result[this.result.length - 1]; // Create the result: two "average" friction equations + let c = this.result[this.result.length - 1]; // Create the result: two "average" friction equations if (!this.createFrictionEquationsFromContact(c, this.frictionResult) || numContacts === 1) { return; } - - var f1 = this.frictionResult[this.frictionResult.length - 2]; - var f2 = this.frictionResult[this.frictionResult.length - 1]; + const f1 = this.frictionResult[this.frictionResult.length - 2]; + const f2 = this.frictionResult[this.frictionResult.length - 1]; averageNormal.setZero(); averageContactPointA.setZero(); averageContactPointB.setZero(); - var bodyA = c.bi; - var bodyB = c.bj; - - for (var i = 0; i !== numContacts; i++) { + const bodyA = c.bi; + const bodyB = c.bj; + for (let i = 0; i !== numContacts; i++) { c = this.result[this.result.length - 1 - i]; - if (c.bi !== bodyA) { averageNormal.vadd(c.ni, averageNormal); averageContactPointA.vadd(c.ri, averageContactPointA); @@ -11241,8 +9571,7 @@ var Narrowphase = /*#__PURE__*/function () { averageContactPointB.vadd(c.ri, averageContactPointB); } } - - var invNumContacts = 1 / numContacts; + const invNumContacts = 1 / numContacts; averageContactPointA.scale(invNumContacts, f1.ri); averageContactPointB.scale(invNumContacts, f1.rj); f2.ri.copy(f1.ri); // Should be the same @@ -11260,67 +9589,55 @@ var Narrowphase = /*#__PURE__*/function () { * @param {array} result Array to store generated contacts * @param {array} oldcontacts Optional. Array of reusable contact objects */ - ; - _proto.getContacts = function getContacts(p1, p2, world, result, oldcontacts, frictionResult, frictionPool) { + getContacts(p1, p2, world, result, oldcontacts, frictionResult, frictionPool) { // Save old contact objects this.contactPointPool = oldcontacts; this.frictionEquationPool = frictionPool; this.result = result; this.frictionResult = frictionResult; - var qi = tmpQuat1; - var qj = tmpQuat2; - var xi = tmpVec1$3; - var xj = tmpVec2$3; - - for (var k = 0, N = p1.length; k !== N; k++) { + const qi = tmpQuat1; + const qj = tmpQuat2; + const xi = tmpVec1$2; + const xj = tmpVec2$2; + for (let k = 0, N = p1.length; k !== N; k++) { // Get current collision bodies - var bi = p1[k]; - var bj = p2[k]; // Get contact material - - var bodyContactMaterial = null; + const bi = p1[k]; + const bj = p2[k]; // Get contact material + let bodyContactMaterial = null; if (bi.material && bj.material) { bodyContactMaterial = world.getContactMaterial(bi.material, bj.material) || null; } - - var justTest = bi.type & Body.KINEMATIC && bj.type & Body.STATIC || bi.type & Body.STATIC && bj.type & Body.KINEMATIC || bi.type & Body.KINEMATIC && bj.type & Body.KINEMATIC; - - for (var i = 0; i < bi.shapes.length; i++) { + const justTest = bi.type & Body.KINEMATIC && bj.type & Body.STATIC || bi.type & Body.STATIC && bj.type & Body.KINEMATIC || bi.type & Body.KINEMATIC && bj.type & Body.KINEMATIC; + for (let i = 0; i < bi.shapes.length; i++) { bi.quaternion.mult(bi.shapeOrientations[i], qi); bi.quaternion.vmult(bi.shapeOffsets[i], xi); xi.vadd(bi.position, xi); - var si = bi.shapes[i]; - - for (var j = 0; j < bj.shapes.length; j++) { + const si = bi.shapes[i]; + for (let j = 0; j < bj.shapes.length; j++) { // Compute world transform of shapes bj.quaternion.mult(bj.shapeOrientations[j], qj); bj.quaternion.vmult(bj.shapeOffsets[j], xj); xj.vadd(bj.position, xj); - var sj = bj.shapes[j]; - + const sj = bj.shapes[j]; if (!(si.collisionFilterMask & sj.collisionFilterGroup && sj.collisionFilterMask & si.collisionFilterGroup)) { continue; } - if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) { continue; } // Get collision material - - var shapeContactMaterial = null; - + let shapeContactMaterial = null; if (si.material && sj.material) { shapeContactMaterial = world.getContactMaterial(si.material, sj.material) || null; } - this.currentContactMaterial = shapeContactMaterial || bodyContactMaterial || world.defaultContactMaterial; // Get contacts - var resolverIndex = si.type | sj.type; - var resolver = this[resolverIndex]; - + const resolverIndex = si.type | sj.type; + const resolver = this[resolverIndex]; if (resolver) { - var retval = false; // TO DO: investigate why sphereParticle and convexParticle + let retval = false; // TO DO: investigate why sphereParticle and convexParticle // resolvers expect si and sj shapes to be in reverse order // (i.e. larger integer value type first instead of smaller first) @@ -11329,7 +9646,6 @@ var Narrowphase = /*#__PURE__*/function () { } else { retval = resolver.call(this, sj, si, xj, xi, qj, qi, bj, bi, si, sj, justTest); } - if (retval && justTest) { // Register overlap world.shapeOverlapKeeper.set(si.id, sj.id); @@ -11339,15 +9655,13 @@ var Narrowphase = /*#__PURE__*/function () { } } } - }; - - _proto.sphereSphere = function sphereSphere(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + } + sphereSphere(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { if (justTest) { - return xi.distanceSquared(xj) < Math.pow(si.radius + sj.radius, 2); + return xi.distanceSquared(xj) < (si.radius + sj.radius) ** 2; } // We will have only one contact in this case - - var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); // Contact normal + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); // Contact normal xj.vsub(xi, r.ni); r.ni.normalize(); // Contact point locations @@ -11362,11 +9676,10 @@ var Narrowphase = /*#__PURE__*/function () { r.rj.vsub(bj.position, r.rj); this.result.push(r); this.createFrictionEquationsFromContact(r, this.frictionResult); - }; - - _proto.spherePlane = function spherePlane(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + } + spherePlane(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { // We will have one contact in this case - var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); // Contact normal + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); // Contact normal r.ni.set(0, 0, 1); qj.vmult(r.ni, r.ni); @@ -11386,9 +9699,8 @@ var Narrowphase = /*#__PURE__*/function () { return true; } // Make it relative to the body - - var ri = r.ri; - var rj = r.rj; + const ri = r.ri; + const rj = r.rj; ri.vadd(xi, ri); ri.vsub(bi.position, ri); rj.vadd(xj, rj); @@ -11396,62 +9708,55 @@ var Narrowphase = /*#__PURE__*/function () { this.result.push(r); this.createFrictionEquationsFromContact(r, this.frictionResult); } - }; - - _proto.boxBox = function boxBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + } + boxBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { si.convexPolyhedronRepresentation.material = si.material; sj.convexPolyhedronRepresentation.material = sj.material; si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse; sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse; return this.convexConvex(si.convexPolyhedronRepresentation, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj, si, sj, justTest); - }; - - _proto.sphereBox = function sphereBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { - var v3pool = this.v3pool; // we refer to the box as body j + } + sphereBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + const v3pool = this.v3pool; // we refer to the box as body j - var sides = sphereBox_sides; + const sides = sphereBox_sides; xi.vsub(xj, box_to_sphere); sj.getSideNormals(sides, qj); - var R = si.radius; - - var found = false; // Store the resulting side penetration info - - var side_ns = sphereBox_side_ns; - var side_ns1 = sphereBox_side_ns1; - var side_ns2 = sphereBox_side_ns2; - var side_h = null; - var side_penetrations = 0; - var side_dot1 = 0; - var side_dot2 = 0; - var side_distance = null; - - for (var idx = 0, nsides = sides.length; idx !== nsides && found === false; idx++) { + const R = si.radius; + let found = false; // Store the resulting side penetration info + + const side_ns = sphereBox_side_ns; + const side_ns1 = sphereBox_side_ns1; + const side_ns2 = sphereBox_side_ns2; + let side_h = null; + let side_penetrations = 0; + let side_dot1 = 0; + let side_dot2 = 0; + let side_distance = null; + for (let idx = 0, nsides = sides.length; idx !== nsides && found === false; idx++) { // Get the plane side normal (ns) - var ns = sphereBox_ns; + const ns = sphereBox_ns; ns.copy(sides[idx]); - var h = ns.length(); + const h = ns.length(); ns.normalize(); // The normal/distance dot product tells which side of the plane we are - var dot = box_to_sphere.dot(ns); - + const dot = box_to_sphere.dot(ns); if (dot < h + R && dot > 0) { // Intersects plane. Now check the other two dimensions - var ns1 = sphereBox_ns1; - var ns2 = sphereBox_ns2; + const ns1 = sphereBox_ns1; + const ns2 = sphereBox_ns2; ns1.copy(sides[(idx + 1) % 3]); ns2.copy(sides[(idx + 2) % 3]); - var h1 = ns1.length(); - var h2 = ns2.length(); + const h1 = ns1.length(); + const h2 = ns2.length(); ns1.normalize(); ns2.normalize(); - var dot1 = box_to_sphere.dot(ns1); - var dot2 = box_to_sphere.dot(ns2); - + const dot1 = box_to_sphere.dot(ns1); + const dot2 = box_to_sphere.dot(ns2); if (dot1 < h1 && dot1 > -h1 && dot2 < h2 && dot2 > -h2) { - var _dist = Math.abs(dot - h - R); - - if (side_distance === null || _dist < side_distance) { - side_distance = _dist; + const dist = Math.abs(dot - h - R); + if (side_distance === null || dist < side_distance) { + side_distance = dist; side_dot1 = dot1; side_dot2 = dot2; side_h = h; @@ -11459,7 +9764,6 @@ var Narrowphase = /*#__PURE__*/function () { side_ns1.copy(ns1); side_ns2.copy(ns2); side_penetrations++; - if (justTest) { return true; } @@ -11467,154 +9771,117 @@ var Narrowphase = /*#__PURE__*/function () { } } } - if (side_penetrations) { found = true; + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + side_ns.scale(-R, r.ri); // Sphere r - var _r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); - - side_ns.scale(-R, _r.ri); // Sphere r - - _r.ni.copy(side_ns); - - _r.ni.negate(_r.ni); // Normal should be out of sphere - + r.ni.copy(side_ns); + r.ni.negate(r.ni); // Normal should be out of sphere side_ns.scale(side_h, side_ns); side_ns1.scale(side_dot1, side_ns1); side_ns.vadd(side_ns1, side_ns); side_ns2.scale(side_dot2, side_ns2); - side_ns.vadd(side_ns2, _r.rj); // Make relative to bodies - - _r.ri.vadd(xi, _r.ri); - - _r.ri.vsub(bi.position, _r.ri); + side_ns.vadd(side_ns2, r.rj); // Make relative to bodies - _r.rj.vadd(xj, _r.rj); - - _r.rj.vsub(bj.position, _r.rj); - - this.result.push(_r); - this.createFrictionEquationsFromContact(_r, this.frictionResult); + r.ri.vadd(xi, r.ri); + r.ri.vsub(bi.position, r.ri); + r.rj.vadd(xj, r.rj); + r.rj.vsub(bj.position, r.rj); + this.result.push(r); + this.createFrictionEquationsFromContact(r, this.frictionResult); } // Check corners - - var rj = v3pool.get(); - var sphere_to_corner = sphereBox_sphere_to_corner; - - for (var j = 0; j !== 2 && !found; j++) { - for (var k = 0; k !== 2 && !found; k++) { - for (var l = 0; l !== 2 && !found; l++) { + let rj = v3pool.get(); + const sphere_to_corner = sphereBox_sphere_to_corner; + for (let j = 0; j !== 2 && !found; j++) { + for (let k = 0; k !== 2 && !found; k++) { + for (let l = 0; l !== 2 && !found; l++) { rj.set(0, 0, 0); - if (j) { rj.vadd(sides[0], rj); } else { rj.vsub(sides[0], rj); } - if (k) { rj.vadd(sides[1], rj); } else { rj.vsub(sides[1], rj); } - if (l) { rj.vadd(sides[2], rj); } else { rj.vsub(sides[2], rj); } // World position of corner - xj.vadd(rj, sphere_to_corner); sphere_to_corner.vsub(xi, sphere_to_corner); - if (sphere_to_corner.lengthSquared() < R * R) { if (justTest) { return true; } - found = true; - - var _r2 = this.createContactEquation(bi, bj, si, sj, rsi, rsj); - - _r2.ri.copy(sphere_to_corner); - - _r2.ri.normalize(); - - _r2.ni.copy(_r2.ri); - - _r2.ri.scale(R, _r2.ri); - - _r2.rj.copy(rj); // Make relative to bodies - - - _r2.ri.vadd(xi, _r2.ri); - - _r2.ri.vsub(bi.position, _r2.ri); - - _r2.rj.vadd(xj, _r2.rj); - - _r2.rj.vsub(bj.position, _r2.rj); - - this.result.push(_r2); - this.createFrictionEquationsFromContact(_r2, this.frictionResult); + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + r.ri.copy(sphere_to_corner); + r.ri.normalize(); + r.ni.copy(r.ri); + r.ri.scale(R, r.ri); + r.rj.copy(rj); // Make relative to bodies + + r.ri.vadd(xi, r.ri); + r.ri.vsub(bi.position, r.ri); + r.rj.vadd(xj, r.rj); + r.rj.vsub(bj.position, r.rj); + this.result.push(r); + this.createFrictionEquationsFromContact(r, this.frictionResult); } } } } - v3pool.release(rj); rj = null; // Check edges - var edgeTangent = v3pool.get(); - var edgeCenter = v3pool.get(); - var r = v3pool.get(); // r = edge center to sphere center - - var orthogonal = v3pool.get(); - var dist = v3pool.get(); - var Nsides = sides.length; + const edgeTangent = v3pool.get(); + const edgeCenter = v3pool.get(); + const r = v3pool.get(); // r = edge center to sphere center - for (var _j = 0; _j !== Nsides && !found; _j++) { - for (var _k = 0; _k !== Nsides && !found; _k++) { - if (_j % 3 !== _k % 3) { + const orthogonal = v3pool.get(); + const dist = v3pool.get(); + const Nsides = sides.length; + for (let j = 0; j !== Nsides && !found; j++) { + for (let k = 0; k !== Nsides && !found; k++) { + if (j % 3 !== k % 3) { // Get edge tangent - sides[_k].cross(sides[_j], edgeTangent); - + sides[k].cross(sides[j], edgeTangent); edgeTangent.normalize(); - - sides[_j].vadd(sides[_k], edgeCenter); - + sides[j].vadd(sides[k], edgeCenter); r.copy(xi); r.vsub(edgeCenter, r); r.vsub(xj, r); - var orthonorm = r.dot(edgeTangent); // distance from edge center to sphere center in the tangent direction + const orthonorm = r.dot(edgeTangent); // distance from edge center to sphere center in the tangent direction edgeTangent.scale(orthonorm, orthogonal); // Vector from edge center to sphere center in the tangent direction // Find the third side orthogonal to this one - var _l = 0; - - while (_l === _j % 3 || _l === _k % 3) { - _l++; + let l = 0; + while (l === j % 3 || l === k % 3) { + l++; } // vec from edge center to sphere projected to the plane orthogonal to the edge tangent - dist.copy(xi); dist.vsub(orthogonal, dist); dist.vsub(edgeCenter, dist); dist.vsub(xj, dist); // Distances in tangent direction and distance in the plane orthogonal to it - var tdist = Math.abs(orthonorm); - var ndist = dist.length(); - - if (tdist < sides[_l].length() && ndist < R) { + const tdist = Math.abs(orthonorm); + const ndist = dist.length(); + if (tdist < sides[l].length() && ndist < R) { if (justTest) { return true; } - found = true; - var res = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + const res = this.createContactEquation(bi, bj, si, sj, rsi, rsj); edgeCenter.vadd(orthogonal, res.rj); // box rj res.rj.copy(res.rj); @@ -11636,38 +9903,31 @@ var Narrowphase = /*#__PURE__*/function () { } } } - v3pool.release(edgeTangent, edgeCenter, r, orthogonal, dist); - }; - - _proto.planeBox = function planeBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + } + planeBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { sj.convexPolyhedronRepresentation.material = sj.material; sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse; sj.convexPolyhedronRepresentation.id = sj.id; return this.planeConvex(si, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj, si, sj, justTest); - }; - - _proto.convexConvex = function convexConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest, faceListA, faceListB) { - var sepAxis = convexConvex_sepAxis; - + } + convexConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest, faceListA, faceListB) { + const sepAxis = convexConvex_sepAxis; if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) { return; } - if (si.findSeparatingAxis(sj, xi, qi, xj, qj, sepAxis, faceListA, faceListB)) { - var res = []; - var q = convexConvex_q; + const res = []; + const q = convexConvex_q; si.clipAgainstHull(xi, qi, sj, xj, qj, sepAxis, -100, 100, res); - var numContacts = 0; - - for (var j = 0; j !== res.length; j++) { + let numContacts = 0; + for (let j = 0; j !== res.length; j++) { if (justTest) { return true; } - - var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); - var ri = r.ri; - var rj = r.rj; + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + const ri = r.ri; + const rj = r.rj; sepAxis.negate(r.ni); res[j].normal.negate(q); q.scale(res[j].depth, q); @@ -11683,46 +9943,41 @@ var Narrowphase = /*#__PURE__*/function () { rj.vsub(bj.position, rj); this.result.push(r); numContacts++; - if (!this.enableFrictionReduction) { this.createFrictionEquationsFromContact(r, this.frictionResult); } } - if (this.enableFrictionReduction && numContacts) { this.createFrictionFromAverage(numContacts); } } - }; - - _proto.sphereConvex = function sphereConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { - var v3pool = this.v3pool; + } + sphereConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + const v3pool = this.v3pool; xi.vsub(xj, convex_to_sphere); - var normals = sj.faceNormals; - var faces = sj.faces; - var verts = sj.vertices; - var R = si.radius; + const normals = sj.faceNormals; + const faces = sj.faces; + const verts = sj.vertices; + const R = si.radius; // return; // } - var found = false; // Check corners + let found = false; // Check corners - for (var i = 0; i !== verts.length; i++) { - var v = verts[i]; // World position of corner + for (let i = 0; i !== verts.length; i++) { + const v = verts[i]; // World position of corner - var worldCorner = sphereConvex_worldCorner; + const worldCorner = sphereConvex_worldCorner; qj.vmult(v, worldCorner); xj.vadd(worldCorner, worldCorner); - var sphere_to_corner = sphereConvex_sphereToCorner; + const sphere_to_corner = sphereConvex_sphereToCorner; worldCorner.vsub(xi, sphere_to_corner); - if (sphere_to_corner.lengthSquared() < R * R) { if (justTest) { return true; } - found = true; - var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); r.ri.copy(sphere_to_corner); r.ri.normalize(); r.ni.copy(r.ri); @@ -11740,110 +9995,96 @@ var Narrowphase = /*#__PURE__*/function () { } } // Check side (plane) intersections + for (let i = 0, nfaces = faces.length; i !== nfaces && found === false; i++) { + const normal = normals[i]; + const face = faces[i]; // Get world-transformed normal of the face - for (var _i = 0, nfaces = faces.length; _i !== nfaces && found === false; _i++) { - var normal = normals[_i]; - var face = faces[_i]; // Get world-transformed normal of the face - - var worldNormal = sphereConvex_worldNormal; + const worldNormal = sphereConvex_worldNormal; qj.vmult(normal, worldNormal); // Get a world vertex from the face - var worldPoint = sphereConvex_worldPoint; + const worldPoint = sphereConvex_worldPoint; qj.vmult(verts[face[0]], worldPoint); worldPoint.vadd(xj, worldPoint); // Get a point on the sphere, closest to the face normal - var worldSpherePointClosestToPlane = sphereConvex_worldSpherePointClosestToPlane; + const worldSpherePointClosestToPlane = sphereConvex_worldSpherePointClosestToPlane; worldNormal.scale(-R, worldSpherePointClosestToPlane); xi.vadd(worldSpherePointClosestToPlane, worldSpherePointClosestToPlane); // Vector from a face point to the closest point on the sphere - var penetrationVec = sphereConvex_penetrationVec; + const penetrationVec = sphereConvex_penetrationVec; worldSpherePointClosestToPlane.vsub(worldPoint, penetrationVec); // The penetration. Negative value means overlap. - var penetration = penetrationVec.dot(worldNormal); - var worldPointToSphere = sphereConvex_sphereToWorldPoint; + const penetration = penetrationVec.dot(worldNormal); + const worldPointToSphere = sphereConvex_sphereToWorldPoint; xi.vsub(worldPoint, worldPointToSphere); - if (penetration < 0 && worldPointToSphere.dot(worldNormal) > 0) { // Intersects plane. Now check if the sphere is inside the face polygon - var faceVerts = []; // Face vertices, in world coords + const faceVerts = []; // Face vertices, in world coords - for (var j = 0, Nverts = face.length; j !== Nverts; j++) { - var worldVertex = v3pool.get(); + for (let j = 0, Nverts = face.length; j !== Nverts; j++) { + const worldVertex = v3pool.get(); qj.vmult(verts[face[j]], worldVertex); xj.vadd(worldVertex, worldVertex); faceVerts.push(worldVertex); } - if (pointInPolygon(faceVerts, worldNormal, xi)) { // Is the sphere center in the face polygon? if (justTest) { return true; } - found = true; + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + worldNormal.scale(-R, r.ri); // Contact offset, from sphere center to contact - var _r3 = this.createContactEquation(bi, bj, si, sj, rsi, rsj); - - worldNormal.scale(-R, _r3.ri); // Contact offset, from sphere center to contact + worldNormal.negate(r.ni); // Normal pointing out of sphere - worldNormal.negate(_r3.ni); // Normal pointing out of sphere - - var penetrationVec2 = v3pool.get(); + const penetrationVec2 = v3pool.get(); worldNormal.scale(-penetration, penetrationVec2); - var penetrationSpherePoint = v3pool.get(); + const penetrationSpherePoint = v3pool.get(); worldNormal.scale(-R, penetrationSpherePoint); //xi.vsub(xj).vadd(penetrationSpherePoint).vadd(penetrationVec2 , r.rj); - xi.vsub(xj, _r3.rj); - - _r3.rj.vadd(penetrationSpherePoint, _r3.rj); - - _r3.rj.vadd(penetrationVec2, _r3.rj); // Should be relative to the body. - - - _r3.rj.vadd(xj, _r3.rj); - - _r3.rj.vsub(bj.position, _r3.rj); // Should be relative to the body. - - - _r3.ri.vadd(xi, _r3.ri); + xi.vsub(xj, r.rj); + r.rj.vadd(penetrationSpherePoint, r.rj); + r.rj.vadd(penetrationVec2, r.rj); // Should be relative to the body. - _r3.ri.vsub(bi.position, _r3.ri); + r.rj.vadd(xj, r.rj); + r.rj.vsub(bj.position, r.rj); // Should be relative to the body. + r.ri.vadd(xi, r.ri); + r.ri.vsub(bi.position, r.ri); v3pool.release(penetrationVec2); v3pool.release(penetrationSpherePoint); - this.result.push(_r3); - this.createFrictionEquationsFromContact(_r3, this.frictionResult); // Release world vertices + this.result.push(r); + this.createFrictionEquationsFromContact(r, this.frictionResult); // Release world vertices - for (var _j2 = 0, Nfaceverts = faceVerts.length; _j2 !== Nfaceverts; _j2++) { - v3pool.release(faceVerts[_j2]); + for (let j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) { + v3pool.release(faceVerts[j]); } - return; // We only expect *one* face contact } else { // Edge? - for (var _j3 = 0; _j3 !== face.length; _j3++) { + for (let j = 0; j !== face.length; j++) { // Get two world transformed vertices - var v1 = v3pool.get(); - var v2 = v3pool.get(); - qj.vmult(verts[face[(_j3 + 1) % face.length]], v1); - qj.vmult(verts[face[(_j3 + 2) % face.length]], v2); + const v1 = v3pool.get(); + const v2 = v3pool.get(); + qj.vmult(verts[face[(j + 1) % face.length]], v1); + qj.vmult(verts[face[(j + 2) % face.length]], v2); xj.vadd(v1, v1); xj.vadd(v2, v2); // Construct edge vector - var edge = sphereConvex_edge; + const edge = sphereConvex_edge; v2.vsub(v1, edge); // Construct the same vector, but normalized - var edgeUnit = sphereConvex_edgeUnit; + const edgeUnit = sphereConvex_edgeUnit; edge.unit(edgeUnit); // p is xi projected onto the edge - var p = v3pool.get(); - var v1_to_xi = v3pool.get(); + const p = v3pool.get(); + const v1_to_xi = v3pool.get(); xi.vsub(v1, v1_to_xi); - var dot = v1_to_xi.dot(edgeUnit); + const dot = v1_to_xi.dot(edgeUnit); edgeUnit.scale(dot, p); p.vadd(v1, p); // Compute a vector from p to the center of the sphere - var xi_to_p = v3pool.get(); + const xi_to_p = v3pool.get(); p.vsub(xi, xi_to_p); // Collision if the edge-sphere distance is less than the radius // AND if p is in between v1 and v2 @@ -11853,33 +10094,23 @@ var Narrowphase = /*#__PURE__*/function () { if (justTest) { return true; } - - var _r4 = this.createContactEquation(bi, bj, si, sj, rsi, rsj); - - p.vsub(xj, _r4.rj); - p.vsub(xi, _r4.ni); - - _r4.ni.normalize(); - - _r4.ni.scale(R, _r4.ri); // Should be relative to the body. - - - _r4.rj.vadd(xj, _r4.rj); - - _r4.rj.vsub(bj.position, _r4.rj); // Should be relative to the body. - - - _r4.ri.vadd(xi, _r4.ri); - - _r4.ri.vsub(bi.position, _r4.ri); - - this.result.push(_r4); - this.createFrictionEquationsFromContact(_r4, this.frictionResult); // Release world vertices - - for (var _j4 = 0, _Nfaceverts = faceVerts.length; _j4 !== _Nfaceverts; _j4++) { - v3pool.release(faceVerts[_j4]); + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + p.vsub(xj, r.rj); + p.vsub(xi, r.ni); + r.ni.normalize(); + r.ni.scale(R, r.ri); // Should be relative to the body. + + r.rj.vadd(xj, r.rj); + r.rj.vsub(bj.position, r.rj); // Should be relative to the body. + + r.ri.vadd(xi, r.ri); + r.ri.vsub(bi.position, r.ri); + this.result.push(r); + this.createFrictionEquationsFromContact(r, this.frictionResult); // Release world vertices + + for (let j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) { + v3pool.release(faceVerts[j]); } - v3pool.release(v1); v3pool.release(v2); v3pool.release(p); @@ -11887,7 +10118,6 @@ var Narrowphase = /*#__PURE__*/function () { v3pool.release(v1_to_xi); return; } - v3pool.release(v1); v3pool.release(v2); v3pool.release(p); @@ -11896,40 +10126,35 @@ var Narrowphase = /*#__PURE__*/function () { } } // Release world vertices - - for (var _j5 = 0, _Nfaceverts2 = faceVerts.length; _j5 !== _Nfaceverts2; _j5++) { - v3pool.release(faceVerts[_j5]); + for (let j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) { + v3pool.release(faceVerts[j]); } } } - }; - - _proto.planeConvex = function planeConvex(planeShape, convexShape, planePosition, convexPosition, planeQuat, convexQuat, planeBody, convexBody, si, sj, justTest) { + } + planeConvex(planeShape, convexShape, planePosition, convexPosition, planeQuat, convexQuat, planeBody, convexBody, si, sj, justTest) { // Simply return the points behind the plane. - var worldVertex = planeConvex_v; - var worldNormal = planeConvex_normal; + const worldVertex = planeConvex_v; + const worldNormal = planeConvex_normal; worldNormal.set(0, 0, 1); planeQuat.vmult(worldNormal, worldNormal); // Turn normal according to plane orientation - var numContacts = 0; - var relpos = planeConvex_relpos; - - for (var i = 0; i !== convexShape.vertices.length; i++) { + let numContacts = 0; + const relpos = planeConvex_relpos; + for (let i = 0; i !== convexShape.vertices.length; i++) { // Get world convex vertex worldVertex.copy(convexShape.vertices[i]); convexQuat.vmult(worldVertex, worldVertex); convexPosition.vadd(worldVertex, worldVertex); worldVertex.vsub(planePosition, relpos); - var dot = worldNormal.dot(relpos); - + const dot = worldNormal.dot(relpos); if (dot <= 0.0) { if (justTest) { return true; } + const r = this.createContactEquation(planeBody, convexBody, planeShape, convexShape, si, sj); // Get vertex position projected on plane - var r = this.createContactEquation(planeBody, convexBody, planeShape, convexShape, si, sj); // Get vertex position projected on plane - - var projected = planeConvex_projected; + const projected = planeConvex_projected; worldNormal.scale(worldNormal.dot(relpos), projected); worldVertex.vsub(projected, projected); projected.vsub(planePosition, r.ri); // From plane to vertex projected on plane @@ -11945,116 +10170,94 @@ var Narrowphase = /*#__PURE__*/function () { r.rj.vsub(convexBody.position, r.rj); this.result.push(r); numContacts++; - if (!this.enableFrictionReduction) { this.createFrictionEquationsFromContact(r, this.frictionResult); } } } - if (this.enableFrictionReduction && numContacts) { this.createFrictionFromAverage(numContacts); } - }; - - _proto.boxConvex = function boxConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + } + boxConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { si.convexPolyhedronRepresentation.material = si.material; si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse; return this.convexConvex(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest); - }; - - _proto.sphereHeightfield = function sphereHeightfield(sphereShape, hfShape, spherePos, hfPos, sphereQuat, hfQuat, sphereBody, hfBody, rsi, rsj, justTest) { - var data = hfShape.data; - var radius = sphereShape.radius; - var w = hfShape.elementSize; - var worldPillarOffset = sphereHeightfield_tmp2; // Get sphere position to heightfield local! + } + sphereHeightfield(sphereShape, hfShape, spherePos, hfPos, sphereQuat, hfQuat, sphereBody, hfBody, rsi, rsj, justTest) { + const data = hfShape.data; + const radius = sphereShape.radius; + const w = hfShape.elementSize; + const worldPillarOffset = sphereHeightfield_tmp2; // Get sphere position to heightfield local! - var localSpherePos = sphereHeightfield_tmp1; + const localSpherePos = sphereHeightfield_tmp1; Transform.pointToLocalFrame(hfPos, hfQuat, spherePos, localSpherePos); // Get the index of the data points to test against - var iMinX = Math.floor((localSpherePos.x - radius) / w) - 1; - var iMaxX = Math.ceil((localSpherePos.x + radius) / w) + 1; - var iMinY = Math.floor((localSpherePos.y - radius) / w) - 1; - var iMaxY = Math.ceil((localSpherePos.y + radius) / w) + 1; // Bail out if we are out of the terrain + let iMinX = Math.floor((localSpherePos.x - radius) / w) - 1; + let iMaxX = Math.ceil((localSpherePos.x + radius) / w) + 1; + let iMinY = Math.floor((localSpherePos.y - radius) / w) - 1; + let iMaxY = Math.ceil((localSpherePos.y + radius) / w) + 1; // Bail out if we are out of the terrain if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) { return; } // Clamp index to edges - if (iMinX < 0) { iMinX = 0; } - if (iMaxX < 0) { iMaxX = 0; } - if (iMinY < 0) { iMinY = 0; } - if (iMaxY < 0) { iMaxY = 0; } - if (iMinX >= data.length) { iMinX = data.length - 1; } - if (iMaxX >= data.length) { iMaxX = data.length - 1; } - if (iMaxY >= data[0].length) { iMaxY = data[0].length - 1; } - if (iMinY >= data[0].length) { iMinY = data[0].length - 1; } - - var minMax = []; + const minMax = []; hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax); - var min = minMax[0]; - var max = minMax[1]; // Bail out if we can't touch the bounding height box + const min = minMax[0]; + const max = minMax[1]; // Bail out if we can't touch the bounding height box if (localSpherePos.z - radius > max || localSpherePos.z + radius < min) { return; } - - var result = this.result; - - for (var i = iMinX; i < iMaxX; i++) { - for (var j = iMinY; j < iMaxY; j++) { - var numContactsBefore = result.length; - var intersecting = false; // Lower triangle + const result = this.result; + for (let i = iMinX; i < iMaxX; i++) { + for (let j = iMinY; j < iMaxY; j++) { + const numContactsBefore = result.length; + let intersecting = false; // Lower triangle hfShape.getConvexTrianglePillar(i, j, false); Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset); - if (spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) { intersecting = this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody, sphereShape, hfShape, justTest); } - if (justTest && intersecting) { return true; } // Upper triangle - hfShape.getConvexTrianglePillar(i, j, true); Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset); - if (spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) { intersecting = this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody, sphereShape, hfShape, justTest); } - if (justTest && intersecting) { return true; } - - var numContacts = result.length - numContactsBefore; - + const numContacts = result.length - numContactsBefore; if (numContacts > 2) { return; } @@ -12064,121 +10267,101 @@ var Narrowphase = /*#__PURE__*/function () { result.pop(); } */ - } } - }; + } - _proto.boxHeightfield = function boxHeightfield(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + boxHeightfield(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { si.convexPolyhedronRepresentation.material = si.material; si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse; return this.convexHeightfield(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest); - }; - - _proto.convexHeightfield = function convexHeightfield(convexShape, hfShape, convexPos, hfPos, convexQuat, hfQuat, convexBody, hfBody, rsi, rsj, justTest) { - var data = hfShape.data; - var w = hfShape.elementSize; - var radius = convexShape.boundingSphereRadius; - var worldPillarOffset = convexHeightfield_tmp2; - var faceList = convexHeightfield_faceList; // Get sphere position to heightfield local! + } + convexHeightfield(convexShape, hfShape, convexPos, hfPos, convexQuat, hfQuat, convexBody, hfBody, rsi, rsj, justTest) { + const data = hfShape.data; + const w = hfShape.elementSize; + const radius = convexShape.boundingSphereRadius; + const worldPillarOffset = convexHeightfield_tmp2; + const faceList = convexHeightfield_faceList; // Get sphere position to heightfield local! - var localConvexPos = convexHeightfield_tmp1; + const localConvexPos = convexHeightfield_tmp1; Transform.pointToLocalFrame(hfPos, hfQuat, convexPos, localConvexPos); // Get the index of the data points to test against - var iMinX = Math.floor((localConvexPos.x - radius) / w) - 1; - var iMaxX = Math.ceil((localConvexPos.x + radius) / w) + 1; - var iMinY = Math.floor((localConvexPos.y - radius) / w) - 1; - var iMaxY = Math.ceil((localConvexPos.y + radius) / w) + 1; // Bail out if we are out of the terrain + let iMinX = Math.floor((localConvexPos.x - radius) / w) - 1; + let iMaxX = Math.ceil((localConvexPos.x + radius) / w) + 1; + let iMinY = Math.floor((localConvexPos.y - radius) / w) - 1; + let iMaxY = Math.ceil((localConvexPos.y + radius) / w) + 1; // Bail out if we are out of the terrain if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) { return; } // Clamp index to edges - if (iMinX < 0) { iMinX = 0; } - if (iMaxX < 0) { iMaxX = 0; } - if (iMinY < 0) { iMinY = 0; } - if (iMaxY < 0) { iMaxY = 0; } - if (iMinX >= data.length) { iMinX = data.length - 1; } - if (iMaxX >= data.length) { iMaxX = data.length - 1; } - if (iMaxY >= data[0].length) { iMaxY = data[0].length - 1; } - if (iMinY >= data[0].length) { iMinY = data[0].length - 1; } - - var minMax = []; + const minMax = []; hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax); - var min = minMax[0]; - var max = minMax[1]; // Bail out if we're cant touch the bounding height box + const min = minMax[0]; + const max = minMax[1]; // Bail out if we're cant touch the bounding height box if (localConvexPos.z - radius > max || localConvexPos.z + radius < min) { return; } - - for (var i = iMinX; i < iMaxX; i++) { - for (var j = iMinY; j < iMaxY; j++) { - var intersecting = false; // Lower triangle + for (let i = iMinX; i < iMaxX; i++) { + for (let j = iMinY; j < iMaxY; j++) { + let intersecting = false; // Lower triangle hfShape.getConvexTrianglePillar(i, j, false); Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset); - if (convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) { intersecting = this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, null, null, justTest, faceList, null); } - if (justTest && intersecting) { return true; } // Upper triangle - hfShape.getConvexTrianglePillar(i, j, true); Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset); - if (convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) { intersecting = this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, null, null, justTest, faceList, null); } - if (justTest && intersecting) { return true; } } } - }; - - _proto.sphereParticle = function sphereParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) { + } + sphereParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) { // The normal is the unit vector from sphere center to particle center - var normal = particleSphere_normal; + const normal = particleSphere_normal; normal.set(0, 0, 1); xi.vsub(xj, normal); - var lengthSquared = normal.lengthSquared(); - + const lengthSquared = normal.lengthSquared(); if (lengthSquared <= sj.radius * sj.radius) { if (justTest) { return true; } - - var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); normal.normalize(); r.rj.copy(normal); r.rj.scale(sj.radius, r.rj); @@ -12190,30 +10373,27 @@ var Narrowphase = /*#__PURE__*/function () { this.result.push(r); this.createFrictionEquationsFromContact(r, this.frictionResult); } - }; - - _proto.planeParticle = function planeParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) { - var normal = particlePlane_normal; + } + planeParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) { + const normal = particlePlane_normal; normal.set(0, 0, 1); bj.quaternion.vmult(normal, normal); // Turn normal according to plane orientation - var relpos = particlePlane_relpos; + const relpos = particlePlane_relpos; xi.vsub(bj.position, relpos); - var dot = normal.dot(relpos); - + const dot = normal.dot(relpos); if (dot <= 0.0) { if (justTest) { return true; } - - var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); r.ni.copy(normal); // Contact normal is the plane normal r.ni.negate(r.ni); r.ri.set(0, 0, 0); // Center of particle // Get particle position projected on plane - var projected = particlePlane_projected; + const projected = particlePlane_projected; normal.scale(normal.dot(xi), projected); xi.vsub(projected, projected); //projected.vadd(bj.position,projected); // rj is now the projected world position minus plane position @@ -12222,59 +10402,50 @@ var Narrowphase = /*#__PURE__*/function () { this.result.push(r); this.createFrictionEquationsFromContact(r, this.frictionResult); } - }; - - _proto.boxParticle = function boxParticle(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { + } + boxParticle(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) { si.convexPolyhedronRepresentation.material = si.material; si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse; return this.convexParticle(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest); - }; - - _proto.convexParticle = function convexParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) { - var penetratedFaceIndex = -1; - var penetratedFaceNormal = convexParticle_penetratedFaceNormal; - var worldPenetrationVec = convexParticle_worldPenetrationVec; - var minPenetration = null; - - var local = convexParticle_local; + } + convexParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) { + let penetratedFaceIndex = -1; + const penetratedFaceNormal = convexParticle_penetratedFaceNormal; + const worldPenetrationVec = convexParticle_worldPenetrationVec; + let minPenetration = null; + const local = convexParticle_local; local.copy(xi); local.vsub(xj, local); // Convert position to relative the convex origin qj.conjugate(cqj); cqj.vmult(local, local); - if (sj.pointIsInside(local)) { if (sj.worldVerticesNeedsUpdate) { sj.computeWorldVertices(xj, qj); } - if (sj.worldFaceNormalsNeedsUpdate) { sj.computeWorldFaceNormals(qj); } // For each world polygon in the polyhedra - - for (var i = 0, nfaces = sj.faces.length; i !== nfaces; i++) { + for (let i = 0, nfaces = sj.faces.length; i !== nfaces; i++) { // Construct world face vertices - var verts = [sj.worldVertices[sj.faces[i][0]]]; - var normal = sj.worldFaceNormals[i]; // Check how much the particle penetrates the polygon plane. + const verts = [sj.worldVertices[sj.faces[i][0]]]; + const normal = sj.worldFaceNormals[i]; // Check how much the particle penetrates the polygon plane. xi.vsub(verts[0], convexParticle_vertexToParticle); - var penetration = -normal.dot(convexParticle_vertexToParticle); - + const penetration = -normal.dot(convexParticle_vertexToParticle); if (minPenetration === null || Math.abs(penetration) < Math.abs(minPenetration)) { if (justTest) { return true; } - minPenetration = penetration; penetratedFaceIndex = i; penetratedFaceNormal.copy(normal); } } - if (penetratedFaceIndex !== -1) { // Setup contact - var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); + const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj); penetratedFaceNormal.scale(minPenetration, worldPenetrationVec); // rj is the particle position projected to the face worldPenetrationVec.vadd(xi, worldPenetrationVec); @@ -12287,8 +10458,8 @@ var Narrowphase = /*#__PURE__*/function () { r.ri.set(0, 0, 0); // Center of particle - var ri = r.ri; - var rj = r.rj; // Make relative to bodies + const ri = r.ri; + const rj = r.rj; // Make relative to bodies ri.vadd(xi, ri); ri.vsub(bi.position, ri); @@ -12300,48 +10471,43 @@ var Narrowphase = /*#__PURE__*/function () { console.warn('Point found inside convex, but did not find penetrating face!'); } } - }; - - _proto.sphereTrimesh = function sphereTrimesh(sphereShape, trimeshShape, spherePos, trimeshPos, sphereQuat, trimeshQuat, sphereBody, trimeshBody, rsi, rsj, justTest) { - var edgeVertexA = sphereTrimesh_edgeVertexA; - var edgeVertexB = sphereTrimesh_edgeVertexB; - var edgeVector = sphereTrimesh_edgeVector; - var edgeVectorUnit = sphereTrimesh_edgeVectorUnit; - var localSpherePos = sphereTrimesh_localSpherePos; - var tmp = sphereTrimesh_tmp; - var localSphereAABB = sphereTrimesh_localSphereAABB; - var v2 = sphereTrimesh_v2; - var relpos = sphereTrimesh_relpos; - var triangles = sphereTrimesh_triangles; // Convert sphere position to local in the trimesh + } + sphereTrimesh(sphereShape, trimeshShape, spherePos, trimeshPos, sphereQuat, trimeshQuat, sphereBody, trimeshBody, rsi, rsj, justTest) { + const edgeVertexA = sphereTrimesh_edgeVertexA; + const edgeVertexB = sphereTrimesh_edgeVertexB; + const edgeVector = sphereTrimesh_edgeVector; + const edgeVectorUnit = sphereTrimesh_edgeVectorUnit; + const localSpherePos = sphereTrimesh_localSpherePos; + const tmp = sphereTrimesh_tmp; + const localSphereAABB = sphereTrimesh_localSphereAABB; + const v2 = sphereTrimesh_v2; + const relpos = sphereTrimesh_relpos; + const triangles = sphereTrimesh_triangles; // Convert sphere position to local in the trimesh Transform.pointToLocalFrame(trimeshPos, trimeshQuat, spherePos, localSpherePos); // Get the aabb of the sphere locally in the trimesh - var sphereRadius = sphereShape.radius; + const sphereRadius = sphereShape.radius; localSphereAABB.lowerBound.set(localSpherePos.x - sphereRadius, localSpherePos.y - sphereRadius, localSpherePos.z - sphereRadius); localSphereAABB.upperBound.set(localSpherePos.x + sphereRadius, localSpherePos.y + sphereRadius, localSpherePos.z + sphereRadius); trimeshShape.getTrianglesInAABB(localSphereAABB, triangles); //for (let i = 0; i < trimeshShape.indices.length / 3; i++) triangles.push(i); // All // Vertices - var v = sphereTrimesh_v; - var radiusSquared = sphereShape.radius * sphereShape.radius; - - for (var i = 0; i < triangles.length; i++) { - for (var j = 0; j < 3; j++) { + const v = sphereTrimesh_v; + const radiusSquared = sphereShape.radius * sphereShape.radius; + for (let i = 0; i < triangles.length; i++) { + for (let j = 0; j < 3; j++) { trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], v); // Check vertex overlap in sphere v.vsub(localSpherePos, relpos); - if (relpos.lengthSquared() <= radiusSquared) { // Safe up v2.copy(v); Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v); v.vsub(spherePos, relpos); - if (justTest) { return true; } - - var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj); + let r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj); r.ni.copy(relpos); r.ni.normalize(); // ri is the vector from sphere center to the sphere surface @@ -12358,18 +10524,16 @@ var Narrowphase = /*#__PURE__*/function () { } } // Check all edges - - for (var _i2 = 0; _i2 < triangles.length; _i2++) { - for (var _j6 = 0; _j6 < 3; _j6++) { - trimeshShape.getVertex(trimeshShape.indices[triangles[_i2] * 3 + _j6], edgeVertexA); - trimeshShape.getVertex(trimeshShape.indices[triangles[_i2] * 3 + (_j6 + 1) % 3], edgeVertexB); + for (let i = 0; i < triangles.length; i++) { + for (let j = 0; j < 3; j++) { + trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], edgeVertexA); + trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + (j + 1) % 3], edgeVertexB); edgeVertexB.vsub(edgeVertexA, edgeVector); // Project sphere position to the edge localSpherePos.vsub(edgeVertexB, tmp); - var positionAlongEdgeB = tmp.dot(edgeVector); + const positionAlongEdgeB = tmp.dot(edgeVector); localSpherePos.vsub(edgeVertexA, tmp); - var positionAlongEdgeA = tmp.dot(edgeVector); - + let positionAlongEdgeA = tmp.dot(edgeVector); if (positionAlongEdgeA > 0 && positionAlongEdgeB < 0) { // Now check the orthogonal distance from edge to sphere center localSpherePos.vsub(edgeVertexA, tmp); @@ -12379,112 +10543,88 @@ var Narrowphase = /*#__PURE__*/function () { edgeVectorUnit.scale(positionAlongEdgeA, tmp); tmp.vadd(edgeVertexA, tmp); // tmp is now the sphere center position projected to the edge, defined locally in the trimesh frame - var dist = tmp.distanceTo(localSpherePos); - + const dist = tmp.distanceTo(localSpherePos); if (dist < sphereShape.radius) { if (justTest) { return true; } - - var _r5 = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj); - - tmp.vsub(localSpherePos, _r5.ni); - - _r5.ni.normalize(); - - _r5.ni.scale(sphereShape.radius, _r5.ri); - - _r5.ri.vadd(spherePos, _r5.ri); - - _r5.ri.vsub(sphereBody.position, _r5.ri); - + const r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj); + tmp.vsub(localSpherePos, r.ni); + r.ni.normalize(); + r.ni.scale(sphereShape.radius, r.ri); + r.ri.vadd(spherePos, r.ri); + r.ri.vsub(sphereBody.position, r.ri); Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp); - tmp.vsub(trimeshBody.position, _r5.rj); - Transform.vectorToWorldFrame(trimeshQuat, _r5.ni, _r5.ni); - Transform.vectorToWorldFrame(trimeshQuat, _r5.ri, _r5.ri); - this.result.push(_r5); - this.createFrictionEquationsFromContact(_r5, this.frictionResult); + tmp.vsub(trimeshBody.position, r.rj); + Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni); + Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri); + this.result.push(r); + this.createFrictionEquationsFromContact(r, this.frictionResult); } } } } // Triangle faces - - var va = sphereTrimesh_va; - var vb = sphereTrimesh_vb; - var vc = sphereTrimesh_vc; - var normal = sphereTrimesh_normal; - - for (var _i3 = 0, N = triangles.length; _i3 !== N; _i3++) { - trimeshShape.getTriangleVertices(triangles[_i3], va, vb, vc); - trimeshShape.getNormal(triangles[_i3], normal); + const va = sphereTrimesh_va; + const vb = sphereTrimesh_vb; + const vc = sphereTrimesh_vc; + const normal = sphereTrimesh_normal; + for (let i = 0, N = triangles.length; i !== N; i++) { + trimeshShape.getTriangleVertices(triangles[i], va, vb, vc); + trimeshShape.getNormal(triangles[i], normal); localSpherePos.vsub(va, tmp); - - var _dist2 = tmp.dot(normal); - - normal.scale(_dist2, tmp); + let dist = tmp.dot(normal); + normal.scale(dist, tmp); localSpherePos.vsub(tmp, tmp); // tmp is now the sphere position projected to the triangle plane - _dist2 = tmp.distanceTo(localSpherePos); - - if (Ray.pointInTriangle(tmp, va, vb, vc) && _dist2 < sphereShape.radius) { + dist = tmp.distanceTo(localSpherePos); + if (Ray.pointInTriangle(tmp, va, vb, vc) && dist < sphereShape.radius) { if (justTest) { return true; } - - var _r6 = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj); - - tmp.vsub(localSpherePos, _r6.ni); - - _r6.ni.normalize(); - - _r6.ni.scale(sphereShape.radius, _r6.ri); - - _r6.ri.vadd(spherePos, _r6.ri); - - _r6.ri.vsub(sphereBody.position, _r6.ri); - + let r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj); + tmp.vsub(localSpherePos, r.ni); + r.ni.normalize(); + r.ni.scale(sphereShape.radius, r.ri); + r.ri.vadd(spherePos, r.ri); + r.ri.vsub(sphereBody.position, r.ri); Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp); - tmp.vsub(trimeshBody.position, _r6.rj); - Transform.vectorToWorldFrame(trimeshQuat, _r6.ni, _r6.ni); - Transform.vectorToWorldFrame(trimeshQuat, _r6.ri, _r6.ri); - this.result.push(_r6); - this.createFrictionEquationsFromContact(_r6, this.frictionResult); + tmp.vsub(trimeshBody.position, r.rj); + Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni); + Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri); + this.result.push(r); + this.createFrictionEquationsFromContact(r, this.frictionResult); } } - triangles.length = 0; - }; - - _proto.planeTrimesh = function planeTrimesh(planeShape, trimeshShape, planePos, trimeshPos, planeQuat, trimeshQuat, planeBody, trimeshBody, rsi, rsj, justTest) { + } + planeTrimesh(planeShape, trimeshShape, planePos, trimeshPos, planeQuat, trimeshQuat, planeBody, trimeshBody, rsi, rsj, justTest) { // Make contacts! - var v = new Vec3(); - var normal = planeTrimesh_normal; + const v = new Vec3(); + const normal = planeTrimesh_normal; normal.set(0, 0, 1); planeQuat.vmult(normal, normal); // Turn normal according to plane - for (var i = 0; i < trimeshShape.vertices.length / 3; i++) { + for (let i = 0; i < trimeshShape.vertices.length / 3; i++) { // Get world vertex from trimesh trimeshShape.getVertex(i, v); // Safe up - var v2 = new Vec3(); + const v2 = new Vec3(); v2.copy(v); Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v); // Check plane side - var relpos = planeTrimesh_relpos; + const relpos = planeTrimesh_relpos; v.vsub(planePos, relpos); - var dot = normal.dot(relpos); - + const dot = normal.dot(relpos); if (dot <= 0.0) { if (justTest) { return true; } - - var r = this.createContactEquation(planeBody, trimeshBody, planeShape, trimeshShape, rsi, rsj); + const r = this.createContactEquation(planeBody, trimeshBody, planeShape, trimeshShape, rsi, rsj); r.ni.copy(normal); // Contact normal is the plane normal // Get vertex position projected on plane - var projected = planeTrimesh_projected; + const projected = planeTrimesh_projected; normal.scale(relpos.dot(normal), projected); v.vsub(projected, projected); // ri is the projected world position minus plane position @@ -12555,160 +10695,144 @@ var Narrowphase = /*#__PURE__*/function () { // } // } // } - ; - - return Narrowphase; -}(); -var averageNormal = new Vec3(); -var averageContactPointA = new Vec3(); -var averageContactPointB = new Vec3(); -var tmpVec1$3 = new Vec3(); -var tmpVec2$3 = new Vec3(); -var tmpQuat1 = new Quaternion(); -var tmpQuat2 = new Quaternion(); - +} +exports.Narrowphase = Narrowphase; +const averageNormal = new Vec3(); +const averageContactPointA = new Vec3(); +const averageContactPointB = new Vec3(); +const tmpVec1$2 = new Vec3(); +const tmpVec2$2 = new Vec3(); +const tmpQuat1 = new Quaternion(); +const tmpQuat2 = new Quaternion(); Narrowphase.prototype[COLLISION_TYPES.boxBox] = Narrowphase.prototype.boxBox; Narrowphase.prototype[COLLISION_TYPES.boxConvex] = Narrowphase.prototype.boxConvex; Narrowphase.prototype[COLLISION_TYPES.boxParticle] = Narrowphase.prototype.boxParticle; Narrowphase.prototype[COLLISION_TYPES.sphereSphere] = Narrowphase.prototype.sphereSphere; -var planeTrimesh_normal = new Vec3(); -var planeTrimesh_relpos = new Vec3(); -var planeTrimesh_projected = new Vec3(); +const planeTrimesh_normal = new Vec3(); +const planeTrimesh_relpos = new Vec3(); +const planeTrimesh_projected = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.planeTrimesh] = Narrowphase.prototype.planeTrimesh; -var sphereTrimesh_normal = new Vec3(); -var sphereTrimesh_relpos = new Vec3(); -var sphereTrimesh_projected = new Vec3(); -var sphereTrimesh_v = new Vec3(); -var sphereTrimesh_v2 = new Vec3(); -var sphereTrimesh_edgeVertexA = new Vec3(); -var sphereTrimesh_edgeVertexB = new Vec3(); -var sphereTrimesh_edgeVector = new Vec3(); -var sphereTrimesh_edgeVectorUnit = new Vec3(); -var sphereTrimesh_localSpherePos = new Vec3(); -var sphereTrimesh_tmp = new Vec3(); -var sphereTrimesh_va = new Vec3(); -var sphereTrimesh_vb = new Vec3(); -var sphereTrimesh_vc = new Vec3(); -var sphereTrimesh_localSphereAABB = new AABB(); -var sphereTrimesh_triangles = []; +const sphereTrimesh_normal = new Vec3(); +const sphereTrimesh_relpos = new Vec3(); +const sphereTrimesh_v = new Vec3(); +const sphereTrimesh_v2 = new Vec3(); +const sphereTrimesh_edgeVertexA = new Vec3(); +const sphereTrimesh_edgeVertexB = new Vec3(); +const sphereTrimesh_edgeVector = new Vec3(); +const sphereTrimesh_edgeVectorUnit = new Vec3(); +const sphereTrimesh_localSpherePos = new Vec3(); +const sphereTrimesh_tmp = new Vec3(); +const sphereTrimesh_va = new Vec3(); +const sphereTrimesh_vb = new Vec3(); +const sphereTrimesh_vc = new Vec3(); +const sphereTrimesh_localSphereAABB = new AABB(); +const sphereTrimesh_triangles = []; Narrowphase.prototype[COLLISION_TYPES.sphereTrimesh] = Narrowphase.prototype.sphereTrimesh; -var point_on_plane_to_sphere = new Vec3(); -var plane_to_sphere_ortho = new Vec3(); +const point_on_plane_to_sphere = new Vec3(); +const plane_to_sphere_ortho = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.spherePlane] = Narrowphase.prototype.spherePlane; // See http://bulletphysics.com/Bullet/BulletFull/SphereTriangleDetector_8cpp_source.html -var pointInPolygon_edge = new Vec3(); -var pointInPolygon_edge_x_normal = new Vec3(); -var pointInPolygon_vtp = new Vec3(); - +const pointInPolygon_edge = new Vec3(); +const pointInPolygon_edge_x_normal = new Vec3(); +const pointInPolygon_vtp = new Vec3(); function pointInPolygon(verts, normal, p) { - var positiveResult = null; - var N = verts.length; + let positiveResult = null; + const N = verts.length; + for (let i = 0; i !== N; i++) { + const v = verts[i]; // Get edge to the next vertex - for (var i = 0; i !== N; i++) { - var v = verts[i]; // Get edge to the next vertex - - var edge = pointInPolygon_edge; + const edge = pointInPolygon_edge; verts[(i + 1) % N].vsub(v, edge); // Get cross product between polygon normal and the edge - var edge_x_normal = pointInPolygon_edge_x_normal; //const edge_x_normal = new Vec3(); + const edge_x_normal = pointInPolygon_edge_x_normal; //const edge_x_normal = new Vec3(); edge.cross(normal, edge_x_normal); // Get vector between point and current vertex - var vertex_to_p = pointInPolygon_vtp; + const vertex_to_p = pointInPolygon_vtp; p.vsub(v, vertex_to_p); // This dot product determines which side of the edge the point is - var r = edge_x_normal.dot(vertex_to_p); // If all such dot products have same sign, we are inside the polygon. + const r = edge_x_normal.dot(vertex_to_p); // If all such dot products have same sign, we are inside the polygon. if (positiveResult === null || r > 0 && positiveResult === true || r <= 0 && positiveResult === false) { if (positiveResult === null) { positiveResult = r > 0; } - continue; } else { return false; // Encountered some other sign. Exit. } } // If we got here, all dot products were of the same sign. - return true; } - -var box_to_sphere = new Vec3(); -var sphereBox_ns = new Vec3(); -var sphereBox_ns1 = new Vec3(); -var sphereBox_ns2 = new Vec3(); -var sphereBox_sides = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()]; -var sphereBox_sphere_to_corner = new Vec3(); -var sphereBox_side_ns = new Vec3(); -var sphereBox_side_ns1 = new Vec3(); -var sphereBox_side_ns2 = new Vec3(); +const box_to_sphere = new Vec3(); +const sphereBox_ns = new Vec3(); +const sphereBox_ns1 = new Vec3(); +const sphereBox_ns2 = new Vec3(); +const sphereBox_sides = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()]; +const sphereBox_sphere_to_corner = new Vec3(); +const sphereBox_side_ns = new Vec3(); +const sphereBox_side_ns1 = new Vec3(); +const sphereBox_side_ns2 = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.sphereBox] = Narrowphase.prototype.sphereBox; -var convex_to_sphere = new Vec3(); -var sphereConvex_edge = new Vec3(); -var sphereConvex_edgeUnit = new Vec3(); -var sphereConvex_sphereToCorner = new Vec3(); -var sphereConvex_worldCorner = new Vec3(); -var sphereConvex_worldNormal = new Vec3(); -var sphereConvex_worldPoint = new Vec3(); -var sphereConvex_worldSpherePointClosestToPlane = new Vec3(); -var sphereConvex_penetrationVec = new Vec3(); -var sphereConvex_sphereToWorldPoint = new Vec3(); +const convex_to_sphere = new Vec3(); +const sphereConvex_edge = new Vec3(); +const sphereConvex_edgeUnit = new Vec3(); +const sphereConvex_sphereToCorner = new Vec3(); +const sphereConvex_worldCorner = new Vec3(); +const sphereConvex_worldNormal = new Vec3(); +const sphereConvex_worldPoint = new Vec3(); +const sphereConvex_worldSpherePointClosestToPlane = new Vec3(); +const sphereConvex_penetrationVec = new Vec3(); +const sphereConvex_sphereToWorldPoint = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.sphereConvex] = Narrowphase.prototype.sphereConvex; -var planeBox_normal = new Vec3(); -var plane_to_corner = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.planeBox] = Narrowphase.prototype.planeBox; -var planeConvex_v = new Vec3(); -var planeConvex_normal = new Vec3(); -var planeConvex_relpos = new Vec3(); -var planeConvex_projected = new Vec3(); +const planeConvex_v = new Vec3(); +const planeConvex_normal = new Vec3(); +const planeConvex_relpos = new Vec3(); +const planeConvex_projected = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.planeConvex] = Narrowphase.prototype.planeConvex; -var convexConvex_sepAxis = new Vec3(); -var convexConvex_q = new Vec3(); +const convexConvex_sepAxis = new Vec3(); +const convexConvex_q = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.convexConvex] = Narrowphase.prototype.convexConvex; // Narrowphase.prototype[COLLISION_TYPES.convexTrimesh] = Narrowphase.prototype.convexTrimesh -var particlePlane_normal = new Vec3(); -var particlePlane_relpos = new Vec3(); -var particlePlane_projected = new Vec3(); +const particlePlane_normal = new Vec3(); +const particlePlane_relpos = new Vec3(); +const particlePlane_projected = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.planeParticle] = Narrowphase.prototype.planeParticle; -var particleSphere_normal = new Vec3(); +const particleSphere_normal = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.sphereParticle] = Narrowphase.prototype.sphereParticle; // WIP -var cqj = new Quaternion(); -var convexParticle_local = new Vec3(); -var convexParticle_normal = new Vec3(); -var convexParticle_penetratedFaceNormal = new Vec3(); -var convexParticle_vertexToParticle = new Vec3(); -var convexParticle_worldPenetrationVec = new Vec3(); +const cqj = new Quaternion(); +const convexParticle_local = new Vec3(); +const convexParticle_penetratedFaceNormal = new Vec3(); +const convexParticle_vertexToParticle = new Vec3(); +const convexParticle_worldPenetrationVec = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.convexParticle] = Narrowphase.prototype.convexParticle; Narrowphase.prototype[COLLISION_TYPES.boxHeightfield] = Narrowphase.prototype.boxHeightfield; -var convexHeightfield_tmp1 = new Vec3(); -var convexHeightfield_tmp2 = new Vec3(); -var convexHeightfield_faceList = [0]; +const convexHeightfield_tmp1 = new Vec3(); +const convexHeightfield_tmp2 = new Vec3(); +const convexHeightfield_faceList = [0]; Narrowphase.prototype[COLLISION_TYPES.convexHeightfield] = Narrowphase.prototype.convexHeightfield; -var sphereHeightfield_tmp1 = new Vec3(); -var sphereHeightfield_tmp2 = new Vec3(); +const sphereHeightfield_tmp1 = new Vec3(); +const sphereHeightfield_tmp2 = new Vec3(); Narrowphase.prototype[COLLISION_TYPES.sphereHeightfield] = Narrowphase.prototype.sphereHeightfield; /** * @class OverlapKeeper * @constructor */ -var OverlapKeeper = /*#__PURE__*/function () { - function OverlapKeeper() { +class OverlapKeeper { + constructor() { this.current = []; this.previous = []; } - - var _proto = OverlapKeeper.prototype; - - _proto.getKey = function getKey(i, j) { + getKey(i, j) { if (j < i) { - var temp = j; + const temp = j; j = i; i = temp; } - return i << 16 | j; } /** @@ -12716,35 +10840,30 @@ var OverlapKeeper = /*#__PURE__*/function () { * @param {Number} i * @param {Number} j */ - ; - _proto.set = function set(i, j) { + set(i, j) { // Insertion sort. This way the diff will have linear complexity. - var key = this.getKey(i, j); - var current = this.current; - var index = 0; - + const key = this.getKey(i, j); + const current = this.current; + let index = 0; while (key > current[index]) { index++; } - if (key === current[index]) { return; // Pair was already added } - for (var _j = current.length - 1; _j >= index; _j--) { - current[_j + 1] = current[_j]; + for (let j = current.length - 1; j >= index; j--) { + current[j + 1] = current[j]; } - current[index] = key; } /** * @method tick */ - ; - _proto.tick = function tick() { - var tmp = this.current; + tick() { + const tmp = this.current; this.current = this.previous; this.previous = tmp; this.current.length = 0; @@ -12754,51 +10873,38 @@ var OverlapKeeper = /*#__PURE__*/function () { * @param {array} additions * @param {array} removals */ - ; - - _proto.getDiff = function getDiff(additions, removals) { - var a = this.current; - var b = this.previous; - var al = a.length; - var bl = b.length; - var j = 0; - - for (var i = 0; i < al; i++) { - var found = false; - var keyA = a[i]; + getDiff(additions, removals) { + const a = this.current; + const b = this.previous; + const al = a.length; + const bl = b.length; + let j = 0; + for (let i = 0; i < al; i++) { + let found = false; + const keyA = a[i]; while (keyA > b[j]) { j++; } - found = keyA === b[j]; - if (!found) { unpackAndPush(additions, keyA); } } - j = 0; - - for (var _i = 0; _i < bl; _i++) { - var _found = false; - var keyB = b[_i]; - + for (let i = 0; i < bl; i++) { + let found = false; + const keyB = b[i]; while (keyB > a[j]) { j++; } - - _found = a[j] === keyB; - - if (!_found) { + found = a[j] === keyB; + if (!found) { unpackAndPush(removals, keyB); } } - }; - - return OverlapKeeper; -}(); - + } +} function unpackAndPush(array, key) { array.push((key & 0xffff0000) >> 16, key & 0x0000ffff); } @@ -12807,8 +10913,8 @@ function unpackAndPush(array, key) { * @class TupleDictionary * @constructor */ -var TupleDictionary = /*#__PURE__*/function () { - function TupleDictionary() { +class TupleDictionary { + constructor() { this.data = { keys: [] }; @@ -12820,17 +10926,13 @@ var TupleDictionary = /*#__PURE__*/function () { * @return {Object} */ - - var _proto = TupleDictionary.prototype; - - _proto.get = function get(i, j) { + get(i, j) { if (i > j) { // swap - var temp = j; + const temp = j; j = i; i = temp; } - return this.data[i + "-" + j]; } /** @@ -12839,40 +10941,33 @@ var TupleDictionary = /*#__PURE__*/function () { * @param {Number} j * @param {Object} value */ - ; - _proto.set = function set(i, j, value) { + set(i, j, value) { if (i > j) { - var temp = j; + const temp = j; j = i; i = temp; } - - var key = i + "-" + j; // Check if key already exists + const key = i + "-" + j; // Check if key already exists if (!this.get(i, j)) { this.data.keys.push(key); } - this.data[key] = value; } /** * @method reset */ - ; - - _proto.reset = function reset() { - var data = this.data; - var keys = data.keys; + reset() { + const data = this.data; + const keys = data.keys; while (keys.length > 0) { - var key = keys.pop(); + const key = keys.pop(); delete data[key]; } - }; - - return TupleDictionary; -}(); + } +} /** * The physics world @@ -12887,9 +10982,7 @@ var TupleDictionary = /*#__PURE__*/function () { * @param {boolean} [options.quatNormalizeFast] * @param {number} [options.quatNormalizeSkip] */ -var World = /*#__PURE__*/function (_EventTarget) { - _inheritsLoose(World, _EventTarget); - +class World extends EventTarget { // Currently / last used timestep. Is set to -1 if not available. This value is updated before each internal step, which means that it is "fresh" inside event callbacks. // Makes bodies go to sleep when they've been inactive. // All the current contacts (instances of ContactEquation) in the world. @@ -12909,71 +11002,60 @@ var World = /*#__PURE__*/function (_EventTarget) { // Time accumulator for interpolation. See http://gafferongames.com/game-physics/fix-your-timestep/ // Dispatched after a body has been added to the world. // Dispatched after a body has been removed from the world. - function World(options) { - var _this; - - if (options === void 0) { - options = {}; - } - - _this = _EventTarget.call(this) || this; - _this.dt = -1; - _this.allowSleep = !!options.allowSleep; - _this.contacts = []; - _this.frictionEquations = []; - _this.quatNormalizeSkip = options.quatNormalizeSkip !== undefined ? options.quatNormalizeSkip : 0; - _this.quatNormalizeFast = options.quatNormalizeFast !== undefined ? options.quatNormalizeFast : false; - _this.time = 0.0; - _this.stepnumber = 0; - _this.default_dt = 1 / 60; - _this.nextId = 0; - _this.gravity = new Vec3(); - + constructor(options = {}) { + super(); + this.dt = -1; + this.allowSleep = !!options.allowSleep; + this.contacts = []; + this.frictionEquations = []; + this.quatNormalizeSkip = options.quatNormalizeSkip !== undefined ? options.quatNormalizeSkip : 0; + this.quatNormalizeFast = options.quatNormalizeFast !== undefined ? options.quatNormalizeFast : false; + this.time = 0.0; + this.stepnumber = 0; + this.default_dt = 1 / 60; + this.nextId = 0; + this.gravity = new Vec3(); if (options.gravity) { - _this.gravity.copy(options.gravity); - } - - _this.broadphase = options.broadphase !== undefined ? options.broadphase : new NaiveBroadphase(); - _this.bodies = []; - _this.hasActiveBodies = false; - _this.solver = options.solver !== undefined ? options.solver : new GSSolver(); - _this.constraints = []; - _this.narrowphase = new Narrowphase(_assertThisInitialized(_this)); - _this.collisionMatrix = new ArrayCollisionMatrix(); - _this.collisionMatrixPrevious = new ArrayCollisionMatrix(); - _this.bodyOverlapKeeper = new OverlapKeeper(); - _this.shapeOverlapKeeper = new OverlapKeeper(); - _this.materials = []; - _this.contactmaterials = []; - _this.contactMaterialTable = new TupleDictionary(); - _this.defaultMaterial = new Material('default'); - _this.defaultContactMaterial = new ContactMaterial(_this.defaultMaterial, _this.defaultMaterial, { + this.gravity.copy(options.gravity); + } + this.broadphase = options.broadphase !== undefined ? options.broadphase : new NaiveBroadphase(); + this.bodies = []; + this.hasActiveBodies = false; + this.solver = options.solver !== undefined ? options.solver : new GSSolver(); + this.constraints = []; + this.narrowphase = new Narrowphase(this); + this.collisionMatrix = new ArrayCollisionMatrix(); + this.collisionMatrixPrevious = new ArrayCollisionMatrix(); + this.bodyOverlapKeeper = new OverlapKeeper(); + this.shapeOverlapKeeper = new OverlapKeeper(); + this.materials = []; + this.contactmaterials = []; + this.contactMaterialTable = new TupleDictionary(); + this.defaultMaterial = new Material('default'); + this.defaultContactMaterial = new ContactMaterial(this.defaultMaterial, this.defaultMaterial, { friction: 0.3, restitution: 0.0 }); - _this.doProfiling = false; - _this.profile = { + this.doProfiling = false; + this.profile = { solve: 0, makeContactConstraints: 0, broadphase: 0, integrate: 0, narrowphase: 0 }; - _this.accumulator = 0; - _this.subsystems = []; - _this.addBodyEvent = { + this.accumulator = 0; + this.subsystems = []; + this.addBodyEvent = { type: 'addBody', body: null }; - _this.removeBodyEvent = { + this.removeBodyEvent = { type: 'removeBody', body: null }; - _this.idToBodyMap = {}; - - _this.broadphase.setWorld(_assertThisInitialized(_this)); - - return _this; + this.idToBodyMap = {}; + this.broadphase.setWorld(this); } /** * Get the contact material between materials m1 and m2 @@ -12983,10 +11065,7 @@ var World = /*#__PURE__*/function (_EventTarget) { * @return {ContactMaterial} The contact material if it was found. */ - - var _proto = World.prototype; - - _proto.getContactMaterial = function getContactMaterial(m1, m2) { + getContactMaterial(m1, m2) { return this.contactMaterialTable.get(m1.id, m2.id); } /** @@ -12995,19 +11074,17 @@ var World = /*#__PURE__*/function (_EventTarget) { * @return {Number} * @deprecated */ - ; - _proto.numObjects = function numObjects() { + numObjects() { return this.bodies.length; } /** * Store old collision state info * @method collisionMatrixTick */ - ; - _proto.collisionMatrixTick = function collisionMatrixTick() { - var temp = this.collisionMatrixPrevious; + collisionMatrixTick() { + const temp = this.collisionMatrixPrevious; this.collisionMatrixPrevious = this.collisionMatrix; this.collisionMatrix = temp; this.collisionMatrix.reset(); @@ -13019,9 +11096,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * @method addConstraint * @param {Constraint} c */ - ; - _proto.addConstraint = function addConstraint(c) { + addConstraint(c) { this.constraints.push(c); } /** @@ -13029,11 +11105,9 @@ var World = /*#__PURE__*/function (_EventTarget) { * @method removeConstraint * @param {Constraint} c */ - ; - - _proto.removeConstraint = function removeConstraint(c) { - var idx = this.constraints.indexOf(c); + removeConstraint(c) { + const idx = this.constraints.indexOf(c); if (idx !== -1) { this.constraints.splice(idx, 1); } @@ -13046,9 +11120,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * @param {RaycastResult} result * @deprecated Use .raycastAll, .raycastClosest or .raycastAny instead. */ - ; - _proto.rayTest = function rayTest(from, to, result) { + rayTest(from, to, result) { if (result instanceof RaycastResult) { // Do raycastClosest this.raycastClosest(from, to, { @@ -13074,13 +11147,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * @param {Function} callback * @return {boolean} True if any body was hit. */ - ; - - _proto.raycastAll = function raycastAll(from, to, options, callback) { - if (options === void 0) { - options = {}; - } + raycastAll(from, to, options = {}, callback) { options.mode = Ray.ALL; options.from = from; options.to = to; @@ -13100,13 +11168,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * @param {RaycastResult} result * @return {boolean} True if any body was hit. */ - ; - - _proto.raycastAny = function raycastAny(from, to, options, result) { - if (options === void 0) { - options = {}; - } + raycastAny(from, to, options = {}, result) { options.mode = Ray.ANY; options.from = from; options.to = to; @@ -13126,13 +11189,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * @param {RaycastResult} result * @return {boolean} True if any body was hit. */ - ; - - _proto.raycastClosest = function raycastClosest(from, to, options, result) { - if (options === void 0) { - options = {}; - } + raycastClosest(from, to, options = {}, result) { options.mode = Ray.CLOSEST; options.from = from; options.to = to; @@ -13146,25 +11204,21 @@ var World = /*#__PURE__*/function (_EventTarget) { * @todo If the simulation has not yet started, why recrete and copy arrays for each body? Accumulate in dynamic arrays in this case. * @todo Adding an array of bodies should be possible. This would save some loops too */ - ; - _proto.addBody = function addBody(body) { + addBody(body) { if (this.bodies.includes(body)) { return; } - body.index = this.bodies.length; this.bodies.push(body); body.world = this; body.initPosition.copy(body.position); body.initVelocity.copy(body.velocity); body.timeLastSleepy = this.time; - if (body instanceof Body) { body.initAngularVelocity.copy(body.angularVelocity); body.initQuaternion.copy(body.quaternion); } - this.collisionMatrix.setNumObjects(this.bodies.length); this.addBodyEvent.body = body; this.idToBodyMap[body.id] = body; @@ -13175,43 +11229,35 @@ var World = /*#__PURE__*/function (_EventTarget) { * @method remove * @param {Body} body */ - ; - _proto.removeBody = function removeBody(body) { + removeBody(body) { body.world = null; - var n = this.bodies.length - 1; - var bodies = this.bodies; - var idx = bodies.indexOf(body); - + const n = this.bodies.length - 1; + const bodies = this.bodies; + const idx = bodies.indexOf(body); if (idx !== -1) { bodies.splice(idx, 1); // Todo: should use a garbage free method // Recompute index - for (var i = 0; i !== bodies.length; i++) { + for (let i = 0; i !== bodies.length; i++) { bodies[i].index = i; } - this.collisionMatrix.setNumObjects(n); this.removeBodyEvent.body = body; delete this.idToBodyMap[body.id]; this.dispatchEvent(this.removeBodyEvent); } - }; - - _proto.getBodyById = function getBodyById(id) { + } + getBodyById(id) { return this.idToBodyMap[id]; } // TODO Make a faster map - ; - - _proto.getShapeById = function getShapeById(id) { - var bodies = this.bodies; - - for (var i = 0, bl = bodies.length; i < bl; i++) { - var shapes = bodies[i].shapes; - - for (var j = 0, sl = shapes.length; j < sl; j++) { - var shape = shapes[j]; + getShapeById(id) { + const bodies = this.bodies; + for (let i = 0, bl = bodies.length; i < bl; i++) { + const shapes = bodies[i].shapes; + for (let j = 0, sl = shapes.length; j < sl; j++) { + const shape = shapes[j]; if (shape.id === id) { return shape; } @@ -13224,9 +11270,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * @param {Material} m * @todo Necessary? */ - ; - _proto.addMaterial = function addMaterial(m) { + addMaterial(m) { this.materials.push(m); } /** @@ -13234,9 +11279,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * @method addContactMaterial * @param {ContactMaterial} cmat */ - ; - _proto.addContactMaterial = function addContactMaterial(cmat) { + addContactMaterial(cmat) { // Add contact material this.contactmaterials.push(cmat); // Add current contact material to the material table @@ -13258,17 +11302,8 @@ var World = /*#__PURE__*/function (_EventTarget) { * * @see http://bulletphysics.org/mediawiki-1.5.8/index.php/Stepping_The_World */ - ; - - _proto.step = function step(dt, timeSinceLastCalled, maxSubSteps) { - if (timeSinceLastCalled === void 0) { - timeSinceLastCalled = 0; - } - - if (maxSubSteps === void 0) { - maxSubSteps = 10; - } + step(dt, timeSinceLastCalled = 0, maxSubSteps = 10) { if (timeSinceLastCalled === 0) { // Fixed, simple stepping this.internalStep(dt); // Increment time @@ -13276,94 +11311,79 @@ var World = /*#__PURE__*/function (_EventTarget) { this.time += dt; } else { this.accumulator += timeSinceLastCalled; - var substeps = 0; - + let substeps = 0; while (this.accumulator >= dt && substeps < maxSubSteps) { // Do fixed steps to catch up this.internalStep(dt); this.accumulator -= dt; substeps++; } - - var t = this.accumulator % dt / dt; - - for (var j = 0; j !== this.bodies.length; j++) { - var b = this.bodies[j]; + const t = this.accumulator % dt / dt; + for (let j = 0; j !== this.bodies.length; j++) { + const b = this.bodies[j]; b.previousPosition.lerp(b.position, t, b.interpolatedPosition); b.previousQuaternion.slerp(b.quaternion, t, b.interpolatedQuaternion); b.previousQuaternion.normalize(); } - this.time += timeSinceLastCalled; } - }; - - _proto.internalStep = function internalStep(dt) { + } + internalStep(dt) { this.dt = dt; - var contacts = this.contacts; - var p1 = World_step_p1; - var p2 = World_step_p2; - var N = this.numObjects(); - var bodies = this.bodies; - var solver = this.solver; - var gravity = this.gravity; - var doProfiling = this.doProfiling; - var profile = this.profile; - var DYNAMIC = Body.DYNAMIC; - var profilingStart = -Infinity; - var constraints = this.constraints; - var frictionEquationPool = World_step_frictionEquationPool; - var gnorm = gravity.length(); - var gx = gravity.x; - var gy = gravity.y; - var gz = gravity.z; - var i = 0; - + const contacts = this.contacts; + const p1 = World_step_p1; + const p2 = World_step_p2; + const N = this.numObjects(); + const bodies = this.bodies; + const solver = this.solver; + const gravity = this.gravity; + const doProfiling = this.doProfiling; + const profile = this.profile; + const DYNAMIC = Body.DYNAMIC; + let profilingStart = -Infinity; + const constraints = this.constraints; + const frictionEquationPool = World_step_frictionEquationPool; + const gnorm = gravity.length(); + const gx = gravity.x; + const gy = gravity.y; + const gz = gravity.z; + let i = 0; if (doProfiling) { profilingStart = performance.now(); } // Add gravity to all objects - for (i = 0; i !== N; i++) { - var bi = bodies[i]; - + const bi = bodies[i]; if (bi.type === DYNAMIC) { // Only for dynamic bodies - var f = bi.force; - var m = bi.mass; + const f = bi.force; + const m = bi.mass; f.x += m * gx; f.y += m * gy; f.z += m * gz; } } // Update subsystems - - for (var _i = 0, Nsubsystems = this.subsystems.length; _i !== Nsubsystems; _i++) { - this.subsystems[_i].update(); + for (let i = 0, Nsubsystems = this.subsystems.length; i !== Nsubsystems; i++) { + this.subsystems[i].update(); } // Collision detection - if (doProfiling) { profilingStart = performance.now(); } - p1.length = 0; // Clean up pair arrays from last step p2.length = 0; this.broadphase.collisionPairs(this, p1, p2); - if (doProfiling) { profile.broadphase = performance.now() - profilingStart; } // Remove constrained pairs with collideConnected == false - - var Nconstraints = constraints.length; - + let Nconstraints = constraints.length; for (i = 0; i !== Nconstraints; i++) { - var c = constraints[i]; - + const c = constraints[i]; if (!c.collideConnected) { - for (var j = p1.length - 1; j >= 0; j -= 1) { + for (let j = p1.length - 1; j >= 0; j -= 1) { if (c.bodyA === p1[j] && c.bodyB === p2[j] || c.bodyB === p1[j] && c.bodyA === p2[j]) { p1.splice(j, 1); p2.splice(j, 1); @@ -13371,76 +11391,63 @@ var World = /*#__PURE__*/function (_EventTarget) { } } } - this.collisionMatrixTick(); // Generate contacts if (doProfiling) { profilingStart = performance.now(); } - - var oldcontacts = World_step_oldContacts; - var NoldContacts = contacts.length; - + const oldcontacts = World_step_oldContacts; + const NoldContacts = contacts.length; for (i = 0; i !== NoldContacts; i++) { oldcontacts.push(contacts[i]); } - contacts.length = 0; // Transfer FrictionEquation from current list to the pool for reuse - var NoldFrictionEquations = this.frictionEquations.length; - + const NoldFrictionEquations = this.frictionEquations.length; for (i = 0; i !== NoldFrictionEquations; i++) { frictionEquationPool.push(this.frictionEquations[i]); } - this.frictionEquations.length = 0; - this.narrowphase.getContacts(p1, p2, this, contacts, oldcontacts, // To be reused + this.narrowphase.getContacts(p1, p2, this, contacts, oldcontacts, + // To be reused this.frictionEquations, frictionEquationPool); - if (doProfiling) { profile.narrowphase = performance.now() - profilingStart; } // Loop over all collisions - if (doProfiling) { profilingStart = performance.now(); } // Add all friction eqs - for (i = 0; i < this.frictionEquations.length; i++) { solver.addEquation(this.frictionEquations[i]); } - - var ncontacts = contacts.length; - - for (var k = 0; k !== ncontacts; k++) { + const ncontacts = contacts.length; + for (let k = 0; k !== ncontacts; k++) { // Current contact - var _c = contacts[k]; // Get current collision indeces - - var _bi = _c.bi; - var bj = _c.bj; - var si = _c.si; - var sj = _c.sj; // Get collision properties + const c = contacts[k]; // Get current collision indeces - var cm = void 0; + const bi = c.bi; + const bj = c.bj; + const si = c.si; + const sj = c.sj; // Get collision properties - if (_bi.material && bj.material) { - cm = this.getContactMaterial(_bi.material, bj.material) || this.defaultContactMaterial; + let cm; + if (bi.material && bj.material) { + cm = this.getContactMaterial(bi.material, bj.material) || this.defaultContactMaterial; } else { cm = this.defaultContactMaterial; } // c.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse; - - var mu = cm.friction; // c.restitution = cm.restitution; + let mu = cm.friction; // c.restitution = cm.restitution; // If friction or restitution were specified in the material, use them - if (_bi.material && bj.material) { - if (_bi.material.friction >= 0 && bj.material.friction >= 0) { - mu = _bi.material.friction * bj.material.friction; + if (bi.material && bj.material) { + if (bi.material.friction >= 0 && bj.material.friction >= 0) { + mu = bi.material.friction * bj.material.friction; } - - if (_bi.material.restitution >= 0 && bj.material.restitution >= 0) { - _c.restitution = _bi.material.restitution * bj.material.restitution; + if (bi.material.restitution >= 0 && bj.material.restitution >= 0) { + c.restitution = bi.material.restitution * bj.material.restitution; } } // c.setSpookParams( // cm.contactEquationStiffness, @@ -13448,8 +11455,7 @@ var World = /*#__PURE__*/function (_EventTarget) { // dt // ); - - solver.addEquation(_c); // // Add friction constraint equation + solver.addEquation(c); // // Add friction constraint equation // if(mu > 0){ // // Create 2 tangent equations // const mug = mu * gnorm; @@ -13481,254 +11487,203 @@ var World = /*#__PURE__*/function (_EventTarget) { // solver.addEquation(c2); // } - if (_bi.allowSleep && _bi.type === Body.DYNAMIC && _bi.sleepState === Body.SLEEPING && bj.sleepState === Body.AWAKE && bj.type !== Body.STATIC) { - var speedSquaredB = bj.velocity.lengthSquared() + bj.angularVelocity.lengthSquared(); - var speedLimitSquaredB = Math.pow(bj.sleepSpeedLimit, 2); - + if (bi.allowSleep && bi.type === Body.DYNAMIC && bi.sleepState === Body.SLEEPING && bj.sleepState === Body.AWAKE && bj.type !== Body.STATIC) { + const speedSquaredB = bj.velocity.lengthSquared() + bj.angularVelocity.lengthSquared(); + const speedLimitSquaredB = bj.sleepSpeedLimit ** 2; if (speedSquaredB >= speedLimitSquaredB * 2) { - _bi.wakeUpAfterNarrowphase = true; + bi.wakeUpAfterNarrowphase = true; } } - - if (bj.allowSleep && bj.type === Body.DYNAMIC && bj.sleepState === Body.SLEEPING && _bi.sleepState === Body.AWAKE && _bi.type !== Body.STATIC) { - var speedSquaredA = _bi.velocity.lengthSquared() + _bi.angularVelocity.lengthSquared(); - - var speedLimitSquaredA = Math.pow(_bi.sleepSpeedLimit, 2); - + if (bj.allowSleep && bj.type === Body.DYNAMIC && bj.sleepState === Body.SLEEPING && bi.sleepState === Body.AWAKE && bi.type !== Body.STATIC) { + const speedSquaredA = bi.velocity.lengthSquared() + bi.angularVelocity.lengthSquared(); + const speedLimitSquaredA = bi.sleepSpeedLimit ** 2; if (speedSquaredA >= speedLimitSquaredA * 2) { bj.wakeUpAfterNarrowphase = true; } } // Now we know that i and j are in contact. Set collision matrix state - - this.collisionMatrix.set(_bi, bj, true); - - if (!this.collisionMatrixPrevious.get(_bi, bj)) { + this.collisionMatrix.set(bi, bj, true); + if (!this.collisionMatrixPrevious.get(bi, bj)) { // First contact! // We reuse the collideEvent object, otherwise we will end up creating new objects for each new contact, even if there's no event listener attached. World_step_collideEvent.body = bj; - World_step_collideEvent.contact = _c; - - _bi.dispatchEvent(World_step_collideEvent); - - World_step_collideEvent.body = _bi; + World_step_collideEvent.contact = c; + bi.dispatchEvent(World_step_collideEvent); + World_step_collideEvent.body = bi; bj.dispatchEvent(World_step_collideEvent); } - - this.bodyOverlapKeeper.set(_bi.id, bj.id); + this.bodyOverlapKeeper.set(bi.id, bj.id); this.shapeOverlapKeeper.set(si.id, sj.id); } - this.emitContactEvents(); - if (doProfiling) { profile.makeContactConstraints = performance.now() - profilingStart; profilingStart = performance.now(); } // Wake up bodies - for (i = 0; i !== N; i++) { - var _bi2 = bodies[i]; - - if (_bi2.wakeUpAfterNarrowphase) { - _bi2.wakeUp(); - - _bi2.wakeUpAfterNarrowphase = false; + const bi = bodies[i]; + if (bi.wakeUpAfterNarrowphase) { + bi.wakeUp(); + bi.wakeUpAfterNarrowphase = false; } } // Add user-added constraints - Nconstraints = constraints.length; - for (i = 0; i !== Nconstraints; i++) { - var _c2 = constraints[i]; - - _c2.update(); - - for (var _j = 0, Neq = _c2.equations.length; _j !== Neq; _j++) { - var eq = _c2.equations[_j]; + const c = constraints[i]; + c.update(); + for (let j = 0, Neq = c.equations.length; j !== Neq; j++) { + const eq = c.equations[j]; solver.addEquation(eq); } } // Solve the constrained system - solver.solve(dt, this); - if (doProfiling) { profile.solve = performance.now() - profilingStart; } // Remove all contacts from solver - solver.removeAllEquations(); // Apply damping, see http://code.google.com/p/bullet/issues/detail?id=74 for details - var pow = Math.pow; - + const pow = Math.pow; for (i = 0; i !== N; i++) { - var _bi3 = bodies[i]; - - if (_bi3.type & DYNAMIC) { + const bi = bodies[i]; + if (bi.type & DYNAMIC) { // Only for dynamic bodies - var ld = pow(1.0 - _bi3.linearDamping, dt); - var v = _bi3.velocity; + const ld = pow(1.0 - bi.linearDamping, dt); + const v = bi.velocity; v.scale(ld, v); - var av = _bi3.angularVelocity; - + const av = bi.angularVelocity; if (av) { - var ad = pow(1.0 - _bi3.angularDamping, dt); + const ad = pow(1.0 - bi.angularDamping, dt); av.scale(ad, av); } } } - this.dispatchEvent(World_step_preStepEvent); // Invoke pre-step callbacks for (i = 0; i !== N; i++) { - var _bi4 = bodies[i]; - - if (_bi4.preStep) { - _bi4.preStep.call(_bi4); + const bi = bodies[i]; + if (bi.preStep) { + bi.preStep.call(bi); } } // Leap frog // vnew = v + h*f/m // xnew = x + h*vnew - if (doProfiling) { profilingStart = performance.now(); } - - var stepnumber = this.stepnumber; - var quatNormalize = stepnumber % (this.quatNormalizeSkip + 1) === 0; - var quatNormalizeFast = this.quatNormalizeFast; - + const stepnumber = this.stepnumber; + const quatNormalize = stepnumber % (this.quatNormalizeSkip + 1) === 0; + const quatNormalizeFast = this.quatNormalizeFast; for (i = 0; i !== N; i++) { bodies[i].integrate(dt, quatNormalize, quatNormalizeFast); } - this.clearForces(); this.broadphase.dirty = true; - if (doProfiling) { profile.integrate = performance.now() - profilingStart; } // Update world time - this.time += dt; this.stepnumber += 1; this.dispatchEvent(World_step_postStepEvent); // Invoke post-step callbacks for (i = 0; i !== N; i++) { - var _bi5 = bodies[i]; - var postStep = _bi5.postStep; - + const bi = bodies[i]; + const postStep = bi.postStep; if (postStep) { - postStep.call(_bi5); + postStep.call(bi); } } // Sleeping update - - var hasActiveBodies = true; - + let hasActiveBodies = true; if (this.allowSleep) { hasActiveBodies = false; - for (i = 0; i !== N; i++) { - var _bi6 = bodies[i]; - - _bi6.sleepTick(this.time); - - if (_bi6.sleepState !== Body.SLEEPING) { + const bi = bodies[i]; + bi.sleepTick(this.time); + if (bi.sleepState !== Body.SLEEPING) { hasActiveBodies = true; } } } - this.hasActiveBodies = hasActiveBodies; } /** * Sets all body forces in the world to zero. * @method clearForces */ - ; - _proto.clearForces = function clearForces() { - var bodies = this.bodies; - var N = bodies.length; - - for (var i = 0; i !== N; i++) { - var b = bodies[i]; - var force = b.force; - var tau = b.torque; + clearForces() { + const bodies = this.bodies; + const N = bodies.length; + for (let i = 0; i !== N; i++) { + const b = bodies[i]; + const force = b.force; + const tau = b.torque; b.force.set(0, 0, 0); b.torque.set(0, 0, 0); } - }; - - return World; -}(EventTarget); // Temp stuff - -var tmpAABB1 = new AABB(); -var tmpRay$1 = new Ray(); // performance.now() + } +} // Temp stuff +exports.World = World; +const tmpAABB1 = new AABB(); +const tmpRay$1 = new Ray(); // performance.now() if (typeof performance === 'undefined') { performance = {}; } - if (!performance.now) { - var nowOffset = Date.now(); - + let nowOffset = Date.now(); if (performance.timing && performance.timing.navigationStart) { nowOffset = performance.timing.navigationStart; } - - performance.now = function () { - return Date.now() - nowOffset; - }; + performance.now = () => Date.now() - nowOffset; } - -var step_tmp1 = new Vec3(); // Dispatched after the world has stepped forward in time. // Reusable event objects to save memory. -var World_step_postStepEvent = { +const World_step_postStepEvent = { type: 'postStep' }; // Dispatched before the world steps forward in time. -var World_step_preStepEvent = { +const World_step_preStepEvent = { type: 'preStep' }; -var World_step_collideEvent = { +const World_step_collideEvent = { type: Body.COLLIDE_EVENT_NAME, body: null, contact: null }; // Pools for unused objects -var World_step_oldContacts = []; -var World_step_frictionEquationPool = []; // Reusable arrays for collision pairs - -var World_step_p1 = []; -var World_step_p2 = []; +const World_step_oldContacts = []; +const World_step_frictionEquationPool = []; // Reusable arrays for collision pairs -World.prototype.emitContactEvents = function () { - var additions = []; - var removals = []; - var beginContactEvent = { +const World_step_p1 = []; +const World_step_p2 = []; +World.prototype.emitContactEvents = (() => { + const additions = []; + const removals = []; + const beginContactEvent = { type: 'beginContact', bodyA: null, bodyB: null }; - var endContactEvent = { + const endContactEvent = { type: 'endContact', bodyA: null, bodyB: null }; - var beginShapeContactEvent = { + const beginShapeContactEvent = { type: 'beginShapeContact', bodyA: null, bodyB: null, shapeA: null, shapeB: null }; - var endShapeContactEvent = { + const endShapeContactEvent = { type: 'endShapeContact', bodyA: null, bodyB: null, @@ -13736,179 +11691,118 @@ World.prototype.emitContactEvents = function () { shapeB: null }; return function () { - var hasBeginContact = this.hasAnyEventListener('beginContact'); - var hasEndContact = this.hasAnyEventListener('endContact'); - + const hasBeginContact = this.hasAnyEventListener('beginContact'); + const hasEndContact = this.hasAnyEventListener('endContact'); if (hasBeginContact || hasEndContact) { this.bodyOverlapKeeper.getDiff(additions, removals); } - if (hasBeginContact) { - for (var i = 0, l = additions.length; i < l; i += 2) { + for (let i = 0, l = additions.length; i < l; i += 2) { beginContactEvent.bodyA = this.getBodyById(additions[i]); beginContactEvent.bodyB = this.getBodyById(additions[i + 1]); this.dispatchEvent(beginContactEvent); } - beginContactEvent.bodyA = beginContactEvent.bodyB = null; } - if (hasEndContact) { - for (var _i2 = 0, _l = removals.length; _i2 < _l; _i2 += 2) { - endContactEvent.bodyA = this.getBodyById(removals[_i2]); - endContactEvent.bodyB = this.getBodyById(removals[_i2 + 1]); + for (let i = 0, l = removals.length; i < l; i += 2) { + endContactEvent.bodyA = this.getBodyById(removals[i]); + endContactEvent.bodyB = this.getBodyById(removals[i + 1]); this.dispatchEvent(endContactEvent); } - endContactEvent.bodyA = endContactEvent.bodyB = null; } - additions.length = removals.length = 0; - var hasBeginShapeContact = this.hasAnyEventListener('beginShapeContact'); - var hasEndShapeContact = this.hasAnyEventListener('endShapeContact'); - + const hasBeginShapeContact = this.hasAnyEventListener('beginShapeContact'); + const hasEndShapeContact = this.hasAnyEventListener('endShapeContact'); if (hasBeginShapeContact || hasEndShapeContact) { this.shapeOverlapKeeper.getDiff(additions, removals); } - if (hasBeginShapeContact) { - for (var _i3 = 0, _l2 = additions.length; _i3 < _l2; _i3 += 2) { - var shapeA = this.getShapeById(additions[_i3]); - var shapeB = this.getShapeById(additions[_i3 + 1]); + for (let i = 0, l = additions.length; i < l; i += 2) { + const shapeA = this.getShapeById(additions[i]); + const shapeB = this.getShapeById(additions[i + 1]); beginShapeContactEvent.shapeA = shapeA; beginShapeContactEvent.shapeB = shapeB; beginShapeContactEvent.bodyA = shapeA.body; beginShapeContactEvent.bodyB = shapeB.body; this.dispatchEvent(beginShapeContactEvent); } - beginShapeContactEvent.bodyA = beginShapeContactEvent.bodyB = beginShapeContactEvent.shapeA = beginShapeContactEvent.shapeB = null; } - if (hasEndShapeContact) { - for (var _i4 = 0, _l3 = removals.length; _i4 < _l3; _i4 += 2) { - var _shapeA = this.getShapeById(removals[_i4]); - - var _shapeB = this.getShapeById(removals[_i4 + 1]); - - endShapeContactEvent.shapeA = _shapeA; - endShapeContactEvent.shapeB = _shapeB; - endShapeContactEvent.bodyA = _shapeA.body; - endShapeContactEvent.bodyB = _shapeB.body; + for (let i = 0, l = removals.length; i < l; i += 2) { + const shapeA = this.getShapeById(removals[i]); + const shapeB = this.getShapeById(removals[i + 1]); + endShapeContactEvent.shapeA = shapeA; + endShapeContactEvent.shapeB = shapeB; + endShapeContactEvent.bodyA = shapeA.body; + endShapeContactEvent.bodyB = shapeB.body; this.dispatchEvent(endShapeContactEvent); } - endShapeContactEvent.bodyA = endShapeContactEvent.bodyB = endShapeContactEvent.shapeA = endShapeContactEvent.shapeB = null; } }; -}(); - -exports.AABB = AABB; -exports.ArrayCollisionMatrix = ArrayCollisionMatrix; -exports.BODY_SLEEP_STATES = BODY_SLEEP_STATES; -exports.BODY_TYPES = BODY_TYPES; -exports.Body = Body; -exports.Box = Box; -exports.Broadphase = Broadphase; -exports.COLLISION_TYPES = COLLISION_TYPES; -exports.ConeTwistConstraint = ConeTwistConstraint; -exports.Constraint = Constraint; -exports.ContactEquation = ContactEquation; -exports.ContactMaterial = ContactMaterial; -exports.ConvexPolyhedron = ConvexPolyhedron; -exports.Cylinder = Cylinder; -exports.DistanceConstraint = DistanceConstraint; -exports.Equation = Equation; -exports.EventTarget = EventTarget; -exports.FrictionEquation = FrictionEquation; -exports.GSSolver = GSSolver; -exports.GridBroadphase = GridBroadphase; -exports.Heightfield = Heightfield; -exports.HingeConstraint = HingeConstraint; -exports.JacobianElement = JacobianElement; -exports.LockConstraint = LockConstraint; -exports.Mat3 = Mat3; -exports.Material = Material; -exports.NaiveBroadphase = NaiveBroadphase; -exports.Narrowphase = Narrowphase; -exports.ObjectCollisionMatrix = ObjectCollisionMatrix; -exports.Particle = Particle; -exports.Plane = Plane; -exports.PointToPointConstraint = PointToPointConstraint; -exports.Pool = Pool; -exports.Quaternion = Quaternion; -exports.RAY_MODES = RAY_MODES; -exports.Ray = Ray; -exports.RaycastResult = RaycastResult; -exports.RaycastVehicle = RaycastVehicle; -exports.RigidVehicle = RigidVehicle; -exports.RotationalEquation = RotationalEquation; -exports.RotationalMotorEquation = RotationalMotorEquation; -exports.SAPBroadphase = SAPBroadphase; -exports.SHAPE_TYPES = SHAPE_TYPES; -exports.SPHSystem = SPHSystem; -exports.Shape = Shape; -exports.Solver = Solver; -exports.Sphere = Sphere; -exports.SplitSolver = SplitSolver; -exports.Spring = Spring; -exports.Transform = Transform; -exports.Trimesh = Trimesh; -exports.Vec3 = Vec3; -exports.Vec3Pool = Vec3Pool; -exports.World = World; +})(); },{}],6:[function(require,module,exports){ +(function (global){ "use strict"; -/* global Ammo,THREE */ -const TYPE = (exports.TYPE = { +/* global Ammo */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.iterateGeometries = exports.createVHACDShapes = exports.createTriMeshShape = exports.createSphereShape = exports.createHullShape = exports.createHeightfieldTerrainShape = exports.createHACDShapes = exports.createCylinderShape = exports.createConeShape = exports.createCollisionShapes = exports.createCapsuleShape = exports.createBoxShape = exports.TYPE = exports.HEIGHTFIELD_DATA_TYPE = exports.FIT = void 0; +var THREE = _interopRequireWildcard((typeof window !== "undefined" ? window['THREE'] : typeof global !== "undefined" ? global['THREE'] : null)); +function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } +function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } +const TYPE = exports.TYPE = { BOX: "box", CYLINDER: "cylinder", SPHERE: "sphere", CAPSULE: "capsule", CONE: "cone", HULL: "hull", - HACD: "hacd", //Hierarchical Approximate Convex Decomposition - VHACD: "vhacd", //Volumetric Hierarchical Approximate Convex Decomposition + HACD: "hacd", + //Hierarchical Approximate Convex Decomposition + VHACD: "vhacd", + //Volumetric Hierarchical Approximate Convex Decomposition MESH: "mesh", HEIGHTFIELD: "heightfield" -}); - -const FIT = (exports.FIT = { - ALL: "all", //A single shape is automatically sized to bound all meshes within the entity. +}; +const FIT = exports.FIT = { + ALL: "all", + //A single shape is automatically sized to bound all meshes within the entity. MANUAL: "manual" //A single shape is sized manually. Requires halfExtents or sphereRadius. -}); +}; -const HEIGHTFIELD_DATA_TYPE = (exports.HEIGHTFIELD_DATA_TYPE = { +const HEIGHTFIELD_DATA_TYPE = exports.HEIGHTFIELD_DATA_TYPE = { short: "short", float: "float" -}); - -const hasUpdateMatricesFunction = THREE.Object3D.prototype.hasOwnProperty("updateMatrices"); - -exports.createCollisionShapes = function(root, options) { +}; +const createCollisionShapes = function (vertices, matrices, indexes, matrixWorld, options = {}) { switch (options.type) { case TYPE.BOX: - return [this.createBoxShape(root, options)]; + return [createBoxShape(vertices, matrices, matrixWorld, options)]; case TYPE.CYLINDER: - return [this.createCylinderShape(root, options)]; + return [createCylinderShape(vertices, matrices, matrixWorld, options)]; case TYPE.CAPSULE: - return [this.createCapsuleShape(root, options)]; + return [createCapsuleShape(vertices, matrices, matrixWorld, options)]; case TYPE.CONE: - return [this.createConeShape(root, options)]; + return [createConeShape(vertices, matrices, matrixWorld, options)]; case TYPE.SPHERE: - return [this.createSphereShape(root, options)]; + return [createSphereShape(vertices, matrices, matrixWorld, options)]; case TYPE.HULL: - return [this.createHullShape(root, options)]; + return [createHullShape(vertices, matrices, matrixWorld, options)]; case TYPE.HACD: - return this.createHACDShapes(root, options); + return createHACDShapes(vertices, matrices, indexes, matrixWorld, options); case TYPE.VHACD: - return this.createVHACDShapes(root, options); + return createVHACDShapes(vertices, matrices, indexes, matrixWorld, options); case TYPE.MESH: - return [this.createTriMeshShape(root, options)]; + return [createTriMeshShape(vertices, matrices, indexes, matrixWorld, options)]; case TYPE.HEIGHTFIELD: - return [this.createHeightfieldTerrainShape(root, options)]; + return [createHeightfieldTerrainShape(options)]; default: console.warn(options.type + " is not currently supported"); return []; @@ -13916,41 +11810,26 @@ exports.createCollisionShapes = function(root, options) { }; //TODO: support gimpact (dynamic trimesh) and heightmap - -exports.createBoxShape = function(root, options) { +exports.createCollisionShapes = createCollisionShapes; +const createBoxShape = function (vertices, matrices, matrixWorld, options = {}) { options.type = TYPE.BOX; _setOptions(options); - if (options.fit === FIT.ALL) { - options.halfExtents = _computeHalfExtents( - root, - _computeBounds(root, options), - options.minHalfExtent, - options.maxHalfExtent - ); + options.halfExtents = _computeHalfExtents(_computeBounds(vertices, matrices), options.minHalfExtent, options.maxHalfExtent); } - const btHalfExtents = new Ammo.btVector3(options.halfExtents.x, options.halfExtents.y, options.halfExtents.z); const collisionShape = new Ammo.btBoxShape(btHalfExtents); Ammo.destroy(btHalfExtents); - - _finishCollisionShape(collisionShape, options, _computeScale(root, options)); + _finishCollisionShape(collisionShape, options, _computeScale(matrixWorld, options)); return collisionShape; }; - -exports.createCylinderShape = function(root, options) { +exports.createBoxShape = createBoxShape; +const createCylinderShape = function (vertices, matrices, matrixWorld, options = {}) { options.type = TYPE.CYLINDER; _setOptions(options); - if (options.fit === FIT.ALL) { - options.halfExtents = _computeHalfExtents( - root, - _computeBounds(root, options), - options.minHalfExtent, - options.maxHalfExtent - ); + options.halfExtents = _computeHalfExtents(_computeBounds(vertices, matrices), options.minHalfExtent, options.maxHalfExtent); } - const btHalfExtents = new Ammo.btVector3(options.halfExtents.x, options.halfExtents.y, options.halfExtents.z); const collisionShape = (() => { switch (options.cylinderAxis) { @@ -13964,25 +11843,21 @@ exports.createCylinderShape = function(root, options) { return null; })(); Ammo.destroy(btHalfExtents); - - _finishCollisionShape(collisionShape, options, _computeScale(root, options)); + _finishCollisionShape(collisionShape, options, _computeScale(matrixWorld, options)); return collisionShape; }; - -exports.createCapsuleShape = function(root, options) { +exports.createCylinderShape = createCylinderShape; +const createCapsuleShape = function (vertices, matrices, matrixWorld, options = {}) { options.type = TYPE.CAPSULE; _setOptions(options); - if (options.fit === FIT.ALL) { - options.halfExtents = _computeHalfExtents( - root, - _computeBounds(root, options), - options.minHalfExtent, - options.maxHalfExtent - ); + options.halfExtents = _computeHalfExtents(_computeBounds(vertices, matrices), options.minHalfExtent, options.maxHalfExtent); } - - const { x, y, z } = options.halfExtents; + const { + x, + y, + z + } = options.halfExtents; const collisionShape = (() => { switch (options.cylinderAxis) { case "y": @@ -13994,25 +11869,21 @@ exports.createCapsuleShape = function(root, options) { } return null; })(); - - _finishCollisionShape(collisionShape, options, _computeScale(root, options)); + _finishCollisionShape(collisionShape, options, _computeScale(matrixWorld, options)); return collisionShape; }; - -exports.createConeShape = function(root, options) { +exports.createCapsuleShape = createCapsuleShape; +const createConeShape = function (vertices, matrices, matrixWorld, options = {}) { options.type = TYPE.CONE; _setOptions(options); - if (options.fit === FIT.ALL) { - options.halfExtents = _computeHalfExtents( - root, - _computeBounds(root, options), - options.minHalfExtent, - options.maxHalfExtent - ); + options.halfExtents = _computeHalfExtents(_computeBounds(vertices, matrices), options.minHalfExtent, options.maxHalfExtent); } - - const { x, y, z } = options.halfExtents; + const { + x, + y, + z + } = options.halfExtents; const collisionShape = (() => { switch (options.cylinderAxis) { case "y": @@ -14024,72 +11895,63 @@ exports.createConeShape = function(root, options) { } return null; })(); - - _finishCollisionShape(collisionShape, options, _computeScale(root, options)); + _finishCollisionShape(collisionShape, options, _computeScale(matrixWorld, options)); return collisionShape; }; - -exports.createSphereShape = function(root, options) { +exports.createConeShape = createConeShape; +const createSphereShape = function (vertices, matrices, matrixWorld, options = {}) { options.type = TYPE.SPHERE; _setOptions(options); - let radius; if (options.fit === FIT.MANUAL && !isNaN(options.sphereRadius)) { radius = options.sphereRadius; } else { - radius = _computeRadius(root, options, _computeBounds(root, options)); + radius = _computeRadius(vertices, matrices, _computeBounds(vertices, matrices)); } - const collisionShape = new Ammo.btSphereShape(radius); - _finishCollisionShape(collisionShape, options, _computeScale(root, options)); - + _finishCollisionShape(collisionShape, options, _computeScale(matrixWorld, options)); return collisionShape; }; - -exports.createHullShape = (function() { +exports.createSphereShape = createSphereShape; +const createHullShape = exports.createHullShape = function () { const vertex = new THREE.Vector3(); const center = new THREE.Vector3(); - return function(root, options) { + const matrix = new THREE.Matrix4(); + return function (vertices, matrices, matrixWorld, options = {}) { options.type = TYPE.HULL; _setOptions(options); - if (options.fit === FIT.MANUAL) { console.warn("cannot use fit: manual with type: hull"); return null; } - - const bounds = _computeBounds(root, options); - + const bounds = _computeBounds(vertices, matrices); const btVertex = new Ammo.btVector3(); const originalHull = new Ammo.btConvexHullShape(); originalHull.setMargin(options.margin); center.addVectors(bounds.max, bounds.min).multiplyScalar(0.5); - let vertexCount = 0; - _iterateGeometries(root, options, geo => { - vertexCount += geo.attributes.position.array.length / 3; - }); - + for (let i = 0; i < vertices.length; i++) { + vertexCount += vertices[i].length / 3; + } const maxVertices = options.hullMaxVertices || 100000; // todo: might want to implement this in a deterministic way that doesn't do O(verts) calls to Math.random if (vertexCount > maxVertices) { console.warn(`too many vertices for hull shape; sampling ~${maxVertices} from ~${vertexCount} vertices`); } const p = Math.min(1, maxVertices / vertexCount); - - _iterateGeometries(root, options, (geo, transform) => { - const components = geo.attributes.position.array; - for (let i = 0; i < components.length; i += 3) { - if (Math.random() <= p) { - vertex - .set(components[i], components[i + 1], components[i + 2]) - .applyMatrix4(transform) - .sub(center); + for (let i = 0; i < vertices.length; i++) { + const components = vertices[i]; + matrix.fromArray(matrices[i]); + for (let j = 0; j < components.length; j += 3) { + const isLastVertex = i === vertices.length - 1 && j === components.length - 3; + if (Math.random() <= p || isLastVertex) { + // always include the last vertex + vertex.set(components[j], components[j + 1], components[j + 2]).applyMatrix4(matrix).sub(center); btVertex.setValue(vertex.x, vertex.y, vertex.z); - originalHull.addPoint(btVertex, i === components.length - 3); // todo: better to recalc AABB only on last geometry + originalHull.addPoint(btVertex, isLastVertex); // recalc AABB only on last geometry } } - }); + } let collisionShape = originalHull; if (originalHull.getNumVertices() >= 100) { @@ -14097,98 +11959,84 @@ exports.createHullShape = (function() { const shapeHull = new Ammo.btShapeHull(originalHull); shapeHull.buildHull(options.margin); Ammo.destroy(originalHull); - collisionShape = new Ammo.btConvexHullShape( - Ammo.getPointer(shapeHull.getVertexPointer()), - shapeHull.numVertices() - ); + collisionShape = new Ammo.btConvexHullShape(Ammo.getPointer(shapeHull.getVertexPointer()), shapeHull.numVertices()); Ammo.destroy(shapeHull); // btConvexHullShape makes a copy } Ammo.destroy(btVertex); - - _finishCollisionShape(collisionShape, options, _computeScale(root, options)); + _finishCollisionShape(collisionShape, options, _computeScale(matrixWorld, options)); return collisionShape; }; -})(); - -exports.createHACDShapes = (function() { - const v = new THREE.Vector3(); +}(); +const createHACDShapes = exports.createHACDShapes = function () { + const vector = new THREE.Vector3(); const center = new THREE.Vector3(); - return function(root, options) { + const matrix = new THREE.Matrix4(); + return function (vertices, matrices, indexes, matrixWorld, options = {}) { options.type = TYPE.HACD; _setOptions(options); - if (options.fit === FIT.MANUAL) { console.warn("cannot use fit: manual with type: hacd"); return []; } - if (!Ammo.hasOwnProperty("HACD")) { - console.warn( - "HACD unavailable in included build of Ammo.js. Visit https://github.com/mozillareality/ammo.js for the latest version." - ); + console.warn("HACD unavailable in included build of Ammo.js. Visit https://github.com/mozillareality/ammo.js for the latest version."); return []; } - - const bounds = _computeBounds(root, options); - const scale = _computeScale(root, options); - + const bounds = _computeBounds(vertices, matrices); + const scale = _computeScale(matrixWorld, options); let vertexCount = 0; let triCount = 0; center.addVectors(bounds.max, bounds.min).multiplyScalar(0.5); - - _iterateGeometries(root, options, geo => { - vertexCount += geo.attributes.position.array.length / 3; - if (geo.index) { - triCount += geo.index.array.length / 3; + for (let i = 0; i < vertices.length; i++) { + vertexCount += vertices[i].length / 3; + if (indexes && indexes[i]) { + triCount += indexes[i].length / 3; } else { - triCount += geo.attributes.position.array.length / 9; + triCount += vertices[i].length / 9; } - }); - + } const hacd = new Ammo.HACD(); if (options.hasOwnProperty("compacityWeight")) hacd.SetCompacityWeight(options.compacityWeight); if (options.hasOwnProperty("volumeWeight")) hacd.SetVolumeWeight(options.volumeWeight); if (options.hasOwnProperty("nClusters")) hacd.SetNClusters(options.nClusters); if (options.hasOwnProperty("nVerticesPerCH")) hacd.SetNVerticesPerCH(options.nVerticesPerCH); if (options.hasOwnProperty("concavity")) hacd.SetConcavity(options.concavity); - const points = Ammo._malloc(vertexCount * 3 * 8); const triangles = Ammo._malloc(triCount * 3 * 4); hacd.SetPoints(points); hacd.SetTriangles(triangles); hacd.SetNPoints(vertexCount); hacd.SetNTriangles(triCount); - - const pptr = points / 8, + let pptr = points / 8, tptr = triangles / 4; - _iterateGeometries(root, options, (geo, transform) => { - const components = geo.attributes.position.array; - const indices = geo.index ? geo.index.array : null; - for (let i = 0; i < components.length; i += 3) { - v.set(components[i + 0], components[i + 1], components[i + 2]) - .applyMatrix4(transform) - .sub(center); - Ammo.HEAPF64[pptr + i + 0] = v.x; - Ammo.HEAPF64[pptr + i + 1] = v.y; - Ammo.HEAPF64[pptr + i + 2] = v.z; - } - if (indices) { - for (let i = 0; i < indices.length; i++) { - Ammo.HEAP32[tptr + i] = indices[i]; + for (let i = 0; i < vertices.length; i++) { + const components = vertices[i]; + matrix.fromArray(matrices[i]); + for (let j = 0; j < components.length; j += 3) { + vector.set(components[j + 0], components[j + 1], components[j + 2]).applyMatrix4(matrix).sub(center); + Ammo.HEAPF64[pptr + 0] = vector.x; + Ammo.HEAPF64[pptr + 1] = vector.y; + Ammo.HEAPF64[pptr + 2] = vector.z; + pptr += 3; + } + if (indexes[i]) { + const indices = indexes[i]; + for (let j = 0; j < indices.length; j++) { + Ammo.HEAP32[tptr] = indices[j]; + tptr++; } } else { - for (let i = 0; i < components.length / 3; i++) { - Ammo.HEAP32[tptr + i] = i; + for (let j = 0; j < components.length / 3; j++) { + Ammo.HEAP32[tptr] = j; + tptr++; } } - }); - + } hacd.Compute(); Ammo._free(points); Ammo._free(triangles); const nClusters = hacd.GetNClusters(); - const shapes = []; for (let i = 0; i < nClusters; i++) { const hull = new Ammo.btConvexHullShape(); @@ -14198,7 +12046,6 @@ exports.createHACDShapes = (function() { const hullPoints = Ammo._malloc(nPoints * 3 * 8); const hullTriangles = Ammo._malloc(nTriangles * 3 * 4); hacd.GetCH(i, hullPoints, hullTriangles); - const pptr = hullPoints / 8; for (let pi = 0; pi < nPoints; pi++) { const btVertex = new Ammo.btVector3(); @@ -14209,50 +12056,40 @@ exports.createHACDShapes = (function() { hull.addPoint(btVertex, pi === nPoints - 1); Ammo.destroy(btVertex); } - _finishCollisionShape(hull, options, scale); shapes.push(hull); } - return shapes; }; -})(); - -exports.createVHACDShapes = (function() { - const v = new THREE.Vector3(); +}(); +const createVHACDShapes = exports.createVHACDShapes = function () { + const vector = new THREE.Vector3(); const center = new THREE.Vector3(); - return function(root, options) { + const matrix = new THREE.Matrix4(); + return function (vertices, matrices, indexes, matrixWorld, options = {}) { options.type = TYPE.VHACD; _setOptions(options); - if (options.fit === FIT.MANUAL) { console.warn("cannot use fit: manual with type: vhacd"); return []; } - if (!Ammo.hasOwnProperty("VHACD")) { - console.warn( - "VHACD unavailable in included build of Ammo.js. Visit https://github.com/mozillareality/ammo.js for the latest version." - ); + console.warn("VHACD unavailable in included build of Ammo.js. Visit https://github.com/mozillareality/ammo.js for the latest version."); return []; } - - const bounds = _computeBounds(root, options); - const scale = _computeScale(root, options); - + const bounds = _computeBounds(vertices, matrices); + const scale = _computeScale(matrixWorld, options); let vertexCount = 0; let triCount = 0; center.addVectors(bounds.max, bounds.min).multiplyScalar(0.5); - - _iterateGeometries(root, options, geo => { - vertexCount += geo.attributes.position.count; - if (geo.index) { - triCount += geo.index.count / 3; + for (let i = 0; i < vertices.length; i++) { + vertexCount += vertices[i].length / 3; + if (indexes && indexes[i]) { + triCount += indexes[i].length / 3; } else { - triCount += geo.attributes.position.count / 3; + triCount += vertices[i].length / 9; } - }); - + } const vhacd = new Ammo.VHACD(); const params = new Ammo.Parameters(); //https://kmamou.blogspot.com/2014/12/v-hacd-20-parameters-description.html @@ -14260,8 +12097,7 @@ exports.createVHACDShapes = (function() { if (options.hasOwnProperty("depth")) params.set_m_depth(options.depth); if (options.hasOwnProperty("concavity")) params.set_m_concavity(options.concavity); if (options.hasOwnProperty("planeDownsampling")) params.set_m_planeDownsampling(options.planeDownsampling); - if (options.hasOwnProperty("convexhullDownsampling")) - params.set_m_convexhullDownsampling(options.convexhullDownsampling); + if (options.hasOwnProperty("convexhullDownsampling")) params.set_m_convexhullDownsampling(options.convexhullDownsampling); if (options.hasOwnProperty("alpha")) params.set_m_alpha(options.alpha); if (options.hasOwnProperty("beta")) params.set_m_beta(options.beta); if (options.hasOwnProperty("gamma")) params.set_m_gamma(options.gamma); @@ -14269,55 +12105,47 @@ exports.createVHACDShapes = (function() { if (options.hasOwnProperty("mode")) params.set_m_mode(options.mode); if (options.hasOwnProperty("maxNumVerticesPerCH")) params.set_m_maxNumVerticesPerCH(options.maxNumVerticesPerCH); if (options.hasOwnProperty("minVolumePerCH")) params.set_m_minVolumePerCH(options.minVolumePerCH); - if (options.hasOwnProperty("convexhullApproximation")) - params.set_m_convexhullApproximation(options.convexhullApproximation); + if (options.hasOwnProperty("convexhullApproximation")) params.set_m_convexhullApproximation(options.convexhullApproximation); if (options.hasOwnProperty("oclAcceleration")) params.set_m_oclAcceleration(options.oclAcceleration); - - const points = Ammo._malloc(vertexCount * 3 * 8); + const points = Ammo._malloc(vertexCount * 3 * 8 + 3); const triangles = Ammo._malloc(triCount * 3 * 4); - let pptr = points / 8, tptr = triangles / 4; - _iterateGeometries(root, options, (geo, transform) => { - const components = geo.attributes.position.array; - const indices = geo.index ? geo.index.array : null; - for (let i = 0; i < components.length; i += 3) { - v.set(components[i + 0], components[i + 1], components[i + 2]) - .applyMatrix4(transform) - .sub(center); - Ammo.HEAPF64[pptr + 0] = v.x; - Ammo.HEAPF64[pptr + 1] = v.y; - Ammo.HEAPF64[pptr + 2] = v.z; + for (let i = 0; i < vertices.length; i++) { + const components = vertices[i]; + matrix.fromArray(matrices[i]); + for (let j = 0; j < components.length; j += 3) { + vector.set(components[j + 0], components[j + 1], components[j + 2]).applyMatrix4(matrix).sub(center); + Ammo.HEAPF64[pptr + 0] = vector.x; + Ammo.HEAPF64[pptr + 1] = vector.y; + Ammo.HEAPF64[pptr + 2] = vector.z; pptr += 3; } - if (indices) { - for (let i = 0; i < indices.length; i++) { - Ammo.HEAP32[tptr] = indices[i]; + if (indexes[i]) { + const indices = indexes[i]; + for (let j = 0; j < indices.length; j++) { + Ammo.HEAP32[tptr] = indices[j]; tptr++; } } else { - for (let i = 0; i < components.length / 3; i++) { - Ammo.HEAP32[tptr] = i; + for (let j = 0; j < components.length / 3; j++) { + Ammo.HEAP32[tptr] = j; tptr++; } } - }); - + } vhacd.Compute(points, 3, vertexCount, triangles, 3, triCount, params); Ammo._free(points); Ammo._free(triangles); const nHulls = vhacd.GetNConvexHulls(); - const shapes = []; const ch = new Ammo.ConvexHull(); for (let i = 0; i < nHulls; i++) { vhacd.GetConvexHull(i, ch); const nPoints = ch.get_m_nPoints(); const hullPoints = ch.get_m_points(); - const hull = new Ammo.btConvexHullShape(); hull.setMargin(options.margin); - for (let pi = 0; pi < nPoints; pi++) { const btVertex = new Ammo.btVector3(); const px = ch.get_m_points(pi * 3 + 0); @@ -14327,84 +12155,74 @@ exports.createVHACDShapes = (function() { hull.addPoint(btVertex, pi === nPoints - 1); Ammo.destroy(btVertex); } - _finishCollisionShape(hull, options, scale); shapes.push(hull); } Ammo.destroy(ch); Ammo.destroy(vhacd); - return shapes; }; -})(); - -exports.createTriMeshShape = (function() { +}(); +const createTriMeshShape = exports.createTriMeshShape = function () { const va = new THREE.Vector3(); const vb = new THREE.Vector3(); const vc = new THREE.Vector3(); - return function(root, options) { + const matrix = new THREE.Matrix4(); + return function (vertices, matrices, indexes, matrixWorld, options = {}) { options.type = TYPE.MESH; _setOptions(options); - if (options.fit === FIT.MANUAL) { console.warn("cannot use fit: manual with type: mesh"); return null; } - - const scale = _computeScale(root, options); - + const scale = _computeScale(matrixWorld, options); const bta = new Ammo.btVector3(); const btb = new Ammo.btVector3(); const btc = new Ammo.btVector3(); const triMesh = new Ammo.btTriangleMesh(true, false); - - _iterateGeometries(root, options, (geo, transform) => { - const components = geo.attributes.position.array; - if (geo.index) { - for (let i = 0; i < geo.index.count; i += 3) { - const ai = geo.index.array[i] * 3; - const bi = geo.index.array[i + 1] * 3; - const ci = geo.index.array[i + 2] * 3; - va.set(components[ai], components[ai + 1], components[ai + 2]).applyMatrix4(transform); - vb.set(components[bi], components[bi + 1], components[bi + 2]).applyMatrix4(transform); - vc.set(components[ci], components[ci + 1], components[ci + 2]).applyMatrix4(transform); + for (let i = 0; i < vertices.length; i++) { + const components = vertices[i]; + const index = indexes[i] ? indexes[i] : null; + matrix.fromArray(matrices[i]); + if (index) { + for (let j = 0; j < index.length; j += 3) { + const ai = index[j] * 3; + const bi = index[j + 1] * 3; + const ci = index[j + 2] * 3; + va.set(components[ai], components[ai + 1], components[ai + 2]).applyMatrix4(matrix); + vb.set(components[bi], components[bi + 1], components[bi + 2]).applyMatrix4(matrix); + vc.set(components[ci], components[ci + 1], components[ci + 2]).applyMatrix4(matrix); bta.setValue(va.x, va.y, va.z); btb.setValue(vb.x, vb.y, vb.z); btc.setValue(vc.x, vc.y, vc.z); triMesh.addTriangle(bta, btb, btc, false); } } else { - for (let i = 0; i < components.length; i += 9) { - va.set(components[i + 0], components[i + 1], components[i + 2]).applyMatrix4(transform); - vb.set(components[i + 3], components[i + 4], components[i + 5]).applyMatrix4(transform); - vc.set(components[i + 6], components[i + 7], components[i + 8]).applyMatrix4(transform); + for (let j = 0; j < components.length; j += 9) { + va.set(components[j + 0], components[j + 1], components[j + 2]).applyMatrix4(matrix); + vb.set(components[j + 3], components[j + 4], components[j + 5]).applyMatrix4(matrix); + vc.set(components[j + 6], components[j + 7], components[j + 8]).applyMatrix4(matrix); bta.setValue(va.x, va.y, va.z); btb.setValue(vb.x, vb.y, vb.z); btc.setValue(vc.x, vc.y, vc.z); triMesh.addTriangle(bta, btb, btc, false); } } - }); - + } const localScale = new Ammo.btVector3(scale.x, scale.y, scale.z); triMesh.setScaling(localScale); Ammo.destroy(localScale); - const collisionShape = new Ammo.btBvhTriangleMeshShape(triMesh, true, true); collisionShape.resources = [triMesh]; - Ammo.destroy(bta); Ammo.destroy(btb); Ammo.destroy(btc); - _finishCollisionShape(collisionShape, options); return collisionShape; }; -})(); - -exports.createHeightfieldTerrainShape = function(root, options) { +}(); +const createHeightfieldTerrainShape = function (options = {}) { _setOptions(options); - if (options.fit === FIT.ALL) { console.warn("cannot use fit: all with type: heightfield"); return null; @@ -14424,13 +12242,10 @@ exports.createHeightfieldTerrainShape = function(root, options) { } })(); const flipQuadEdges = options.hasOwnProperty("flipQuadEdges") ? options.flipQuadEdges : true; - const heightStickLength = heightfieldData.length; const heightStickWidth = heightStickLength > 0 ? heightfieldData[0].length : 0; - const data = Ammo._malloc(heightStickLength * heightStickWidth * 4); const ptr = data / 4; - let minHeight = Number.POSITIVE_INFINITY; let maxHeight = Number.NEGATIVE_INFINITY; let index = 0; @@ -14443,29 +12258,15 @@ exports.createHeightfieldTerrainShape = function(root, options) { maxHeight = Math.max(maxHeight, height); } } - - const collisionShape = new Ammo.btHeightfieldTerrainShape( - heightStickWidth, - heightStickLength, - data, - heightScale, - minHeight, - maxHeight, - upAxis, - hdt, - flipQuadEdges - ); - + const collisionShape = new Ammo.btHeightfieldTerrainShape(heightStickWidth, heightStickLength, data, heightScale, minHeight, maxHeight, upAxis, hdt, flipQuadEdges); const scale = new Ammo.btVector3(heightfieldDistance, 1, heightfieldDistance); collisionShape.setLocalScaling(scale); Ammo.destroy(scale); - collisionShape.heightfieldData = data; - _finishCollisionShape(collisionShape, options); return collisionShape; }; - +exports.createHeightfieldTerrainShape = createHeightfieldTerrainShape; function _setOptions(options) { options.fit = options.hasOwnProperty("fit") ? options.fit : FIT.ALL; options.type = options.type || TYPE.HULL; @@ -14474,17 +12275,14 @@ function _setOptions(options) { options.cylinderAxis = options.cylinderAxis || "y"; options.margin = options.hasOwnProperty("margin") ? options.margin : 0.01; options.includeInvisible = options.hasOwnProperty("includeInvisible") ? options.includeInvisible : false; - if (!options.offset) { options.offset = new THREE.Vector3(); } - if (!options.orientation) { options.orientation = new THREE.Quaternion(); } } - -const _finishCollisionShape = function(collisionShape, options, scale) { +const _finishCollisionShape = function (collisionShape, options, scale) { collisionShape.type = options.type; collisionShape.setMargin(options.margin); collisionShape.destroy = () => { @@ -14496,134 +12294,128 @@ const _finishCollisionShape = function(collisionShape, options, scale) { } Ammo.destroy(collisionShape); }; - const localTransform = new Ammo.btTransform(); const rotation = new Ammo.btQuaternion(); localTransform.setIdentity(); - localTransform.getOrigin().setValue(options.offset.x, options.offset.y, options.offset.z); rotation.setValue(options.orientation.x, options.orientation.y, options.orientation.z, options.orientation.w); - localTransform.setRotation(rotation); Ammo.destroy(rotation); - if (scale) { const localScale = new Ammo.btVector3(scale.x, scale.y, scale.z); collisionShape.setLocalScaling(localScale); Ammo.destroy(localScale); } - collisionShape.localTransform = localTransform; }; - -// Calls `cb(geo, transform)` for each geometry under `root` whose vertices we should take into account for the physics shape. -// `transform` is the transform required to transform the given geometry's vertices into root-local space. -const _iterateGeometries = (function() { - const transform = new THREE.Matrix4(); +const iterateGeometries = exports.iterateGeometries = function () { const inverse = new THREE.Matrix4(); - const bufferGeometry = new THREE.BufferGeometry(); - return function(root, options, cb) { + return function (root, options, cb) { inverse.copy(root.matrixWorld).invert(); + const scale = new THREE.Vector3(); + scale.setFromMatrixScale(root.matrixWorld); root.traverse(mesh => { - if ( - mesh.isMesh && - (!THREE.Sky || mesh.__proto__ != THREE.Sky.prototype) && - (options.includeInvisible || ((mesh.el && mesh.el.object3D.visible) || mesh.visible)) - ) { + const transform = new THREE.Matrix4(); + if (mesh.isMesh && mesh.name !== "Sky" && (options.includeInvisible || mesh.el && mesh.el.object3D.visible || mesh.visible)) { if (mesh === root) { transform.identity(); } else { - if (hasUpdateMatricesFunction) mesh.updateMatrices(); + mesh.updateWorldMatrix(true); transform.multiplyMatrices(inverse, mesh.matrixWorld); } // todo: might want to return null xform if this is the root so that callers can avoid multiplying // things by the identity matrix - cb(mesh.geometry.isBufferGeometry ? mesh.geometry : bufferGeometry.fromGeometry(mesh.geometry), transform); + cb(mesh.geometry.isBufferGeometry ? mesh.geometry.attributes.position.array : mesh.geometry.vertices, transform.elements, mesh.geometry.index ? mesh.geometry.index.array : null); } }); }; -})(); - -const _computeScale = function(root, options) { - const scale = new THREE.Vector3(1, 1, 1); - if (options.fit === FIT.ALL) { - scale.setFromMatrixScale(root.matrixWorld); - } - return scale; -}; - -const _computeRadius = (function() { - const v = new THREE.Vector3(); +}(); +const _computeScale = function () { + const matrix = new THREE.Matrix4(); + return function (matrixWorld, options = {}) { + const scale = new THREE.Vector3(1, 1, 1); + if (options.fit === FIT.ALL) { + matrix.fromArray(matrixWorld); + scale.setFromMatrixScale(matrix); + } + return scale; + }; +}(); +const _computeRadius = function () { const center = new THREE.Vector3(); - return function(root, options, bounds) { + return function (vertices, matrices, bounds) { let maxRadiusSq = 0; - let { x: cx, y: cy, z: cz } = bounds.getCenter(center); - _iterateGeometries(root, options, (geo, transform) => { - const components = geo.attributes.position.array; - for (let i = 0; i < components.length; i += 3) { - v.set(components[i], components[i + 1], components[i + 2]).applyMatrix4(transform); - const dx = cx - v.x; - const dy = cy - v.y; - const dz = cz - v.z; - maxRadiusSq = Math.max(maxRadiusSq, dx * dx + dy * dy + dz * dz); - } + let { + x: cx, + y: cy, + z: cz + } = bounds.getCenter(center); + _iterateVertices(vertices, matrices, v => { + const dx = cx - v.x; + const dy = cy - v.y; + const dz = cz - v.z; + maxRadiusSq = Math.max(maxRadiusSq, dx * dx + dy * dy + dz * dz); }); return Math.sqrt(maxRadiusSq); }; -})(); - -const _computeHalfExtents = function(root, bounds, minHalfExtent, maxHalfExtent) { +}(); +const _computeHalfExtents = function (bounds, minHalfExtent, maxHalfExtent) { const halfExtents = new THREE.Vector3(); - return halfExtents - .subVectors(bounds.max, bounds.min) - .multiplyScalar(0.5) - .clampScalar(minHalfExtent, maxHalfExtent); + return halfExtents.subVectors(bounds.max, bounds.min).multiplyScalar(0.5).clampScalar(minHalfExtent, maxHalfExtent); }; - -const _computeLocalOffset = function(matrix, bounds, target) { - target - .addVectors(bounds.max, bounds.min) - .multiplyScalar(0.5) - .applyMatrix4(matrix); +const _computeLocalOffset = function (matrix, bounds, target) { + target.addVectors(bounds.max, bounds.min).multiplyScalar(0.5).applyMatrix4(matrix); return target; }; // returns the bounding box for the geometries underneath `root`. -const _computeBounds = (function() { - const v = new THREE.Vector3(); - return function(root, options) { - const bounds = new THREE.Box3(); - let minX = +Infinity; - let minY = +Infinity; - let minZ = +Infinity; - let maxX = -Infinity; - let maxY = -Infinity; - let maxZ = -Infinity; - bounds.min.set(0, 0, 0); - bounds.max.set(0, 0, 0); - _iterateGeometries(root, options, (geo, transform) => { - const components = geo.attributes.position.array; - for (let i = 0; i < components.length; i += 3) { - v.set(components[i], components[i + 1], components[i + 2]).applyMatrix4(transform); - if (v.x < minX) minX = v.x; - if (v.y < minY) minY = v.y; - if (v.z < minZ) minZ = v.z; - if (v.x > maxX) maxX = v.x; - if (v.y > maxY) maxY = v.y; - if (v.z > maxZ) maxZ = v.z; +const _computeBounds = function (vertices, matrices) { + const bounds = new THREE.Box3(); + let minX = +Infinity; + let minY = +Infinity; + let minZ = +Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + let maxZ = -Infinity; + bounds.min.set(0, 0, 0); + bounds.max.set(0, 0, 0); + _iterateVertices(vertices, matrices, v => { + if (v.x < minX) minX = v.x; + if (v.y < minY) minY = v.y; + if (v.z < minZ) minZ = v.z; + if (v.x > maxX) maxX = v.x; + if (v.y > maxY) maxY = v.y; + if (v.z > maxZ) maxZ = v.z; + }); + bounds.min.set(minX, minY, minZ); + bounds.max.set(maxX, maxY, maxZ); + return bounds; +}; +const _iterateVertices = function () { + const vertex = new THREE.Vector3(); + const matrix = new THREE.Matrix4(); + return function (vertices, matrices, cb) { + for (let i = 0; i < vertices.length; i++) { + matrix.fromArray(matrices[i]); + for (let j = 0; j < vertices[i].length; j += 3) { + vertex.set(vertices[i][j], vertices[i][j + 1], vertices[i][j + 2]).applyMatrix4(matrix); + cb(vertex); } - }); - bounds.min.set(minX, minY, minZ); - bounds.max.set(maxX, maxY, maxZ); - return bounds; + } }; -})(); +}(); +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],7:[function(require,module,exports){ (function (global){ -var cannonEs = require('cannon-es'); -var three = (typeof window !== "undefined" ? window['THREE'] : typeof global !== "undefined" ? global['THREE'] : null); +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.threeToCannon = exports.getShapeParameters = exports.ShapeType = void 0; +var _cannonEs = require("cannon-es"); +var _three = (typeof window !== "undefined" ? window['THREE'] : typeof global !== "undefined" ? global['THREE'] : null); /** * Ported from: https://github.com/maurizzzio/quickhull3d/ by Mauricio Poppe (https://github.com/maurizzzio) */ @@ -14631,8 +12423,7 @@ var three = (typeof window !== "undefined" ? window['THREE'] : typeof global !== var ConvexHull = function () { var Visible = 0; var Deleted = 1; - var v1 = new three.Vector3(); - + var v1 = new _three.Vector3(); function ConvexHull() { this.tolerance = -1; this.faces = []; // the generated faces of the convex hull @@ -14659,17 +12450,13 @@ var ConvexHull = function () { if (Array.isArray(points) !== true) { console.error('THREE.ConvexHull: Points parameter is not an array.'); } - if (points.length < 4) { console.error('THREE.ConvexHull: The algorithm needs at least four points.'); } - this.makeEmpty(); - for (var i = 0, l = points.length; i < l; i++) { this.vertices.push(new VertexNode(points[i])); } - this.compute(); return this; }, @@ -14680,17 +12467,14 @@ var ConvexHull = function () { var i, l, point; var geometry = node.geometry; if (geometry === undefined) return; - if (geometry.isGeometry) { - geometry = geometry.toBufferGeometry ? geometry.toBufferGeometry() : new three.BufferGeometry().fromGeometry(geometry); + geometry = geometry.toBufferGeometry ? geometry.toBufferGeometry() : new _three.BufferGeometry().fromGeometry(geometry); } - if (geometry.isBufferGeometry) { var attribute = geometry.attributes.position; - if (attribute !== undefined) { for (i = 0, l = attribute.count; i < l; i++) { - point = new three.Vector3(); + point = new _three.Vector3(); point.fromBufferAttribute(attribute, i).applyMatrix4(node.matrixWorld); points.push(point); } @@ -14701,13 +12485,11 @@ var ConvexHull = function () { }, containsPoint: function (point) { var faces = this.faces; - for (var i = 0, l = faces.length; i < l; i++) { var face = faces[i]; // compute signed distance and check on what half space the point lies if (face.distanceToPoint(point) > this.tolerance) return false; } - return true; }, intersectRay: function (ray, target) { @@ -14715,7 +12497,6 @@ var ConvexHull = function () { var faces = this.faces; var tNear = -Infinity; var tFar = Infinity; - for (var i = 0, l = faces.length; i < l; i++) { var face = faces[i]; // interpret faces as planes for the further computation @@ -14737,7 +12518,6 @@ var ConvexHull = function () { // front-face tNear = Math.max(t, tNear); } - if (tNear > tFar) { // if tNear ever is greater than tFar, the ray must miss the convex hull return null; @@ -14745,13 +12525,11 @@ var ConvexHull = function () { } // evaluate intersection point // always try tNear first since its the closer intersection point - if (tNear !== -Infinity) { ray.at(tNear, target); } else { ray.at(tFar, target); } - return target; }, intersectsRay: function (ray) { @@ -14765,13 +12543,11 @@ var ConvexHull = function () { // Adds a vertex to the 'assigned' list of vertices and assigns it to the given face addVertexToFace: function (vertex, face) { vertex.face = face; - if (face.outside === null) { this.assigned.append(vertex); } else { this.assigned.insertBefore(face.outside, vertex); } - face.outside = vertex; return this; }, @@ -14787,7 +12563,6 @@ var ConvexHull = function () { face.outside = null; } } - this.assigned.remove(vertex); return this; }, @@ -14797,11 +12572,9 @@ var ConvexHull = function () { // reference to the first and last vertex of this face var start = face.outside; var end = face.outside; - while (end.next !== null && end.next.face === face) { end = end.next; } - this.assigned.removeSubList(start, end); // fix references start.prev = end.next = null; @@ -14812,7 +12585,6 @@ var ConvexHull = function () { // Removes all the visible vertices that 'face' is able to see deleteFaceVertices: function (face, absorbingFace) { var faceVertices = this.removeAllVerticesFromFace(face); - if (faceVertices !== undefined) { if (absorbingFace === undefined) { // mark the vertices to be reassigned to some other face @@ -14820,7 +12592,6 @@ var ConvexHull = function () { } else { // if there's an absorbing face try to assign as many vertices as possible to it var vertex = faceVertices; - do { // we need to buffer the subsequent vertex at this point because the 'vertex.next' reference // will be changed by upcoming method calls @@ -14833,55 +12604,45 @@ var ConvexHull = function () { this.unassigned.append(vertex); } // now assign next vertex - vertex = nextVertex; } while (vertex !== null); } } - return this; }, // Reassigns as many vertices as possible from the unassigned list to the new faces resolveUnassignedPoints: function (newFaces) { if (this.unassigned.isEmpty() === false) { var vertex = this.unassigned.first(); - do { // buffer 'next' reference, see .deleteFaceVertices() var nextVertex = vertex.next; var maxDistance = this.tolerance; var maxFace = null; - for (var i = 0; i < newFaces.length; i++) { var face = newFaces[i]; - if (face.mark === Visible) { var distance = face.distanceToPoint(vertex.point); - if (distance > maxDistance) { maxDistance = distance; maxFace = face; } - if (maxDistance > 1000 * this.tolerance) break; } } // 'maxFace' can be null e.g. if there are identical vertices - if (maxFace !== null) { this.addVertexToFace(vertex, maxFace); } - vertex = nextVertex; } while (vertex !== null); } - return this; }, // Computes the extremes of a simplex which will be the initial hull computeExtremes: function () { - var min = new three.Vector3(); - var max = new three.Vector3(); + var min = new _three.Vector3(); + var max = new _three.Vector3(); var minVertices = []; var maxVertices = []; var i, l, j; // initially assume that the first vertex is the min/max @@ -14889,7 +12650,6 @@ var ConvexHull = function () { for (i = 0; i < 3; i++) { minVertices[i] = maxVertices[i] = this.vertices[0]; } - min.copy(this.vertices[0].point); max.copy(this.vertices[0].point); // compute the min/max vertex on all six directions @@ -14904,7 +12664,6 @@ var ConvexHull = function () { } } // update the max coordinates - for (j = 0; j < 3; j++) { if (point.getComponent(j) > max.getComponent(j)) { max.setComponent(j, point.getComponent(j)); @@ -14913,7 +12672,6 @@ var ConvexHull = function () { } } // use min/max vectors to compute an optimal epsilon - this.tolerance = 3 * Number.EPSILON * (Math.max(Math.abs(min.x), Math.abs(max.x)) + Math.max(Math.abs(min.y), Math.abs(max.y)) + Math.max(Math.abs(min.z), Math.abs(max.z))); return { min: minVertices, @@ -14926,13 +12684,12 @@ var ConvexHull = function () { var line3, plane, closestPoint; return function computeInitialHull() { if (line3 === undefined) { - line3 = new three.Line3(); - plane = new three.Plane(); - closestPoint = new three.Vector3(); + line3 = new _three.Line3(); + plane = new _three.Plane(); + closestPoint = new _three.Vector3(); } - var vertex, - vertices = this.vertices; + vertices = this.vertices; var extremes = this.computeExtremes(); var min = extremes.min; var max = extremes.max; @@ -14943,31 +12700,25 @@ var ConvexHull = function () { // (max.z - min.z) var distance, - maxDistance = 0; + maxDistance = 0; var index = 0; - for (i = 0; i < 3; i++) { distance = max[i].point.getComponent(i) - min[i].point.getComponent(i); - if (distance > maxDistance) { maxDistance = distance; index = i; } } - v0 = min[index]; v1 = max[index]; // 2. The next vertex 'v2' is the one farthest to the line formed by 'v0' and 'v1' maxDistance = 0; line3.set(v0.point, v1.point); - for (i = 0, l = this.vertices.length; i < l; i++) { vertex = vertices[i]; - if (vertex !== v0 && vertex !== v1) { line3.closestPointToPoint(vertex.point, true, closestPoint); distance = closestPoint.distanceToSquared(vertex.point); - if (distance > maxDistance) { maxDistance = distance; v2 = vertex; @@ -14975,25 +12726,19 @@ var ConvexHull = function () { } } // 3. The next vertex 'v3' is the one farthest to the plane 'v0', 'v1', 'v2' - maxDistance = -1; plane.setFromCoplanarPoints(v0.point, v1.point, v2.point); - for (i = 0, l = this.vertices.length; i < l; i++) { vertex = vertices[i]; - if (vertex !== v0 && vertex !== v1 && vertex !== v2) { distance = Math.abs(plane.distanceToPoint(vertex.point)); - if (distance > maxDistance) { maxDistance = distance; v3 = vertex; } } } - var faces = []; - if (plane.distanceToPoint(v3.point) < 0) { // the face is not able to see the point so 'plane.normal' is pointing outside the tetrahedron faces.push(Face.create(v0, v1, v2), Face.create(v3, v1, v0), Face.create(v3, v2, v1), Face.create(v3, v0, v2)); // set the twin edge @@ -15018,49 +12763,39 @@ var ConvexHull = function () { } } // the initial hull is the tetrahedron - for (i = 0; i < 4; i++) { this.faces.push(faces[i]); } // initial assignment of vertices to the faces of the tetrahedron - for (i = 0, l = vertices.length; i < l; i++) { vertex = vertices[i]; - if (vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3) { maxDistance = this.tolerance; var maxFace = null; - for (j = 0; j < 4; j++) { distance = this.faces[j].distanceToPoint(vertex.point); - if (distance > maxDistance) { maxDistance = distance; maxFace = this.faces[j]; } } - if (maxFace !== null) { this.addVertexToFace(vertex, maxFace); } } } - return this; }; }(), // Removes inactive faces reindexFaces: function () { var activeFaces = []; - for (var i = 0; i < this.faces.length; i++) { var face = this.faces[i]; - if (face.mark === Visible) { activeFaces.push(face); } } - this.faces = activeFaces; return this; }, @@ -15069,22 +12804,19 @@ var ConvexHull = function () { // if the 'assigned' list of vertices is empty, no vertices are left. return with 'undefined' if (this.assigned.isEmpty() === false) { var eyeVertex, - maxDistance = 0; // grap the first available face and start with the first visible vertex of that face + maxDistance = 0; // grap the first available face and start with the first visible vertex of that face var eyeFace = this.assigned.first().face; var vertex = eyeFace.outside; // now calculate the farthest vertex that face can see do { var distance = eyeFace.distanceToPoint(vertex.point); - if (distance > maxDistance) { maxDistance = distance; eyeVertex = vertex; } - vertex = vertex.next; } while (vertex !== null && vertex.face === eyeFace); - return eyeVertex; } }, @@ -15096,7 +12828,6 @@ var ConvexHull = function () { this.deleteFaceVertices(face); face.mark = Deleted; var edge; - if (crossEdge === null) { edge = crossEdge = face.getEdge(0); } else { @@ -15104,11 +12835,9 @@ var ConvexHull = function () { // (actually 'crossEdge.twin' was the edge who called this method recursively) edge = crossEdge.next; } - do { var twinEdge = edge.twin; var oppositeFace = twinEdge.face; - if (oppositeFace.mark === Visible) { if (oppositeFace.distanceToPoint(eyePoint) > this.tolerance) { // the opposite face can see the vertex, so proceed with next edge @@ -15118,10 +12847,8 @@ var ConvexHull = function () { horizon.push(edge); } } - edge = edge.next; } while (edge !== crossEdge); - return this; }, // Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order @@ -15133,30 +12860,27 @@ var ConvexHull = function () { face.getEdge(-1).setTwin(horizonEdge.twin); return face.getEdge(0); // the half edge whose vertex is the eyeVertex }, + // Adds 'horizon.length' faces to the hull, each face will be linked with the // horizon opposite face and the face on the left/right addNewFaces: function (eyeVertex, horizon) { this.newFaces = []; var firstSideEdge = null; var previousSideEdge = null; - for (var i = 0; i < horizon.length; i++) { var horizonEdge = horizon[i]; // returns the right side edge var sideEdge = this.addAdjoiningFace(eyeVertex, horizonEdge); - if (firstSideEdge === null) { firstSideEdge = sideEdge; } else { // joins face.getEdge( 1 ) with previousFace.getEdge( 0 ) sideEdge.next.setTwin(previousSideEdge); } - this.newFaces.push(sideEdge.face); previousSideEdge = sideEdge; } // perform final join of new faces - firstSideEdge.next.setTwin(previousSideEdge); return this; }, @@ -15185,7 +12909,6 @@ var ConvexHull = function () { while ((vertex = this.nextVertexToAdd()) !== undefined) { this.addVertexToHull(vertex); } - this.reindexFaces(); this.cleanup(); return this; @@ -15193,8 +12916,8 @@ var ConvexHull = function () { }); // function Face() { - this.normal = new three.Vector3(); - this.midpoint = new three.Vector3(); + this.normal = new _three.Vector3(); + this.midpoint = new _three.Vector3(); this.area = 0; this.constant = 0; // signed distance from face to the origin @@ -15203,7 +12926,6 @@ var ConvexHull = function () { this.mark = Visible; this.edge = null; } - Object.assign(Face, { create: function (a, b, c) { var face = new Face(); @@ -15222,23 +12944,20 @@ var ConvexHull = function () { Object.assign(Face.prototype, { getEdge: function (i) { var edge = this.edge; - while (i > 0) { edge = edge.next; i--; } - while (i < 0) { edge = edge.prev; i++; } - return edge; }, compute: function () { var triangle; return function compute() { - if (triangle === undefined) triangle = new three.Triangle(); + if (triangle === undefined) triangle = new _three.Triangle(); var a = this.edge.tail(); var b = this.edge.head(); var c = this.edge.next.head(); @@ -15262,7 +12981,6 @@ var ConvexHull = function () { this.twin = null; this.face = face; } - Object.assign(HalfEdge.prototype, { head: function () { return this.vertex; @@ -15273,21 +12991,17 @@ var ConvexHull = function () { length: function () { var head = this.head(); var tail = this.tail(); - if (tail !== null) { return tail.point.distanceTo(head.point); } - return -1; }, lengthSquared: function () { var head = this.head(); var tail = this.tail(); - if (tail !== null) { return tail.point.distanceToSquared(head.point); } - return -1; }, setTwin: function (edge) { @@ -15304,12 +13018,10 @@ var ConvexHull = function () { this.face = null; // the face that is able to see this vertex } // A double linked list that contains vertex nodes. - function VertexList() { this.head = null; this.tail = null; } - Object.assign(VertexList.prototype, { first: function () { return this.head; @@ -15325,13 +13037,11 @@ var ConvexHull = function () { insertBefore: function (target, vertex) { vertex.prev = target.prev; vertex.next = target; - if (vertex.prev === null) { this.head = vertex; } else { vertex.prev.next = vertex; } - target.prev = vertex; return this; }, @@ -15339,13 +13049,11 @@ var ConvexHull = function () { insertAfter: function (target, vertex) { vertex.prev = target; vertex.next = target.next; - if (vertex.next === null) { this.tail = vertex; } else { vertex.next.prev = vertex; } - target.next = vertex; return this; }, @@ -15356,7 +13064,6 @@ var ConvexHull = function () { } else { this.tail.next = vertex; } - vertex.prev = this.tail; vertex.next = null; // the tail has no subsequent vertex @@ -15370,13 +13077,11 @@ var ConvexHull = function () { } else { this.tail.next = vertex; } - vertex.prev = this.tail; // ensure that the 'tail' reference points to the last vertex of the chain while (vertex.next !== null) { vertex = vertex.next; } - this.tail = vertex; return this; }, @@ -15387,13 +13092,11 @@ var ConvexHull = function () { } else { vertex.prev.next = vertex.next; } - if (vertex.next === null) { this.tail = vertex.prev; } else { vertex.next.prev = vertex.prev; } - return this; }, // Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b @@ -15403,13 +13106,11 @@ var ConvexHull = function () { } else { a.prev.next = b.next; } - if (b.next === null) { this.tail = a.prev; } else { b.next.prev = a.prev; } - return this; }, isEmpty: function () { @@ -15418,19 +13119,15 @@ var ConvexHull = function () { }); return ConvexHull; }(); - -const _v1 = new three.Vector3(); - -const _v2 = new three.Vector3(); - -const _q1 = new three.Quaternion(); +const _v1 = new _three.Vector3(); +const _v2 = new _three.Vector3(); +const _q1 = new _three.Quaternion(); /** * Returns a single geometry for the given object. If the object is compound, * its geometries are automatically merged. Bake world scale into each * geometry, because we can't easily apply that to the cannonjs shapes later. */ - function getGeometry(object) { const meshes = getMeshes(object); if (meshes.length === 0) return null; // Single mesh. Return, preserving original type. @@ -15439,27 +13136,21 @@ function getGeometry(object) { return normalizeGeometry(meshes[0]); } // Multiple meshes. Merge and return. - let mesh; const geometries = []; - while (mesh = meshes.pop()) { geometries.push(simplifyGeometry(normalizeGeometry(mesh))); } - return mergeBufferGeometries(geometries); } - function normalizeGeometry(mesh) { let geometry = mesh.geometry; - if (geometry.toBufferGeometry) { geometry = geometry.toBufferGeometry(); } else { // Preserve original type, e.g. CylinderBufferGeometry. geometry = geometry.clone(); } - mesh.updateMatrixWorld(); mesh.matrixWorld.decompose(_v1, _q1, _v2); geometry.scale(_v2.x, _v2.y, _v2.z); @@ -15471,24 +13162,18 @@ function normalizeGeometry(mesh) { * other attributes, we throw everything else away. */ - function mergeBufferGeometries(geometries) { let vertexCount = 0; - for (let i = 0; i < geometries.length; i++) { const position = geometries[i].attributes.position; - if (position && position.itemSize === 3) { vertexCount += position.count; } } - const positionArray = new Float32Array(vertexCount * 3); let positionOffset = 0; - for (let i = 0; i < geometries.length; i++) { const position = geometries[i].attributes.position; - if (position && position.itemSize === 3) { for (let j = 0; j < position.count; j++) { positionArray[positionOffset++] = position.getX(j); @@ -15497,20 +13182,16 @@ function mergeBufferGeometries(geometries) { } } } - - return new three.BufferGeometry().setAttribute('position', new three.BufferAttribute(positionArray, 3)); + return new _three.BufferGeometry().setAttribute('position', new _three.BufferAttribute(positionArray, 3)); } - function getVertices(geometry) { const position = geometry.attributes.position; const vertices = new Float32Array(position.count * 3); - for (let i = 0; i < position.count; i++) { vertices[i * 3] = position.getX(i); vertices[i * 3 + 1] = position.getY(i); vertices[i * 3 + 2] = position.getZ(i); } - return vertices; } /** @@ -15529,19 +13210,15 @@ function getMeshes(object) { }); return meshes; } - function getComponent(v, component) { switch (component) { case 'x': return v.x; - case 'y': return v.y; - case 'z': return v.z; } - throw new Error("Unexpected component " + component); } /** @@ -15568,7 +13245,6 @@ function simplifyGeometry(geometry, tolerance = 1e-4) { const decimalShift = Math.log10(1 / tolerance); const shiftMultiplier = Math.pow(10, decimalShift); - for (let i = 0; i < vertexCount; i++) { const index = indices ? indices.getX(i) : i; // Generate a hash for the vertex attributes at the current index 'i'. @@ -15591,71 +13267,59 @@ function simplifyGeometry(geometry, tolerance = 1e-4) { } } // Construct merged BufferGeometry. - - const positionAttribute = new three.BufferAttribute(new Float32Array(newPositions), positions.itemSize, positions.normalized); - const result = new three.BufferGeometry(); + const positionAttribute = new _three.BufferAttribute(new Float32Array(newPositions), positions.itemSize, positions.normalized); + const result = new _three.BufferGeometry(); result.setAttribute('position', positionAttribute); result.setIndex(newIndices); return result; } - const PI_2 = Math.PI / 2; -exports.ShapeType = void 0; - +var ShapeType; (function (ShapeType) { ShapeType["BOX"] = "Box"; ShapeType["CYLINDER"] = "Cylinder"; ShapeType["SPHERE"] = "Sphere"; ShapeType["HULL"] = "ConvexPolyhedron"; ShapeType["MESH"] = "Trimesh"; -})(exports.ShapeType || (exports.ShapeType = {})); +})(ShapeType || (exports.ShapeType = ShapeType = {})); /** * Given a THREE.Object3D instance, creates parameters for a CANNON shape. */ - const getShapeParameters = function (object, options = {}) { let geometry; - - if (options.type === exports.ShapeType.BOX) { + if (options.type === ShapeType.BOX) { return getBoundingBoxParameters(object); - } else if (options.type === exports.ShapeType.CYLINDER) { + } else if (options.type === ShapeType.CYLINDER) { return getBoundingCylinderParameters(object, options); - } else if (options.type === exports.ShapeType.SPHERE) { + } else if (options.type === ShapeType.SPHERE) { return getBoundingSphereParameters(object, options); - } else if (options.type === exports.ShapeType.HULL) { + } else if (options.type === ShapeType.HULL) { return getConvexPolyhedronParameters(object); - } else if (options.type === exports.ShapeType.MESH) { + } else if (options.type === ShapeType.MESH) { geometry = getGeometry(object); return geometry ? getTrimeshParameters(geometry) : null; } else if (options.type) { throw new Error("[CANNON.getShapeParameters] Invalid type \"" + options.type + "\"."); } - geometry = getGeometry(object); if (!geometry) return null; - switch (geometry.type) { case 'BoxGeometry': case 'BoxBufferGeometry': return getBoxParameters(geometry); - case 'CylinderGeometry': case 'CylinderBufferGeometry': return getCylinderParameters(geometry); - case 'PlaneGeometry': case 'PlaneBufferGeometry': return getPlaneParameters(geometry); - case 'SphereGeometry': case 'SphereBufferGeometry': return getSphereParameters(geometry); - case 'TubeGeometry': case 'BufferGeometry': return getBoundingBoxParameters(object); - default: console.warn('Unrecognized geometry: "%s". Using bounding box as shape.', geometry.type); return getBoxParameters(geometry); @@ -15664,14 +13328,12 @@ const getShapeParameters = function (object, options = {}) { /** * Given a THREE.Object3D instance, creates a corresponding CANNON shape. */ - +exports.getShapeParameters = getShapeParameters; const threeToCannon = function (object, options = {}) { const shapeParameters = getShapeParameters(object, options); - if (!shapeParameters) { return null; } - const { type, params, @@ -15679,19 +13341,17 @@ const threeToCannon = function (object, options = {}) { orientation } = shapeParameters; let shape; - - if (type === exports.ShapeType.BOX) { + if (type === ShapeType.BOX) { shape = createBox(params); - } else if (type === exports.ShapeType.CYLINDER) { + } else if (type === ShapeType.CYLINDER) { shape = createCylinder(params); - } else if (type === exports.ShapeType.SPHERE) { + } else if (type === ShapeType.SPHERE) { shape = createSphere(params); - } else if (type === exports.ShapeType.HULL) { + } else if (type === ShapeType.HULL) { shape = createConvexPolyhedron(params); } else { shape = createTrimesh(params); } - return { shape, offset, @@ -15701,17 +13361,16 @@ const threeToCannon = function (object, options = {}) { /****************************************************************************** * Shape construction */ - +exports.threeToCannon = threeToCannon; function createBox(params) { const { x, y, z } = params; - const shape = new cannonEs.Box(new cannonEs.Vec3(x, y, z)); + const shape = new _cannonEs.Box(new _cannonEs.Vec3(x, y, z)); return shape; } - function createCylinder(params) { const { radiusTop, @@ -15719,7 +13378,7 @@ function createCylinder(params) { height, segments } = params; - const shape = new cannonEs.Cylinder(radiusTop, radiusBottom, height, segments); // Include metadata for serialization. + const shape = new _cannonEs.Cylinder(radiusTop, radiusBottom, height, segments); // Include metadata for serialization. // TODO(cleanup): Is this still necessary? shape.radiusTop = radiusBottom; @@ -15728,50 +13387,44 @@ function createCylinder(params) { shape.numSegments = segments; return shape; } - function createSphere(params) { - const shape = new cannonEs.Sphere(params.radius); + const shape = new _cannonEs.Sphere(params.radius); return shape; } - function createConvexPolyhedron(params) { const { faces, vertices: verticesArray } = params; const vertices = []; - for (let i = 0; i < verticesArray.length; i += 3) { - vertices.push(new cannonEs.Vec3(verticesArray[i], verticesArray[i + 1], verticesArray[i + 2])); + vertices.push(new _cannonEs.Vec3(verticesArray[i], verticesArray[i + 1], verticesArray[i + 2])); } - - const shape = new cannonEs.ConvexPolyhedron({ + const shape = new _cannonEs.ConvexPolyhedron({ faces, vertices }); return shape; } - function createTrimesh(params) { const { vertices, indices } = params; - const shape = new cannonEs.Trimesh(vertices, indices); + const shape = new _cannonEs.Trimesh(vertices, indices); return shape; } /****************************************************************************** * Shape parameters */ - function getBoxParameters(geometry) { const vertices = getVertices(geometry); if (!vertices.length) return null; geometry.computeBoundingBox(); const box = geometry.boundingBox; return { - type: exports.ShapeType.BOX, + type: ShapeType.BOX, params: { x: (box.max.x - box.min.x) / 2, y: (box.max.y - box.min.y) / 2, @@ -15781,50 +13434,44 @@ function getBoxParameters(geometry) { } /** Bounding box needs to be computed with the entire subtree, not just geometry. */ - function getBoundingBoxParameters(object) { const clone = object.clone(); clone.quaternion.set(0, 0, 0, 1); clone.updateMatrixWorld(); - const box = new three.Box3().setFromObject(clone); + const box = new _three.Box3().setFromObject(clone); if (!isFinite(box.min.lengthSq())) return null; - const localPosition = box.translate(clone.position.negate()).getCenter(new three.Vector3()); + const localPosition = box.translate(clone.position.negate()).getCenter(new _three.Vector3()); return { - type: exports.ShapeType.BOX, + type: ShapeType.BOX, params: { x: (box.max.x - box.min.x) / 2, y: (box.max.y - box.min.y) / 2, z: (box.max.z - box.min.z) / 2 }, - offset: localPosition.lengthSq() ? new cannonEs.Vec3(localPosition.x, localPosition.y, localPosition.z) : undefined + offset: localPosition.lengthSq() ? new _cannonEs.Vec3(localPosition.x, localPosition.y, localPosition.z) : undefined }; } /** Computes 3D convex hull as a CANNON.ConvexPolyhedron. */ - function getConvexPolyhedronParameters(object) { const geometry = getGeometry(object); if (!geometry) return null; // Perturb. const eps = 1e-4; - for (let i = 0; i < geometry.attributes.position.count; i++) { geometry.attributes.position.setXYZ(i, geometry.attributes.position.getX(i) + (Math.random() - 0.5) * eps, geometry.attributes.position.getY(i) + (Math.random() - 0.5) * eps, geometry.attributes.position.getZ(i) + (Math.random() - 0.5) * eps); } // Compute the 3D convex hull. - - const hull = new ConvexHull().setFromObject(new three.Mesh(geometry)); + const hull = new ConvexHull().setFromObject(new _three.Mesh(geometry)); const hullFaces = hull.faces; const vertices = []; const faces = []; let currentFaceVertex = 0; - for (let i = 0; i < hullFaces.length; i++) { const hullFace = hullFaces[i]; const face = []; faces.push(face); let edge = hullFace.edge; - do { const point = edge.head().point; vertices.push(point.x, point.y, point.z); @@ -15833,37 +13480,34 @@ function getConvexPolyhedronParameters(object) { edge = edge.next; } while (edge !== hullFace.edge); } - const verticesTypedArray = new Float32Array(vertices.length); verticesTypedArray.set(vertices); return { - type: exports.ShapeType.HULL, + type: ShapeType.HULL, params: { vertices: verticesTypedArray, faces } }; } - function getCylinderParameters(geometry) { const params = geometry.parameters; return { - type: exports.ShapeType.CYLINDER, + type: ShapeType.CYLINDER, params: { radiusTop: params.radiusTop, radiusBottom: params.radiusBottom, height: params.height, segments: params.radialSegments }, - orientation: new cannonEs.Quaternion().setFromEuler(three.MathUtils.degToRad(-90), 0, 0, 'XYZ').normalize() + orientation: new _cannonEs.Quaternion().setFromEuler(_three.MathUtils.degToRad(-90), 0, 0, 'XYZ').normalize() }; } - function getBoundingCylinderParameters(object, options) { const axes = ['x', 'y', 'z']; const majorAxis = options.cylinderAxis || 'y'; const minorAxes = axes.splice(axes.indexOf(majorAxis), 1) && axes; - const box = new three.Box3().setFromObject(object); + const box = new _three.Box3().setFromObject(object); if (!isFinite(box.min.lengthSq())) return null; // Compute cylinder dimensions. const height = box.max[majorAxis] - box.min[majorAxis]; @@ -15871,22 +13515,21 @@ function getBoundingCylinderParameters(object, options) { const eulerX = majorAxis === 'y' ? PI_2 : 0; const eulerY = majorAxis === 'z' ? PI_2 : 0; return { - type: exports.ShapeType.CYLINDER, + type: ShapeType.CYLINDER, params: { radiusTop: radius, radiusBottom: radius, height, segments: 12 }, - orientation: new cannonEs.Quaternion().setFromEuler(eulerX, eulerY, 0, 'XYZ').normalize() + orientation: new _cannonEs.Quaternion().setFromEuler(eulerX, eulerY, 0, 'XYZ').normalize() }; } - function getPlaneParameters(geometry) { geometry.computeBoundingBox(); const box = geometry.boundingBox; return { - type: exports.ShapeType.BOX, + type: ShapeType.BOX, params: { x: (box.max.x - box.min.x) / 2 || 0.1, y: (box.max.y - box.min.y) / 2 || 0.1, @@ -15894,48 +13537,42 @@ function getPlaneParameters(geometry) { } }; } - function getSphereParameters(geometry) { return { - type: exports.ShapeType.SPHERE, + type: ShapeType.SPHERE, params: { radius: geometry.parameters.radius } }; } - function getBoundingSphereParameters(object, options) { if (options.sphereRadius) { return { - type: exports.ShapeType.SPHERE, + type: ShapeType.SPHERE, params: { radius: options.sphereRadius } }; } - const geometry = getGeometry(object); if (!geometry) return null; geometry.computeBoundingSphere(); return { - type: exports.ShapeType.SPHERE, + type: ShapeType.SPHERE, params: { radius: geometry.boundingSphere.radius } }; } - function getTrimeshParameters(geometry) { const vertices = getVertices(geometry); if (!vertices.length) return null; const indices = new Uint32Array(vertices.length); - for (let i = 0; i < vertices.length; i++) { indices[i] = i; } - return { - type: exports.ShapeType.MESH, + type: ShapeType.MESH, params: { vertices, indices @@ -15943,3475 +13580,3479 @@ function getTrimeshParameters(geometry) { }; } -exports.getShapeParameters = getShapeParameters; -exports.threeToCannon = threeToCannon; - - }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"cannon-es":5}],8:[function(require,module,exports){ +"use strict"; + var bundleFn = arguments[3]; var sources = arguments[4]; var cache = arguments[5]; - var stringify = JSON.stringify; - module.exports = function (fn, options) { - var wkey; - var cacheKeys = Object.keys(cache); - + var wkey; + var cacheKeys = Object.keys(cache); + for (var i = 0, l = cacheKeys.length; i < l; i++) { + var key = cacheKeys[i]; + var exp = cache[key].exports; + // Using babel as a transpiler to use esmodule, the export will always + // be an object with the default export as a property of it. To ensure + // the existing api and babel esmodule exports are both supported we + // check for both + if (exp === fn || exp && exp.default === fn) { + wkey = key; + break; + } + } + if (!wkey) { + wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); + var wcache = {}; for (var i = 0, l = cacheKeys.length; i < l; i++) { - var key = cacheKeys[i]; - var exp = cache[key].exports; - // Using babel as a transpiler to use esmodule, the export will always - // be an object with the default export as a property of it. To ensure - // the existing api and babel esmodule exports are both supported we - // check for both - if (exp === fn || exp && exp.default === fn) { - wkey = key; - break; - } + var key = cacheKeys[i]; + wcache[key] = key; + } + sources[wkey] = [Function(['require', 'module', 'exports'], '(' + fn + ')(self)'), wcache]; + } + var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); + var scache = {}; + scache[wkey] = wkey; + sources[skey] = [Function(['require'], + // try to call default if defined to also support babel esmodule + // exports + 'var f = require(' + stringify(wkey) + ');' + '(f.default ? f.default : f)(self);'), scache]; + var workerSources = {}; + resolveSources(skey); + function resolveSources(key) { + workerSources[key] = true; + for (var depPath in sources[key][1]) { + var depKey = sources[key][1][depPath]; + if (!workerSources[depKey]) { + resolveSources(depKey); + } } + } + var src = '(' + bundleFn + ')({' + Object.keys(workerSources).map(function (key) { + return stringify(key) + ':[' + sources[key][0] + ',' + stringify(sources[key][1]) + ']'; + }).join(',') + '},{},[' + stringify(skey) + '])'; + var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; + var blob = new Blob([src], { + type: 'text/javascript' + }); + if (options && options.bare) { + return blob; + } + var workerUrl = URL.createObjectURL(blob); + var worker = new Worker(workerUrl); + worker.objectURL = workerUrl; + return worker; +}; - if (!wkey) { - wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); - var wcache = {}; - for (var i = 0, l = cacheKeys.length; i < l; i++) { - var key = cacheKeys[i]; - wcache[key] = key; - } - sources[wkey] = [ - Function(['require','module','exports'], '(' + fn + ')(self)'), - wcache - ]; - } - var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); - - var scache = {}; scache[wkey] = wkey; - sources[skey] = [ - Function(['require'], ( - // try to call default if defined to also support babel esmodule - // exports - 'var f = require(' + stringify(wkey) + ');' + - '(f.default ? f.default : f)(self);' - )), - scache - ]; +},{}],9:[function(require,module,exports){ +/* global Ammo */ +const CONSTRAINT = require("../constants").CONSTRAINT; + +module.exports = AFRAME.registerComponent("ammo-constraint", { + multiple: true, + + schema: { + // Type of constraint. + type: { + default: CONSTRAINT.LOCK, + oneOf: [ + CONSTRAINT.LOCK, + CONSTRAINT.FIXED, + CONSTRAINT.SPRING, + CONSTRAINT.SLIDER, + CONSTRAINT.HINGE, + CONSTRAINT.CONE_TWIST, + CONSTRAINT.POINT_TO_POINT + ] + }, - var workerSources = {}; - resolveSources(skey); + // Target (other) body for the constraint. + target: { type: "selector" }, - function resolveSources(key) { - workerSources[key] = true; + // Offset of the hinge or point-to-point constraint, defined locally in the body. Used for hinge, coneTwist pointToPoint constraints. + pivot: { type: "vec3" }, + targetPivot: { type: "vec3" }, - for (var depPath in sources[key][1]) { - var depKey = sources[key][1][depPath]; - if (!workerSources[depKey]) { - resolveSources(depKey); - } + // An axis that each body can rotate around, defined locally to that body. Used for hinge constraints. + axis: { type: "vec3", default: { x: 0, y: 0, z: 1 } }, + targetAxis: { type: "vec3", default: { x: 0, y: 0, z: 1 } }, + + // damping & stuffness - used for spring contraints only + damping: { type: "number", default: 1 }, + stiffness: { type: "number", default: 100 }, + }, + + init: function() { + this.system = this.el.sceneEl.systems.physics; + this.constraint = null; + }, + + remove: function() { + if (!this.constraint) return; + + this.system.removeConstraint(this.constraint); + this.constraint = null; + }, + + update: function() { + const el = this.el, + data = this.data; + + this.remove(); + + if (!el.body || !data.target.body) { + (el.body ? data.target : el).addEventListener("body-loaded", this.update.bind(this, {}), { once: true }); + return; + } + + this.constraint = this.createConstraint(); + this.system.addConstraint(this.constraint); + }, + + /** + * @return {Ammo.btTypedConstraint} + */ + createConstraint: function() { + let constraint; + const data = this.data, + body = this.el.body, + targetBody = data.target.body; + + const bodyTransform = body + .getCenterOfMassTransform() + .inverse() + .op_mul(targetBody.getWorldTransform()); + const targetTransform = new Ammo.btTransform(); + targetTransform.setIdentity(); + + switch (data.type) { + case CONSTRAINT.LOCK: { + constraint = new Ammo.btGeneric6DofConstraint(body, targetBody, bodyTransform, targetTransform, true); + const zero = new Ammo.btVector3(0, 0, 0); + //TODO: allow these to be configurable + constraint.setLinearLowerLimit(zero); + constraint.setLinearUpperLimit(zero); + constraint.setAngularLowerLimit(zero); + constraint.setAngularUpperLimit(zero); + Ammo.destroy(zero); + break; + } + //TODO: test and verify all other constraint types + case CONSTRAINT.FIXED: { + //btFixedConstraint does not seem to debug render + bodyTransform.setRotation(body.getWorldTransform().getRotation()); + targetTransform.setRotation(targetBody.getWorldTransform().getRotation()); + constraint = new Ammo.btFixedConstraint(body, targetBody, bodyTransform, targetTransform); + break; + } + case CONSTRAINT.SPRING: { + constraint = new Ammo.btGeneric6DofSpringConstraint(body, targetBody, bodyTransform, targetTransform, true); + + // Very limited initial implementation of spring constraint. + // See: https://github.com/n5ro/aframe-physics-system/issues/171 + for (var i in [0,1,2,3,4,5]) { + constraint.enableSpring(1, true) + constraint.setStiffness(1, this.data.stiffness) + constraint.setDamping(1, this.data.damping) } + const upper = new Ammo.btVector3(-1, -1, -1); + const lower = new Ammo.btVector3(1, 1, 1); + constraint.setLinearUpperLimit(upper); + constraint.setLinearLowerLimit(lower) + Ammo.destroy(upper); + Ammo.destroy(lower); + break; + } + case CONSTRAINT.SLIDER: { + //TODO: support setting linear and angular limits + constraint = new Ammo.btSliderConstraint(body, targetBody, bodyTransform, targetTransform, true); + constraint.setLowerLinLimit(-1); + constraint.setUpperLinLimit(1); + // constraint.setLowerAngLimit(); + // constraint.setUpperAngLimit(); + break; + } + case CONSTRAINT.HINGE: { + const pivot = new Ammo.btVector3(data.pivot.x, data.pivot.y, data.pivot.z); + const targetPivot = new Ammo.btVector3(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z); + + const axis = new Ammo.btVector3(data.axis.x, data.axis.y, data.axis.z); + const targetAxis = new Ammo.btVector3(data.targetAxis.x, data.targetAxis.y, data.targetAxis.z); + + constraint = new Ammo.btHingeConstraint(body, targetBody, pivot, targetPivot, axis, targetAxis, true); + + Ammo.destroy(pivot); + Ammo.destroy(targetPivot); + Ammo.destroy(axis); + Ammo.destroy(targetAxis); + break; + } + case CONSTRAINT.CONE_TWIST: { + const pivotTransform = new Ammo.btTransform(); + pivotTransform.setIdentity(); + pivotTransform.getOrigin().setValue(data.pivot.x, data.pivot.y, data.pivot.z); + const targetPivotTransform = new Ammo.btTransform(); + targetPivotTransform.setIdentity(); + targetPivotTransform.getOrigin().setValue(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z); + constraint = new Ammo.btConeTwistConstraint(body, targetBody, pivotTransform, targetPivotTransform); + Ammo.destroy(pivotTransform); + Ammo.destroy(targetPivotTransform); + break; + } + case CONSTRAINT.POINT_TO_POINT: { + const pivot = new Ammo.btVector3(data.pivot.x, data.pivot.y, data.pivot.z); + const targetPivot = new Ammo.btVector3(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z); + + constraint = new Ammo.btPoint2PointConstraint(body, targetBody, pivot, targetPivot); + + Ammo.destroy(pivot); + Ammo.destroy(targetPivot); + break; + } + default: + throw new Error("[constraint] Unexpected type: " + data.type); } - var src = '(' + bundleFn + ')({' - + Object.keys(workerSources).map(function (key) { - return stringify(key) + ':[' - + sources[key][0] - + ',' + stringify(sources[key][1]) + ']' - ; - }).join(',') - + '},{},[' + stringify(skey) + '])' - ; - - var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; - - var blob = new Blob([src], { type: 'text/javascript' }); - if (options && options.bare) { return blob; } - var workerUrl = URL.createObjectURL(blob); - var worker = new Worker(workerUrl); - worker.objectURL = workerUrl; - return worker; + Ammo.destroy(bodyTransform); + Ammo.destroy(targetTransform); + + return constraint; + } +}); + +},{"../constants":20}],10:[function(require,module,exports){ +/* global Ammo,THREE */ +const AmmoDebugDrawer = require("ammo-debug-drawer"); +const threeToAmmo = require("three-to-ammo"); +const CONSTANTS = require("../../constants"), + ACTIVATION_STATE = CONSTANTS.ACTIVATION_STATE, + COLLISION_FLAG = CONSTANTS.COLLISION_FLAG, + SHAPE = CONSTANTS.SHAPE, + TYPE = CONSTANTS.TYPE, + FIT = CONSTANTS.FIT; + +const ACTIVATION_STATES = [ + ACTIVATION_STATE.ACTIVE_TAG, + ACTIVATION_STATE.ISLAND_SLEEPING, + ACTIVATION_STATE.WANTS_DEACTIVATION, + ACTIVATION_STATE.DISABLE_DEACTIVATION, + ACTIVATION_STATE.DISABLE_SIMULATION +]; + +const RIGID_BODY_FLAGS = { + NONE: 0, + DISABLE_WORLD_GRAVITY: 1 }; -},{}],9:[function(require,module,exports){ -/* global Ammo */ -const CONSTRAINT = require("../constants").CONSTRAINT; - -module.exports = AFRAME.registerComponent("ammo-constraint", { - multiple: true, - - schema: { - // Type of constraint. - type: { - default: CONSTRAINT.LOCK, - oneOf: [ - CONSTRAINT.LOCK, - CONSTRAINT.FIXED, - CONSTRAINT.SPRING, - CONSTRAINT.SLIDER, - CONSTRAINT.HINGE, - CONSTRAINT.CONE_TWIST, - CONSTRAINT.POINT_TO_POINT - ] - }, - - // Target (other) body for the constraint. - target: { type: "selector" }, - - // Offset of the hinge or point-to-point constraint, defined locally in the body. Used for hinge, coneTwist pointToPoint constraints. - pivot: { type: "vec3" }, - targetPivot: { type: "vec3" }, - - // An axis that each body can rotate around, defined locally to that body. Used for hinge constraints. - axis: { type: "vec3", default: { x: 0, y: 0, z: 1 } }, - targetAxis: { type: "vec3", default: { x: 0, y: 0, z: 1 } }, - - // damping & stuffness - used for spring contraints only - damping: { type: "number", default: 1 }, - stiffness: { type: "number", default: 100 }, - }, - - init: function() { - this.system = this.el.sceneEl.systems.physics; - this.constraint = null; - }, - - remove: function() { - if (!this.constraint) return; - - this.system.removeConstraint(this.constraint); - this.constraint = null; - }, - - update: function() { - const el = this.el, - data = this.data; - - this.remove(); - - if (!el.body || !data.target.body) { - (el.body ? data.target : el).addEventListener("body-loaded", this.update.bind(this, {}), { once: true }); - return; - } - - this.constraint = this.createConstraint(); - this.system.addConstraint(this.constraint); - }, - - /** - * @return {Ammo.btTypedConstraint} - */ - createConstraint: function() { - let constraint; - const data = this.data, - body = this.el.body, - targetBody = data.target.body; - - const bodyTransform = body - .getCenterOfMassTransform() - .inverse() - .op_mul(targetBody.getWorldTransform()); - const targetTransform = new Ammo.btTransform(); - targetTransform.setIdentity(); - - switch (data.type) { - case CONSTRAINT.LOCK: { - constraint = new Ammo.btGeneric6DofConstraint(body, targetBody, bodyTransform, targetTransform, true); - const zero = new Ammo.btVector3(0, 0, 0); - //TODO: allow these to be configurable - constraint.setLinearLowerLimit(zero); - constraint.setLinearUpperLimit(zero); - constraint.setAngularLowerLimit(zero); - constraint.setAngularUpperLimit(zero); - Ammo.destroy(zero); - break; - } - //TODO: test and verify all other constraint types - case CONSTRAINT.FIXED: { - //btFixedConstraint does not seem to debug render - bodyTransform.setRotation(body.getWorldTransform().getRotation()); - targetTransform.setRotation(targetBody.getWorldTransform().getRotation()); - constraint = new Ammo.btFixedConstraint(body, targetBody, bodyTransform, targetTransform); - break; - } - case CONSTRAINT.SPRING: { - constraint = new Ammo.btGeneric6DofSpringConstraint(body, targetBody, bodyTransform, targetTransform, true); - - // Very limited initial implementation of spring constraint. - // See: https://github.com/n5ro/aframe-physics-system/issues/171 - for (var i in [0,1,2,3,4,5]) { - constraint.enableSpring(1, true) - constraint.setStiffness(1, this.data.stiffness) - constraint.setDamping(1, this.data.damping) - } - const upper = new Ammo.btVector3(-1, -1, -1); - const lower = new Ammo.btVector3(1, 1, 1); - constraint.setLinearUpperLimit(upper); - constraint.setLinearLowerLimit(lower) - Ammo.destroy(upper); - Ammo.destroy(lower); - break; - } - case CONSTRAINT.SLIDER: { - //TODO: support setting linear and angular limits - constraint = new Ammo.btSliderConstraint(body, targetBody, bodyTransform, targetTransform, true); - constraint.setLowerLinLimit(-1); - constraint.setUpperLinLimit(1); - // constraint.setLowerAngLimit(); - // constraint.setUpperAngLimit(); - break; - } - case CONSTRAINT.HINGE: { - const pivot = new Ammo.btVector3(data.pivot.x, data.pivot.y, data.pivot.z); - const targetPivot = new Ammo.btVector3(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z); - - const axis = new Ammo.btVector3(data.axis.x, data.axis.y, data.axis.z); - const targetAxis = new Ammo.btVector3(data.targetAxis.x, data.targetAxis.y, data.targetAxis.z); - - constraint = new Ammo.btHingeConstraint(body, targetBody, pivot, targetPivot, axis, targetAxis, true); - - Ammo.destroy(pivot); - Ammo.destroy(targetPivot); - Ammo.destroy(axis); - Ammo.destroy(targetAxis); - break; - } - case CONSTRAINT.CONE_TWIST: { - const pivotTransform = new Ammo.btTransform(); - pivotTransform.setIdentity(); - pivotTransform.getOrigin().setValue(data.pivot.x, data.pivot.y, data.pivot.z); - const targetPivotTransform = new Ammo.btTransform(); - targetPivotTransform.setIdentity(); - targetPivotTransform.getOrigin().setValue(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z); - constraint = new Ammo.btConeTwistConstraint(body, targetBody, pivotTransform, targetPivotTransform); - Ammo.destroy(pivotTransform); - Ammo.destroy(targetPivotTransform); - break; - } - case CONSTRAINT.POINT_TO_POINT: { - const pivot = new Ammo.btVector3(data.pivot.x, data.pivot.y, data.pivot.z); - const targetPivot = new Ammo.btVector3(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z); - - constraint = new Ammo.btPoint2PointConstraint(body, targetBody, pivot, targetPivot); - - Ammo.destroy(pivot); - Ammo.destroy(targetPivot); - break; - } - default: - throw new Error("[constraint] Unexpected type: " + data.type); - } - - Ammo.destroy(bodyTransform); - Ammo.destroy(targetTransform); - - return constraint; - } -}); +function almostEqualsVector3(epsilon, u, v) { + return Math.abs(u.x - v.x) < epsilon && Math.abs(u.y - v.y) < epsilon && Math.abs(u.z - v.z) < epsilon; +} + +function almostEqualsBtVector3(epsilon, u, v) { + return Math.abs(u.x() - v.x()) < epsilon && Math.abs(u.y() - v.y()) < epsilon && Math.abs(u.z() - v.z()) < epsilon; +} + +function almostEqualsQuaternion(epsilon, u, v) { + return ( + (Math.abs(u.x - v.x) < epsilon && + Math.abs(u.y - v.y) < epsilon && + Math.abs(u.z - v.z) < epsilon && + Math.abs(u.w - v.w) < epsilon) || + (Math.abs(u.x + v.x) < epsilon && + Math.abs(u.y + v.y) < epsilon && + Math.abs(u.z + v.z) < epsilon && + Math.abs(u.w + v.w) < epsilon) + ); +} + +let AmmoBody = { + schema: { + loadedEvent: { default: "" }, + mass: { default: 1 }, + gravity: { type: "vec3", default: { x: undefined, y: undefined, z: undefined } }, + linearDamping: { default: 0.01 }, + angularDamping: { default: 0.01 }, + linearSleepingThreshold: { default: 1.6 }, + angularSleepingThreshold: { default: 2.5 }, + angularFactor: { type: "vec3", default: { x: 1, y: 1, z: 1 } }, + activationState: { + default: ACTIVATION_STATE.ACTIVE_TAG, + oneOf: ACTIVATION_STATES + }, + type: { default: "dynamic", oneOf: [TYPE.STATIC, TYPE.DYNAMIC, TYPE.KINEMATIC] }, + emitCollisionEvents: { default: false }, + disableCollision: { default: false }, + collisionFilterGroup: { default: 1 }, //32-bit mask, + collisionFilterMask: { default: 1 }, //32-bit mask + scaleAutoUpdate: { default: true }, + restitution: {default: 0} // does not support updates + }, + + /** + * Initializes a body component, assigning it to the physics system and binding listeners for + * parsing the elements geometry. + */ + init: function() { + this.system = this.el.sceneEl.systems.physics; + this.shapeComponents = []; + + if (this.data.loadedEvent === "") { + this.loadedEventFired = true; + } else { + this.el.addEventListener( + this.data.loadedEvent, + () => { + this.loadedEventFired = true; + }, + { once: true } + ); + } + + if (this.system.initialized && this.loadedEventFired) { + this.initBody(); + } + }, + + /** + * Parses an element's geometry and component metadata to create an Ammo body instance for the + * component. + */ + initBody: (function() { + const pos = new THREE.Vector3(); + const quat = new THREE.Quaternion(); + const boundingBox = new THREE.Box3(); + + return function() { + const el = this.el, + data = this.data; + const clamp = (num, min, max) => Math.min(Math.max(num, min), max) + + this.localScaling = new Ammo.btVector3(); + + const obj = this.el.object3D; + obj.getWorldPosition(pos); + obj.getWorldQuaternion(quat); + + this.prevScale = new THREE.Vector3(1, 1, 1); + this.prevNumChildShapes = 0; + + this.msTransform = new Ammo.btTransform(); + this.msTransform.setIdentity(); + this.rotation = new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w); + + this.msTransform.getOrigin().setValue(pos.x, pos.y, pos.z); + this.msTransform.setRotation(this.rotation); + + this.motionState = new Ammo.btDefaultMotionState(this.msTransform); + + this.localInertia = new Ammo.btVector3(0, 0, 0); + + this.compoundShape = new Ammo.btCompoundShape(true); + + this.rbInfo = new Ammo.btRigidBodyConstructionInfo( + data.mass, + this.motionState, + this.compoundShape, + this.localInertia + ); + this.rbInfo.m_restitution = clamp(this.data.restitution, 0, 1); + this.body = new Ammo.btRigidBody(this.rbInfo); + this.body.setActivationState(ACTIVATION_STATES.indexOf(data.activationState) + 1); + this.body.setSleepingThresholds(data.linearSleepingThreshold, data.angularSleepingThreshold); + + this.body.setDamping(data.linearDamping, data.angularDamping); + + const angularFactor = new Ammo.btVector3(data.angularFactor.x, data.angularFactor.y, data.angularFactor.z); + this.body.setAngularFactor(angularFactor); + Ammo.destroy(angularFactor); + + this._updateBodyGravity(data.gravity) + + this.updateCollisionFlags(); + + this.el.body = this.body; + this.body.el = el; + + this.isLoaded = true; + + this.el.emit("body-loaded", { body: this.el.body }); + + this._addToSystem(); + }; + })(), + + tick: function() { + if (this.system.initialized && !this.isLoaded && this.loadedEventFired) { + this.initBody(); + } + }, + + _updateBodyGravity(gravity) { + + if (gravity.x !== undefined && + gravity.y !== undefined && + gravity.z !== undefined) { + const gravityBtVec = new Ammo.btVector3(gravity.x, gravity.y, gravity.z); + if (!almostEqualsBtVector3(0.001, gravityBtVec, this.system.driver.physicsWorld.getGravity())) { + this.body.setFlags(RIGID_BODY_FLAGS.DISABLE_WORLD_GRAVITY); + } else { + this.body.setFlags(RIGID_BODY_FLAGS.NONE); + } + this.body.setGravity(gravityBtVec); + Ammo.destroy(gravityBtVec); + } + else { + // no per-body gravity specified - just use world gravity + this.body.setFlags(RIGID_BODY_FLAGS.NONE); + } + }, + + _updateShapes: (function() { + const needsPolyhedralInitialization = [SHAPE.HULL, SHAPE.HACD, SHAPE.VHACD]; + return function() { + let updated = false; + + const obj = this.el.object3D; + if (this.data.scaleAutoUpdate && this.prevScale && !almostEqualsVector3(0.001, obj.scale, this.prevScale)) { + this.prevScale.copy(obj.scale); + updated = true; + + this.localScaling.setValue(this.prevScale.x, this.prevScale.y, this.prevScale.z); + this.compoundShape.setLocalScaling(this.localScaling); + } + + if (this.shapeComponentsChanged) { + this.shapeComponentsChanged = false; + updated = true; + for (let i = 0; i < this.shapeComponents.length; i++) { + const shapeComponent = this.shapeComponents[i]; + if (shapeComponent.getShapes().length === 0) { + this._createCollisionShape(shapeComponent); + } + const collisionShapes = shapeComponent.getShapes(); + for (let j = 0; j < collisionShapes.length; j++) { + const collisionShape = collisionShapes[j]; + if (!collisionShape.added) { + this.compoundShape.addChildShape(collisionShape.localTransform, collisionShape); + collisionShape.added = true; + } + } + } + + if (this.data.type === TYPE.DYNAMIC) { + this.updateMass(); + } + + this.system.driver.updateBody(this.body); + } + + //call initializePolyhedralFeatures for hull shapes if debug is turned on and/or scale changes + if (this.system.debug && (updated || !this.polyHedralFeaturesInitialized)) { + for (let i = 0; i < this.shapeComponents.length; i++) { + const collisionShapes = this.shapeComponents[i].getShapes(); + for (let j = 0; j < collisionShapes.length; j++) { + const collisionShape = collisionShapes[j]; + if (needsPolyhedralInitialization.indexOf(collisionShape.type) !== -1) { + collisionShape.initializePolyhedralFeatures(0); + } + } + } + this.polyHedralFeaturesInitialized = true; + } + }; + })(), + + _createCollisionShape: function(shapeComponent) { + const data = shapeComponent.data; + const vertices = []; + const matrices = []; + const indexes = []; + + const root = shapeComponent.el.object3D; + const matrixWorld = root.matrixWorld; + + threeToAmmo.iterateGeometries(root, {}, (vertexArray, matrixArray, indexArray) => { + vertices.push(vertexArray); + matrices.push(matrixArray); + indexes.push(indexArray); + }); + + const collisionShapes = threeToAmmo.createCollisionShapes(vertices, matrices, indexes, matrixWorld.elements, data); + shapeComponent.addShapes(collisionShapes); + return; + }, + + /** + * Registers the component with the physics system. + */ + play: function() { + if (this.isLoaded) { + this._addToSystem(); + } + }, + + _addToSystem: function() { + if (!this.addedToSystem) { + this.system.addBody(this.body, this.data.collisionFilterGroup, this.data.collisionFilterMask); + + if (this.data.emitCollisionEvents) { + this.system.driver.addEventListener(this.body); + } + + this.system.addComponent(this); + this.addedToSystem = true; + } + }, + + /** + * Unregisters the component with the physics system. + */ + pause: function() { + if (this.addedToSystem) { + this.system.removeComponent(this); + this.system.removeBody(this.body); + this.addedToSystem = false; + } + }, + + /** + * Updates the rigid body instance, where possible. + */ + update: function(prevData) { + if (this.isLoaded) { + if (!this.hasUpdated) { + //skip the first update + this.hasUpdated = true; + return; + } + + const data = this.data; + + if (prevData.type !== data.type || prevData.disableCollision !== data.disableCollision) { + this.updateCollisionFlags(); + } + + if (prevData.activationState !== data.activationState) { + this.body.forceActivationState(ACTIVATION_STATES.indexOf(data.activationState) + 1); + if (data.activationState === ACTIVATION_STATE.ACTIVE_TAG) { + this.body.activate(true); + } + } + + if ( + prevData.collisionFilterGroup !== data.collisionFilterGroup || + prevData.collisionFilterMask !== data.collisionFilterMask + ) { + const broadphaseProxy = this.body.getBroadphaseProxy(); + broadphaseProxy.set_m_collisionFilterGroup(data.collisionFilterGroup); + broadphaseProxy.set_m_collisionFilterMask(data.collisionFilterMask); + this.system.driver.broadphase + .getOverlappingPairCache() + .removeOverlappingPairsContainingProxy(broadphaseProxy, this.system.driver.dispatcher); + } + + if (prevData.linearDamping != data.linearDamping || prevData.angularDamping != data.angularDamping) { + this.body.setDamping(data.linearDamping, data.angularDamping); + } + + if (!almostEqualsVector3(0.001, prevData.gravity, data.gravity)) { + this._updateBodyGravity(data.gravity) + } + + if ( + prevData.linearSleepingThreshold != data.linearSleepingThreshold || + prevData.angularSleepingThreshold != data.angularSleepingThreshold + ) { + this.body.setSleepingThresholds(data.linearSleepingThreshold, data.angularSleepingThreshold); + } + + if (!almostEqualsVector3(0.001, prevData.angularFactor, data.angularFactor)) { + const angularFactor = new Ammo.btVector3(data.angularFactor.x, data.angularFactor.y, data.angularFactor.z); + this.body.setAngularFactor(angularFactor); + Ammo.destroy(angularFactor); + } + + if (prevData.restitution != data.restitution ) { + console.warn("ammo-body restitution cannot be updated from its initial value.") + } + + //TODO: support dynamic update for other properties + } + }, + + /** + * Removes the component and all physics and scene side effects. + */ + remove: function() { + if (this.triMesh) Ammo.destroy(this.triMesh); + if (this.localScaling) Ammo.destroy(this.localScaling); + if (this.compoundShape) Ammo.destroy(this.compoundShape); + if (this.body) { + Ammo.destroy(this.body); + delete this.body; + } + Ammo.destroy(this.rbInfo); + Ammo.destroy(this.msTransform); + Ammo.destroy(this.motionState); + Ammo.destroy(this.localInertia); + Ammo.destroy(this.rotation); + }, + + beforeStep: function() { + this._updateShapes(); + // Note that since static objects don't move, + // we don't sync them to physics on a routine basis. + if (this.data.type === TYPE.KINEMATIC) { + this.syncToPhysics(); + } + }, + + step: function() { + if (this.data.type === TYPE.DYNAMIC) { + this.syncFromPhysics(); + } + }, + + /** + * Updates the rigid body's position, velocity, and rotation, based on the scene. + */ + syncToPhysics: (function() { + const q = new THREE.Quaternion(); + const v = new THREE.Vector3(); + const q2 = new THREE.Vector3(); + const v2 = new THREE.Vector3(); + return function() { + const el = this.el, + parentEl = el.parentEl, + body = this.body; + + if (!body) return; + + this.motionState.getWorldTransform(this.msTransform); + + if (parentEl.isScene) { + v.copy(el.object3D.position); + q.copy(el.object3D.quaternion); + } else { + el.object3D.getWorldPosition(v); + el.object3D.getWorldQuaternion(q); + } + + const position = this.msTransform.getOrigin(); + v2.set(position.x(), position.y(), position.z()); + + const quaternion = this.msTransform.getRotation(); + q2.set(quaternion.x(), quaternion.y(), quaternion.z(), quaternion.w()); + + if (!almostEqualsVector3(0.001, v, v2) || !almostEqualsQuaternion(0.001, q, q2)) { + if (!this.body.isActive()) { + this.body.activate(true); + } + this.msTransform.getOrigin().setValue(v.x, v.y, v.z); + this.rotation.setValue(q.x, q.y, q.z, q.w); + this.msTransform.setRotation(this.rotation); + this.motionState.setWorldTransform(this.msTransform); + + if (this.data.type === TYPE.STATIC) { + this.body.setCenterOfMassTransform(this.msTransform); + } + } + }; + })(), + + /** + * Updates the scene object's position and rotation, based on the physics simulation. + */ + syncFromPhysics: (function() { + const v = new THREE.Vector3(), + q1 = new THREE.Quaternion(), + q2 = new THREE.Quaternion(); + return function() { + this.motionState.getWorldTransform(this.msTransform); + const position = this.msTransform.getOrigin(); + const quaternion = this.msTransform.getRotation(); + + const el = this.el, + body = this.body; + + // For the parent, prefer to use the THHREE.js scene graph parent (if it can be determined) + // and only use the HTML scene graph parent as a fallback. + // Usually these are the same, but there are various cases where it's useful to modify the THREE.js + // scene graph so that it deviates from the HTML. + // In these cases the THREE.js scene graph should be considered the definitive reference in terms + // of object positioning etc. + // For specific examples, and more discussion, see: + // https://github.com/c-frame/aframe-physics-system/pull/1#issuecomment-1264686433 + const parentEl = el.object3D.parent.el ? el.object3D.parent.el : el.parentEl; + + if (!body) return; + if (!parentEl) return; + + if (parentEl.isScene) { + el.object3D.position.set(position.x(), position.y(), position.z()); + el.object3D.quaternion.set(quaternion.x(), quaternion.y(), quaternion.z(), quaternion.w()); + } else { + q1.set(quaternion.x(), quaternion.y(), quaternion.z(), quaternion.w()); + parentEl.object3D.getWorldQuaternion(q2); + q1.multiply(q2.invert()); + el.object3D.quaternion.copy(q1); + + v.set(position.x(), position.y(), position.z()); + parentEl.object3D.worldToLocal(v); + el.object3D.position.copy(v); + } + }; + })(), + + addShapeComponent: function(shapeComponent) { + if (shapeComponent.data.type === SHAPE.MESH && this.data.type !== TYPE.STATIC) { + console.warn("non-static mesh colliders not supported"); + return; + } + + this.shapeComponents.push(shapeComponent); + this.shapeComponentsChanged = true; + }, + + removeShapeComponent: function(shapeComponent) { + const index = this.shapeComponents.indexOf(shapeComponent); + if (this.compoundShape && index !== -1 && this.body) { + const shapes = shapeComponent.getShapes(); + for (var i = 0; i < shapes.length; i++) { + this.compoundShape.removeChildShape(shapes[i]); + } + this.shapeComponentsChanged = true; + this.shapeComponents.splice(index, 1); + } + }, + + updateMass: function() { + const shape = this.body.getCollisionShape(); + const mass = this.data.type === TYPE.DYNAMIC ? this.data.mass : 0; + shape.calculateLocalInertia(mass, this.localInertia); + this.body.setMassProps(mass, this.localInertia); + this.body.updateInertiaTensor(); + }, + + updateCollisionFlags: function() { + let flags = this.data.disableCollision ? 4 : 0; + switch (this.data.type) { + case TYPE.STATIC: + flags |= COLLISION_FLAG.STATIC_OBJECT; + break; + case TYPE.KINEMATIC: + flags |= COLLISION_FLAG.KINEMATIC_OBJECT; + break; + default: + this.body.applyGravity(); + break; + } + this.body.setCollisionFlags(flags); + + this.updateMass(); + + // TODO: enable CCD if dynamic? + // this.body.setCcdMotionThreshold(0.001); + // this.body.setCcdSweptSphereRadius(0.001); + + this.system.driver.updateBody(this.body); + }, + + getVelocity: function() { + return this.body.getLinearVelocity(); + } +}; + +module.exports.definition = AmmoBody; +module.exports.Component = AFRAME.registerComponent("ammo-body", AmmoBody); + +},{"../../constants":20,"ammo-debug-drawer":4,"three-to-ammo":6}],11:[function(require,module,exports){ +var CANNON = require('cannon-es'); +const { threeToCannon, ShapeType } = require('three-to-cannon'); +const identityQuaternion = new THREE.Quaternion() + +function mesh2shape (object, options) { + + const result = threeToCannon(object, options); + return result; +} + +require('../../../lib/CANNON-shape2mesh'); + +var Body = { + dependencies: ['velocity'], + + schema: { + mass: {default: 5, if: {type: 'dynamic'}}, + linearDamping: { default: 0.01, if: {type: 'dynamic'}}, + angularDamping: { default: 0.01, if: {type: 'dynamic'}}, + shape: {default: 'auto', oneOf: ['auto', 'box', 'cylinder', 'sphere', 'hull', 'mesh', 'none']}, + cylinderAxis: {default: 'y', oneOf: ['x', 'y', 'z']}, + sphereRadius: {default: NaN}, + type: {default: 'dynamic', oneOf: ['static', 'dynamic']} + }, + + /** + * Initializes a body component, assigning it to the physics system and binding listeners for + * parsing the elements geometry. + */ + init: function () { + this.system = this.el.sceneEl.systems.physics; + + if (this.el.sceneEl.hasLoaded) { + this.initBody(); + } else { + this.el.sceneEl.addEventListener('loaded', this.initBody.bind(this)); + } + }, + + /** + * Parses an element's geometry and component metadata to create a CANNON.Body instance for the + * component. + */ + initBody: function () { + var el = this.el, + data = this.data; + + var obj = this.el.object3D; + var pos = obj.position; + var quat = obj.quaternion; + + this.body = new CANNON.Body({ + mass: data.type === 'static' ? 0 : data.mass || 0, + material: this.system.getMaterial('defaultMaterial'), + position: new CANNON.Vec3(pos.x, pos.y, pos.z), + quaternion: new CANNON.Quaternion(quat.x, quat.y, quat.z, quat.w), + linearDamping: data.linearDamping, + angularDamping: data.angularDamping, + type: data.type === 'dynamic' ? CANNON.Body.DYNAMIC : CANNON.Body.STATIC, + }); + + // Matrix World must be updated at root level, if scale is to be applied – updateMatrixWorld() + // only checks an object's parent, not the rest of the ancestors. Hence, a wrapping entity with + // scale="0.5 0.5 0.5" will be ignored. + // Reference: https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L511-L541 + // Potential fix: https://github.com/mrdoob/three.js/pull/7019 + this.el.object3D.updateMatrixWorld(true); + + if(data.shape !== 'none') { + var options = data.shape === 'auto' ? undefined : AFRAME.utils.extend({}, this.data, { + type: ShapeType[data.shape.toUpperCase()] + }); + + const shapeInfo = mesh2shape(this.el.object3D, options); + let shape, offset, orientation; + if (shapeInfo) { + ({ shape, offset, orientation } = shapeInfo); + } + + if (!shape) { + el.addEventListener('object3dset', this.initBody.bind(this)); + return; + } + + this.body.addShape(shape, offset, orientation); + + // Show wireframe + if (this.system.debug) { + this.shouldUpdateWireframe = true; + } + + this.hasShape = true; + } + + this.el.body = this.body; + this.body.el = el; + + // If component wasn't initialized when play() was called, finish up. + if (this.isPlaying) { + this._play(); + } + + if (this.hasShape) { + this.el.emit('body-loaded', {body: this.el.body}); + } + }, + + addShape: function(shape, offset, orientation) { + if (this.data.shape !== 'none') { + console.warn('shape can only be added if shape property is none'); + return; + } + + if (!shape) { + console.warn('shape cannot be null'); + return; + } + + if (!this.body) { + console.warn('shape cannot be added before body is loaded'); + return; + } + this.body.addShape(shape, offset, orientation); + + if (this.system.debug) { + this.shouldUpdateWireframe = true; + } + + this.shouldUpdateBody = true; + }, + + tick: function () { + if (this.shouldUpdateBody) { + + // Calling play will result in the object being re-added to the + // physics system with the updated body / shape data. + // But we mustn't add it twice, so any previously loaded body should be paused first. + this._pause(); + this.hasShape = true; + this._play() + + this.el.emit('body-loaded', {body: this.el.body}); + this.shouldUpdateBody = false; + } + + if (this.shouldUpdateWireframe) { + this.createWireframe(this.body); + this.shouldUpdateWireframe = false; + } + }, + + /** + * Registers the component with the physics system, if ready. + */ + play: function () { + this._play(); + }, + + /** + * Internal helper to register component with physics system. + */ + _play: function () { + + if (!this.hasShape) return; + + this.syncToPhysics(); + this.system.addComponent(this); + this.system.addBody(this.body); + if (this.wireframe) this.el.sceneEl.object3D.add(this.wireframe); + }, + + /** + * Unregisters the component with the physics system. + */ + pause: function () { + this._pause(); + }, + + _pause: function () { + + if (!this.hasShape) return; + + this.system.removeComponent(this); + if (this.body) this.system.removeBody(this.body); + if (this.wireframe) this.el.sceneEl.object3D.remove(this.wireframe); + }, + + /** + * Updates the CANNON.Body instance, where possible. + */ + update: function (prevData) { + if (!this.body) return; + + var data = this.data; + + if (prevData.type != undefined && data.type != prevData.type) { + this.body.type = data.type === 'dynamic' ? CANNON.Body.DYNAMIC : CANNON.Body.STATIC; + } + + this.body.mass = data.mass || 0; + if (data.type === 'dynamic') { + this.body.linearDamping = data.linearDamping; + this.body.angularDamping = data.angularDamping; + } + if (data.mass !== prevData.mass) { + this.body.updateMassProperties(); + } + if (this.body.updateProperties) this.body.updateProperties(); + }, + + /** + * Removes the component and all physics and scene side effects. + */ + remove: function () { + if (this.body) { + delete this.body.el; + delete this.body; + } + delete this.el.body; + delete this.wireframe; + }, + + beforeStep: function () { + if (this.body.mass === 0) { + this.syncToPhysics(); + } + }, + + step: function () { + if (this.body.mass !== 0) { + this.syncFromPhysics(); + } + }, + + /** + * Creates a wireframe for the body, for debugging. + * TODO(donmccurdy) – Refactor this into a standalone utility or component. + * @param {CANNON.Body} body + * @param {CANNON.Shape} shape + */ + createWireframe: function (body) { + if (this.wireframe) { + this.el.sceneEl.object3D.remove(this.wireframe); + delete this.wireframe; + } + this.wireframe = new THREE.Object3D(); + this.el.sceneEl.object3D.add(this.wireframe); + + var offset, mesh; + var orientation = new THREE.Quaternion(); + for (var i = 0; i < this.body.shapes.length; i++) + { + offset = this.body.shapeOffsets[i], + orientation.copy(this.body.shapeOrientations[i]), + mesh = CANNON.shape2mesh(this.body).children[i]; + + var wireframe = new THREE.LineSegments( + new THREE.EdgesGeometry(mesh.geometry), + new THREE.LineBasicMaterial({color: 0xff0000}) + ); + + if (offset) { + wireframe.position.copy(offset); + } + + if (orientation) { + wireframe.quaternion.copy(orientation); + } + + this.wireframe.add(wireframe); + } + + this.syncWireframe(); + }, + + /** + * Updates the debugging wireframe's position and rotation. + */ + syncWireframe: function () { + var offset, + wireframe = this.wireframe; + + if (!this.wireframe) return; + + // Apply rotation. If the shape required custom orientation, also apply + // that on the wireframe. + wireframe.quaternion.copy(this.body.quaternion); + if (wireframe.orientation) { + wireframe.quaternion.multiply(wireframe.orientation); + } + + // Apply position. If the shape required custom offset, also apply that on + // the wireframe. + wireframe.position.copy(this.body.position); + if (wireframe.offset) { + offset = wireframe.offset.clone().applyQuaternion(wireframe.quaternion); + wireframe.position.add(offset); + } + + wireframe.updateMatrix(); + }, + + /** + * Updates the CANNON.Body instance's position, velocity, and rotation, based on the scene. + */ + syncToPhysics: (function () { + var q = new THREE.Quaternion(), + v = new THREE.Vector3(); + return function () { + var el = this.el, + parentEl = el.parentEl, + body = this.body; + + if (!body) return; + + if (el.components.velocity) body.velocity.copy(el.getAttribute('velocity')); + + if (parentEl.isScene) { + body.quaternion.copy(el.object3D.quaternion); + body.position.copy(el.object3D.position); + } else { + el.object3D.getWorldQuaternion(q); + body.quaternion.copy(q); + el.object3D.getWorldPosition(v); + body.position.copy(v); + } + + if (this.body.updateProperties) this.body.updateProperties(); + if (this.wireframe) this.syncWireframe(); + }; + }()), + + /** + * Updates the scene object's position and rotation, based on the physics simulation. + */ + syncFromPhysics: (function () { + var v = new THREE.Vector3(), + q1 = new THREE.Quaternion(), + q2 = new THREE.Quaternion(); + return function () { + var el = this.el, + parentEl = el.parentEl, + body = this.body; + + if (!body) return; + if (!parentEl) return; + + if (parentEl.isScene) { + el.object3D.quaternion.copy(body.quaternion); + el.object3D.position.copy(body.position); + } else { + q1.copy(body.quaternion); + parentEl.object3D.getWorldQuaternion(q2); + q1.premultiply(q2.invert()); + el.object3D.quaternion.copy(q1); + + v.copy(body.position); + parentEl.object3D.worldToLocal(v); + el.object3D.position.copy(v); + } + + if (this.wireframe) this.syncWireframe(); + }; + }()) +}; + +module.exports.definition = Body; +module.exports.Component = AFRAME.registerComponent('body', Body); + +},{"../../../lib/CANNON-shape2mesh":2,"cannon-es":5,"three-to-cannon":7}],12:[function(require,module,exports){ +var Body = require('./body'); + +/** + * Dynamic body. + * + * Moves according to physics simulation, and may collide with other objects. + */ +var DynamicBody = AFRAME.utils.extend({}, Body.definition); + +module.exports = AFRAME.registerComponent('dynamic-body', DynamicBody); + +},{"./body":11}],13:[function(require,module,exports){ +var Body = require('./body'); + +/** + * Static body. + * + * Solid body with a fixed position. Unaffected by gravity and collisions, but + * other objects may collide with it. + */ +var StaticBody = AFRAME.utils.extend({}, Body.definition); + +StaticBody.schema = AFRAME.utils.extend({}, Body.definition.schema, { + type: {default: 'static', oneOf: ['static', 'dynamic']}, + mass: {default: 0} +}); + +module.exports = AFRAME.registerComponent('static-body', StaticBody); + +},{"./body":11}],14:[function(require,module,exports){ +var CANNON = require("cannon-es"); + +module.exports = AFRAME.registerComponent("constraint", { + multiple: true, + + schema: { + // Type of constraint. + type: { default: "lock", oneOf: ["coneTwist", "distance", "hinge", "lock", "pointToPoint"] }, + + // Target (other) body for the constraint. + target: { type: "selector" }, + + // Maximum force that should be applied to constraint the bodies. + maxForce: { default: 1e6, min: 0 }, + + // If true, bodies can collide when they are connected. + collideConnected: { default: true }, + + // Wake up bodies when connected. + wakeUpBodies: { default: true }, + + // The distance to be kept between the bodies. If 0, will be set to current distance. + distance: { default: 0, min: 0 }, + + // Offset of the hinge or point-to-point constraint, defined locally in the body. + pivot: { type: "vec3" }, + targetPivot: { type: "vec3" }, + + // An axis that each body can rotate around, defined locally to that body. + axis: { type: "vec3", default: { x: 0, y: 0, z: 1 } }, + targetAxis: { type: "vec3", default: { x: 0, y: 0, z: 1 } } + }, + + init: function() { + this.system = this.el.sceneEl.systems.physics; + this.constraint = /* {CANNON.Constraint} */ null; + }, + + remove: function() { + if (!this.constraint) return; + + this.system.removeConstraint(this.constraint); + this.constraint = null; + }, + + update: function() { + var el = this.el, + data = this.data; + + this.remove(); + + if (!el.body || !data.target.body) { + (el.body ? data.target : el).addEventListener("body-loaded", this.update.bind(this, {})); + return; + } + + this.constraint = this.createConstraint(); + this.system.addConstraint(this.constraint); + }, + + /** + * Creates a new constraint, given current component data. The CANNON.js constructors are a bit + * different for each constraint type. A `.type` property is added to each constraint, because + * `instanceof` checks are not reliable for some types. These types are needed for serialization. + * @return {CANNON.Constraint} + */ + createConstraint: function() { + var constraint, + data = this.data, + pivot = new CANNON.Vec3(data.pivot.x, data.pivot.y, data.pivot.z), + targetPivot = new CANNON.Vec3(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z), + axis = new CANNON.Vec3(data.axis.x, data.axis.y, data.axis.z), + targetAxis = new CANNON.Vec3(data.targetAxis.x, data.targetAxis.y, data.targetAxis.z); + + var constraint; + + switch (data.type) { + case "lock": + constraint = new CANNON.LockConstraint(this.el.body, data.target.body, { maxForce: data.maxForce }); + constraint.type = "LockConstraint"; + break; + + case "distance": + constraint = new CANNON.DistanceConstraint(this.el.body, data.target.body, data.distance, data.maxForce); + constraint.type = "DistanceConstraint"; + break; + + case "hinge": + constraint = new CANNON.HingeConstraint(this.el.body, data.target.body, { + pivotA: pivot, + pivotB: targetPivot, + axisA: axis, + axisB: targetAxis, + maxForce: data.maxForce + }); + constraint.type = "HingeConstraint"; + break; + + case "coneTwist": + constraint = new CANNON.ConeTwistConstraint(this.el.body, data.target.body, { + pivotA: pivot, + pivotB: targetPivot, + axisA: axis, + axisB: targetAxis, + maxForce: data.maxForce + }); + constraint.type = "ConeTwistConstraint"; + break; + + case "pointToPoint": + constraint = new CANNON.PointToPointConstraint( + this.el.body, + pivot, + data.target.body, + targetPivot, + data.maxForce + ); + constraint.type = "PointToPointConstraint"; + break; + + default: + throw new Error("[constraint] Unexpected type: " + data.type); + } + + constraint.collideConnected = data.collideConnected; + return constraint; + } +}); + +},{"cannon-es":5}],15:[function(require,module,exports){ +module.exports = { + 'velocity': require('./velocity'), + + registerAll: function (AFRAME) { + if (this._registered) return; + + AFRAME = AFRAME || window.AFRAME; + + if (!AFRAME.components['velocity']) AFRAME.registerComponent('velocity', this.velocity); + + this._registered = true; + } +}; + +},{"./velocity":16}],16:[function(require,module,exports){ +/** + * Velocity, in m/s. + */ +module.exports = AFRAME.registerComponent('velocity', { + schema: {type: 'vec3'}, + + init: function () { + this.system = this.el.sceneEl.systems.physics; + + if (this.system) { + this.system.addComponent(this); + } + }, + + remove: function () { + if (this.system) { + this.system.removeComponent(this); + } + }, + + tick: function (t, dt) { + if (!dt) return; + if (this.system) return; + this.afterStep(t, dt); + }, + + afterStep: function (t, dt) { + if (!dt) return; + + var physics = this.el.sceneEl.systems.physics || {data: {maxInterval: 1 / 60}}, + + // TODO - There's definitely a bug with getComputedAttribute and el.data. + velocity = this.el.getAttribute('velocity') || {x: 0, y: 0, z: 0}, + position = this.el.object3D.position || {x: 0, y: 0, z: 0}; + + dt = Math.min(dt, physics.data.maxInterval * 1000); + + this.el.object3D.position.set( + position.x + velocity.x * dt / 1000, + position.y + velocity.y * dt / 1000, + position.z + velocity.z * dt / 1000 + ); + } +}); + +},{}],17:[function(require,module,exports){ +/* global Ammo,THREE */ +const threeToAmmo = require("three-to-ammo"); +const CONSTANTS = require("../../constants"), + SHAPE = CONSTANTS.SHAPE, + FIT = CONSTANTS.FIT; + +var AmmoShape = { + schema: { + type: { + default: SHAPE.HULL, + oneOf: [ + SHAPE.BOX, + SHAPE.CYLINDER, + SHAPE.SPHERE, + SHAPE.CAPSULE, + SHAPE.CONE, + SHAPE.HULL, + SHAPE.HACD, + SHAPE.VHACD, + SHAPE.MESH, + SHAPE.HEIGHTFIELD + ] + }, + fit: { default: FIT.ALL, oneOf: [FIT.ALL, FIT.MANUAL] }, + halfExtents: { type: "vec3", default: { x: 1, y: 1, z: 1 } }, + minHalfExtent: { default: 0 }, + maxHalfExtent: { default: Number.POSITIVE_INFINITY }, + sphereRadius: { default: NaN }, + cylinderAxis: { default: "y", oneOf: ["x", "y", "z"] }, + margin: { default: 0.01 }, + offset: { type: "vec3", default: { x: 0, y: 0, z: 0 } }, + orientation: { type: "vec4", default: { x: 0, y: 0, z: 0, w: 1 } }, + heightfieldData: { default: [] }, + heightfieldDistance: { default: 1 }, + includeInvisible: { default: false } + }, + + multiple: true, + + init: function() { + if (this.data.fit !== FIT.MANUAL) { + if (this.el.object3DMap.mesh) { + this.mesh = this.el.object3DMap.mesh; + } else { + const self = this; + this.el.addEventListener("object3dset", function (e) { + if (e.detail.type === "mesh") { + self.init(); + } + }); + console.log("Cannot use FIT.ALL without object3DMap.mesh. Waiting for it to be set."); + return; + } + } + + this.system = this.el.sceneEl.systems.physics; + this.collisionShapes = []; + + let bodyEl = this.el; + this.body = bodyEl.components["ammo-body"] || null; + while (!this.body && bodyEl.parentNode != this.el.sceneEl) { + bodyEl = bodyEl.parentNode; + if (bodyEl.components["ammo-body"]) { + this.body = bodyEl.components["ammo-body"]; + } + } + if (!this.body) { + console.warn("body not found"); + return; + } + this.body.addShapeComponent(this); + }, + + getMesh: function() { + return this.mesh || null; + }, + + addShapes: function(collisionShapes) { + this.collisionShapes = collisionShapes; + }, + + getShapes: function() { + return this.collisionShapes; + }, + + remove: function() { + if (!this.body) { + return; + } + + this.body.removeShapeComponent(this); + + while (this.collisionShapes.length > 0) { + const collisionShape = this.collisionShapes.pop(); + collisionShape.destroy(); + Ammo.destroy(collisionShape.localTransform); + } + } +}; + +module.exports.definition = AmmoShape; +module.exports.Component = AFRAME.registerComponent("ammo-shape", AmmoShape); + +},{"../../constants":20,"three-to-ammo":6}],18:[function(require,module,exports){ +var CANNON = require('cannon-es'); + +var Shape = { + schema: { + shape: {default: 'box', oneOf: ['box', 'sphere', 'cylinder']}, + offset: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + orientation: {type: 'vec4', default: {x: 0, y: 0, z: 0, w: 1}}, + + // sphere + radius: {type: 'number', default: 1, if: {shape: ['sphere']}}, + + // box + halfExtents: {type: 'vec3', default: {x: 0.5, y: 0.5, z: 0.5}, if: {shape: ['box']}}, + + // cylinder + radiusTop: {type: 'number', default: 1, if: {shape: ['cylinder']}}, + radiusBottom: {type: 'number', default: 1, if: {shape: ['cylinder']}}, + height: {type: 'number', default: 1, if: {shape: ['cylinder']}}, + numSegments: {type: 'int', default: 8, if: {shape: ['cylinder']}} + }, + + multiple: true, + + init: function() { + if (this.el.sceneEl.hasLoaded) { + this.initShape(); + } else { + this.el.sceneEl.addEventListener('loaded', this.initShape.bind(this)); + } + }, + + initShape: function() { + this.bodyEl = this.el; + var bodyType = this._findType(this.bodyEl); + var data = this.data; + + while (!bodyType && this.bodyEl.parentNode != this.el.sceneEl) { + this.bodyEl = this.bodyEl.parentNode; + bodyType = this._findType(this.bodyEl); + } + + if (!bodyType) { + console.warn('body not found'); + return; + } + + var scale = new THREE.Vector3(); + this.bodyEl.object3D.getWorldScale(scale); + var shape, offset, orientation; + + if (data.hasOwnProperty('offset')) { + offset = new CANNON.Vec3( + data.offset.x * scale.x, + data.offset.y * scale.y, + data.offset.z * scale.z + ); + } + + if (data.hasOwnProperty('orientation')) { + orientation = new CANNON.Quaternion(); + orientation.copy(data.orientation); + } + + switch(data.shape) { + case 'sphere': + shape = new CANNON.Sphere(data.radius * scale.x); + break; + case 'box': + var halfExtents = new CANNON.Vec3( + data.halfExtents.x * scale.x, + data.halfExtents.y * scale.y, + data.halfExtents.z * scale.z + ); + shape = new CANNON.Box(halfExtents); + break; + case 'cylinder': + shape = new CANNON.Cylinder( + data.radiusTop * scale.x, + data.radiusBottom * scale.x, + data.height * scale.y, + data.numSegments + ); + + //rotate by 90 degrees similar to mesh2shape:createCylinderShape + var quat = new CANNON.Quaternion(); + quat.setFromEuler(90 * THREE.MathUtils.DEG2RAD, 0, 0, 'XYZ').normalize(); + orientation.mult(quat, orientation); + break; + default: + console.warn(data.shape + ' shape not supported'); + return; + } + + if (this.bodyEl.body) { + this.bodyEl.components[bodyType].addShape(shape, offset, orientation); + } else { + this.bodyEl.addEventListener('body-loaded', function() { + this.bodyEl.components[bodyType].addShape(shape, offset, orientation); + }, {once: true}); + } + }, + + _findType: function(el) { + if (el.hasAttribute('body')) { + return 'body'; + } else if (el.hasAttribute('dynamic-body')) { + return 'dynamic-body'; + } else if (el.hasAttribute('static-body')) { + return'static-body'; + } + return null; + }, + + remove: function() { + if (this.bodyEl.parentNode) { + console.warn('removing shape component not currently supported'); + } + } +}; + +module.exports.definition = Shape; +module.exports.Component = AFRAME.registerComponent('shape', Shape); + +},{"cannon-es":5}],19:[function(require,module,exports){ +var CANNON = require('cannon-es'); + +module.exports = AFRAME.registerComponent('spring', { + + multiple: true, + + schema: { + // Target (other) body for the constraint. + target: {type: 'selector'}, + + // Length of the spring, when no force acts upon it. + restLength: {default: 1, min: 0}, + + // How much will the spring suppress the force. + stiffness: {default: 100, min: 0}, + + // Stretch factor of the spring. + damping: {default: 1, min: 0}, + + // Offsets. + localAnchorA: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + localAnchorB: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + }, + + init: function() { + this.system = this.el.sceneEl.systems.physics; + this.system.addComponent(this); + this.isActive = true; + this.spring = /* {CANNON.Spring} */ null; + }, + + update: function(oldData) { + var el = this.el; + var data = this.data; + + if (!data.target) { + console.warn('Spring: invalid target specified.'); + return; + } + + // wait until the CANNON bodies is created and attached + if (!el.body || !data.target.body) { + (el.body ? data.target : el).addEventListener('body-loaded', this.update.bind(this, {})); + return; + } + + // create the spring if necessary + this.createSpring(); + // apply new data to the spring + this.updateSpring(oldData); + }, + + updateSpring: function(oldData) { + if (!this.spring) { + console.warn('Spring: Component attempted to change spring before its created. No changes made.'); + return; + } + var data = this.data; + var spring = this.spring; + + // Cycle through the schema and check if an attribute has changed. + // if so, apply it to the spring + Object.keys(data).forEach(function(attr) { + if (data[attr] !== oldData[attr]) { + if (attr === 'target') { + // special case for the target selector + spring.bodyB = data.target.body; + return; + } + spring[attr] = data[attr]; + } + }) + }, + + createSpring: function() { + if (this.spring) return; // no need to create a new spring + this.spring = new CANNON.Spring(this.el.body); + }, + + // If the spring is valid, update the force each tick the physics are calculated + step: function(t, dt) { + return this.spring && this.isActive ? this.spring.applyForce() : void 0; + }, + + // resume updating the force when component upon calling play() + play: function() { + this.isActive = true; + }, + + // stop updating the force when component upon calling stop() + pause: function() { + this.isActive = false; + }, + + //remove the event listener + delete the spring + remove: function() { + if (this.spring) + delete this.spring; + this.spring = null; + } +}) + +},{"cannon-es":5}],20:[function(require,module,exports){ +module.exports = { + GRAVITY: -9.8, + MAX_INTERVAL: 4 / 60, + ITERATIONS: 10, + CONTACT_MATERIAL: { + friction: 0.01, + restitution: 0.3, + contactEquationStiffness: 1e8, + contactEquationRelaxation: 3, + frictionEquationStiffness: 1e8, + frictionEquationRegularization: 3 + }, + ACTIVATION_STATE: { + ACTIVE_TAG: "active", + ISLAND_SLEEPING: "islandSleeping", + WANTS_DEACTIVATION: "wantsDeactivation", + DISABLE_DEACTIVATION: "disableDeactivation", + DISABLE_SIMULATION: "disableSimulation" + }, + COLLISION_FLAG: { + STATIC_OBJECT: 1, + KINEMATIC_OBJECT: 2, + NO_CONTACT_RESPONSE: 4, + CUSTOM_MATERIAL_CALLBACK: 8, //this allows per-triangle material (friction/restitution) + CHARACTER_OBJECT: 16, + DISABLE_VISUALIZE_OBJECT: 32, //disable debug drawing + DISABLE_SPU_COLLISION_PROCESSING: 64 //disable parallel/SPU processing + }, + TYPE: { + STATIC: "static", + DYNAMIC: "dynamic", + KINEMATIC: "kinematic" + }, + SHAPE: { + BOX: "box", + CYLINDER: "cylinder", + SPHERE: "sphere", + CAPSULE: "capsule", + CONE: "cone", + HULL: "hull", + HACD: "hacd", + VHACD: "vhacd", + MESH: "mesh", + HEIGHTFIELD: "heightfield" + }, + FIT: { + ALL: "all", + MANUAL: "manual" + }, + CONSTRAINT: { + LOCK: "lock", + FIXED: "fixed", + SPRING: "spring", + SLIDER: "slider", + HINGE: "hinge", + CONE_TWIST: "coneTwist", + POINT_TO_POINT: "pointToPoint" + } +}; + +},{}],21:[function(require,module,exports){ +/* global THREE */ +const Driver = require("./driver"); + +if (typeof window !== 'undefined') { + window.AmmoModule = window.Ammo; + window.Ammo = null; +} + +const EPS = 10e-6; + +function AmmoDriver() { + this.collisionConfiguration = null; + this.dispatcher = null; + this.broadphase = null; + this.solver = null; + this.physicsWorld = null; + this.debugDrawer = null; + + this.els = new Map(); + this.eventListeners = []; + this.collisions = new Map(); + this.collisionKeys = []; + this.currentCollisions = new Map(); +} + +AmmoDriver.prototype = new Driver(); +AmmoDriver.prototype.constructor = AmmoDriver; + +module.exports = AmmoDriver; + +/* @param {object} worldConfig */ +AmmoDriver.prototype.init = function(worldConfig) { + //Emscripten doesn't use real promises, just a .then() callback, so it necessary to wrap in a real promise. + return new Promise(resolve => { + AmmoModule().then(result => { + Ammo = result; + this.epsilon = worldConfig.epsilon || EPS; + this.debugDrawMode = worldConfig.debugDrawMode || THREE.AmmoDebugConstants.NoDebug; + this.maxSubSteps = worldConfig.maxSubSteps || 4; + this.fixedTimeStep = worldConfig.fixedTimeStep || 1 / 60; + this.collisionConfiguration = new Ammo.btDefaultCollisionConfiguration(); + this.dispatcher = new Ammo.btCollisionDispatcher(this.collisionConfiguration); + this.broadphase = new Ammo.btDbvtBroadphase(); + this.solver = new Ammo.btSequentialImpulseConstraintSolver(); + this.physicsWorld = new Ammo.btDiscreteDynamicsWorld( + this.dispatcher, + this.broadphase, + this.solver, + this.collisionConfiguration + ); + this.physicsWorld.setForceUpdateAllAabbs(false); + this.physicsWorld.setGravity( + new Ammo.btVector3(0, worldConfig.hasOwnProperty("gravity") ? worldConfig.gravity : -9.8, 0) + ); + this.physicsWorld.getSolverInfo().set_m_numIterations(worldConfig.solverIterations); + resolve(); + }); + }); +}; + +/* @param {Ammo.btCollisionObject} body */ +AmmoDriver.prototype.addBody = function(body, group, mask) { + this.physicsWorld.addRigidBody(body, group, mask); + this.els.set(Ammo.getPointer(body), body.el); +}; + +/* @param {Ammo.btCollisionObject} body */ +AmmoDriver.prototype.removeBody = function(body) { + this.physicsWorld.removeRigidBody(body); + this.removeEventListener(body); + const bodyptr = Ammo.getPointer(body); + this.els.delete(bodyptr); + this.collisions.delete(bodyptr); + this.collisionKeys.splice(this.collisionKeys.indexOf(bodyptr), 1); + this.currentCollisions.delete(bodyptr); +}; + +AmmoDriver.prototype.updateBody = function(body) { + if (this.els.has(Ammo.getPointer(body))) { + this.physicsWorld.updateSingleAabb(body); + } +}; + +/* @param {number} deltaTime */ +AmmoDriver.prototype.step = function(deltaTime) { + this.physicsWorld.stepSimulation(deltaTime, this.maxSubSteps, this.fixedTimeStep); + + const numManifolds = this.dispatcher.getNumManifolds(); + for (let i = 0; i < numManifolds; i++) { + const persistentManifold = this.dispatcher.getManifoldByIndexInternal(i); + const numContacts = persistentManifold.getNumContacts(); + const body0ptr = Ammo.getPointer(persistentManifold.getBody0()); + const body1ptr = Ammo.getPointer(persistentManifold.getBody1()); + let collided = false; + + for (let j = 0; j < numContacts; j++) { + const manifoldPoint = persistentManifold.getContactPoint(j); + const distance = manifoldPoint.getDistance(); + if (distance <= this.epsilon) { + collided = true; + break; + } + } + + if (collided) { + if (!this.collisions.has(body0ptr)) { + this.collisions.set(body0ptr, []); + this.collisionKeys.push(body0ptr); + } + if (this.collisions.get(body0ptr).indexOf(body1ptr) === -1) { + this.collisions.get(body0ptr).push(body1ptr); + if (this.eventListeners.indexOf(body0ptr) !== -1) { + this.els.get(body0ptr).emit("collidestart", { targetEl: this.els.get(body1ptr) }); + } + if (this.eventListeners.indexOf(body1ptr) !== -1) { + this.els.get(body1ptr).emit("collidestart", { targetEl: this.els.get(body0ptr) }); + } + } + if (!this.currentCollisions.has(body0ptr)) { + this.currentCollisions.set(body0ptr, new Set()); + } + this.currentCollisions.get(body0ptr).add(body1ptr); + } + } + + for (let i = 0; i < this.collisionKeys.length; i++) { + const body0ptr = this.collisionKeys[i]; + const body1ptrs = this.collisions.get(body0ptr); + for (let j = body1ptrs.length - 1; j >= 0; j--) { + const body1ptr = body1ptrs[j]; + if (this.currentCollisions.get(body0ptr).has(body1ptr)) { + continue; + } + if (this.eventListeners.indexOf(body0ptr) !== -1) { + this.els.get(body0ptr).emit("collideend", { targetEl: this.els.get(body1ptr) }); + } + if (this.eventListeners.indexOf(body1ptr) !== -1) { + this.els.get(body1ptr).emit("collideend", { targetEl: this.els.get(body0ptr) }); + } + body1ptrs.splice(j, 1); + } + this.currentCollisions.get(body0ptr).clear(); + } + + if (this.debugDrawer) { + this.debugDrawer.update(); + } +}; + +/* @param {?} constraint */ +AmmoDriver.prototype.addConstraint = function(constraint) { + this.physicsWorld.addConstraint(constraint, false); +}; + +/* @param {?} constraint */ +AmmoDriver.prototype.removeConstraint = function(constraint) { + this.physicsWorld.removeConstraint(constraint); +}; + +/* @param {Ammo.btCollisionObject} body */ +AmmoDriver.prototype.addEventListener = function(body) { + this.eventListeners.push(Ammo.getPointer(body)); +}; + +/* @param {Ammo.btCollisionObject} body */ +AmmoDriver.prototype.removeEventListener = function(body) { + const ptr = Ammo.getPointer(body); + if (this.eventListeners.indexOf(ptr) !== -1) { + this.eventListeners.splice(this.eventListeners.indexOf(ptr), 1); + } +}; + +AmmoDriver.prototype.destroy = function() { + Ammo.destroy(this.collisionConfiguration); + Ammo.destroy(this.dispatcher); + Ammo.destroy(this.broadphase); + Ammo.destroy(this.solver); + Ammo.destroy(this.physicsWorld); + Ammo.destroy(this.debugDrawer); +}; + +/** + * @param {THREE.Scene} scene + * @param {object} options + */ +AmmoDriver.prototype.getDebugDrawer = function(scene, options) { + if (!this.debugDrawer) { + options = options || {}; + options.debugDrawMode = options.debugDrawMode || this.debugDrawMode; + this.debugDrawer = new THREE.AmmoDebugDrawer(scene, this.physicsWorld, options); + } + return this.debugDrawer; +}; + +},{"./driver":22}],22:[function(require,module,exports){ +/** + * Driver - defines limited API to local and remote physics controllers. + */ + +function Driver () {} + +module.exports = Driver; + +/****************************************************************************** + * Lifecycle + */ + +/* @param {object} worldConfig */ +Driver.prototype.init = abstractMethod; + +/* @param {number} deltaMS */ +Driver.prototype.step = abstractMethod; + +Driver.prototype.destroy = abstractMethod; + +/****************************************************************************** + * Bodies + */ + +/* @param {CANNON.Body} body */ +Driver.prototype.addBody = abstractMethod; + +/* @param {CANNON.Body} body */ +Driver.prototype.removeBody = abstractMethod; + +/** + * @param {CANNON.Body} body + * @param {string} methodName + * @param {Array} args + */ +Driver.prototype.applyBodyMethod = abstractMethod; + +/** @param {CANNON.Body} body */ +Driver.prototype.updateBodyProperties = abstractMethod; + +/****************************************************************************** + * Materials + */ + +/** @param {object} materialConfig */ +Driver.prototype.addMaterial = abstractMethod; + +/** + * @param {string} materialName1 + * @param {string} materialName2 + * @param {object} contactMaterialConfig + */ +Driver.prototype.addContactMaterial = abstractMethod; + +/****************************************************************************** + * Constraints + */ + +/* @param {CANNON.Constraint} constraint */ +Driver.prototype.addConstraint = abstractMethod; + +/* @param {CANNON.Constraint} constraint */ +Driver.prototype.removeConstraint = abstractMethod; + +/****************************************************************************** + * Contacts + */ + +/** @return {Array} */ +Driver.prototype.getContacts = abstractMethod; + +/*****************************************************************************/ + +function abstractMethod () { + throw new Error('Method not implemented.'); +} + +},{}],23:[function(require,module,exports){ +module.exports = { + INIT: 'init', + STEP: 'step', + + // Bodies. + ADD_BODY: 'add-body', + REMOVE_BODY: 'remove-body', + APPLY_BODY_METHOD: 'apply-body-method', + UPDATE_BODY_PROPERTIES: 'update-body-properties', + + // Materials. + ADD_MATERIAL: 'add-material', + ADD_CONTACT_MATERIAL: 'add-contact-material', + + // Constraints. + ADD_CONSTRAINT: 'add-constraint', + REMOVE_CONSTRAINT: 'remove-constraint', + + // Events. + COLLIDE: 'collide' +}; + +},{}],24:[function(require,module,exports){ +var CANNON = require('cannon-es'), + Driver = require('./driver'); + +function LocalDriver () { + this.world = null; + this.materials = {}; + this.contactMaterial = null; +} + +LocalDriver.prototype = new Driver(); +LocalDriver.prototype.constructor = LocalDriver; + +module.exports = LocalDriver; + +/****************************************************************************** + * Lifecycle + */ + +/* @param {object} worldConfig */ +LocalDriver.prototype.init = function (worldConfig) { + var world = new CANNON.World(); + world.quatNormalizeSkip = worldConfig.quatNormalizeSkip; + world.quatNormalizeFast = worldConfig.quatNormalizeFast; + world.solver.iterations = worldConfig.solverIterations; + world.gravity.set(0, worldConfig.gravity, 0); + world.broadphase = new CANNON.NaiveBroadphase(); + + this.world = world; +}; + +/* @param {number} deltaMS */ +LocalDriver.prototype.step = function (deltaMS) { + this.world.step(deltaMS); +}; + +LocalDriver.prototype.destroy = function () { + delete this.world; + delete this.contactMaterial; + this.materials = {}; +}; + +/****************************************************************************** + * Bodies + */ + +/* @param {CANNON.Body} body */ +LocalDriver.prototype.addBody = function (body) { + this.world.addBody(body); +}; + +/* @param {CANNON.Body} body */ +LocalDriver.prototype.removeBody = function (body) { + this.world.removeBody(body); +}; -},{"../constants":20}],10:[function(require,module,exports){ -/* global Ammo,THREE */ -const AmmoDebugDrawer = require("ammo-debug-drawer"); -const threeToAmmo = require("three-to-ammo"); -const CONSTANTS = require("../../constants"), - ACTIVATION_STATE = CONSTANTS.ACTIVATION_STATE, - COLLISION_FLAG = CONSTANTS.COLLISION_FLAG, - SHAPE = CONSTANTS.SHAPE, - TYPE = CONSTANTS.TYPE, - FIT = CONSTANTS.FIT; - -const ACTIVATION_STATES = [ - ACTIVATION_STATE.ACTIVE_TAG, - ACTIVATION_STATE.ISLAND_SLEEPING, - ACTIVATION_STATE.WANTS_DEACTIVATION, - ACTIVATION_STATE.DISABLE_DEACTIVATION, - ACTIVATION_STATE.DISABLE_SIMULATION -]; - -const RIGID_BODY_FLAGS = { - NONE: 0, - DISABLE_WORLD_GRAVITY: 1 -}; - -function almostEqualsVector3(epsilon, u, v) { - return Math.abs(u.x - v.x) < epsilon && Math.abs(u.y - v.y) < epsilon && Math.abs(u.z - v.z) < epsilon; -} - -function almostEqualsBtVector3(epsilon, u, v) { - return Math.abs(u.x() - v.x()) < epsilon && Math.abs(u.y() - v.y()) < epsilon && Math.abs(u.z() - v.z()) < epsilon; -} - -function almostEqualsQuaternion(epsilon, u, v) { - return ( - (Math.abs(u.x - v.x) < epsilon && - Math.abs(u.y - v.y) < epsilon && - Math.abs(u.z - v.z) < epsilon && - Math.abs(u.w - v.w) < epsilon) || - (Math.abs(u.x + v.x) < epsilon && - Math.abs(u.y + v.y) < epsilon && - Math.abs(u.z + v.z) < epsilon && - Math.abs(u.w + v.w) < epsilon) - ); -} - -let AmmoBody = { - schema: { - loadedEvent: { default: "" }, - mass: { default: 1 }, - gravity: { type: "vec3", default: { x: undefined, y: undefined, z: undefined } }, - linearDamping: { default: 0.01 }, - angularDamping: { default: 0.01 }, - linearSleepingThreshold: { default: 1.6 }, - angularSleepingThreshold: { default: 2.5 }, - angularFactor: { type: "vec3", default: { x: 1, y: 1, z: 1 } }, - activationState: { - default: ACTIVATION_STATE.ACTIVE_TAG, - oneOf: ACTIVATION_STATES - }, - type: { default: "dynamic", oneOf: [TYPE.STATIC, TYPE.DYNAMIC, TYPE.KINEMATIC] }, - emitCollisionEvents: { default: false }, - disableCollision: { default: false }, - collisionFilterGroup: { default: 1 }, //32-bit mask, - collisionFilterMask: { default: 1 }, //32-bit mask - scaleAutoUpdate: { default: true }, - restitution: {default: 0} // does not support updates - }, - - /** - * Initializes a body component, assigning it to the physics system and binding listeners for - * parsing the elements geometry. - */ - init: function() { - this.system = this.el.sceneEl.systems.physics; - this.shapeComponents = []; - - if (this.data.loadedEvent === "") { - this.loadedEventFired = true; - } else { - this.el.addEventListener( - this.data.loadedEvent, - () => { - this.loadedEventFired = true; - }, - { once: true } - ); - } - - if (this.system.initialized && this.loadedEventFired) { - this.initBody(); - } - }, - - /** - * Parses an element's geometry and component metadata to create an Ammo body instance for the - * component. - */ - initBody: (function() { - const pos = new THREE.Vector3(); - const quat = new THREE.Quaternion(); - const boundingBox = new THREE.Box3(); - - return function() { - const el = this.el, - data = this.data; - const clamp = (num, min, max) => Math.min(Math.max(num, min), max) - - this.localScaling = new Ammo.btVector3(); - - const obj = this.el.object3D; - obj.getWorldPosition(pos); - obj.getWorldQuaternion(quat); - - this.prevScale = new THREE.Vector3(1, 1, 1); - this.prevNumChildShapes = 0; - - this.msTransform = new Ammo.btTransform(); - this.msTransform.setIdentity(); - this.rotation = new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w); - - this.msTransform.getOrigin().setValue(pos.x, pos.y, pos.z); - this.msTransform.setRotation(this.rotation); - - this.motionState = new Ammo.btDefaultMotionState(this.msTransform); - - this.localInertia = new Ammo.btVector3(0, 0, 0); - - this.compoundShape = new Ammo.btCompoundShape(true); - - this.rbInfo = new Ammo.btRigidBodyConstructionInfo( - data.mass, - this.motionState, - this.compoundShape, - this.localInertia - ); - this.rbInfo.m_restitution = clamp(this.data.restitution, 0, 1); - this.body = new Ammo.btRigidBody(this.rbInfo); - this.body.setActivationState(ACTIVATION_STATES.indexOf(data.activationState) + 1); - this.body.setSleepingThresholds(data.linearSleepingThreshold, data.angularSleepingThreshold); - - this.body.setDamping(data.linearDamping, data.angularDamping); - - const angularFactor = new Ammo.btVector3(data.angularFactor.x, data.angularFactor.y, data.angularFactor.z); - this.body.setAngularFactor(angularFactor); - Ammo.destroy(angularFactor); - - this._updateBodyGravity(data.gravity) - - this.updateCollisionFlags(); - - this.el.body = this.body; - this.body.el = el; - - this.isLoaded = true; - - this.el.emit("body-loaded", { body: this.el.body }); - - this._addToSystem(); - }; - })(), - - tick: function() { - if (this.system.initialized && !this.isLoaded && this.loadedEventFired) { - this.initBody(); - } - }, - - _updateBodyGravity(gravity) { - - if (gravity.x !== undefined && - gravity.y !== undefined && - gravity.z !== undefined) { - const gravityBtVec = new Ammo.btVector3(gravity.x, gravity.y, gravity.z); - if (!almostEqualsBtVector3(0.001, gravityBtVec, this.system.driver.physicsWorld.getGravity())) { - this.body.setFlags(RIGID_BODY_FLAGS.DISABLE_WORLD_GRAVITY); - } else { - this.body.setFlags(RIGID_BODY_FLAGS.NONE); - } - this.body.setGravity(gravityBtVec); - Ammo.destroy(gravityBtVec); - } - else { - // no per-body gravity specified - just use world gravity - this.body.setFlags(RIGID_BODY_FLAGS.NONE); - } - }, - - _updateShapes: (function() { - const needsPolyhedralInitialization = [SHAPE.HULL, SHAPE.HACD, SHAPE.VHACD]; - return function() { - let updated = false; - - const obj = this.el.object3D; - if (this.data.scaleAutoUpdate && this.prevScale && !almostEqualsVector3(0.001, obj.scale, this.prevScale)) { - this.prevScale.copy(obj.scale); - updated = true; - - this.localScaling.setValue(this.prevScale.x, this.prevScale.y, this.prevScale.z); - this.compoundShape.setLocalScaling(this.localScaling); - } - - if (this.shapeComponentsChanged) { - this.shapeComponentsChanged = false; - updated = true; - for (let i = 0; i < this.shapeComponents.length; i++) { - const shapeComponent = this.shapeComponents[i]; - if (shapeComponent.getShapes().length === 0) { - this._createCollisionShape(shapeComponent); - } - const collisionShapes = shapeComponent.getShapes(); - for (let j = 0; j < collisionShapes.length; j++) { - const collisionShape = collisionShapes[j]; - if (!collisionShape.added) { - this.compoundShape.addChildShape(collisionShape.localTransform, collisionShape); - collisionShape.added = true; - } - } - } - - if (this.data.type === TYPE.DYNAMIC) { - this.updateMass(); - } - - this.system.driver.updateBody(this.body); - } - - //call initializePolyhedralFeatures for hull shapes if debug is turned on and/or scale changes - if (this.system.debug && (updated || !this.polyHedralFeaturesInitialized)) { - for (let i = 0; i < this.shapeComponents.length; i++) { - const collisionShapes = this.shapeComponents[i].getShapes(); - for (let j = 0; j < collisionShapes.length; j++) { - const collisionShape = collisionShapes[j]; - if (needsPolyhedralInitialization.indexOf(collisionShape.type) !== -1) { - collisionShape.initializePolyhedralFeatures(0); - } - } - } - this.polyHedralFeaturesInitialized = true; - } - }; - })(), - - _createCollisionShape: function(shapeComponent) { - const data = shapeComponent.data; - const collisionShapes = threeToAmmo.createCollisionShapes(shapeComponent.getMesh(), data); - shapeComponent.addShapes(collisionShapes); - return; - }, - - /** - * Registers the component with the physics system. - */ - play: function() { - if (this.isLoaded) { - this._addToSystem(); - } - }, - - _addToSystem: function() { - if (!this.addedToSystem) { - this.system.addBody(this.body, this.data.collisionFilterGroup, this.data.collisionFilterMask); - - if (this.data.emitCollisionEvents) { - this.system.driver.addEventListener(this.body); - } - - this.system.addComponent(this); - this.addedToSystem = true; - } - }, - - /** - * Unregisters the component with the physics system. - */ - pause: function() { - if (this.addedToSystem) { - this.system.removeComponent(this); - this.system.removeBody(this.body); - this.addedToSystem = false; - } - }, - - /** - * Updates the rigid body instance, where possible. - */ - update: function(prevData) { - if (this.isLoaded) { - if (!this.hasUpdated) { - //skip the first update - this.hasUpdated = true; - return; - } - - const data = this.data; - - if (prevData.type !== data.type || prevData.disableCollision !== data.disableCollision) { - this.updateCollisionFlags(); - } - - if (prevData.activationState !== data.activationState) { - this.body.forceActivationState(ACTIVATION_STATES.indexOf(data.activationState) + 1); - if (data.activationState === ACTIVATION_STATE.ACTIVE_TAG) { - this.body.activate(true); - } - } - - if ( - prevData.collisionFilterGroup !== data.collisionFilterGroup || - prevData.collisionFilterMask !== data.collisionFilterMask - ) { - const broadphaseProxy = this.body.getBroadphaseProxy(); - broadphaseProxy.set_m_collisionFilterGroup(data.collisionFilterGroup); - broadphaseProxy.set_m_collisionFilterMask(data.collisionFilterMask); - this.system.driver.broadphase - .getOverlappingPairCache() - .removeOverlappingPairsContainingProxy(broadphaseProxy, this.system.driver.dispatcher); - } - - if (prevData.linearDamping != data.linearDamping || prevData.angularDamping != data.angularDamping) { - this.body.setDamping(data.linearDamping, data.angularDamping); - } - - if (!almostEqualsVector3(0.001, prevData.gravity, data.gravity)) { - this._updateBodyGravity(data.gravity) - } - - if ( - prevData.linearSleepingThreshold != data.linearSleepingThreshold || - prevData.angularSleepingThreshold != data.angularSleepingThreshold - ) { - this.body.setSleepingThresholds(data.linearSleepingThreshold, data.angularSleepingThreshold); - } - - if (!almostEqualsVector3(0.001, prevData.angularFactor, data.angularFactor)) { - const angularFactor = new Ammo.btVector3(data.angularFactor.x, data.angularFactor.y, data.angularFactor.z); - this.body.setAngularFactor(angularFactor); - Ammo.destroy(angularFactor); - } - - if (prevData.restitution != data.restitution ) { - console.warn("ammo-body restitution cannot be updated from its initial value.") - } - - //TODO: support dynamic update for other properties - } - }, - - /** - * Removes the component and all physics and scene side effects. - */ - remove: function() { - if (this.triMesh) Ammo.destroy(this.triMesh); - if (this.localScaling) Ammo.destroy(this.localScaling); - if (this.compoundShape) Ammo.destroy(this.compoundShape); - if (this.body) { - Ammo.destroy(this.body); - delete this.body; - } - Ammo.destroy(this.rbInfo); - Ammo.destroy(this.msTransform); - Ammo.destroy(this.motionState); - Ammo.destroy(this.localInertia); - Ammo.destroy(this.rotation); - }, - - beforeStep: function() { - this._updateShapes(); - // Note that since static objects don't move, - // we don't sync them to physics on a routine basis. - if (this.data.type === TYPE.KINEMATIC) { - this.syncToPhysics(); - } - }, - - step: function() { - if (this.data.type === TYPE.DYNAMIC) { - this.syncFromPhysics(); - } - }, - - /** - * Updates the rigid body's position, velocity, and rotation, based on the scene. - */ - syncToPhysics: (function() { - const q = new THREE.Quaternion(); - const v = new THREE.Vector3(); - const q2 = new THREE.Vector3(); - const v2 = new THREE.Vector3(); - return function() { - const el = this.el, - parentEl = el.parentEl, - body = this.body; - - if (!body) return; - - this.motionState.getWorldTransform(this.msTransform); - - if (parentEl.isScene) { - v.copy(el.object3D.position); - q.copy(el.object3D.quaternion); - } else { - el.object3D.getWorldPosition(v); - el.object3D.getWorldQuaternion(q); - } - - const position = this.msTransform.getOrigin(); - v2.set(position.x(), position.y(), position.z()); - - const quaternion = this.msTransform.getRotation(); - q2.set(quaternion.x(), quaternion.y(), quaternion.z(), quaternion.w()); - - if (!almostEqualsVector3(0.001, v, v2) || !almostEqualsQuaternion(0.001, q, q2)) { - if (!this.body.isActive()) { - this.body.activate(true); - } - this.msTransform.getOrigin().setValue(v.x, v.y, v.z); - this.rotation.setValue(q.x, q.y, q.z, q.w); - this.msTransform.setRotation(this.rotation); - this.motionState.setWorldTransform(this.msTransform); - - if (this.data.type === TYPE.STATIC) { - this.body.setCenterOfMassTransform(this.msTransform); - } - } - }; - })(), - - /** - * Updates the scene object's position and rotation, based on the physics simulation. - */ - syncFromPhysics: (function() { - const v = new THREE.Vector3(), - q1 = new THREE.Quaternion(), - q2 = new THREE.Quaternion(); - return function() { - this.motionState.getWorldTransform(this.msTransform); - const position = this.msTransform.getOrigin(); - const quaternion = this.msTransform.getRotation(); - - const el = this.el, - body = this.body; - - // For the parent, prefer to use the THHREE.js scene graph parent (if it can be determined) - // and only use the HTML scene graph parent as a fallback. - // Usually these are the same, but there are various cases where it's useful to modify the THREE.js - // scene graph so that it deviates from the HTML. - // In these cases the THREE.js scene graph should be considered the definitive reference in terms - // of object positioning etc. - // For specific examples, and more discussion, see: - // https://github.com/c-frame/aframe-physics-system/pull/1#issuecomment-1264686433 - const parentEl = el.object3D.parent.el ? el.object3D.parent.el : el.parentEl; - - if (!body) return; - if (!parentEl) return; - - if (parentEl.isScene) { - el.object3D.position.set(position.x(), position.y(), position.z()); - el.object3D.quaternion.set(quaternion.x(), quaternion.y(), quaternion.z(), quaternion.w()); - } else { - q1.set(quaternion.x(), quaternion.y(), quaternion.z(), quaternion.w()); - parentEl.object3D.getWorldQuaternion(q2); - q1.multiply(q2.invert()); - el.object3D.quaternion.copy(q1); - - v.set(position.x(), position.y(), position.z()); - parentEl.object3D.worldToLocal(v); - el.object3D.position.copy(v); - } - }; - })(), - - addShapeComponent: function(shapeComponent) { - if (shapeComponent.data.type === SHAPE.MESH && this.data.type !== TYPE.STATIC) { - console.warn("non-static mesh colliders not supported"); - return; - } - - this.shapeComponents.push(shapeComponent); - this.shapeComponentsChanged = true; - }, - - removeShapeComponent: function(shapeComponent) { - const index = this.shapeComponents.indexOf(shapeComponent); - if (this.compoundShape && index !== -1 && this.body) { - const shapes = shapeComponent.getShapes(); - for (var i = 0; i < shapes.length; i++) { - this.compoundShape.removeChildShape(shapes[i]); - } - this.shapeComponentsChanged = true; - this.shapeComponents.splice(index, 1); - } - }, - - updateMass: function() { - const shape = this.body.getCollisionShape(); - const mass = this.data.type === TYPE.DYNAMIC ? this.data.mass : 0; - shape.calculateLocalInertia(mass, this.localInertia); - this.body.setMassProps(mass, this.localInertia); - this.body.updateInertiaTensor(); - }, - - updateCollisionFlags: function() { - let flags = this.data.disableCollision ? 4 : 0; - switch (this.data.type) { - case TYPE.STATIC: - flags |= COLLISION_FLAG.STATIC_OBJECT; - break; - case TYPE.KINEMATIC: - flags |= COLLISION_FLAG.KINEMATIC_OBJECT; - break; - default: - this.body.applyGravity(); - break; - } - this.body.setCollisionFlags(flags); - - this.updateMass(); - - // TODO: enable CCD if dynamic? - // this.body.setCcdMotionThreshold(0.001); - // this.body.setCcdSweptSphereRadius(0.001); - - this.system.driver.updateBody(this.body); - }, - - getVelocity: function() { - return this.body.getLinearVelocity(); - } -}; - -module.exports.definition = AmmoBody; -module.exports.Component = AFRAME.registerComponent("ammo-body", AmmoBody); +/** + * @param {CANNON.Body} body + * @param {string} methodName + * @param {Array} args + */ +LocalDriver.prototype.applyBodyMethod = function (body, methodName, args) { + body['__' + methodName].apply(body, args); +}; + +/** @param {CANNON.Body} body */ +LocalDriver.prototype.updateBodyProperties = function () {}; + +/****************************************************************************** + * Materials + */ + +/** + * @param {string} name + * @return {CANNON.Material} + */ +LocalDriver.prototype.getMaterial = function (name) { + return this.materials[name]; +}; + +/** @param {object} materialConfig */ +LocalDriver.prototype.addMaterial = function (materialConfig) { + this.materials[materialConfig.name] = new CANNON.Material(materialConfig); + this.materials[materialConfig.name].name = materialConfig.name; +}; + +/** + * @param {string} matName1 + * @param {string} matName2 + * @param {object} contactMaterialConfig + */ +LocalDriver.prototype.addContactMaterial = function (matName1, matName2, contactMaterialConfig) { + var mat1 = this.materials[matName1], + mat2 = this.materials[matName2]; + this.contactMaterial = new CANNON.ContactMaterial(mat1, mat2, contactMaterialConfig); + this.world.addContactMaterial(this.contactMaterial); +}; + +/****************************************************************************** + * Constraints + */ + +/* @param {CANNON.Constraint} constraint */ +LocalDriver.prototype.addConstraint = function (constraint) { + if (!constraint.type) { + if (constraint instanceof CANNON.LockConstraint) { + constraint.type = 'LockConstraint'; + } else if (constraint instanceof CANNON.DistanceConstraint) { + constraint.type = 'DistanceConstraint'; + } else if (constraint instanceof CANNON.HingeConstraint) { + constraint.type = 'HingeConstraint'; + } else if (constraint instanceof CANNON.ConeTwistConstraint) { + constraint.type = 'ConeTwistConstraint'; + } else if (constraint instanceof CANNON.PointToPointConstraint) { + constraint.type = 'PointToPointConstraint'; + } + } + this.world.addConstraint(constraint); +}; + +/* @param {CANNON.Constraint} constraint */ +LocalDriver.prototype.removeConstraint = function (constraint) { + this.world.removeConstraint(constraint); +}; + +/****************************************************************************** + * Contacts + */ + +/** @return {Array} */ +LocalDriver.prototype.getContacts = function () { + return this.world.contacts; +}; + +},{"./driver":22,"cannon-es":5}],25:[function(require,module,exports){ +var Driver = require('./driver'); + +function NetworkDriver () { + throw new Error('[NetworkDriver] Driver not implemented.'); +} + +NetworkDriver.prototype = new Driver(); +NetworkDriver.prototype.constructor = NetworkDriver; + +module.exports = NetworkDriver; + +},{"./driver":22}],26:[function(require,module,exports){ +/** + * Stub version of webworkify, for debugging code outside of a webworker. + */ +function webworkifyDebug (worker) { + var targetA = new EventTarget(), + targetB = new EventTarget(); + + targetA.setTarget(targetB); + targetB.setTarget(targetA); + + worker(targetA); + return targetB; +} + +module.exports = webworkifyDebug; + +/****************************************************************************** + * EventTarget + */ + +function EventTarget () { + this.listeners = []; +} + +EventTarget.prototype.setTarget = function (target) { + this.target = target; +}; + +EventTarget.prototype.addEventListener = function (type, fn) { + this.listeners.push(fn); +}; + +EventTarget.prototype.dispatchEvent = function (type, event) { + for (var i = 0; i < this.listeners.length; i++) { + this.listeners[i](event); + } +}; + +EventTarget.prototype.postMessage = function (msg) { + this.target.dispatchEvent('message', {data: msg}); +}; + +},{}],27:[function(require,module,exports){ +/* global performance */ + +var webworkify = require('webworkify'), + webworkifyDebug = require('./webworkify-debug'), + Driver = require('./driver'), + Event = require('./event'), + worker = require('./worker'), + protocol = require('../utils/protocol'); + +var ID = protocol.ID; + +/****************************************************************************** + * Constructor + */ + +function WorkerDriver (options) { + this.fps = options.fps; + this.engine = options.engine; + this.interpolate = options.interpolate; + // Approximate number of physics steps to 'pad' rendering. + this.interpBufferSize = options.interpolationBufferSize; + this.debug = options.debug; + + this.bodies = {}; + this.contacts = []; + + // https://gafferongames.com/post/snapshot_interpolation/ + this.frameDelay = this.interpBufferSize * 1000 / this.fps; + this.frameBuffer = []; + + this.worker = this.debug + ? webworkifyDebug(worker) + : webworkify(worker); + this.worker.addEventListener('message', this._onMessage.bind(this)); +} + +WorkerDriver.prototype = new Driver(); +WorkerDriver.prototype.constructor = WorkerDriver; + +module.exports = WorkerDriver; + +/****************************************************************************** + * Lifecycle + */ + +/* @param {object} worldConfig */ +WorkerDriver.prototype.init = function (worldConfig) { + this.worker.postMessage({ + type: Event.INIT, + worldConfig: worldConfig, + fps: this.fps, + engine: this.engine + }); +}; + +/** + * Increments the physics world forward one step, if interpolation is enabled. + * If disabled, increments are performed as messages arrive. + * @param {number} deltaMS + */ +WorkerDriver.prototype.step = function () { + if (!this.interpolate) return; + + // Get the two oldest frames that haven't expired. Ideally we would use all + // available frames to keep things smooth, but lerping is easier and faster. + var prevFrame = this.frameBuffer[0]; + var nextFrame = this.frameBuffer[1]; + var timestamp = performance.now(); + while (prevFrame && nextFrame && timestamp - prevFrame.timestamp > this.frameDelay) { + this.frameBuffer.shift(); + prevFrame = this.frameBuffer[0]; + nextFrame = this.frameBuffer[1]; + } + + if (!prevFrame || !nextFrame) return; + + var mix = (timestamp - prevFrame.timestamp) / this.frameDelay; + mix = (mix - (1 - 1 / this.interpBufferSize)) * this.interpBufferSize; + + for (var id in prevFrame.bodies) { + if (prevFrame.bodies.hasOwnProperty(id) && nextFrame.bodies.hasOwnProperty(id)) { + protocol.deserializeInterpBodyUpdate( + prevFrame.bodies[id], + nextFrame.bodies[id], + this.bodies[id], + mix + ); + } + } +}; + +WorkerDriver.prototype.destroy = function () { + this.worker.terminate(); + delete this.worker; +}; + +/** {Event} event */ +WorkerDriver.prototype._onMessage = function (event) { + if (event.data.type === Event.STEP) { + var data = event.data, + bodies = data.bodies; + + this.contacts = event.data.contacts; + + // If interpolation is enabled, store the frame. If not, update all bodies + // immediately. + if (this.interpolate) { + this.frameBuffer.push({timestamp: performance.now(), bodies: bodies}); + } else { + for (var id in bodies) { + if (bodies.hasOwnProperty(id)) { + protocol.deserializeBodyUpdate(bodies[id], this.bodies[id]); + } + } + } + + } else if (event.data.type === Event.COLLIDE) { + var body = this.bodies[event.data.bodyID]; + var target = this.bodies[event.data.targetID]; + var contact = protocol.deserializeContact(event.data.contact, this.bodies); + if (!body._listeners || !body._listeners.collide) return; + for (var i = 0; i < body._listeners.collide.length; i++) { + body._listeners.collide[i]({target: target, body: body, contact: contact}); + } + + } else { + throw new Error('[WorkerDriver] Unexpected message type.'); + } +}; + +/****************************************************************************** + * Bodies + */ + +/* @param {CANNON.Body} body */ +WorkerDriver.prototype.addBody = function (body) { + protocol.assignID('body', body); + this.bodies[body[ID]] = body; + this.worker.postMessage({type: Event.ADD_BODY, body: protocol.serializeBody(body)}); +}; + +/* @param {CANNON.Body} body */ +WorkerDriver.prototype.removeBody = function (body) { + this.worker.postMessage({type: Event.REMOVE_BODY, bodyID: body[ID]}); + delete this.bodies[body[ID]]; +}; + +/** + * @param {CANNON.Body} body + * @param {string} methodName + * @param {Array} args + */ +WorkerDriver.prototype.applyBodyMethod = function (body, methodName, args) { + switch (methodName) { + case 'applyForce': + case 'applyImpulse': + this.worker.postMessage({ + type: Event.APPLY_BODY_METHOD, + bodyID: body[ID], + methodName: methodName, + args: [args[0].toArray(), args[1].toArray()] + }); + break; + default: + throw new Error('Unexpected methodName: %s', methodName); + } +}; -},{"../../constants":20,"ammo-debug-drawer":4,"three-to-ammo":6}],11:[function(require,module,exports){ -var CANNON = require('cannon-es'); -const { threeToCannon, ShapeType } = require('three-to-cannon'); -const identityQuaternion = new THREE.Quaternion() - -function mesh2shape (object, options) { - - const result = threeToCannon(object, options); - return result; -} - -require('../../../lib/CANNON-shape2mesh'); - -var Body = { - dependencies: ['velocity'], - - schema: { - mass: {default: 5, if: {type: 'dynamic'}}, - linearDamping: { default: 0.01, if: {type: 'dynamic'}}, - angularDamping: { default: 0.01, if: {type: 'dynamic'}}, - shape: {default: 'auto', oneOf: ['auto', 'box', 'cylinder', 'sphere', 'hull', 'mesh', 'none']}, - cylinderAxis: {default: 'y', oneOf: ['x', 'y', 'z']}, - sphereRadius: {default: NaN}, - type: {default: 'dynamic', oneOf: ['static', 'dynamic']} - }, - - /** - * Initializes a body component, assigning it to the physics system and binding listeners for - * parsing the elements geometry. - */ - init: function () { - this.system = this.el.sceneEl.systems.physics; - - if (this.el.sceneEl.hasLoaded) { - this.initBody(); - } else { - this.el.sceneEl.addEventListener('loaded', this.initBody.bind(this)); - } - }, - - /** - * Parses an element's geometry and component metadata to create a CANNON.Body instance for the - * component. - */ - initBody: function () { - var el = this.el, - data = this.data; - - var obj = this.el.object3D; - var pos = obj.position; - var quat = obj.quaternion; - - this.body = new CANNON.Body({ - mass: data.type === 'static' ? 0 : data.mass || 0, - material: this.system.getMaterial('defaultMaterial'), - position: new CANNON.Vec3(pos.x, pos.y, pos.z), - quaternion: new CANNON.Quaternion(quat.x, quat.y, quat.z, quat.w), - linearDamping: data.linearDamping, - angularDamping: data.angularDamping, - type: data.type === 'dynamic' ? CANNON.Body.DYNAMIC : CANNON.Body.STATIC, - }); - - // Matrix World must be updated at root level, if scale is to be applied – updateMatrixWorld() - // only checks an object's parent, not the rest of the ancestors. Hence, a wrapping entity with - // scale="0.5 0.5 0.5" will be ignored. - // Reference: https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L511-L541 - // Potential fix: https://github.com/mrdoob/three.js/pull/7019 - this.el.object3D.updateMatrixWorld(true); - - if(data.shape !== 'none') { - var options = data.shape === 'auto' ? undefined : AFRAME.utils.extend({}, this.data, { - type: ShapeType[data.shape.toUpperCase()] - }); - - var { shape, offset, orientation } = mesh2shape(this.el.object3D, options); - - if (!shape) { - el.addEventListener('object3dset', this.initBody.bind(this)); - return; - } - this.body.addShape(shape, offset, orientation); - - // Show wireframe - if (this.system.debug) { - this.shouldUpdateWireframe = true; - } - - this.hasShape = true; - } - - this.el.body = this.body; - this.body.el = el; - - // If component wasn't initialized when play() was called, finish up. - if (this.isPlaying) { - this._play(); - } - - if (this.hasShape) { - this.el.emit('body-loaded', {body: this.el.body}); - } - }, - - addShape: function(shape, offset, orientation) { - if (this.data.shape !== 'none') { - console.warn('shape can only be added if shape property is none'); - return; - } - - if (!shape) { - console.warn('shape cannot be null'); - return; - } - - if (!this.body) { - console.warn('shape cannot be added before body is loaded'); - return; - } - this.body.addShape(shape, offset, orientation); - - if (this.system.debug) { - this.shouldUpdateWireframe = true; - } - - this.shouldUpdateBody = true; - }, - - tick: function () { - if (this.shouldUpdateBody) { - - // Calling play will result in the object being re-added to the - // physics system with the updated body / shape data. - // But we mustn't add it twice, so any previously loaded body should be paused first. - this._pause(); - this.hasShape = true; - this._play() - - this.el.emit('body-loaded', {body: this.el.body}); - this.shouldUpdateBody = false; - } - - if (this.shouldUpdateWireframe) { - this.createWireframe(this.body); - this.shouldUpdateWireframe = false; - } - }, - - /** - * Registers the component with the physics system, if ready. - */ - play: function () { - this._play(); - }, - - /** - * Internal helper to register component with physics system. - */ - _play: function () { - - if (!this.hasShape) return; - - this.syncToPhysics(); - this.system.addComponent(this); - this.system.addBody(this.body); - if (this.wireframe) this.el.sceneEl.object3D.add(this.wireframe); - }, - - /** - * Unregisters the component with the physics system. - */ - pause: function () { - this._pause(); - }, - - _pause: function () { - - if (!this.hasShape) return; - - this.system.removeComponent(this); - if (this.body) this.system.removeBody(this.body); - if (this.wireframe) this.el.sceneEl.object3D.remove(this.wireframe); - }, - - /** - * Updates the CANNON.Body instance, where possible. - */ - update: function (prevData) { - if (!this.body) return; - - var data = this.data; - - if (prevData.type != undefined && data.type != prevData.type) { - this.body.type = data.type === 'dynamic' ? CANNON.Body.DYNAMIC : CANNON.Body.STATIC; - } - - this.body.mass = data.mass || 0; - if (data.type === 'dynamic') { - this.body.linearDamping = data.linearDamping; - this.body.angularDamping = data.angularDamping; - } - if (data.mass !== prevData.mass) { - this.body.updateMassProperties(); - } - if (this.body.updateProperties) this.body.updateProperties(); - }, - - /** - * Removes the component and all physics and scene side effects. - */ - remove: function () { - if (this.body) { - delete this.body.el; - delete this.body; - } - delete this.el.body; - delete this.wireframe; - }, - - beforeStep: function () { - if (this.body.mass === 0) { - this.syncToPhysics(); - } - }, - - step: function () { - if (this.body.mass !== 0) { - this.syncFromPhysics(); - } - }, - - /** - * Creates a wireframe for the body, for debugging. - * TODO(donmccurdy) – Refactor this into a standalone utility or component. - * @param {CANNON.Body} body - * @param {CANNON.Shape} shape - */ - createWireframe: function (body) { - if (this.wireframe) { - this.el.sceneEl.object3D.remove(this.wireframe); - delete this.wireframe; - } - this.wireframe = new THREE.Object3D(); - this.el.sceneEl.object3D.add(this.wireframe); - - var offset, mesh; - var orientation = new THREE.Quaternion(); - for (var i = 0; i < this.body.shapes.length; i++) - { - offset = this.body.shapeOffsets[i], - orientation.copy(this.body.shapeOrientations[i]), - mesh = CANNON.shape2mesh(this.body).children[i]; - - var wireframe = new THREE.LineSegments( - new THREE.EdgesGeometry(mesh.geometry), - new THREE.LineBasicMaterial({color: 0xff0000}) - ); - - if (offset) { - wireframe.position.copy(offset); - } - - if (orientation) { - wireframe.quaternion.copy(orientation); - } - - this.wireframe.add(wireframe); - } - - this.syncWireframe(); - }, - - /** - * Updates the debugging wireframe's position and rotation. - */ - syncWireframe: function () { - var offset, - wireframe = this.wireframe; - - if (!this.wireframe) return; - - // Apply rotation. If the shape required custom orientation, also apply - // that on the wireframe. - wireframe.quaternion.copy(this.body.quaternion); - if (wireframe.orientation) { - wireframe.quaternion.multiply(wireframe.orientation); - } - - // Apply position. If the shape required custom offset, also apply that on - // the wireframe. - wireframe.position.copy(this.body.position); - if (wireframe.offset) { - offset = wireframe.offset.clone().applyQuaternion(wireframe.quaternion); - wireframe.position.add(offset); - } - - wireframe.updateMatrix(); - }, - - /** - * Updates the CANNON.Body instance's position, velocity, and rotation, based on the scene. - */ - syncToPhysics: (function () { - var q = new THREE.Quaternion(), - v = new THREE.Vector3(); - return function () { - var el = this.el, - parentEl = el.parentEl, - body = this.body; - - if (!body) return; - - if (el.components.velocity) body.velocity.copy(el.getAttribute('velocity')); - - if (parentEl.isScene) { - body.quaternion.copy(el.object3D.quaternion); - body.position.copy(el.object3D.position); - } else { - el.object3D.getWorldQuaternion(q); - body.quaternion.copy(q); - el.object3D.getWorldPosition(v); - body.position.copy(v); - } - - if (this.body.updateProperties) this.body.updateProperties(); - if (this.wireframe) this.syncWireframe(); - }; - }()), - - /** - * Updates the scene object's position and rotation, based on the physics simulation. - */ - syncFromPhysics: (function () { - var v = new THREE.Vector3(), - q1 = new THREE.Quaternion(), - q2 = new THREE.Quaternion(); - return function () { - var el = this.el, - parentEl = el.parentEl, - body = this.body; - - if (!body) return; - if (!parentEl) return; - - if (parentEl.isScene) { - el.object3D.quaternion.copy(body.quaternion); - el.object3D.position.copy(body.position); - } else { - q1.copy(body.quaternion); - parentEl.object3D.getWorldQuaternion(q2); - q1.premultiply(q2.invert()); - el.object3D.quaternion.copy(q1); - - v.copy(body.position); - parentEl.object3D.worldToLocal(v); - el.object3D.position.copy(v); - } - - if (this.wireframe) this.syncWireframe(); - }; - }()) -}; - -module.exports.definition = Body; -module.exports.Component = AFRAME.registerComponent('body', Body); +/** @param {CANNON.Body} body */ +WorkerDriver.prototype.updateBodyProperties = function (body) { + this.worker.postMessage({ + type: Event.UPDATE_BODY_PROPERTIES, + body: protocol.serializeBody(body) + }); +}; -},{"../../../lib/CANNON-shape2mesh":2,"cannon-es":5,"three-to-cannon":7}],12:[function(require,module,exports){ -var Body = require('./body'); - -/** - * Dynamic body. - * - * Moves according to physics simulation, and may collide with other objects. - */ -var DynamicBody = AFRAME.utils.extend({}, Body.definition); - -module.exports = AFRAME.registerComponent('dynamic-body', DynamicBody); +/****************************************************************************** + * Materials + */ -},{"./body":11}],13:[function(require,module,exports){ -var Body = require('./body'); - -/** - * Static body. - * - * Solid body with a fixed position. Unaffected by gravity and collisions, but - * other objects may collide with it. - */ -var StaticBody = AFRAME.utils.extend({}, Body.definition); - -StaticBody.schema = AFRAME.utils.extend({}, Body.definition.schema, { - type: {default: 'static', oneOf: ['static', 'dynamic']}, - mass: {default: 0} -}); - -module.exports = AFRAME.registerComponent('static-body', StaticBody); +/** + * @param {string} name + * @return {CANNON.Material} + */ +WorkerDriver.prototype.getMaterial = function (name) { + // No access to materials here. Eventually we might return the name or ID, if + // multiple materials were selected, but for now there's only one and it's safe + // to assume the worker is already using it. + return undefined; +}; -},{"./body":11}],14:[function(require,module,exports){ -var CANNON = require("cannon-es"); - -module.exports = AFRAME.registerComponent("constraint", { - multiple: true, - - schema: { - // Type of constraint. - type: { default: "lock", oneOf: ["coneTwist", "distance", "hinge", "lock", "pointToPoint"] }, - - // Target (other) body for the constraint. - target: { type: "selector" }, - - // Maximum force that should be applied to constraint the bodies. - maxForce: { default: 1e6, min: 0 }, - - // If true, bodies can collide when they are connected. - collideConnected: { default: true }, - - // Wake up bodies when connected. - wakeUpBodies: { default: true }, - - // The distance to be kept between the bodies. If 0, will be set to current distance. - distance: { default: 0, min: 0 }, - - // Offset of the hinge or point-to-point constraint, defined locally in the body. - pivot: { type: "vec3" }, - targetPivot: { type: "vec3" }, - - // An axis that each body can rotate around, defined locally to that body. - axis: { type: "vec3", default: { x: 0, y: 0, z: 1 } }, - targetAxis: { type: "vec3", default: { x: 0, y: 0, z: 1 } } - }, - - init: function() { - this.system = this.el.sceneEl.systems.physics; - this.constraint = /* {CANNON.Constraint} */ null; - }, - - remove: function() { - if (!this.constraint) return; - - this.system.removeConstraint(this.constraint); - this.constraint = null; - }, - - update: function() { - var el = this.el, - data = this.data; - - this.remove(); - - if (!el.body || !data.target.body) { - (el.body ? data.target : el).addEventListener("body-loaded", this.update.bind(this, {})); - return; - } - - this.constraint = this.createConstraint(); - this.system.addConstraint(this.constraint); - }, - - /** - * Creates a new constraint, given current component data. The CANNON.js constructors are a bit - * different for each constraint type. A `.type` property is added to each constraint, because - * `instanceof` checks are not reliable for some types. These types are needed for serialization. - * @return {CANNON.Constraint} - */ - createConstraint: function() { - var constraint, - data = this.data, - pivot = new CANNON.Vec3(data.pivot.x, data.pivot.y, data.pivot.z), - targetPivot = new CANNON.Vec3(data.targetPivot.x, data.targetPivot.y, data.targetPivot.z), - axis = new CANNON.Vec3(data.axis.x, data.axis.y, data.axis.z), - targetAxis = new CANNON.Vec3(data.targetAxis.x, data.targetAxis.y, data.targetAxis.z); - - var constraint; - - switch (data.type) { - case "lock": - constraint = new CANNON.LockConstraint(this.el.body, data.target.body, { maxForce: data.maxForce }); - constraint.type = "LockConstraint"; - break; - - case "distance": - constraint = new CANNON.DistanceConstraint(this.el.body, data.target.body, data.distance, data.maxForce); - constraint.type = "DistanceConstraint"; - break; - - case "hinge": - constraint = new CANNON.HingeConstraint(this.el.body, data.target.body, { - pivotA: pivot, - pivotB: targetPivot, - axisA: axis, - axisB: targetAxis, - maxForce: data.maxForce - }); - constraint.type = "HingeConstraint"; - break; - - case "coneTwist": - constraint = new CANNON.ConeTwistConstraint(this.el.body, data.target.body, { - pivotA: pivot, - pivotB: targetPivot, - axisA: axis, - axisB: targetAxis, - maxForce: data.maxForce - }); - constraint.type = "ConeTwistConstraint"; - break; - - case "pointToPoint": - constraint = new CANNON.PointToPointConstraint( - this.el.body, - pivot, - data.target.body, - targetPivot, - data.maxForce - ); - constraint.type = "PointToPointConstraint"; - break; - - default: - throw new Error("[constraint] Unexpected type: " + data.type); - } - - constraint.collideConnected = data.collideConnected; - return constraint; - } -}); +/** @param {object} materialConfig */ +WorkerDriver.prototype.addMaterial = function (materialConfig) { + this.worker.postMessage({type: Event.ADD_MATERIAL, materialConfig: materialConfig}); +}; -},{"cannon-es":5}],15:[function(require,module,exports){ -module.exports = { - 'velocity': require('./velocity'), - - registerAll: function (AFRAME) { - if (this._registered) return; - - AFRAME = AFRAME || window.AFRAME; - - if (!AFRAME.components['velocity']) AFRAME.registerComponent('velocity', this.velocity); - - this._registered = true; - } -}; +/** + * @param {string} matName1 + * @param {string} matName2 + * @param {object} contactMaterialConfig + */ +WorkerDriver.prototype.addContactMaterial = function (matName1, matName2, contactMaterialConfig) { + this.worker.postMessage({ + type: Event.ADD_CONTACT_MATERIAL, + materialName1: matName1, + materialName2: matName2, + contactMaterialConfig: contactMaterialConfig + }); +}; + +/****************************************************************************** + * Constraints + */ + +/* @param {CANNON.Constraint} constraint */ +WorkerDriver.prototype.addConstraint = function (constraint) { + if (!constraint.type) { + if (constraint instanceof CANNON.LockConstraint) { + constraint.type = 'LockConstraint'; + } else if (constraint instanceof CANNON.DistanceConstraint) { + constraint.type = 'DistanceConstraint'; + } else if (constraint instanceof CANNON.HingeConstraint) { + constraint.type = 'HingeConstraint'; + } else if (constraint instanceof CANNON.ConeTwistConstraint) { + constraint.type = 'ConeTwistConstraint'; + } else if (constraint instanceof CANNON.PointToPointConstraint) { + constraint.type = 'PointToPointConstraint'; + } + } + protocol.assignID('constraint', constraint); + this.worker.postMessage({ + type: Event.ADD_CONSTRAINT, + constraint: protocol.serializeConstraint(constraint) + }); +}; + +/* @param {CANNON.Constraint} constraint */ +WorkerDriver.prototype.removeConstraint = function (constraint) { + this.worker.postMessage({ + type: Event.REMOVE_CONSTRAINT, + constraintID: constraint[ID] + }); +}; + +/****************************************************************************** + * Contacts + */ + +/** @return {Array} */ +WorkerDriver.prototype.getContacts = function () { + // TODO(donmccurdy): There's some wasted memory allocation here. + var bodies = this.bodies; + return this.contacts.map(function (message) { + return protocol.deserializeContact(message, bodies); + }); +}; + +},{"../utils/protocol":31,"./driver":22,"./event":23,"./webworkify-debug":26,"./worker":28,"webworkify":8}],28:[function(require,module,exports){ +var Event = require('./event'), + LocalDriver = require('./local-driver'), + AmmoDriver = require('./ammo-driver'), + protocol = require('../utils/protocol'); + +var ID = protocol.ID; + +module.exports = function (self) { + var driver = null; + var bodies = {}; + var constraints = {}; + var stepSize; + + self.addEventListener('message', function (event) { + var data = event.data; + + switch (data.type) { + // Lifecycle. + case Event.INIT: + driver = data.engine === 'cannon' + ? new LocalDriver() + : new AmmoDriver(); + driver.init(data.worldConfig); + stepSize = 1 / data.fps; + setInterval(step, 1000 / data.fps); + break; + + // Bodies. + case Event.ADD_BODY: + var body = protocol.deserializeBody(data.body); + body.material = driver.getMaterial( 'defaultMaterial' ); + bodies[body[ID]] = body; + + body.addEventListener('collide', function (evt) { + var message = { + type: Event.COLLIDE, + bodyID: evt.target[ID], // set the target as the body to be identical to the local driver + targetID: evt.body[ID], // set the body as the target to be identical to the local driver + contact: protocol.serializeContact(evt.contact) + } + self.postMessage(message); + }); + driver.addBody(body); + break; + case Event.REMOVE_BODY: + driver.removeBody(bodies[data.bodyID]); + delete bodies[data.bodyID]; + break; + case Event.APPLY_BODY_METHOD: + bodies[data.bodyID][data.methodName]( + protocol.deserializeVec3(data.args[0]), + protocol.deserializeVec3(data.args[1]) + ); + break; + case Event.UPDATE_BODY_PROPERTIES: + protocol.deserializeBodyUpdate(data.body, bodies[data.body.id]); + break; + + // Materials. + case Event.ADD_MATERIAL: + driver.addMaterial(data.materialConfig); + break; + case Event.ADD_CONTACT_MATERIAL: + driver.addContactMaterial( + data.materialName1, + data.materialName2, + data.contactMaterialConfig + ); + break; + + // Constraints. + case Event.ADD_CONSTRAINT: + var constraint = protocol.deserializeConstraint(data.constraint, bodies); + constraints[constraint[ID]] = constraint; + driver.addConstraint(constraint); + break; + case Event.REMOVE_CONSTRAINT: + driver.removeConstraint(constraints[data.constraintID]); + delete constraints[data.constraintID]; + break; + + default: + throw new Error('[Worker] Unexpected event type: %s', data.type); + + } + }); + + function step () { + driver.step(stepSize); + + var bodyMessages = {}; + Object.keys(bodies).forEach(function (id) { + bodyMessages[id] = protocol.serializeBody(bodies[id]); + }); + + self.postMessage({ + type: Event.STEP, + bodies: bodyMessages, + contacts: driver.getContacts().map(protocol.serializeContact) + }); + } +}; + +},{"../utils/protocol":31,"./ammo-driver":21,"./event":23,"./local-driver":24}],29:[function(require,module,exports){ +/* global THREE */ +var CANNON = require('cannon-es'), + CONSTANTS = require('./constants'), + C_GRAV = CONSTANTS.GRAVITY, + C_MAT = CONSTANTS.CONTACT_MATERIAL; + +const { TYPE } = require('./constants'); +var LocalDriver = require('./drivers/local-driver'), + WorkerDriver = require('./drivers/worker-driver'), + NetworkDriver = require('./drivers/network-driver'), + AmmoDriver = require('./drivers/ammo-driver'); +require('aframe-stats-panel') + +/** + * Physics system. + */ +module.exports = AFRAME.registerSystem('physics', { + schema: { + // CANNON.js driver type + driver: { default: 'local', oneOf: ['local', 'worker', 'network', 'ammo'] }, + networkUrl: { default: '', if: {driver: 'network'} }, + workerFps: { default: 60, if: {driver: 'worker'} }, + workerInterpolate: { default: true, if: {driver: 'worker'} }, + workerInterpBufferSize: { default: 2, if: {driver: 'worker'} }, + workerEngine: { default: 'cannon', if: {driver: 'worker'}, oneOf: ['cannon'] }, + workerDebug: { default: false, if: {driver: 'worker'} }, + + gravity: { default: C_GRAV }, + iterations: { default: CONSTANTS.ITERATIONS }, + friction: { default: C_MAT.friction }, + restitution: { default: C_MAT.restitution }, + contactEquationStiffness: { default: C_MAT.contactEquationStiffness }, + contactEquationRelaxation: { default: C_MAT.contactEquationRelaxation }, + frictionEquationStiffness: { default: C_MAT.frictionEquationStiffness }, + frictionEquationRegularization: { default: C_MAT.frictionEquationRegularization }, + + // Never step more than four frames at once. Effectively pauses the scene + // when out of focus, and prevents weird "jumps" when focus returns. + maxInterval: { default: 4 / 60 }, + + // If true, show wireframes around physics bodies. + debug: { default: false }, + + // If using ammo, set the default rendering mode for debug + debugDrawMode: { default: THREE.AmmoDebugConstants.NoDebug }, + // If using ammo, set the max number of steps per frame + maxSubSteps: { default: 4 }, + // If using ammo, set the framerate of the simulation + fixedTimeStep: { default: 1 / 60 }, + // Whether to output stats, and how to output them. One or more of "console", "events", "panel" + stats: {type: 'array', default: []} + }, + + /** + * Initializes the physics system. + */ + async init() { + var data = this.data; + + // If true, show wireframes around physics bodies. + this.debug = data.debug; + this.initStats(); + + this.callbacks = {beforeStep: [], step: [], afterStep: []}; + + this.listeners = {}; + + + this.driver = null; + switch (data.driver) { + case 'local': + this.driver = new LocalDriver(); + break; + + case 'ammo': + this.driver = new AmmoDriver(); + break; + + case 'network': + this.driver = new NetworkDriver(data.networkUrl); + break; -},{"./velocity":16}],16:[function(require,module,exports){ -/** - * Velocity, in m/s. - */ -module.exports = AFRAME.registerComponent('velocity', { - schema: {type: 'vec3'}, - - init: function () { - this.system = this.el.sceneEl.systems.physics; - - if (this.system) { - this.system.addComponent(this); - } - }, - - remove: function () { - if (this.system) { - this.system.removeComponent(this); - } - }, - - tick: function (t, dt) { - if (!dt) return; - if (this.system) return; - this.afterStep(t, dt); - }, - - afterStep: function (t, dt) { - if (!dt) return; - - var physics = this.el.sceneEl.systems.physics || {data: {maxInterval: 1 / 60}}, - - // TODO - There's definitely a bug with getComputedAttribute and el.data. - velocity = this.el.getAttribute('velocity') || {x: 0, y: 0, z: 0}, - position = this.el.object3D.position || {x: 0, y: 0, z: 0}; - - dt = Math.min(dt, physics.data.maxInterval * 1000); - - this.el.object3D.position.set( - position.x + velocity.x * dt / 1000, - position.y + velocity.y * dt / 1000, - position.z + velocity.z * dt / 1000 - ); - } -}); + case 'worker': + this.driver = new WorkerDriver({ + fps: data.workerFps, + engine: data.workerEngine, + interpolate: data.workerInterpolate, + interpolationBufferSize: data.workerInterpBufferSize, + debug: data.workerDebug + }); + break; -},{}],17:[function(require,module,exports){ -/* global Ammo,THREE */ -const threeToAmmo = require("three-to-ammo"); -const CONSTANTS = require("../../constants"), - SHAPE = CONSTANTS.SHAPE, - FIT = CONSTANTS.FIT; - -var AmmoShape = { - schema: { - type: { - default: SHAPE.HULL, - oneOf: [ - SHAPE.BOX, - SHAPE.CYLINDER, - SHAPE.SPHERE, - SHAPE.CAPSULE, - SHAPE.CONE, - SHAPE.HULL, - SHAPE.HACD, - SHAPE.VHACD, - SHAPE.MESH, - SHAPE.HEIGHTFIELD - ] - }, - fit: { default: FIT.ALL, oneOf: [FIT.ALL, FIT.MANUAL] }, - halfExtents: { type: "vec3", default: { x: 1, y: 1, z: 1 } }, - minHalfExtent: { default: 0 }, - maxHalfExtent: { default: Number.POSITIVE_INFINITY }, - sphereRadius: { default: NaN }, - cylinderAxis: { default: "y", oneOf: ["x", "y", "z"] }, - margin: { default: 0.01 }, - offset: { type: "vec3", default: { x: 0, y: 0, z: 0 } }, - orientation: { type: "vec4", default: { x: 0, y: 0, z: 0, w: 1 } }, - heightfieldData: { default: [] }, - heightfieldDistance: { default: 1 }, - includeInvisible: { default: false } - }, - - multiple: true, - - init: function() { - this.system = this.el.sceneEl.systems.physics; - this.collisionShapes = []; - - let bodyEl = this.el; - this.body = bodyEl.components["ammo-body"] || null; - while (!this.body && bodyEl.parentNode != this.el.sceneEl) { - bodyEl = bodyEl.parentNode; - if (bodyEl.components["ammo-body"]) { - this.body = bodyEl.components["ammo-body"]; - } - } - if (!this.body) { - console.warn("body not found"); - return; - } - if (this.data.fit !== FIT.MANUAL) { - if (!this.el.object3DMap.mesh) { - console.error("Cannot use FIT.ALL without object3DMap.mesh"); - return; - } - this.mesh = this.el.object3DMap.mesh; - } - this.body.addShapeComponent(this); - }, - - getMesh: function() { - return this.mesh || null; - }, - - addShapes: function(collisionShapes) { - this.collisionShapes = collisionShapes; - }, - - getShapes: function() { - return this.collisionShapes; - }, - - remove: function() { - if (!this.body) { - return; - } - - this.body.removeShapeComponent(this); - - while (this.collisionShapes.length > 0) { - const collisionShape = this.collisionShapes.pop(); - collisionShape.destroy(); - Ammo.destroy(collisionShape.localTransform); - } - } -}; - -module.exports.definition = AmmoShape; -module.exports.Component = AFRAME.registerComponent("ammo-shape", AmmoShape); + default: + throw new Error('[physics] Driver not recognized: "%s".', data.driver); + } -},{"../../constants":20,"three-to-ammo":6}],18:[function(require,module,exports){ -var CANNON = require('cannon-es'); - -var Shape = { - schema: { - shape: {default: 'box', oneOf: ['box', 'sphere', 'cylinder']}, - offset: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, - orientation: {type: 'vec4', default: {x: 0, y: 0, z: 0, w: 1}}, - - // sphere - radius: {type: 'number', default: 1, if: {shape: ['sphere']}}, - - // box - halfExtents: {type: 'vec3', default: {x: 0.5, y: 0.5, z: 0.5}, if: {shape: ['box']}}, - - // cylinder - radiusTop: {type: 'number', default: 1, if: {shape: ['cylinder']}}, - radiusBottom: {type: 'number', default: 1, if: {shape: ['cylinder']}}, - height: {type: 'number', default: 1, if: {shape: ['cylinder']}}, - numSegments: {type: 'int', default: 8, if: {shape: ['cylinder']}} - }, - - multiple: true, - - init: function() { - if (this.el.sceneEl.hasLoaded) { - this.initShape(); - } else { - this.el.sceneEl.addEventListener('loaded', this.initShape.bind(this)); - } - }, - - initShape: function() { - this.bodyEl = this.el; - var bodyType = this._findType(this.bodyEl); - var data = this.data; - - while (!bodyType && this.bodyEl.parentNode != this.el.sceneEl) { - this.bodyEl = this.bodyEl.parentNode; - bodyType = this._findType(this.bodyEl); - } - - if (!bodyType) { - console.warn('body not found'); - return; - } - - var scale = new THREE.Vector3(); - this.bodyEl.object3D.getWorldScale(scale); - var shape, offset, orientation; - - if (data.hasOwnProperty('offset')) { - offset = new CANNON.Vec3( - data.offset.x * scale.x, - data.offset.y * scale.y, - data.offset.z * scale.z - ); - } - - if (data.hasOwnProperty('orientation')) { - orientation = new CANNON.Quaternion(); - orientation.copy(data.orientation); - } - - switch(data.shape) { - case 'sphere': - shape = new CANNON.Sphere(data.radius * scale.x); - break; - case 'box': - var halfExtents = new CANNON.Vec3( - data.halfExtents.x * scale.x, - data.halfExtents.y * scale.y, - data.halfExtents.z * scale.z - ); - shape = new CANNON.Box(halfExtents); - break; - case 'cylinder': - shape = new CANNON.Cylinder( - data.radiusTop * scale.x, - data.radiusBottom * scale.x, - data.height * scale.y, - data.numSegments - ); - - //rotate by 90 degrees similar to mesh2shape:createCylinderShape - var quat = new CANNON.Quaternion(); - quat.setFromEuler(90 * THREE.MathUtils.DEG2RAD, 0, 0, 'XYZ').normalize(); - orientation.mult(quat, orientation); - break; - default: - console.warn(data.shape + ' shape not supported'); - return; - } - - if (this.bodyEl.body) { - this.bodyEl.components[bodyType].addShape(shape, offset, orientation); - } else { - this.bodyEl.addEventListener('body-loaded', function() { - this.bodyEl.components[bodyType].addShape(shape, offset, orientation); - }, {once: true}); - } - }, - - _findType: function(el) { - if (el.hasAttribute('body')) { - return 'body'; - } else if (el.hasAttribute('dynamic-body')) { - return 'dynamic-body'; - } else if (el.hasAttribute('static-body')) { - return'static-body'; - } - return null; - }, - - remove: function() { - if (this.bodyEl.parentNode) { - console.warn('removing shape component not currently supported'); - } - } -}; - -module.exports.definition = Shape; -module.exports.Component = AFRAME.registerComponent('shape', Shape); + if (data.driver !== 'ammo') { + await this.driver.init({ + quatNormalizeSkip: 0, + quatNormalizeFast: false, + solverIterations: data.iterations, + gravity: data.gravity, + }); + this.driver.addMaterial({name: 'defaultMaterial'}); + this.driver.addMaterial({name: 'staticMaterial'}); + this.driver.addContactMaterial('defaultMaterial', 'defaultMaterial', { + friction: data.friction, + restitution: data.restitution, + contactEquationStiffness: data.contactEquationStiffness, + contactEquationRelaxation: data.contactEquationRelaxation, + frictionEquationStiffness: data.frictionEquationStiffness, + frictionEquationRegularization: data.frictionEquationRegularization + }); + this.driver.addContactMaterial('staticMaterial', 'defaultMaterial', { + friction: 1.0, + restitution: 0.0, + contactEquationStiffness: data.contactEquationStiffness, + contactEquationRelaxation: data.contactEquationRelaxation, + frictionEquationStiffness: data.frictionEquationStiffness, + frictionEquationRegularization: data.frictionEquationRegularization + }); + } else { + await this.driver.init({ + gravity: data.gravity, + debugDrawMode: data.debugDrawMode, + solverIterations: data.iterations, + maxSubSteps: data.maxSubSteps, + fixedTimeStep: data.fixedTimeStep + }); + } -},{"cannon-es":5}],19:[function(require,module,exports){ -var CANNON = require('cannon-es'); - -module.exports = AFRAME.registerComponent('spring', { - - multiple: true, - - schema: { - // Target (other) body for the constraint. - target: {type: 'selector'}, - - // Length of the spring, when no force acts upon it. - restLength: {default: 1, min: 0}, - - // How much will the spring suppress the force. - stiffness: {default: 100, min: 0}, - - // Stretch factor of the spring. - damping: {default: 1, min: 0}, - - // Offsets. - localAnchorA: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, - localAnchorB: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, - }, - - init: function() { - this.system = this.el.sceneEl.systems.physics; - this.system.addComponent(this); - this.isActive = true; - this.spring = /* {CANNON.Spring} */ null; - }, - - update: function(oldData) { - var el = this.el; - var data = this.data; - - if (!data.target) { - console.warn('Spring: invalid target specified.'); - return; - } - - // wait until the CANNON bodies is created and attached - if (!el.body || !data.target.body) { - (el.body ? data.target : el).addEventListener('body-loaded', this.update.bind(this, {})); - return; - } - - // create the spring if necessary - this.createSpring(); - // apply new data to the spring - this.updateSpring(oldData); - }, - - updateSpring: function(oldData) { - if (!this.spring) { - console.warn('Spring: Component attempted to change spring before its created. No changes made.'); - return; - } - var data = this.data; - var spring = this.spring; - - // Cycle through the schema and check if an attribute has changed. - // if so, apply it to the spring - Object.keys(data).forEach(function(attr) { - if (data[attr] !== oldData[attr]) { - if (attr === 'target') { - // special case for the target selector - spring.bodyB = data.target.body; - return; - } - spring[attr] = data[attr]; - } - }) - }, - - createSpring: function() { - if (this.spring) return; // no need to create a new spring - this.spring = new CANNON.Spring(this.el.body); - }, - - // If the spring is valid, update the force each tick the physics are calculated - step: function(t, dt) { - return this.spring && this.isActive ? this.spring.applyForce() : void 0; - }, - - // resume updating the force when component upon calling play() - play: function() { - this.isActive = true; - }, - - // stop updating the force when component upon calling stop() - pause: function() { - this.isActive = false; - }, - - //remove the event listener + delete the spring - remove: function() { - if (this.spring) - delete this.spring; - this.spring = null; - } -}) + this.initialized = true; -},{"cannon-es":5}],20:[function(require,module,exports){ -module.exports = { - GRAVITY: -9.8, - MAX_INTERVAL: 4 / 60, - ITERATIONS: 10, - CONTACT_MATERIAL: { - friction: 0.01, - restitution: 0.3, - contactEquationStiffness: 1e8, - contactEquationRelaxation: 3, - frictionEquationStiffness: 1e8, - frictionEquationRegularization: 3 - }, - ACTIVATION_STATE: { - ACTIVE_TAG: "active", - ISLAND_SLEEPING: "islandSleeping", - WANTS_DEACTIVATION: "wantsDeactivation", - DISABLE_DEACTIVATION: "disableDeactivation", - DISABLE_SIMULATION: "disableSimulation" - }, - COLLISION_FLAG: { - STATIC_OBJECT: 1, - KINEMATIC_OBJECT: 2, - NO_CONTACT_RESPONSE: 4, - CUSTOM_MATERIAL_CALLBACK: 8, //this allows per-triangle material (friction/restitution) - CHARACTER_OBJECT: 16, - DISABLE_VISUALIZE_OBJECT: 32, //disable debug drawing - DISABLE_SPU_COLLISION_PROCESSING: 64 //disable parallel/SPU processing - }, - TYPE: { - STATIC: "static", - DYNAMIC: "dynamic", - KINEMATIC: "kinematic" - }, - SHAPE: { - BOX: "box", - CYLINDER: "cylinder", - SPHERE: "sphere", - CAPSULE: "capsule", - CONE: "cone", - HULL: "hull", - HACD: "hacd", - VHACD: "vhacd", - MESH: "mesh", - HEIGHTFIELD: "heightfield" - }, - FIT: { - ALL: "all", - MANUAL: "manual" - }, - CONSTRAINT: { - LOCK: "lock", - FIXED: "fixed", - SPRING: "spring", - SLIDER: "slider", - HINGE: "hinge", - CONE_TWIST: "coneTwist", - POINT_TO_POINT: "pointToPoint" - } -}; + if (this.debug) { + this.setDebug(true); + } + }, -},{}],21:[function(require,module,exports){ -/* global THREE */ -const Driver = require("./driver"); - -if (typeof window !== 'undefined') { - window.AmmoModule = window.Ammo; - window.Ammo = null; -} - -const EPS = 10e-6; - -function AmmoDriver() { - this.collisionConfiguration = null; - this.dispatcher = null; - this.broadphase = null; - this.solver = null; - this.physicsWorld = null; - this.debugDrawer = null; - - this.els = new Map(); - this.eventListeners = []; - this.collisions = new Map(); - this.collisionKeys = []; - this.currentCollisions = new Map(); -} - -AmmoDriver.prototype = new Driver(); -AmmoDriver.prototype.constructor = AmmoDriver; - -module.exports = AmmoDriver; - -/* @param {object} worldConfig */ -AmmoDriver.prototype.init = function(worldConfig) { - //Emscripten doesn't use real promises, just a .then() callback, so it necessary to wrap in a real promise. - return new Promise(resolve => { - AmmoModule().then(result => { - Ammo = result; - this.epsilon = worldConfig.epsilon || EPS; - this.debugDrawMode = worldConfig.debugDrawMode || THREE.AmmoDebugConstants.NoDebug; - this.maxSubSteps = worldConfig.maxSubSteps || 4; - this.fixedTimeStep = worldConfig.fixedTimeStep || 1 / 60; - this.collisionConfiguration = new Ammo.btDefaultCollisionConfiguration(); - this.dispatcher = new Ammo.btCollisionDispatcher(this.collisionConfiguration); - this.broadphase = new Ammo.btDbvtBroadphase(); - this.solver = new Ammo.btSequentialImpulseConstraintSolver(); - this.physicsWorld = new Ammo.btDiscreteDynamicsWorld( - this.dispatcher, - this.broadphase, - this.solver, - this.collisionConfiguration - ); - this.physicsWorld.setForceUpdateAllAabbs(false); - this.physicsWorld.setGravity( - new Ammo.btVector3(0, worldConfig.hasOwnProperty("gravity") ? worldConfig.gravity : -9.8, 0) - ); - this.physicsWorld.getSolverInfo().set_m_numIterations(worldConfig.solverIterations); - resolve(); - }); - }); -}; - -/* @param {Ammo.btCollisionObject} body */ -AmmoDriver.prototype.addBody = function(body, group, mask) { - this.physicsWorld.addRigidBody(body, group, mask); - this.els.set(Ammo.getPointer(body), body.el); -}; - -/* @param {Ammo.btCollisionObject} body */ -AmmoDriver.prototype.removeBody = function(body) { - this.physicsWorld.removeRigidBody(body); - this.removeEventListener(body); - const bodyptr = Ammo.getPointer(body); - this.els.delete(bodyptr); - this.collisions.delete(bodyptr); - this.collisionKeys.splice(this.collisionKeys.indexOf(bodyptr), 1); - this.currentCollisions.delete(bodyptr); -}; - -AmmoDriver.prototype.updateBody = function(body) { - if (this.els.has(Ammo.getPointer(body))) { - this.physicsWorld.updateSingleAabb(body); - } -}; - -/* @param {number} deltaTime */ -AmmoDriver.prototype.step = function(deltaTime) { - this.physicsWorld.stepSimulation(deltaTime, this.maxSubSteps, this.fixedTimeStep); - - const numManifolds = this.dispatcher.getNumManifolds(); - for (let i = 0; i < numManifolds; i++) { - const persistentManifold = this.dispatcher.getManifoldByIndexInternal(i); - const numContacts = persistentManifold.getNumContacts(); - const body0ptr = Ammo.getPointer(persistentManifold.getBody0()); - const body1ptr = Ammo.getPointer(persistentManifold.getBody1()); - let collided = false; - - for (let j = 0; j < numContacts; j++) { - const manifoldPoint = persistentManifold.getContactPoint(j); - const distance = manifoldPoint.getDistance(); - if (distance <= this.epsilon) { - collided = true; - break; - } - } - - if (collided) { - if (!this.collisions.has(body0ptr)) { - this.collisions.set(body0ptr, []); - this.collisionKeys.push(body0ptr); - } - if (this.collisions.get(body0ptr).indexOf(body1ptr) === -1) { - this.collisions.get(body0ptr).push(body1ptr); - if (this.eventListeners.indexOf(body0ptr) !== -1) { - this.els.get(body0ptr).emit("collidestart", { targetEl: this.els.get(body1ptr) }); - } - if (this.eventListeners.indexOf(body1ptr) !== -1) { - this.els.get(body1ptr).emit("collidestart", { targetEl: this.els.get(body0ptr) }); - } - } - if (!this.currentCollisions.has(body0ptr)) { - this.currentCollisions.set(body0ptr, new Set()); - } - this.currentCollisions.get(body0ptr).add(body1ptr); - } - } - - for (let i = 0; i < this.collisionKeys.length; i++) { - const body0ptr = this.collisionKeys[i]; - const body1ptrs = this.collisions.get(body0ptr); - for (let j = body1ptrs.length - 1; j >= 0; j--) { - const body1ptr = body1ptrs[j]; - if (this.currentCollisions.get(body0ptr).has(body1ptr)) { - continue; - } - if (this.eventListeners.indexOf(body0ptr) !== -1) { - this.els.get(body0ptr).emit("collideend", { targetEl: this.els.get(body1ptr) }); - } - if (this.eventListeners.indexOf(body1ptr) !== -1) { - this.els.get(body1ptr).emit("collideend", { targetEl: this.els.get(body0ptr) }); - } - body1ptrs.splice(j, 1); - } - this.currentCollisions.get(body0ptr).clear(); - } - - if (this.debugDrawer) { - this.debugDrawer.update(); - } -}; - -/* @param {?} constraint */ -AmmoDriver.prototype.addConstraint = function(constraint) { - this.physicsWorld.addConstraint(constraint, false); -}; - -/* @param {?} constraint */ -AmmoDriver.prototype.removeConstraint = function(constraint) { - this.physicsWorld.removeConstraint(constraint); -}; - -/* @param {Ammo.btCollisionObject} body */ -AmmoDriver.prototype.addEventListener = function(body) { - this.eventListeners.push(Ammo.getPointer(body)); -}; - -/* @param {Ammo.btCollisionObject} body */ -AmmoDriver.prototype.removeEventListener = function(body) { - const ptr = Ammo.getPointer(body); - if (this.eventListeners.indexOf(ptr) !== -1) { - this.eventListeners.splice(this.eventListeners.indexOf(ptr), 1); - } -}; - -AmmoDriver.prototype.destroy = function() { - Ammo.destroy(this.collisionConfiguration); - Ammo.destroy(this.dispatcher); - Ammo.destroy(this.broadphase); - Ammo.destroy(this.solver); - Ammo.destroy(this.physicsWorld); - Ammo.destroy(this.debugDrawer); -}; - -/** - * @param {THREE.Scene} scene - * @param {object} options - */ -AmmoDriver.prototype.getDebugDrawer = function(scene, options) { - if (!this.debugDrawer) { - options = options || {}; - options.debugDrawMode = options.debugDrawMode || this.debugDrawMode; - this.debugDrawer = new THREE.AmmoDebugDrawer(scene, this.physicsWorld, options); - } - return this.debugDrawer; -}; + initStats() { + // Data used for performance monitoring. + this.statsToConsole = this.data.stats.includes("console") + this.statsToEvents = this.data.stats.includes("events") + this.statsToPanel = this.data.stats.includes("panel") -},{"./driver":22}],22:[function(require,module,exports){ -/** - * Driver - defines limited API to local and remote physics controllers. - */ - -function Driver () {} - -module.exports = Driver; - -/****************************************************************************** - * Lifecycle - */ - -/* @param {object} worldConfig */ -Driver.prototype.init = abstractMethod; - -/* @param {number} deltaMS */ -Driver.prototype.step = abstractMethod; - -Driver.prototype.destroy = abstractMethod; - -/****************************************************************************** - * Bodies - */ - -/* @param {CANNON.Body} body */ -Driver.prototype.addBody = abstractMethod; - -/* @param {CANNON.Body} body */ -Driver.prototype.removeBody = abstractMethod; - -/** - * @param {CANNON.Body} body - * @param {string} methodName - * @param {Array} args - */ -Driver.prototype.applyBodyMethod = abstractMethod; - -/** @param {CANNON.Body} body */ -Driver.prototype.updateBodyProperties = abstractMethod; - -/****************************************************************************** - * Materials - */ - -/** @param {object} materialConfig */ -Driver.prototype.addMaterial = abstractMethod; - -/** - * @param {string} materialName1 - * @param {string} materialName2 - * @param {object} contactMaterialConfig - */ -Driver.prototype.addContactMaterial = abstractMethod; - -/****************************************************************************** - * Constraints - */ - -/* @param {CANNON.Constraint} constraint */ -Driver.prototype.addConstraint = abstractMethod; - -/* @param {CANNON.Constraint} constraint */ -Driver.prototype.removeConstraint = abstractMethod; - -/****************************************************************************** - * Contacts - */ - -/** @return {Array} */ -Driver.prototype.getContacts = abstractMethod; - -/*****************************************************************************/ - -function abstractMethod () { - throw new Error('Method not implemented.'); -} + if (this.statsToConsole || this.statsToEvents || this.statsToPanel) { + this.trackPerf = true; + this.tickCounter = 0; + + this.statsTickData = {}; + this.statsBodyData = {}; -},{}],23:[function(require,module,exports){ -module.exports = { - INIT: 'init', - STEP: 'step', - - // Bodies. - ADD_BODY: 'add-body', - REMOVE_BODY: 'remove-body', - APPLY_BODY_METHOD: 'apply-body-method', - UPDATE_BODY_PROPERTIES: 'update-body-properties', - - // Materials. - ADD_MATERIAL: 'add-material', - ADD_CONTACT_MATERIAL: 'add-contact-material', - - // Constraints. - ADD_CONSTRAINT: 'add-constraint', - REMOVE_CONSTRAINT: 'remove-constraint', - - // Events. - COLLIDE: 'collide' -}; + this.countBodies = { + "ammo": () => this.countBodiesAmmo(), + "local": () => this.countBodiesCannon(false), + "worker": () => this.countBodiesCannon(true) + } -},{}],24:[function(require,module,exports){ -var CANNON = require('cannon-es'), - Driver = require('./driver'); - -function LocalDriver () { - this.world = null; - this.materials = {}; - this.contactMaterial = null; -} - -LocalDriver.prototype = new Driver(); -LocalDriver.prototype.constructor = LocalDriver; - -module.exports = LocalDriver; - -/****************************************************************************** - * Lifecycle - */ - -/* @param {object} worldConfig */ -LocalDriver.prototype.init = function (worldConfig) { - var world = new CANNON.World(); - world.quatNormalizeSkip = worldConfig.quatNormalizeSkip; - world.quatNormalizeFast = worldConfig.quatNormalizeFast; - world.solver.iterations = worldConfig.solverIterations; - world.gravity.set(0, worldConfig.gravity, 0); - world.broadphase = new CANNON.NaiveBroadphase(); - - this.world = world; -}; - -/* @param {number} deltaMS */ -LocalDriver.prototype.step = function (deltaMS) { - this.world.step(deltaMS); -}; - -LocalDriver.prototype.destroy = function () { - delete this.world; - delete this.contactMaterial; - this.materials = {}; -}; - -/****************************************************************************** - * Bodies - */ - -/* @param {CANNON.Body} body */ -LocalDriver.prototype.addBody = function (body) { - this.world.addBody(body); -}; - -/* @param {CANNON.Body} body */ -LocalDriver.prototype.removeBody = function (body) { - this.world.removeBody(body); -}; - -/** - * @param {CANNON.Body} body - * @param {string} methodName - * @param {Array} args - */ -LocalDriver.prototype.applyBodyMethod = function (body, methodName, args) { - body['__' + methodName].apply(body, args); -}; - -/** @param {CANNON.Body} body */ -LocalDriver.prototype.updateBodyProperties = function () {}; - -/****************************************************************************** - * Materials - */ - -/** - * @param {string} name - * @return {CANNON.Material} - */ -LocalDriver.prototype.getMaterial = function (name) { - return this.materials[name]; -}; - -/** @param {object} materialConfig */ -LocalDriver.prototype.addMaterial = function (materialConfig) { - this.materials[materialConfig.name] = new CANNON.Material(materialConfig); - this.materials[materialConfig.name].name = materialConfig.name; -}; - -/** - * @param {string} matName1 - * @param {string} matName2 - * @param {object} contactMaterialConfig - */ -LocalDriver.prototype.addContactMaterial = function (matName1, matName2, contactMaterialConfig) { - var mat1 = this.materials[matName1], - mat2 = this.materials[matName2]; - this.contactMaterial = new CANNON.ContactMaterial(mat1, mat2, contactMaterialConfig); - this.world.addContactMaterial(this.contactMaterial); -}; - -/****************************************************************************** - * Constraints - */ - -/* @param {CANNON.Constraint} constraint */ -LocalDriver.prototype.addConstraint = function (constraint) { - if (!constraint.type) { - if (constraint instanceof CANNON.LockConstraint) { - constraint.type = 'LockConstraint'; - } else if (constraint instanceof CANNON.DistanceConstraint) { - constraint.type = 'DistanceConstraint'; - } else if (constraint instanceof CANNON.HingeConstraint) { - constraint.type = 'HingeConstraint'; - } else if (constraint instanceof CANNON.ConeTwistConstraint) { - constraint.type = 'ConeTwistConstraint'; - } else if (constraint instanceof CANNON.PointToPointConstraint) { - constraint.type = 'PointToPointConstraint'; - } - } - this.world.addConstraint(constraint); -}; - -/* @param {CANNON.Constraint} constraint */ -LocalDriver.prototype.removeConstraint = function (constraint) { - this.world.removeConstraint(constraint); -}; - -/****************************************************************************** - * Contacts - */ - -/** @return {Array} */ -LocalDriver.prototype.getContacts = function () { - return this.world.contacts; -}; + this.bodyTypeToStatsPropertyMap = { + "ammo": { + [TYPE.STATIC] : "staticBodies", + [TYPE.KINEMATIC] : "kinematicBodies", + [TYPE.DYNAMIC] : "dynamicBodies", + }, + "cannon": { + [CANNON.Body.STATIC] : "staticBodies", + [CANNON.Body.DYNAMIC] : "dynamicBodies" + } + } + + const scene = this.el.sceneEl; + scene.setAttribute("stats-collector", `inEvent: physics-tick-data; + properties: before, after, engine, total; + outputFrequency: 100; + outEvent: physics-tick-summary; + outputs: percentile__50, percentile__90, max`); + } + + if (this.statsToPanel) { + const scene = this.el.sceneEl; + const space = "   " + + scene.setAttribute("stats-panel", "") + scene.setAttribute("stats-group__bodies", `label: Physics Bodies`) + scene.setAttribute("stats-row__b1", `group: bodies; + event:physics-body-data; + properties: staticBodies; + label: Static`) + scene.setAttribute("stats-row__b2", `group: bodies; + event:physics-body-data; + properties: dynamicBodies; + label: Dynamic`) + if (this.data.driver === 'local' || this.data.driver === 'worker') { + scene.setAttribute("stats-row__b3", `group: bodies; + event:physics-body-data; + properties: contacts; + label: Contacts`) + } + else if (this.data.driver === 'ammo') { + scene.setAttribute("stats-row__b3", `group: bodies; + event:physics-body-data; + properties: kinematicBodies; + label: Kinematic`) + scene.setAttribute("stats-row__b4", `group: bodies; + event: physics-body-data; + properties: manifolds; + label: Manifolds`) + scene.setAttribute("stats-row__b5", `group: bodies; + event: physics-body-data; + properties: manifoldContacts; + label: Contacts`) + scene.setAttribute("stats-row__b6", `group: bodies; + event: physics-body-data; + properties: collisions; + label: Collisions`) + scene.setAttribute("stats-row__b7", `group: bodies; + event: physics-body-data; + properties: collisionKeys; + label: Coll Keys`) + } -},{"./driver":22,"cannon-es":5}],25:[function(require,module,exports){ -var Driver = require('./driver'); - -function NetworkDriver () { - throw new Error('[NetworkDriver] Driver not implemented.'); -} - -NetworkDriver.prototype = new Driver(); -NetworkDriver.prototype.constructor = NetworkDriver; - -module.exports = NetworkDriver; + scene.setAttribute("stats-group__tick", `label: Physics Ticks: Median${space}90th%${space}99th%`) + scene.setAttribute("stats-row__1", `group: tick; + event:physics-tick-summary; + properties: before.percentile__50, + before.percentile__90, + before.max; + label: Before`) + scene.setAttribute("stats-row__2", `group: tick; + event:physics-tick-summary; + properties: after.percentile__50, + after.percentile__90, + after.max; + label: After`) + scene.setAttribute("stats-row__3", `group: tick; + event:physics-tick-summary; + properties: engine.percentile__50, + engine.percentile__90, + engine.max; + label: Engine`) + scene.setAttribute("stats-row__4", `group: tick; + event:physics-tick-summary; + properties: total.percentile__50, + total.percentile__90, + total.max; + label: Total`) + } + }, -},{"./driver":22}],26:[function(require,module,exports){ -/** - * Stub version of webworkify, for debugging code outside of a webworker. - */ -function webworkifyDebug (worker) { - var targetA = new EventTarget(), - targetB = new EventTarget(); - - targetA.setTarget(targetB); - targetB.setTarget(targetA); - - worker(targetA); - return targetB; -} - -module.exports = webworkifyDebug; - -/****************************************************************************** - * EventTarget - */ - -function EventTarget () { - this.listeners = []; -} - -EventTarget.prototype.setTarget = function (target) { - this.target = target; -}; - -EventTarget.prototype.addEventListener = function (type, fn) { - this.listeners.push(fn); -}; - -EventTarget.prototype.dispatchEvent = function (type, event) { - for (var i = 0; i < this.listeners.length; i++) { - this.listeners[i](event); - } -}; - -EventTarget.prototype.postMessage = function (msg) { - this.target.dispatchEvent('message', {data: msg}); -}; + /** + * Updates the physics world on each tick of the A-Frame scene. It would be + * entirely possible to separate the two – updating physics more or less + * frequently than the scene – if greater precision or performance were + * necessary. + * @param {number} t + * @param {number} dt + */ + tick: function (t, dt) { + if (!this.initialized || !dt) return; -},{}],27:[function(require,module,exports){ -/* global performance */ - -var webworkify = require('webworkify'), - webworkifyDebug = require('./webworkify-debug'), - Driver = require('./driver'), - Event = require('./event'), - worker = require('./worker'), - protocol = require('../utils/protocol'); - -var ID = protocol.ID; - -/****************************************************************************** - * Constructor - */ - -function WorkerDriver (options) { - this.fps = options.fps; - this.engine = options.engine; - this.interpolate = options.interpolate; - // Approximate number of physics steps to 'pad' rendering. - this.interpBufferSize = options.interpolationBufferSize; - this.debug = options.debug; - - this.bodies = {}; - this.contacts = []; - - // https://gafferongames.com/post/snapshot_interpolation/ - this.frameDelay = this.interpBufferSize * 1000 / this.fps; - this.frameBuffer = []; - - this.worker = this.debug - ? webworkifyDebug(worker) - : webworkify(worker); - this.worker.addEventListener('message', this._onMessage.bind(this)); -} - -WorkerDriver.prototype = new Driver(); -WorkerDriver.prototype.constructor = WorkerDriver; - -module.exports = WorkerDriver; - -/****************************************************************************** - * Lifecycle - */ - -/* @param {object} worldConfig */ -WorkerDriver.prototype.init = function (worldConfig) { - this.worker.postMessage({ - type: Event.INIT, - worldConfig: worldConfig, - fps: this.fps, - engine: this.engine - }); -}; - -/** - * Increments the physics world forward one step, if interpolation is enabled. - * If disabled, increments are performed as messages arrive. - * @param {number} deltaMS - */ -WorkerDriver.prototype.step = function () { - if (!this.interpolate) return; - - // Get the two oldest frames that haven't expired. Ideally we would use all - // available frames to keep things smooth, but lerping is easier and faster. - var prevFrame = this.frameBuffer[0]; - var nextFrame = this.frameBuffer[1]; - var timestamp = performance.now(); - while (prevFrame && nextFrame && timestamp - prevFrame.timestamp > this.frameDelay) { - this.frameBuffer.shift(); - prevFrame = this.frameBuffer[0]; - nextFrame = this.frameBuffer[1]; - } - - if (!prevFrame || !nextFrame) return; - - var mix = (timestamp - prevFrame.timestamp) / this.frameDelay; - mix = (mix - (1 - 1 / this.interpBufferSize)) * this.interpBufferSize; - - for (var id in prevFrame.bodies) { - if (prevFrame.bodies.hasOwnProperty(id) && nextFrame.bodies.hasOwnProperty(id)) { - protocol.deserializeInterpBodyUpdate( - prevFrame.bodies[id], - nextFrame.bodies[id], - this.bodies[id], - mix - ); - } - } -}; - -WorkerDriver.prototype.destroy = function () { - this.worker.terminate(); - delete this.worker; -}; - -/** {Event} event */ -WorkerDriver.prototype._onMessage = function (event) { - if (event.data.type === Event.STEP) { - var data = event.data, - bodies = data.bodies; - - this.contacts = event.data.contacts; - - // If interpolation is enabled, store the frame. If not, update all bodies - // immediately. - if (this.interpolate) { - this.frameBuffer.push({timestamp: performance.now(), bodies: bodies}); - } else { - for (var id in bodies) { - if (bodies.hasOwnProperty(id)) { - protocol.deserializeBodyUpdate(bodies[id], this.bodies[id]); - } - } - } - - } else if (event.data.type === Event.COLLIDE) { - var body = this.bodies[event.data.bodyID]; - var target = this.bodies[event.data.targetID]; - var contact = protocol.deserializeContact(event.data.contact, this.bodies); - if (!body._listeners || !body._listeners.collide) return; - for (var i = 0; i < body._listeners.collide.length; i++) { - body._listeners.collide[i]({target: target, body: body, contact: contact}); - } - - } else { - throw new Error('[WorkerDriver] Unexpected message type.'); - } -}; - -/****************************************************************************** - * Bodies - */ - -/* @param {CANNON.Body} body */ -WorkerDriver.prototype.addBody = function (body) { - protocol.assignID('body', body); - this.bodies[body[ID]] = body; - this.worker.postMessage({type: Event.ADD_BODY, body: protocol.serializeBody(body)}); -}; - -/* @param {CANNON.Body} body */ -WorkerDriver.prototype.removeBody = function (body) { - this.worker.postMessage({type: Event.REMOVE_BODY, bodyID: body[ID]}); - delete this.bodies[body[ID]]; -}; - -/** - * @param {CANNON.Body} body - * @param {string} methodName - * @param {Array} args - */ -WorkerDriver.prototype.applyBodyMethod = function (body, methodName, args) { - switch (methodName) { - case 'applyForce': - case 'applyImpulse': - this.worker.postMessage({ - type: Event.APPLY_BODY_METHOD, - bodyID: body[ID], - methodName: methodName, - args: [args[0].toArray(), args[1].toArray()] - }); - break; - default: - throw new Error('Unexpected methodName: %s', methodName); - } -}; - -/** @param {CANNON.Body} body */ -WorkerDriver.prototype.updateBodyProperties = function (body) { - this.worker.postMessage({ - type: Event.UPDATE_BODY_PROPERTIES, - body: protocol.serializeBody(body) - }); -}; - -/****************************************************************************** - * Materials - */ - -/** - * @param {string} name - * @return {CANNON.Material} - */ -WorkerDriver.prototype.getMaterial = function (name) { - // No access to materials here. Eventually we might return the name or ID, if - // multiple materials were selected, but for now there's only one and it's safe - // to assume the worker is already using it. - return undefined; -}; - -/** @param {object} materialConfig */ -WorkerDriver.prototype.addMaterial = function (materialConfig) { - this.worker.postMessage({type: Event.ADD_MATERIAL, materialConfig: materialConfig}); -}; - -/** - * @param {string} matName1 - * @param {string} matName2 - * @param {object} contactMaterialConfig - */ -WorkerDriver.prototype.addContactMaterial = function (matName1, matName2, contactMaterialConfig) { - this.worker.postMessage({ - type: Event.ADD_CONTACT_MATERIAL, - materialName1: matName1, - materialName2: matName2, - contactMaterialConfig: contactMaterialConfig - }); -}; - -/****************************************************************************** - * Constraints - */ - -/* @param {CANNON.Constraint} constraint */ -WorkerDriver.prototype.addConstraint = function (constraint) { - if (!constraint.type) { - if (constraint instanceof CANNON.LockConstraint) { - constraint.type = 'LockConstraint'; - } else if (constraint instanceof CANNON.DistanceConstraint) { - constraint.type = 'DistanceConstraint'; - } else if (constraint instanceof CANNON.HingeConstraint) { - constraint.type = 'HingeConstraint'; - } else if (constraint instanceof CANNON.ConeTwistConstraint) { - constraint.type = 'ConeTwistConstraint'; - } else if (constraint instanceof CANNON.PointToPointConstraint) { - constraint.type = 'PointToPointConstraint'; - } - } - protocol.assignID('constraint', constraint); - this.worker.postMessage({ - type: Event.ADD_CONSTRAINT, - constraint: protocol.serializeConstraint(constraint) - }); -}; - -/* @param {CANNON.Constraint} constraint */ -WorkerDriver.prototype.removeConstraint = function (constraint) { - this.worker.postMessage({ - type: Event.REMOVE_CONSTRAINT, - constraintID: constraint[ID] - }); -}; - -/****************************************************************************** - * Contacts - */ - -/** @return {Array} */ -WorkerDriver.prototype.getContacts = function () { - // TODO(donmccurdy): There's some wasted memory allocation here. - var bodies = this.bodies; - return this.contacts.map(function (message) { - return protocol.deserializeContact(message, bodies); - }); -}; + const beforeStartTime = performance.now(); -},{"../utils/protocol":31,"./driver":22,"./event":23,"./webworkify-debug":26,"./worker":28,"webworkify":8}],28:[function(require,module,exports){ -var Event = require('./event'), - LocalDriver = require('./local-driver'), - AmmoDriver = require('./ammo-driver'), - protocol = require('../utils/protocol'); - -var ID = protocol.ID; - -module.exports = function (self) { - var driver = null; - var bodies = {}; - var constraints = {}; - var stepSize; - - self.addEventListener('message', function (event) { - var data = event.data; - - switch (data.type) { - // Lifecycle. - case Event.INIT: - driver = data.engine === 'cannon' - ? new LocalDriver() - : new AmmoDriver(); - driver.init(data.worldConfig); - stepSize = 1 / data.fps; - setInterval(step, 1000 / data.fps); - break; - - // Bodies. - case Event.ADD_BODY: - var body = protocol.deserializeBody(data.body); - body.material = driver.getMaterial( 'defaultMaterial' ); - bodies[body[ID]] = body; - - body.addEventListener('collide', function (evt) { - var message = { - type: Event.COLLIDE, - bodyID: evt.target[ID], // set the target as the body to be identical to the local driver - targetID: evt.body[ID], // set the body as the target to be identical to the local driver - contact: protocol.serializeContact(evt.contact) - } - self.postMessage(message); - }); - driver.addBody(body); - break; - case Event.REMOVE_BODY: - driver.removeBody(bodies[data.bodyID]); - delete bodies[data.bodyID]; - break; - case Event.APPLY_BODY_METHOD: - bodies[data.bodyID][data.methodName]( - protocol.deserializeVec3(data.args[0]), - protocol.deserializeVec3(data.args[1]) - ); - break; - case Event.UPDATE_BODY_PROPERTIES: - protocol.deserializeBodyUpdate(data.body, bodies[data.body.id]); - break; - - // Materials. - case Event.ADD_MATERIAL: - driver.addMaterial(data.materialConfig); - break; - case Event.ADD_CONTACT_MATERIAL: - driver.addContactMaterial( - data.materialName1, - data.materialName2, - data.contactMaterialConfig - ); - break; - - // Constraints. - case Event.ADD_CONSTRAINT: - var constraint = protocol.deserializeConstraint(data.constraint, bodies); - constraints[constraint[ID]] = constraint; - driver.addConstraint(constraint); - break; - case Event.REMOVE_CONSTRAINT: - driver.removeConstraint(constraints[data.constraintID]); - delete constraints[data.constraintID]; - break; - - default: - throw new Error('[Worker] Unexpected event type: %s', data.type); - - } - }); - - function step () { - driver.step(stepSize); - - var bodyMessages = {}; - Object.keys(bodies).forEach(function (id) { - bodyMessages[id] = protocol.serializeBody(bodies[id]); - }); - - self.postMessage({ - type: Event.STEP, - bodies: bodyMessages, - contacts: driver.getContacts().map(protocol.serializeContact) - }); - } -}; + var i; + var callbacks = this.callbacks; -},{"../utils/protocol":31,"./ammo-driver":21,"./event":23,"./local-driver":24}],29:[function(require,module,exports){ -/* global THREE */ -var CANNON = require('cannon-es'), - CONSTANTS = require('./constants'), - C_GRAV = CONSTANTS.GRAVITY, - C_MAT = CONSTANTS.CONTACT_MATERIAL; - -const { TYPE } = require('./constants'); -var LocalDriver = require('./drivers/local-driver'), - WorkerDriver = require('./drivers/worker-driver'), - NetworkDriver = require('./drivers/network-driver'), - AmmoDriver = require('./drivers/ammo-driver'); -require('aframe-stats-panel') - -/** - * Physics system. - */ -module.exports = AFRAME.registerSystem('physics', { - schema: { - // CANNON.js driver type - driver: { default: 'local', oneOf: ['local', 'worker', 'network', 'ammo'] }, - networkUrl: { default: '', if: {driver: 'network'} }, - workerFps: { default: 60, if: {driver: 'worker'} }, - workerInterpolate: { default: true, if: {driver: 'worker'} }, - workerInterpBufferSize: { default: 2, if: {driver: 'worker'} }, - workerEngine: { default: 'cannon', if: {driver: 'worker'}, oneOf: ['cannon'] }, - workerDebug: { default: false, if: {driver: 'worker'} }, - - gravity: { default: C_GRAV }, - iterations: { default: CONSTANTS.ITERATIONS }, - friction: { default: C_MAT.friction }, - restitution: { default: C_MAT.restitution }, - contactEquationStiffness: { default: C_MAT.contactEquationStiffness }, - contactEquationRelaxation: { default: C_MAT.contactEquationRelaxation }, - frictionEquationStiffness: { default: C_MAT.frictionEquationStiffness }, - frictionEquationRegularization: { default: C_MAT.frictionEquationRegularization }, - - // Never step more than four frames at once. Effectively pauses the scene - // when out of focus, and prevents weird "jumps" when focus returns. - maxInterval: { default: 4 / 60 }, - - // If true, show wireframes around physics bodies. - debug: { default: false }, - - // If using ammo, set the default rendering mode for debug - debugDrawMode: { default: THREE.AmmoDebugConstants.NoDebug }, - // If using ammo, set the max number of steps per frame - maxSubSteps: { default: 4 }, - // If using ammo, set the framerate of the simulation - fixedTimeStep: { default: 1 / 60 }, - // Whether to output stats, and how to output them. One or more of "console", "events", "panel" - stats: {type: 'array', default: []} - }, - - /** - * Initializes the physics system. - */ - async init() { - var data = this.data; - - // If true, show wireframes around physics bodies. - this.debug = data.debug; - this.initStats(); - - this.callbacks = {beforeStep: [], step: [], afterStep: []}; - - this.listeners = {}; - - - this.driver = null; - switch (data.driver) { - case 'local': - this.driver = new LocalDriver(); - break; - - case 'ammo': - this.driver = new AmmoDriver(); - break; - - case 'network': - this.driver = new NetworkDriver(data.networkUrl); - break; - - case 'worker': - this.driver = new WorkerDriver({ - fps: data.workerFps, - engine: data.workerEngine, - interpolate: data.workerInterpolate, - interpolationBufferSize: data.workerInterpBufferSize, - debug: data.workerDebug - }); - break; - - default: - throw new Error('[physics] Driver not recognized: "%s".', data.driver); - } - - if (data.driver !== 'ammo') { - await this.driver.init({ - quatNormalizeSkip: 0, - quatNormalizeFast: false, - solverIterations: data.iterations, - gravity: data.gravity, - }); - this.driver.addMaterial({name: 'defaultMaterial'}); - this.driver.addMaterial({name: 'staticMaterial'}); - this.driver.addContactMaterial('defaultMaterial', 'defaultMaterial', { - friction: data.friction, - restitution: data.restitution, - contactEquationStiffness: data.contactEquationStiffness, - contactEquationRelaxation: data.contactEquationRelaxation, - frictionEquationStiffness: data.frictionEquationStiffness, - frictionEquationRegularization: data.frictionEquationRegularization - }); - this.driver.addContactMaterial('staticMaterial', 'defaultMaterial', { - friction: 1.0, - restitution: 0.0, - contactEquationStiffness: data.contactEquationStiffness, - contactEquationRelaxation: data.contactEquationRelaxation, - frictionEquationStiffness: data.frictionEquationStiffness, - frictionEquationRegularization: data.frictionEquationRegularization - }); - } else { - await this.driver.init({ - gravity: data.gravity, - debugDrawMode: data.debugDrawMode, - solverIterations: data.iterations, - maxSubSteps: data.maxSubSteps, - fixedTimeStep: data.fixedTimeStep - }); - } - - this.initialized = true; - - if (this.debug) { - this.setDebug(true); - } - }, - - initStats() { - // Data used for performance monitoring. - this.statsToConsole = this.data.stats.includes("console") - this.statsToEvents = this.data.stats.includes("events") - this.statsToPanel = this.data.stats.includes("panel") - - if (this.statsToConsole || this.statsToEvents || this.statsToPanel) { - this.trackPerf = true; - this.tickCounter = 0; - - this.statsTickData = {}; - this.statsBodyData = {}; - - this.countBodies = { - "ammo": () => this.countBodiesAmmo(), - "local": () => this.countBodiesCannon(false), - "worker": () => this.countBodiesCannon(true) - } - - this.bodyTypeToStatsPropertyMap = { - "ammo": { - [TYPE.STATIC] : "staticBodies", - [TYPE.KINEMATIC] : "kinematicBodies", - [TYPE.DYNAMIC] : "dynamicBodies", - }, - "cannon": { - [CANNON.Body.STATIC] : "staticBodies", - [CANNON.Body.DYNAMIC] : "dynamicBodies" - } - } - - const scene = this.el.sceneEl; - scene.setAttribute("stats-collector", `inEvent: physics-tick-data; - properties: before, after, engine, total; - outputFrequency: 100; - outEvent: physics-tick-summary; - outputs: percentile__50, percentile__90, max`); - } - - if (this.statsToPanel) { - const scene = this.el.sceneEl; - const space = "   " - - scene.setAttribute("stats-panel", "") - scene.setAttribute("stats-group__bodies", `label: Physics Bodies`) - scene.setAttribute("stats-row__b1", `group: bodies; - event:physics-body-data; - properties: staticBodies; - label: Static`) - scene.setAttribute("stats-row__b2", `group: bodies; - event:physics-body-data; - properties: dynamicBodies; - label: Dynamic`) - if (this.data.driver === 'local' || this.data.driver === 'worker') { - scene.setAttribute("stats-row__b3", `group: bodies; - event:physics-body-data; - properties: contacts; - label: Contacts`) - } - else if (this.data.driver === 'ammo') { - scene.setAttribute("stats-row__b3", `group: bodies; - event:physics-body-data; - properties: kinematicBodies; - label: Kinematic`) - scene.setAttribute("stats-row__b4", `group: bodies; - event: physics-body-data; - properties: manifolds; - label: Manifolds`) - scene.setAttribute("stats-row__b5", `group: bodies; - event: physics-body-data; - properties: manifoldContacts; - label: Contacts`) - scene.setAttribute("stats-row__b6", `group: bodies; - event: physics-body-data; - properties: collisions; - label: Collisions`) - scene.setAttribute("stats-row__b7", `group: bodies; - event: physics-body-data; - properties: collisionKeys; - label: Coll Keys`) - } - - scene.setAttribute("stats-group__tick", `label: Physics Ticks: Median${space}90th%${space}99th%`) - scene.setAttribute("stats-row__1", `group: tick; - event:physics-tick-summary; - properties: before.percentile__50, - before.percentile__90, - before.max; - label: Before`) - scene.setAttribute("stats-row__2", `group: tick; - event:physics-tick-summary; - properties: after.percentile__50, - after.percentile__90, - after.max; - label: After`) - scene.setAttribute("stats-row__3", `group: tick; - event:physics-tick-summary; - properties: engine.percentile__50, - engine.percentile__90, - engine.max; - label: Engine`) - scene.setAttribute("stats-row__4", `group: tick; - event:physics-tick-summary; - properties: total.percentile__50, - total.percentile__90, - total.max; - label: Total`) - } - }, - - /** - * Updates the physics world on each tick of the A-Frame scene. It would be - * entirely possible to separate the two – updating physics more or less - * frequently than the scene – if greater precision or performance were - * necessary. - * @param {number} t - * @param {number} dt - */ - tick: function (t, dt) { - if (!this.initialized || !dt) return; - - const beforeStartTime = performance.now(); - - var i; - var callbacks = this.callbacks; - - for (i = 0; i < this.callbacks.beforeStep.length; i++) { - this.callbacks.beforeStep[i].beforeStep(t, dt); - } - - const engineStartTime = performance.now(); - - this.driver.step(Math.min(dt / 1000, this.data.maxInterval)); - - const engineEndTime = performance.now(); - - for (i = 0; i < callbacks.step.length; i++) { - callbacks.step[i].step(t, dt); - } - - for (i = 0; i < callbacks.afterStep.length; i++) { - callbacks.afterStep[i].afterStep(t, dt); - } - - if (this.trackPerf) { - const afterEndTime = performance.now(); - - this.statsTickData.before = engineStartTime - beforeStartTime - this.statsTickData.engine = engineEndTime - engineStartTime - this.statsTickData.after = afterEndTime - engineEndTime - this.statsTickData.total = afterEndTime - beforeStartTime - - this.el.emit("physics-tick-data", this.statsTickData) - - this.tickCounter++; - - if (this.tickCounter === 100) { - - this.countBodies[this.data.driver]() - - if (this.statsToConsole) { - console.log("Physics body stats:", this.statsBodyData) - } - - if (this.statsToEvents || this.statsToPanel) { - this.el.emit("physics-body-data", this.statsBodyData) - } - this.tickCounter = 0; - } - } - }, - - countBodiesAmmo() { - - const statsData = this.statsBodyData - statsData.manifolds = this.driver.dispatcher.getNumManifolds(); - statsData.manifoldContacts = 0; - for (let i = 0; i < statsData.manifolds; i++) { - const manifold = this.driver.dispatcher.getManifoldByIndexInternal(i); - statsData.manifoldContacts += manifold.getNumContacts(); - } - statsData.collisions = this.driver.collisions.size; - statsData.collisionKeys = this.driver.collisionKeys.length; - statsData.staticBodies = 0 - statsData.kinematicBodies = 0 - statsData.dynamicBodies = 0 - - function type(el) { - return el.components['ammo-body'].data.type - } - - this.driver.els.forEach((el) => { - const property = this.bodyTypeToStatsPropertyMap["ammo"][type(el)] - statsData[property]++ - }) - }, - - countBodiesCannon(worker) { - - const statsData = this.statsBodyData - statsData.contacts = worker ? this.driver.contacts.length : this.driver.world.contacts.length; - statsData.staticBodies = 0 - statsData.dynamicBodies = 0 - - const bodies = worker ? Object.values(this.driver.bodies) : this.driver.world.bodies - - bodies.forEach((body) => { - const property = this.bodyTypeToStatsPropertyMap["cannon"][body.type] - statsData[property]++ - }) - }, - - setDebug: function(debug) { - this.debug = debug; - if (this.data.driver === 'ammo' && this.initialized) { - if (debug && !this.debugDrawer) { - this.debugDrawer = this.driver.getDebugDrawer(this.el.object3D); - this.debugDrawer.enable(); - } else if (this.debugDrawer) { - this.debugDrawer.disable(); - this.debugDrawer = null; - } - } - }, - - /** - * Adds a body to the scene, and binds proxied methods to the driver. - * @param {CANNON.Body} body - */ - addBody: function (body, group, mask) { - var driver = this.driver; - - if (this.data.driver === 'local') { - body.__applyImpulse = body.applyImpulse; - body.applyImpulse = function () { - driver.applyBodyMethod(body, 'applyImpulse', arguments); - }; - - body.__applyForce = body.applyForce; - body.applyForce = function () { - driver.applyBodyMethod(body, 'applyForce', arguments); - }; - - body.updateProperties = function () { - driver.updateBodyProperties(body); - }; - - this.listeners[body.id] = function (e) { body.el.emit('collide', e); }; - body.addEventListener('collide', this.listeners[body.id]); - } - - this.driver.addBody(body, group, mask); - }, - - /** - * Removes a body and its proxied methods. - * @param {CANNON.Body} body - */ - removeBody: function (body) { - this.driver.removeBody(body); - - if (this.data.driver === 'local' || this.data.driver === 'worker') { - body.removeEventListener('collide', this.listeners[body.id]); - delete this.listeners[body.id]; - - body.applyImpulse = body.__applyImpulse; - delete body.__applyImpulse; - - body.applyForce = body.__applyForce; - delete body.__applyForce; - - delete body.updateProperties; - } - }, - - /** @param {CANNON.Constraint or Ammo.btTypedConstraint} constraint */ - addConstraint: function (constraint) { - this.driver.addConstraint(constraint); - }, - - /** @param {CANNON.Constraint or Ammo.btTypedConstraint} constraint */ - removeConstraint: function (constraint) { - this.driver.removeConstraint(constraint); - }, - - /** - * Adds a component instance to the system and schedules its update methods to be called - * the given phase. - * @param {Component} component - * @param {string} phase - */ - addComponent: function (component) { - var callbacks = this.callbacks; - if (component.beforeStep) callbacks.beforeStep.push(component); - if (component.step) callbacks.step.push(component); - if (component.afterStep) callbacks.afterStep.push(component); - }, - - /** - * Removes a component instance from the system. - * @param {Component} component - * @param {string} phase - */ - removeComponent: function (component) { - var callbacks = this.callbacks; - if (component.beforeStep) { - callbacks.beforeStep.splice(callbacks.beforeStep.indexOf(component), 1); - } - if (component.step) { - callbacks.step.splice(callbacks.step.indexOf(component), 1); - } - if (component.afterStep) { - callbacks.afterStep.splice(callbacks.afterStep.indexOf(component), 1); - } - }, - - /** @return {Array} */ - getContacts: function () { - return this.driver.getContacts(); - }, - - getMaterial: function (name) { - return this.driver.getMaterial(name); - } -}); + for (i = 0; i < this.callbacks.beforeStep.length; i++) { + this.callbacks.beforeStep[i].beforeStep(t, dt); + } + + const engineStartTime = performance.now(); + + this.driver.step(Math.min(dt / 1000, this.data.maxInterval)); + + const engineEndTime = performance.now(); + + for (i = 0; i < callbacks.step.length; i++) { + callbacks.step[i].step(t, dt); + } + + for (i = 0; i < callbacks.afterStep.length; i++) { + callbacks.afterStep[i].afterStep(t, dt); + } + + if (this.trackPerf) { + const afterEndTime = performance.now(); + + this.statsTickData.before = engineStartTime - beforeStartTime + this.statsTickData.engine = engineEndTime - engineStartTime + this.statsTickData.after = afterEndTime - engineEndTime + this.statsTickData.total = afterEndTime - beforeStartTime + + this.el.emit("physics-tick-data", this.statsTickData) + + this.tickCounter++; + + if (this.tickCounter === 100) { + + this.countBodies[this.data.driver]() + + if (this.statsToConsole) { + console.log("Physics body stats:", this.statsBodyData) + } + + if (this.statsToEvents || this.statsToPanel) { + this.el.emit("physics-body-data", this.statsBodyData) + } + this.tickCounter = 0; + } + } + }, + + countBodiesAmmo() { + + const statsData = this.statsBodyData + statsData.manifolds = this.driver.dispatcher.getNumManifolds(); + statsData.manifoldContacts = 0; + for (let i = 0; i < statsData.manifolds; i++) { + const manifold = this.driver.dispatcher.getManifoldByIndexInternal(i); + statsData.manifoldContacts += manifold.getNumContacts(); + } + statsData.collisions = this.driver.collisions.size; + statsData.collisionKeys = this.driver.collisionKeys.length; + statsData.staticBodies = 0 + statsData.kinematicBodies = 0 + statsData.dynamicBodies = 0 + + function type(el) { + return el.components['ammo-body'].data.type + } + + this.driver.els.forEach((el) => { + const property = this.bodyTypeToStatsPropertyMap["ammo"][type(el)] + statsData[property]++ + }) + }, + + countBodiesCannon(worker) { + + const statsData = this.statsBodyData + statsData.contacts = worker ? this.driver.contacts.length : this.driver.world.contacts.length; + statsData.staticBodies = 0 + statsData.dynamicBodies = 0 + + const bodies = worker ? Object.values(this.driver.bodies) : this.driver.world.bodies + + bodies.forEach((body) => { + const property = this.bodyTypeToStatsPropertyMap["cannon"][body.type] + statsData[property]++ + }) + }, + + setDebug: function(debug) { + this.debug = debug; + if (this.data.driver === 'ammo' && this.initialized) { + if (debug && !this.debugDrawer) { + this.debugDrawer = this.driver.getDebugDrawer(this.el.object3D); + this.debugDrawer.enable(); + } else if (this.debugDrawer) { + this.debugDrawer.disable(); + this.debugDrawer = null; + } + } + }, + + /** + * Adds a body to the scene, and binds proxied methods to the driver. + * @param {CANNON.Body} body + */ + addBody: function (body, group, mask) { + var driver = this.driver; + + if (this.data.driver === 'local') { + body.__applyImpulse = body.applyImpulse; + body.applyImpulse = function () { + driver.applyBodyMethod(body, 'applyImpulse', arguments); + }; + + body.__applyForce = body.applyForce; + body.applyForce = function () { + driver.applyBodyMethod(body, 'applyForce', arguments); + }; + + body.updateProperties = function () { + driver.updateBodyProperties(body); + }; + + this.listeners[body.id] = function (e) { body.el.emit('collide', e); }; + body.addEventListener('collide', this.listeners[body.id]); + } + + this.driver.addBody(body, group, mask); + }, + + /** + * Removes a body and its proxied methods. + * @param {CANNON.Body} body + */ + removeBody: function (body) { + this.driver.removeBody(body); + + if (this.data.driver === 'local' || this.data.driver === 'worker') { + body.removeEventListener('collide', this.listeners[body.id]); + delete this.listeners[body.id]; + + body.applyImpulse = body.__applyImpulse; + delete body.__applyImpulse; + + body.applyForce = body.__applyForce; + delete body.__applyForce; + + delete body.updateProperties; + } + }, + + /** @param {CANNON.Constraint or Ammo.btTypedConstraint} constraint */ + addConstraint: function (constraint) { + this.driver.addConstraint(constraint); + }, + + /** @param {CANNON.Constraint or Ammo.btTypedConstraint} constraint */ + removeConstraint: function (constraint) { + this.driver.removeConstraint(constraint); + }, + + /** + * Adds a component instance to the system and schedules its update methods to be called + * the given phase. + * @param {Component} component + * @param {string} phase + */ + addComponent: function (component) { + var callbacks = this.callbacks; + if (component.beforeStep) callbacks.beforeStep.push(component); + if (component.step) callbacks.step.push(component); + if (component.afterStep) callbacks.afterStep.push(component); + }, + + /** + * Removes a component instance from the system. + * @param {Component} component + * @param {string} phase + */ + removeComponent: function (component) { + var callbacks = this.callbacks; + if (component.beforeStep) { + callbacks.beforeStep.splice(callbacks.beforeStep.indexOf(component), 1); + } + if (component.step) { + callbacks.step.splice(callbacks.step.indexOf(component), 1); + } + if (component.afterStep) { + callbacks.afterStep.splice(callbacks.afterStep.indexOf(component), 1); + } + }, + + /** @return {Array} */ + getContacts: function () { + return this.driver.getContacts(); + }, + + getMaterial: function (name) { + return this.driver.getMaterial(name); + } +}); },{"./constants":20,"./drivers/ammo-driver":21,"./drivers/local-driver":24,"./drivers/network-driver":25,"./drivers/worker-driver":27,"aframe-stats-panel":3,"cannon-es":5}],30:[function(require,module,exports){ -module.exports.slerp = function ( a, b, t ) { - if ( t <= 0 ) return a; - if ( t >= 1 ) return b; - - var x = a[0], y = a[1], z = a[2], w = a[3]; - - // https://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - - var cosHalfTheta = w * b[3] + x * b[0] + y * b[1] + z * b[2]; - - if ( cosHalfTheta < 0 ) { - - a = a.slice(); - - a[3] = - b[3]; - a[0] = - b[0]; - a[1] = - b[1]; - a[2] = - b[2]; - - cosHalfTheta = - cosHalfTheta; - - } else { - - return b; - - } - - if ( cosHalfTheta >= 1.0 ) { - - a[3] = w; - a[0] = x; - a[1] = y; - a[2] = z; - - return this; - - } - - var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); - - if ( Math.abs( sinHalfTheta ) < 0.001 ) { - - a[3] = 0.5 * ( w + a[3] ); - a[0] = 0.5 * ( x + a[0] ); - a[1] = 0.5 * ( y + a[1] ); - a[2] = 0.5 * ( z + a[2] ); - - return this; - - } - - var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta; - var ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - a[3] = ( w * ratioA + a[3] * ratioB ); - a[0] = ( x * ratioA + a[0] * ratioB ); - a[1] = ( y * ratioA + a[1] * ratioB ); - a[2] = ( z * ratioA + a[2] * ratioB ); - - return a; - -}; +module.exports.slerp = function ( a, b, t ) { + if ( t <= 0 ) return a; + if ( t >= 1 ) return b; + + var x = a[0], y = a[1], z = a[2], w = a[3]; + + // https://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ + + var cosHalfTheta = w * b[3] + x * b[0] + y * b[1] + z * b[2]; + + if ( cosHalfTheta < 0 ) { + + a = a.slice(); + + a[3] = - b[3]; + a[0] = - b[0]; + a[1] = - b[1]; + a[2] = - b[2]; + + cosHalfTheta = - cosHalfTheta; + + } else { + + return b; + + } + + if ( cosHalfTheta >= 1.0 ) { + + a[3] = w; + a[0] = x; + a[1] = y; + a[2] = z; + + return this; + + } + + var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); + + if ( Math.abs( sinHalfTheta ) < 0.001 ) { + + a[3] = 0.5 * ( w + a[3] ); + a[0] = 0.5 * ( x + a[0] ); + a[1] = 0.5 * ( y + a[1] ); + a[2] = 0.5 * ( z + a[2] ); + + return this; + + } + + var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); + var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta; + var ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; + + a[3] = ( w * ratioA + a[3] * ratioB ); + a[0] = ( x * ratioA + a[0] * ratioB ); + a[1] = ( y * ratioA + a[1] * ratioB ); + a[2] = ( z * ratioA + a[2] * ratioB ); + + return a; + +}; },{}],31:[function(require,module,exports){ -var CANNON = require('cannon-es'); -var mathUtils = require('./math'); - -/****************************************************************************** - * IDs - */ - -var ID = '__id'; -module.exports.ID = ID; - -var nextID = {}; -module.exports.assignID = function (prefix, object) { - if (object[ID]) return; - nextID[prefix] = nextID[prefix] || 1; - object[ID] = prefix + '_' + nextID[prefix]++; -}; - -/****************************************************************************** - * Bodies - */ - -module.exports.serializeBody = function (body) { - var message = { - // Shapes. - shapes: body.shapes.map(serializeShape), - shapeOffsets: body.shapeOffsets.map(serializeVec3), - shapeOrientations: body.shapeOrientations.map(serializeQuaternion), - - // Vectors. - position: serializeVec3(body.position), - quaternion: body.quaternion.toArray(), - velocity: serializeVec3(body.velocity), - angularVelocity: serializeVec3(body.angularVelocity), - - // Properties. - id: body[ID], - mass: body.mass, - linearDamping: body.linearDamping, - angularDamping: body.angularDamping, - fixedRotation: body.fixedRotation, - allowSleep: body.allowSleep, - sleepSpeedLimit: body.sleepSpeedLimit, - sleepTimeLimit: body.sleepTimeLimit - }; - - return message; -}; - -module.exports.deserializeBodyUpdate = function (message, body) { - body.position.set(message.position[0], message.position[1], message.position[2]); - body.quaternion.set(message.quaternion[0], message.quaternion[1], message.quaternion[2], message.quaternion[3]); - body.velocity.set(message.velocity[0], message.velocity[1], message.velocity[2]); - body.angularVelocity.set(message.angularVelocity[0], message.angularVelocity[1], message.angularVelocity[2]); - - body.linearDamping = message.linearDamping; - body.angularDamping = message.angularDamping; - body.fixedRotation = message.fixedRotation; - body.allowSleep = message.allowSleep; - body.sleepSpeedLimit = message.sleepSpeedLimit; - body.sleepTimeLimit = message.sleepTimeLimit; - - if (body.mass !== message.mass) { - body.mass = message.mass; - body.updateMassProperties(); - } - - return body; -}; - -module.exports.deserializeInterpBodyUpdate = function (message1, message2, body, mix) { - var weight1 = 1 - mix; - var weight2 = mix; - - body.position.set( - message1.position[0] * weight1 + message2.position[0] * weight2, - message1.position[1] * weight1 + message2.position[1] * weight2, - message1.position[2] * weight1 + message2.position[2] * weight2 - ); - var quaternion = mathUtils.slerp(message1.quaternion, message2.quaternion, mix); - body.quaternion.set(quaternion[0], quaternion[1], quaternion[2], quaternion[3]); - body.velocity.set( - message1.velocity[0] * weight1 + message2.velocity[0] * weight2, - message1.velocity[1] * weight1 + message2.velocity[1] * weight2, - message1.velocity[2] * weight1 + message2.velocity[2] * weight2 - ); - body.angularVelocity.set( - message1.angularVelocity[0] * weight1 + message2.angularVelocity[0] * weight2, - message1.angularVelocity[1] * weight1 + message2.angularVelocity[1] * weight2, - message1.angularVelocity[2] * weight1 + message2.angularVelocity[2] * weight2 - ); - - body.linearDamping = message2.linearDamping; - body.angularDamping = message2.angularDamping; - body.fixedRotation = message2.fixedRotation; - body.allowSleep = message2.allowSleep; - body.sleepSpeedLimit = message2.sleepSpeedLimit; - body.sleepTimeLimit = message2.sleepTimeLimit; - - if (body.mass !== message2.mass) { - body.mass = message2.mass; - body.updateMassProperties(); - } - - return body; -}; - -module.exports.deserializeBody = function (message) { - var body = new CANNON.Body({ - mass: message.mass, - - position: deserializeVec3(message.position), - quaternion: deserializeQuaternion(message.quaternion), - velocity: deserializeVec3(message.velocity), - angularVelocity: deserializeVec3(message.angularVelocity), - - linearDamping: message.linearDamping, - angularDamping: message.angularDamping, - fixedRotation: message.fixedRotation, - allowSleep: message.allowSleep, - sleepSpeedLimit: message.sleepSpeedLimit, - sleepTimeLimit: message.sleepTimeLimit - }); - - for (var shapeMsg, i = 0; (shapeMsg = message.shapes[i]); i++) { - body.addShape( - deserializeShape(shapeMsg), - deserializeVec3(message.shapeOffsets[i]), - deserializeQuaternion(message.shapeOrientations[i]) - ); - } - - body[ID] = message.id; - - return body; -}; - -/****************************************************************************** - * Shapes - */ - -module.exports.serializeShape = serializeShape; -function serializeShape (shape) { - var shapeMsg = {type: shape.type}; - if (shape.type === CANNON.Shape.types.BOX) { - shapeMsg.halfExtents = serializeVec3(shape.halfExtents); - - } else if (shape.type === CANNON.Shape.types.SPHERE) { - shapeMsg.radius = shape.radius; - - // Patch schteppe/cannon.js#329. - } else if (shape._type === CANNON.Shape.types.CYLINDER) { - shapeMsg.type = CANNON.Shape.types.CYLINDER; - shapeMsg.radiusTop = shape.radiusTop; - shapeMsg.radiusBottom = shape.radiusBottom; - shapeMsg.height = shape.height; - shapeMsg.numSegments = shape.numSegments; - - } else { - // TODO(donmccurdy): Support for other shape types. - throw new Error('Unimplemented shape type: %s', shape.type); - } - return shapeMsg; -} - -module.exports.deserializeShape = deserializeShape; -function deserializeShape (message) { - var shape; - - if (message.type === CANNON.Shape.types.BOX) { - shape = new CANNON.Box(deserializeVec3(message.halfExtents)); - - } else if (message.type === CANNON.Shape.types.SPHERE) { - shape = new CANNON.Sphere(message.radius); - - // Patch schteppe/cannon.js#329. - } else if (message.type === CANNON.Shape.types.CYLINDER) { - shape = new CANNON.Cylinder(message.radiusTop, message.radiusBottom, message.height, message.numSegments); - shape._type = CANNON.Shape.types.CYLINDER; - - } else { - // TODO(donmccurdy): Support for other shape types. - throw new Error('Unimplemented shape type: %s', message.type); - } - - return shape; -} - -/****************************************************************************** - * Constraints - */ - -module.exports.serializeConstraint = function (constraint) { - - var message = { - id: constraint[ID], - type: constraint.type, - maxForce: constraint.maxForce, - bodyA: constraint.bodyA[ID], - bodyB: constraint.bodyB[ID] - }; - - switch (constraint.type) { - case 'LockConstraint': - break; - case 'DistanceConstraint': - message.distance = constraint.distance; - break; - case 'HingeConstraint': - case 'ConeTwistConstraint': - message.axisA = serializeVec3(constraint.axisA); - message.axisB = serializeVec3(constraint.axisB); - message.pivotA = serializeVec3(constraint.pivotA); - message.pivotB = serializeVec3(constraint.pivotB); - break; - case 'PointToPointConstraint': - message.pivotA = serializeVec3(constraint.pivotA); - message.pivotB = serializeVec3(constraint.pivotB); - break; - default: - throw new Error('' - + 'Unexpected constraint type: ' + constraint.type + '. ' - + 'You may need to manually set `constraint.type = "FooConstraint";`.' - ); - } - - return message; -}; - -module.exports.deserializeConstraint = function (message, bodies) { - var TypedConstraint = CANNON[message.type]; - var bodyA = bodies[message.bodyA]; - var bodyB = bodies[message.bodyB]; - - var constraint; - - switch (message.type) { - case 'LockConstraint': - constraint = new CANNON.LockConstraint(bodyA, bodyB, message); - break; - - case 'DistanceConstraint': - constraint = new CANNON.DistanceConstraint( - bodyA, - bodyB, - message.distance, - message.maxForce - ); - break; - - case 'HingeConstraint': - case 'ConeTwistConstraint': - constraint = new TypedConstraint(bodyA, bodyB, { - pivotA: deserializeVec3(message.pivotA), - pivotB: deserializeVec3(message.pivotB), - axisA: deserializeVec3(message.axisA), - axisB: deserializeVec3(message.axisB), - maxForce: message.maxForce - }); - break; - - case 'PointToPointConstraint': - constraint = new CANNON.PointToPointConstraint( - bodyA, - deserializeVec3(message.pivotA), - bodyB, - deserializeVec3(message.pivotB), - message.maxForce - ); - break; - - default: - throw new Error('Unexpected constraint type: ' + message.type); - } - - constraint[ID] = message.id; - return constraint; -}; - -/****************************************************************************** - * Contacts - */ - -module.exports.serializeContact = function (contact) { - return { - bi: contact.bi[ID], - bj: contact.bj[ID], - ni: serializeVec3(contact.ni), - ri: serializeVec3(contact.ri), - rj: serializeVec3(contact.rj) - }; -}; - -module.exports.deserializeContact = function (message, bodies) { - return { - bi: bodies[message.bi], - bj: bodies[message.bj], - ni: deserializeVec3(message.ni), - ri: deserializeVec3(message.ri), - rj: deserializeVec3(message.rj) - }; -}; - -/****************************************************************************** - * Math - */ - -module.exports.serializeVec3 = serializeVec3; -function serializeVec3 (vec3) { - return vec3.toArray(); -} - -module.exports.deserializeVec3 = deserializeVec3; -function deserializeVec3 (message) { - return new CANNON.Vec3(message[0], message[1], message[2]); -} - -module.exports.serializeQuaternion = serializeQuaternion; -function serializeQuaternion (quat) { - return quat.toArray(); -} - -module.exports.deserializeQuaternion = deserializeQuaternion; -function deserializeQuaternion (message) { - return new CANNON.Quaternion(message[0], message[1], message[2], message[3]); -} +var CANNON = require('cannon-es'); +var mathUtils = require('./math'); + +/****************************************************************************** + * IDs + */ + +var ID = '__id'; +module.exports.ID = ID; + +var nextID = {}; +module.exports.assignID = function (prefix, object) { + if (object[ID]) return; + nextID[prefix] = nextID[prefix] || 1; + object[ID] = prefix + '_' + nextID[prefix]++; +}; + +/****************************************************************************** + * Bodies + */ + +module.exports.serializeBody = function (body) { + var message = { + // Shapes. + shapes: body.shapes.map(serializeShape), + shapeOffsets: body.shapeOffsets.map(serializeVec3), + shapeOrientations: body.shapeOrientations.map(serializeQuaternion), + + // Vectors. + position: serializeVec3(body.position), + quaternion: body.quaternion.toArray(), + velocity: serializeVec3(body.velocity), + angularVelocity: serializeVec3(body.angularVelocity), + + // Properties. + id: body[ID], + mass: body.mass, + linearDamping: body.linearDamping, + angularDamping: body.angularDamping, + fixedRotation: body.fixedRotation, + allowSleep: body.allowSleep, + sleepSpeedLimit: body.sleepSpeedLimit, + sleepTimeLimit: body.sleepTimeLimit + }; + + return message; +}; + +module.exports.deserializeBodyUpdate = function (message, body) { + body.position.set(message.position[0], message.position[1], message.position[2]); + body.quaternion.set(message.quaternion[0], message.quaternion[1], message.quaternion[2], message.quaternion[3]); + body.velocity.set(message.velocity[0], message.velocity[1], message.velocity[2]); + body.angularVelocity.set(message.angularVelocity[0], message.angularVelocity[1], message.angularVelocity[2]); + + body.linearDamping = message.linearDamping; + body.angularDamping = message.angularDamping; + body.fixedRotation = message.fixedRotation; + body.allowSleep = message.allowSleep; + body.sleepSpeedLimit = message.sleepSpeedLimit; + body.sleepTimeLimit = message.sleepTimeLimit; + + if (body.mass !== message.mass) { + body.mass = message.mass; + body.updateMassProperties(); + } + + return body; +}; + +module.exports.deserializeInterpBodyUpdate = function (message1, message2, body, mix) { + var weight1 = 1 - mix; + var weight2 = mix; + + body.position.set( + message1.position[0] * weight1 + message2.position[0] * weight2, + message1.position[1] * weight1 + message2.position[1] * weight2, + message1.position[2] * weight1 + message2.position[2] * weight2 + ); + var quaternion = mathUtils.slerp(message1.quaternion, message2.quaternion, mix); + body.quaternion.set(quaternion[0], quaternion[1], quaternion[2], quaternion[3]); + body.velocity.set( + message1.velocity[0] * weight1 + message2.velocity[0] * weight2, + message1.velocity[1] * weight1 + message2.velocity[1] * weight2, + message1.velocity[2] * weight1 + message2.velocity[2] * weight2 + ); + body.angularVelocity.set( + message1.angularVelocity[0] * weight1 + message2.angularVelocity[0] * weight2, + message1.angularVelocity[1] * weight1 + message2.angularVelocity[1] * weight2, + message1.angularVelocity[2] * weight1 + message2.angularVelocity[2] * weight2 + ); + + body.linearDamping = message2.linearDamping; + body.angularDamping = message2.angularDamping; + body.fixedRotation = message2.fixedRotation; + body.allowSleep = message2.allowSleep; + body.sleepSpeedLimit = message2.sleepSpeedLimit; + body.sleepTimeLimit = message2.sleepTimeLimit; + + if (body.mass !== message2.mass) { + body.mass = message2.mass; + body.updateMassProperties(); + } + + return body; +}; + +module.exports.deserializeBody = function (message) { + var body = new CANNON.Body({ + mass: message.mass, + + position: deserializeVec3(message.position), + quaternion: deserializeQuaternion(message.quaternion), + velocity: deserializeVec3(message.velocity), + angularVelocity: deserializeVec3(message.angularVelocity), + + linearDamping: message.linearDamping, + angularDamping: message.angularDamping, + fixedRotation: message.fixedRotation, + allowSleep: message.allowSleep, + sleepSpeedLimit: message.sleepSpeedLimit, + sleepTimeLimit: message.sleepTimeLimit + }); + + for (var shapeMsg, i = 0; (shapeMsg = message.shapes[i]); i++) { + body.addShape( + deserializeShape(shapeMsg), + deserializeVec3(message.shapeOffsets[i]), + deserializeQuaternion(message.shapeOrientations[i]) + ); + } + + body[ID] = message.id; + + return body; +}; + +/****************************************************************************** + * Shapes + */ + +module.exports.serializeShape = serializeShape; +function serializeShape (shape) { + var shapeMsg = {type: shape.type}; + if (shape.type === CANNON.Shape.types.BOX) { + shapeMsg.halfExtents = serializeVec3(shape.halfExtents); + + } else if (shape.type === CANNON.Shape.types.SPHERE) { + shapeMsg.radius = shape.radius; + + // Patch schteppe/cannon.js#329. + } else if (shape._type === CANNON.Shape.types.CYLINDER) { + shapeMsg.type = CANNON.Shape.types.CYLINDER; + shapeMsg.radiusTop = shape.radiusTop; + shapeMsg.radiusBottom = shape.radiusBottom; + shapeMsg.height = shape.height; + shapeMsg.numSegments = shape.numSegments; + + } else { + // TODO(donmccurdy): Support for other shape types. + throw new Error('Unimplemented shape type: %s', shape.type); + } + return shapeMsg; +} + +module.exports.deserializeShape = deserializeShape; +function deserializeShape (message) { + var shape; + + if (message.type === CANNON.Shape.types.BOX) { + shape = new CANNON.Box(deserializeVec3(message.halfExtents)); + + } else if (message.type === CANNON.Shape.types.SPHERE) { + shape = new CANNON.Sphere(message.radius); + + // Patch schteppe/cannon.js#329. + } else if (message.type === CANNON.Shape.types.CYLINDER) { + shape = new CANNON.Cylinder(message.radiusTop, message.radiusBottom, message.height, message.numSegments); + shape._type = CANNON.Shape.types.CYLINDER; + + } else { + // TODO(donmccurdy): Support for other shape types. + throw new Error('Unimplemented shape type: %s', message.type); + } + + return shape; +} + +/****************************************************************************** + * Constraints + */ + +module.exports.serializeConstraint = function (constraint) { + + var message = { + id: constraint[ID], + type: constraint.type, + maxForce: constraint.maxForce, + bodyA: constraint.bodyA[ID], + bodyB: constraint.bodyB[ID] + }; + + switch (constraint.type) { + case 'LockConstraint': + break; + case 'DistanceConstraint': + message.distance = constraint.distance; + break; + case 'HingeConstraint': + case 'ConeTwistConstraint': + message.axisA = serializeVec3(constraint.axisA); + message.axisB = serializeVec3(constraint.axisB); + message.pivotA = serializeVec3(constraint.pivotA); + message.pivotB = serializeVec3(constraint.pivotB); + break; + case 'PointToPointConstraint': + message.pivotA = serializeVec3(constraint.pivotA); + message.pivotB = serializeVec3(constraint.pivotB); + break; + default: + throw new Error('' + + 'Unexpected constraint type: ' + constraint.type + '. ' + + 'You may need to manually set `constraint.type = "FooConstraint";`.' + ); + } + + return message; +}; + +module.exports.deserializeConstraint = function (message, bodies) { + var TypedConstraint = CANNON[message.type]; + var bodyA = bodies[message.bodyA]; + var bodyB = bodies[message.bodyB]; + + var constraint; + + switch (message.type) { + case 'LockConstraint': + constraint = new CANNON.LockConstraint(bodyA, bodyB, message); + break; + + case 'DistanceConstraint': + constraint = new CANNON.DistanceConstraint( + bodyA, + bodyB, + message.distance, + message.maxForce + ); + break; + + case 'HingeConstraint': + case 'ConeTwistConstraint': + constraint = new TypedConstraint(bodyA, bodyB, { + pivotA: deserializeVec3(message.pivotA), + pivotB: deserializeVec3(message.pivotB), + axisA: deserializeVec3(message.axisA), + axisB: deserializeVec3(message.axisB), + maxForce: message.maxForce + }); + break; + + case 'PointToPointConstraint': + constraint = new CANNON.PointToPointConstraint( + bodyA, + deserializeVec3(message.pivotA), + bodyB, + deserializeVec3(message.pivotB), + message.maxForce + ); + break; + + default: + throw new Error('Unexpected constraint type: ' + message.type); + } + + constraint[ID] = message.id; + return constraint; +}; + +/****************************************************************************** + * Contacts + */ + +module.exports.serializeContact = function (contact) { + return { + bi: contact.bi[ID], + bj: contact.bj[ID], + ni: serializeVec3(contact.ni), + ri: serializeVec3(contact.ri), + rj: serializeVec3(contact.rj) + }; +}; + +module.exports.deserializeContact = function (message, bodies) { + return { + bi: bodies[message.bi], + bj: bodies[message.bj], + ni: deserializeVec3(message.ni), + ri: deserializeVec3(message.ri), + rj: deserializeVec3(message.rj) + }; +}; + +/****************************************************************************** + * Math + */ + +module.exports.serializeVec3 = serializeVec3; +function serializeVec3 (vec3) { + return vec3.toArray(); +} + +module.exports.deserializeVec3 = deserializeVec3; +function deserializeVec3 (message) { + return new CANNON.Vec3(message[0], message[1], message[2]); +} + +module.exports.serializeQuaternion = serializeQuaternion; +function serializeQuaternion (quat) { + return quat.toArray(); +} + +module.exports.deserializeQuaternion = deserializeQuaternion; +function deserializeQuaternion (message) { + return new CANNON.Quaternion(message[0], message[1], message[2], message[3]); +} },{"./math":30,"cannon-es":5}]},{},[1]); diff --git a/dist/aframe-physics-system.min.js b/dist/aframe-physics-system.min.js index 32a95a0..29c21c4 100644 --- a/dist/aframe-physics-system.min.js +++ b/dist/aframe-physics-system.min.js @@ -1 +1 @@ -!function(){return 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){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i{const counterValue=document.createElement("div");counterValue.classList.add("rs-counter-value"),counterValue.innerHTML="...",this.counter.appendChild(counterValue),this.counterValues[property]=counterValue}),this.updateData=this.updateData.bind(this),this.el.addEventListener(this.data.event,this.updateData),this.splitCache={}):console.warn(`Couldn't find stats group ${groupComponentName}`)},updateData(e){this.data.properties.forEach(property=>{const split=this.splitDot(property);let value=e.detail;for(i=0;i{this.outputDetail[property]={}}),this.statsReceived=this.statsReceived.bind(this),this.el.addEventListener(this.data.inEvent,this.statsReceived)},resetData(){this.counter=0,this.data.properties.forEach(property=>{this.statsData[property]=[]})},statsReceived(e){this.updateData(e.detail),this.counter++,this.counter===this.data.outputFrequency&&(this.outputData(),this.resetData())},updateData(detail){this.data.properties.forEach(property=>{let value=detail;value=value[property],this.statsData[property].push(value)})},outputData(){this.data.properties.forEach(property=>{this.data.outputs.forEach(output=>{this.outputDetail[property][output]=this.computeOutput(output,this.statsData[property])})}),this.data.outEvent&&this.el.emit(this.data.outEvent,this.outputDetail),this.data.outputToConsole&&console.log(this.data.outputToConsole,this.outputDetail)},computeOutput(outputInstruction,data){const outputInstructions=outputInstruction.split("__");let output;switch(outputInstructions[0]){case"mean":output=data.reduce((a,b)=>a+b,0)/data.length;break;case"max":output=Math.max(...data);break;case"min":output=Math.min(...data);break;case"percentile":const sorted=data.sort((a,b)=>a-b),proportion=+outputInstructions[1].replace("_",".")/100,position=(data.length-1)*proportion,base=Math.floor(position),delta=position-base;output=void 0!==sorted[base+1]?sorted[base]+delta*(sorted[base+1]-sorted[base]):sorted[base]}return output.toFixed(2)}})},{}],4:[function(require,module,exports){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:2048,DrawConstraintLimits:4096,FastWireframe:8192,DrawNormals:16384,DrawOnTop:32768,MAX_DEBUG_DRAW_MODE:4294967295},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||!1,maxBufferSize=options.maxBufferSize||1e6;this.geometry=new THREE.BufferGeometry;var vertices=new Float32Array(3*maxBufferSize),colors=new Float32Array(3*maxBufferSize);this.geometry.setAttribute("position",new THREE.BufferAttribute(vertices,3).setUsage(THREE.DynamicDrawUsage)),this.geometry.setAttribute("color",new THREE.BufferAttribute(colors,3).setUsage(THREE.DynamicDrawUsage)),this.index=0;var material=new THREE.LineBasicMaterial({vertexColors:!0,depthTest:!drawOnTop});this.mesh=new THREE.LineSegments(this.geometry,material),drawOnTop&&(this.mesh.renderOrder=999),this.mesh.frustumCulled=!1,this.enabled=!1,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=!0,this.scene.add(this.mesh)},THREE.AmmoDebugDrawer.prototype.disable=function(){this.enabled=!1,this.scene.remove(this.mesh)},THREE.AmmoDebugDrawer.prototype.update=function(){this.enabled&&(0!=this.index&&(this.geometry.attributes.position.needsUpdate=!0,this.geometry.attributes.color.needsUpdate=!0),this.index=0,this.world.debugDrawWorld(),this.geometry.setDrawRange(0,this.index))},THREE.AmmoDebugDrawer.prototype.drawLine=function(from,to,color){const heap=Ammo.HEAPF32,r=heap[(color+0)/4],g=heap[(color+4)/4],b=heap[(color+8)/4],fromX=heap[(from+0)/4],fromY=heap[(from+4)/4],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],toY=heap[(to+4)/4],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)},THREE.AmmoDebugDrawer.prototype.drawContactPoint=function(pointOnB,normalOnB,distance,lifeTime,color){const heap=Ammo.HEAPF32,r=heap[(color+0)/4],g=heap[(color+4)/4],b=heap[(color+8)/4],x=heap[(pointOnB+0)/4],y=heap[(pointOnB+4)/4],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,dy=heap[(normalOnB+4)/4]*distance,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){Ammo.hasOwnProperty("Pointer_stringify")?console.warn(Ammo.Pointer_stringify(warningString)):this.warnedOnce||(this.warnedOnce=!0,console.warn("Cannot print warningString, please rebuild Ammo.js using 'debug' flag"))},THREE.AmmoDebugDrawer.prototype.draw3dText=function(location,textString){console.warn("TODO: draw3dText")},THREE.AmmoDebugDrawer.prototype.setDebugMode=function(debugMode){this.debugDrawMode=debugMode},THREE.AmmoDebugDrawer.prototype.getDebugMode=function(){return this.debugDrawMode}},{}],5:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var ObjectCollisionMatrix=function(){function ObjectCollisionMatrix(){this.matrix={}}var _proto=ObjectCollisionMatrix.prototype;return _proto.get=function(bi,bj){var i=bi.id,j=bj.id;if(j>i){var temp=j;j=i,i=temp}return i+"-"+j in this.matrix},_proto.set=function(bi,bj,value){var i=bi.id,j=bj.id;if(j>i){var temp=j;j=i,i=temp}value?this.matrix[i+"-"+j]=!0:delete this.matrix[i+"-"+j]},_proto.reset=function(){this.matrix={}},_proto.setNumObjects=function(n){},ObjectCollisionMatrix}(),Mat3=function(){function Mat3(elements){void 0===elements&&(elements=[0,0,0,0,0,0,0,0,0]),this.elements=elements}var _proto=Mat3.prototype;return _proto.identity=function(){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},_proto.setZero=function(){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},_proto.setTrace=function(vector){var e=this.elements;e[0]=vector.x,e[4]=vector.y,e[8]=vector.z},_proto.getTrace=function(target){void 0===target&&(target=new Vec3);var e=this.elements;target.x=e[0],target.y=e[4],target.z=e[8]},_proto.vmult=function(v,target){void 0===target&&(target=new Vec3);var e=this.elements,x=v.x,y=v.y,z=v.z;return 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,target},_proto.smult=function(s){for(var i=0;i0){var invN=1/n;this.x*=invN,this.y*=invN,this.z*=invN}else this.x=0,this.y=0,this.z=0;return n},_proto.unit=function(target){void 0===target&&(target=new Vec3);var x=this.x,y=this.y,z=this.z,ninv=Math.sqrt(x*x+y*y+z*z);return ninv>0?(ninv=1/ninv,target.x=x*ninv,target.y=y*ninv,target.z=z*ninv):(target.x=1,target.y=0,target.z=0),target},_proto.length=function(){var x=this.x,y=this.y,z=this.z;return Math.sqrt(x*x+y*y+z*z)},_proto.lengthSquared=function(){return this.dot(this)},_proto.distanceTo=function(p){var x=this.x,y=this.y,z=this.z,px=p.x,py=p.y,pz=p.z;return Math.sqrt((px-x)*(px-x)+(py-y)*(py-y)+(pz-z)*(pz-z))},_proto.distanceSquared=function(p){var x=this.x,y=this.y,z=this.z,px=p.x,py=p.y,pz=p.z;return(px-x)*(px-x)+(py-y)*(py-y)+(pz-z)*(pz-z)},_proto.scale=function(scalar,target){void 0===target&&(target=new Vec3);var x=this.x,y=this.y,z=this.z;return target.x=scalar*x,target.y=scalar*y,target.z=scalar*z,target},_proto.vmul=function(vector,target){return void 0===target&&(target=new Vec3),target.x=vector.x*this.x,target.y=vector.y*this.y,target.z=vector.z*this.z,target},_proto.addScaledVector=function(scalar,vector,target){return void 0===target&&(target=new Vec3),target.x=this.x+scalar*vector.x,target.y=this.y+scalar*vector.y,target.z=this.z+scalar*vector.z,target},_proto.dot=function(vector){return this.x*vector.x+this.y*vector.y+this.z*vector.z},_proto.isZero=function(){return 0===this.x&&0===this.y&&0===this.z},_proto.negate=function(target){return void 0===target&&(target=new Vec3),target.x=-this.x,target.y=-this.y,target.z=-this.z,target},_proto.tangents=function(t1,t2){var norm=this.length();if(norm>0){var n=Vec3_tangents_n,inorm=1/norm;n.set(this.x*inorm,this.y*inorm,this.z*inorm);var randVec=Vec3_tangents_randVec;Math.abs(n.x)<.9?(randVec.set(1,0,0),n.cross(randVec,t1)):(randVec.set(0,1,0),n.cross(randVec,t1)),n.cross(t1,t2)}else t1.set(1,0,0),t2.set(0,1,0)},_proto.toString=function(){return this.x+","+this.y+","+this.z},_proto.toArray=function(){return[this.x,this.y,this.z]},_proto.copy=function(vector){return this.x=vector.x,this.y=vector.y,this.z=vector.z,this},_proto.lerp=function(vector,t,target){var x=this.x,y=this.y,z=this.z;target.x=x+(vector.x-x)*t,target.y=y+(vector.y-y)*t,target.z=z+(vector.z-z)*t},_proto.almostEquals=function(vector,precision){return void 0===precision&&(precision=1e-6),!(Math.abs(this.x-vector.x)>precision||Math.abs(this.y-vector.y)>precision||Math.abs(this.z-vector.z)>precision)},_proto.almostZero=function(precision){return void 0===precision&&(precision=1e-6),!(Math.abs(this.x)>precision||Math.abs(this.y)>precision||Math.abs(this.z)>precision)},_proto.isAntiparallelTo=function(vector,precision){return this.negate(antip_neg),antip_neg.almostEquals(vector,precision)},_proto.clone=function(){return new Vec3(this.x,this.y,this.z)},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);var Vec3_tangents_n=new Vec3,Vec3_tangents_randVec=new Vec3,antip_neg=new Vec3,AABB=function(){function AABB(options){void 0===options&&(options={}),this.lowerBound=new Vec3,this.upperBound=new Vec3,options.lowerBound&&this.lowerBound.copy(options.lowerBound),options.upperBound&&this.upperBound.copy(options.upperBound)}var _proto=AABB.prototype;return _proto.setFromPoints=function(points,position,quaternion,skinSize){var l=this.lowerBound,u=this.upperBound,q=quaternion;l.copy(points[0]),q&&q.vmult(l,l),u.copy(l);for(var i=1;iu.x&&(u.x=p.x),p.xu.y&&(u.y=p.y),p.yu.z&&(u.z=p.z),p.z=u2.x&&l1.y<=l2.y&&u1.y>=u2.y&&l1.z<=l2.z&&u1.z>=u2.z},_proto.getCorners=function(a,b,c,d,e,f,g,h){var l=this.lowerBound,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)},_proto.toLocalFrame=function(frame,target){var corners=transformIntoFrame_corners,a=corners[0],b=corners[1],c=corners[2],d=corners[3],e=corners[4],f=corners[5],g=corners[6],h=corners[7];this.getCorners(a,b,c,d,e,f,g,h);for(var i=0;8!==i;i++){var corner=corners[i];frame.pointToLocal(corner,corner)}return target.setFromPoints(corners)},_proto.toWorldFrame=function(frame,target){var corners=transformIntoFrame_corners,a=corners[0],b=corners[1],c=corners[2],d=corners[3],e=corners[4],f=corners[5],g=corners[6],h=corners[7];this.getCorners(a,b,c,d,e,f,g,h);for(var i=0;8!==i;i++){var corner=corners[i];frame.pointToWorld(corner,corner)}return target.setFromPoints(corners)},_proto.overlapsRay=function(ray){var direction=ray.direction,from=ray.from,dirFracX=1/direction.x,dirFracY=1/direction.y,dirFracZ=1/direction.z,t1=(this.lowerBound.x-from.x)*dirFracX,t2=(this.upperBound.x-from.x)*dirFracX,t3=(this.lowerBound.y-from.y)*dirFracY,t4=(this.upperBound.y-from.y)*dirFracY,t5=(this.lowerBound.z-from.z)*dirFracZ,t6=(this.upperBound.z-from.z)*dirFracZ,tmin=Math.max(Math.max(Math.min(t1,t2),Math.min(t3,t4)),Math.min(t5,t6)),tmax=Math.min(Math.min(Math.max(t1,t2),Math.max(t3,t4)),Math.max(t5,t6));return!(tmax<0)&&!(tmin>tmax)},AABB}(),tmp=new Vec3,transformIntoFrame_corners=[new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3],ArrayCollisionMatrix=function(){function ArrayCollisionMatrix(){this.matrix=[]}var _proto=ArrayCollisionMatrix.prototype;return _proto.get=function(bi,bj){var i=bi.index,j=bj.index;if(j>i){var temp=j;j=i,i=temp}return this.matrix[(i*(i+1)>>1)+j-1]},_proto.set=function(bi,bj,value){var i=bi.index,j=bj.index;if(j>i){var temp=j;j=i,i=temp}this.matrix[(i*(i+1)>>1)+j-1]=value?1:0},_proto.reset=function(){for(var i=0,l=this.matrix.length;i!==l;i++)this.matrix[i]=0},_proto.setNumObjects=function(n){this.matrix.length=n*(n-1)>>1},ArrayCollisionMatrix}();function _inheritsLoose(subClass,superClass){subClass.prototype=Object.create(superClass.prototype),subClass.prototype.constructor=subClass,subClass.__proto__=superClass}function _assertThisInitialized(self){if(void 0===self)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return self}var EventTarget=function(){function EventTarget(){}var _proto=EventTarget.prototype;return _proto.addEventListener=function(type,listener){void 0===this._listeners&&(this._listeners={});var listeners=this._listeners;return void 0===listeners[type]&&(listeners[type]=[]),listeners[type].includes(listener)||listeners[type].push(listener),this},_proto.hasEventListener=function(type,listener){if(void 0===this._listeners)return!1;var listeners=this._listeners;return!(void 0===listeners[type]||!listeners[type].includes(listener))},_proto.hasAnyEventListener=function(type){return void 0!==this._listeners&&void 0!==this._listeners[type]},_proto.removeEventListener=function(type,listener){if(void 0===this._listeners)return this;var listeners=this._listeners;if(void 0===listeners[type])return this;var index=listeners[type].indexOf(listener);return-1!==index&&listeners[type].splice(index,1),this},_proto.dispatchEvent=function(event){if(void 0===this._listeners)return this;var listenerArray=this._listeners[event.type];if(void 0!==listenerArray){event.target=this;for(var i=0,l=listenerArray.length;i.499&&(heading=2*Math.atan2(x,w),attitude=Math.PI/2,bank=0),test<-.499&&(heading=-2*Math.atan2(x,w),attitude=-Math.PI/2,bank=0),void 0===heading){var sqx=x*x,sqy=y*y,sqz=z*z;heading=Math.atan2(2*y*w-2*x*z,1-2*sqy-2*sqz),attitude=Math.asin(2*test),bank=Math.atan2(2*x*w-2*y*z,1-2*sqx-2*sqz)}break;default:throw new Error("Euler order "+order+" not supported yet.")}target.y=heading,target.z=attitude,target.x=bank},_proto.setFromEuler=function(x,y,z,order){void 0===order&&(order="XYZ");var c1=Math.cos(x/2),c2=Math.cos(y/2),c3=Math.cos(z/2),s1=Math.sin(x/2),s2=Math.sin(y/2),s3=Math.sin(z/2);return"XYZ"===order?(this.x=s1*c2*c3+c1*s2*s3,this.y=c1*s2*c3-s1*c2*s3,this.z=c1*c2*s3+s1*s2*c3,this.w=c1*c2*c3-s1*s2*s3):"YXZ"===order?(this.x=s1*c2*c3+c1*s2*s3,this.y=c1*s2*c3-s1*c2*s3,this.z=c1*c2*s3-s1*s2*c3,this.w=c1*c2*c3+s1*s2*s3):"ZXY"===order?(this.x=s1*c2*c3-c1*s2*s3,this.y=c1*s2*c3+s1*c2*s3,this.z=c1*c2*s3+s1*s2*c3,this.w=c1*c2*c3-s1*s2*s3):"ZYX"===order?(this.x=s1*c2*c3-c1*s2*s3,this.y=c1*s2*c3+s1*c2*s3,this.z=c1*c2*s3-s1*s2*c3,this.w=c1*c2*c3+s1*s2*s3):"YZX"===order?(this.x=s1*c2*c3+c1*s2*s3,this.y=c1*s2*c3+s1*c2*s3,this.z=c1*c2*s3-s1*s2*c3,this.w=c1*c2*c3-s1*s2*s3):"XZY"===order&&(this.x=s1*c2*c3-c1*s2*s3,this.y=c1*s2*c3-s1*c2*s3,this.z=c1*c2*s3+s1*s2*c3,this.w=c1*c2*c3+s1*s2*s3),this},_proto.clone=function(){return new Quaternion(this.x,this.y,this.z,this.w)},_proto.slerp=function(toQuat,t,target){void 0===target&&(target=new Quaternion);var omega,cosom,sinom,scale0,scale1,ax=this.x,ay=this.y,az=this.z,aw=this.w,bx=toQuat.x,by=toQuat.y,bz=toQuat.z,bw=toQuat.w;return(cosom=ax*bx+ay*by+az*bz+aw*bw)<0&&(cosom=-cosom,bx=-bx,by=-by,bz=-bz,bw=-bw),1-cosom>1e-6?(omega=Math.acos(cosom),sinom=Math.sin(omega),scale0=Math.sin((1-t)*omega)/sinom,scale1=Math.sin(t*omega)/sinom):(scale0=1-t,scale1=t),target.x=scale0*ax+scale1*bx,target.y=scale0*ay+scale1*by,target.z=scale0*az+scale1*bz,target.w=scale0*aw+scale1*bw,target},_proto.integrate=function(angularVelocity,dt,angularFactor,target){void 0===target&&(target=new Quaternion);var ax=angularVelocity.x*angularFactor.x,ay=angularVelocity.y*angularFactor.y,az=angularVelocity.z*angularFactor.z,bx=this.x,by=this.y,bz=this.z,bw=this.w,half_dt=.5*dt;return target.x+=half_dt*(ax*bw+ay*bz-az*by),target.y+=half_dt*(ay*bw+az*bx-ax*bz),target.z+=half_dt*(az*bw+ax*by-ay*bx),target.w+=half_dt*(-ax*bx-ay*by-az*bz),target},Quaternion}(),sfv_t1=new Vec3,sfv_t2=new Vec3,SHAPE_TYPES={SPHERE:1,PLANE:2,BOX:4,COMPOUND:8,CONVEXPOLYHEDRON:16,HEIGHTFIELD:32,PARTICLE:64,CYLINDER:128,TRIMESH:256},Shape=function(){function Shape(options){void 0===options&&(options={}),this.id=Shape.idCounter++,this.type=options.type||0,this.boundingSphereRadius=0,this.collisionResponse=!options.collisionResponse||options.collisionResponse,this.collisionFilterGroup=void 0!==options.collisionFilterGroup?options.collisionFilterGroup:1,this.collisionFilterMask=void 0!==options.collisionFilterMask?options.collisionFilterMask:-1,this.material=options.material?options.material:null,this.body=null}var _proto=Shape.prototype;return _proto.updateBoundingSphereRadius=function(){throw"computeBoundingSphereRadius() not implemented for shape type "+this.type},_proto.volume=function(){throw"volume() not implemented for shape type "+this.type},_proto.calculateLocalInertia=function(mass,target){throw"calculateLocalInertia() not implemented for shape type "+this.type},_proto.calculateWorldAABB=function(pos,quat,min,max){throw"calculateWorldAABB() not implemented for shape type "+this.type},Shape}();Shape.idCounter=0,Shape.types=SHAPE_TYPES;var Transform=function(){function Transform(options){void 0===options&&(options={}),this.position=new Vec3,this.quaternion=new Quaternion,options.position&&this.position.copy(options.position),options.quaternion&&this.quaternion.copy(options.quaternion)}var _proto=Transform.prototype;return _proto.pointToLocal=function(worldPoint,result){return Transform.pointToLocalFrame(this.position,this.quaternion,worldPoint,result)},_proto.pointToWorld=function(localPoint,result){return Transform.pointToWorldFrame(this.position,this.quaternion,localPoint,result)},_proto.vectorToWorldFrame=function(localVector,result){return void 0===result&&(result=new Vec3),this.quaternion.vmult(localVector,result),result},Transform.pointToLocalFrame=function(position,quaternion,worldPoint,result){return void 0===result&&(result=new Vec3),worldPoint.vsub(position,result),quaternion.conjugate(tmpQuat),tmpQuat.vmult(result,result),result},Transform.pointToWorldFrame=function(position,quaternion,localPoint,result){return void 0===result&&(result=new Vec3),quaternion.vmult(localPoint,result),result.vadd(position,result),result},Transform.vectorToWorldFrame=function(quaternion,localVector,result){return void 0===result&&(result=new Vec3),quaternion.vmult(localVector,result),result},Transform.vectorToLocalFrame=function(position,quaternion,worldVector,result){return void 0===result&&(result=new Vec3),quaternion.w*=-1,quaternion.vmult(worldVector,result),quaternion.w*=-1,result},Transform}(),tmpQuat=new Quaternion,ConvexPolyhedron=function(_Shape){function ConvexPolyhedron(props){var _this;void 0===props&&(props={});var _props=props,_props$vertices=_props.vertices,vertices=void 0===_props$vertices?[]:_props$vertices,_props$faces=_props.faces,faces=void 0===_props$faces?[]:_props$faces,_props$normals=_props.normals,normals=void 0===_props$normals?[]:_props$normals,axes=_props.axes,boundingSphereRadius=_props.boundingSphereRadius;return(_this=_Shape.call(this,{type:Shape.types.CONVEXPOLYHEDRON})||this).vertices=vertices,_this.faces=faces,_this.faceNormals=normals,0===_this.faceNormals.length&&_this.computeNormals(),boundingSphereRadius?_this.boundingSphereRadius=boundingSphereRadius:_this.updateBoundingSphereRadius(),_this.worldVertices=[],_this.worldVerticesNeedsUpdate=!0,_this.worldFaceNormals=[],_this.worldFaceNormalsNeedsUpdate=!0,_this.uniqueAxes=axes?axes.slice():null,_this.uniqueEdges=[],_this.computeEdges(),_this}_inheritsLoose(ConvexPolyhedron,_Shape);var _proto=ConvexPolyhedron.prototype;return _proto.computeEdges=function(){var faces=this.faces,vertices=this.vertices,edges=this.uniqueEdges;edges.length=0;for(var edge=new Vec3,i=0;i!==faces.length;i++)for(var face=faces[i],numVertices=face.length,j=0;j!==numVertices;j++){var k=(j+1)%numVertices;vertices[face[j]].vsub(vertices[face[k]],edge),edge.normalize();for(var found=!1,p=0;p!==edges.length;p++)if(edges[p].almostEquals(edge)||edges[p].almostEquals(edge)){found=!0;break}found||edges.push(edge.clone())}},_proto.computeNormals=function(){this.faceNormals.length=this.faces.length;for(var i=0;idmax&&(dmax=d,closestFaceB=face)}for(var worldVertsB1=[],i=0;i=0&&this.clipFaceAgainstHull(separatingNormal,posA,quatA,worldVertsB1,minDist,maxDist,result)},_proto.findSeparatingAxis=function(hullB,posA,quatA,posB,quatB,target,faceListA,faceListB){var faceANormalWS3=new Vec3,Worldnormal1=new Vec3,deltaC=new Vec3,worldEdge0=new Vec3,worldEdge1=new Vec3,Cross=new Vec3,dmin=Number.MAX_VALUE;if(this.uniqueAxes)for(var _i=0;_i!==this.uniqueAxes.length;_i++){quatA.vmult(this.uniqueAxes[_i],faceANormalWS3);var _d=this.testSepAxis(faceANormalWS3,hullB,posA,quatA,posB,quatB);if(!1===_d)return!1;_d0&&target.negate(target),!0},_proto.testSepAxis=function(axis,hullB,posA,quatA,posB,quatB){ConvexPolyhedron.project(this,axis,posA,quatA,maxminA),ConvexPolyhedron.project(hullB,axis,posB,quatB,maxminB);var maxA=maxminA[0],minA=maxminA[1],maxB=maxminB[0],minB=maxminB[1];if(maxA0?1/mass:0,_this.material=options.material||null,_this.linearDamping="number"==typeof options.linearDamping?options.linearDamping:.01,_this.type=mass<=0?Body.STATIC:Body.DYNAMIC,typeof options.type==typeof Body.STATIC&&(_this.type=options.type),_this.allowSleep=void 0===options.allowSleep||options.allowSleep,_this.sleepState=0,_this.sleepSpeedLimit=void 0!==options.sleepSpeedLimit?options.sleepSpeedLimit:.1,_this.sleepTimeLimit=void 0!==options.sleepTimeLimit?options.sleepTimeLimit:1,_this.timeLastSleepy=0,_this.wakeUpAfterNarrowphase=!1,_this.torque=new Vec3,_this.quaternion=new Quaternion,_this.initQuaternion=new Quaternion,_this.previousQuaternion=new Quaternion,_this.interpolatedQuaternion=new Quaternion,options.quaternion&&(_this.quaternion.copy(options.quaternion),_this.initQuaternion.copy(options.quaternion),_this.previousQuaternion.copy(options.quaternion),_this.interpolatedQuaternion.copy(options.quaternion)),_this.angularVelocity=new Vec3,options.angularVelocity&&_this.angularVelocity.copy(options.angularVelocity),_this.initAngularVelocity=new Vec3,_this.shapes=[],_this.shapeOffsets=[],_this.shapeOrientations=[],_this.inertia=new Vec3,_this.invInertia=new Vec3,_this.invInertiaWorld=new Mat3,_this.invMassSolve=0,_this.invInertiaSolve=new Vec3,_this.invInertiaWorldSolve=new Mat3,_this.fixedRotation=void 0!==options.fixedRotation&&options.fixedRotation,_this.angularDamping=void 0!==options.angularDamping?options.angularDamping:.01,_this.linearFactor=new Vec3(1,1,1),options.linearFactor&&_this.linearFactor.copy(options.linearFactor),_this.angularFactor=new Vec3(1,1,1),options.angularFactor&&_this.angularFactor.copy(options.angularFactor),_this.aabb=new AABB,_this.aabbNeedsUpdate=!0,_this.boundingRadius=0,_this.wlambda=new Vec3,options.shape&&_this.addShape(options.shape),_this.updateMassProperties(),_this}_inheritsLoose(Body,_EventTarget);var _proto=Body.prototype;return _proto.wakeUp=function(){var prevState=this.sleepState;this.sleepState=0,this.wakeUpAfterNarrowphase=!1,prevState===Body.SLEEPING&&this.dispatchEvent(Body.wakeupEvent)},_proto.sleep=function(){this.sleepState=Body.SLEEPING,this.velocity.set(0,0,0),this.angularVelocity.set(0,0,0),this.wakeUpAfterNarrowphase=!1},_proto.sleepTick=function(time){if(this.allowSleep){var sleepState=this.sleepState,speedSquared=this.velocity.lengthSquared()+this.angularVelocity.lengthSquared(),speedLimitSquared=Math.pow(this.sleepSpeedLimit,2);sleepState===Body.AWAKE&&speedSquaredspeedLimitSquared?this.wakeUp():sleepState===Body.SLEEPY&&time-this.timeLastSleepy>this.sleepTimeLimit&&(this.sleep(),this.dispatchEvent(Body.sleepEvent))}},_proto.updateSolveMassProperties=function(){this.sleepState===Body.SLEEPING||this.type===Body.KINEMATIC?(this.invMassSolve=0,this.invInertiaSolve.setZero(),this.invInertiaWorldSolve.setZero()):(this.invMassSolve=this.invMass,this.invInertiaSolve.copy(this.invInertia),this.invInertiaWorldSolve.copy(this.invInertiaWorld))},_proto.pointToLocalFrame=function(worldPoint,result){return void 0===result&&(result=new Vec3),worldPoint.vsub(this.position,result),this.quaternion.conjugate().vmult(result,result),result},_proto.vectorToLocalFrame=function(worldVector,result){return void 0===result&&(result=new Vec3),this.quaternion.conjugate().vmult(worldVector,result),result},_proto.pointToWorldFrame=function(localPoint,result){return void 0===result&&(result=new Vec3),this.quaternion.vmult(localPoint,result),result.vadd(this.position,result),result},_proto.vectorToWorldFrame=function(localVector,result){return void 0===result&&(result=new Vec3),this.quaternion.vmult(localVector,result),result},_proto.addShape=function(shape,_offset,_orientation){var offset=new Vec3,orientation=new Quaternion;return _offset&&offset.copy(_offset),_orientation&&orientation.copy(_orientation),this.shapes.push(shape),this.shapeOffsets.push(offset),this.shapeOrientations.push(orientation),this.updateMassProperties(),this.updateBoundingRadius(),this.aabbNeedsUpdate=!0,shape.body=this,this},_proto.updateBoundingRadius=function(){for(var shapes=this.shapes,shapeOffsets=this.shapeOffsets,N=shapes.length,radius=0,i=0;i!==N;i++){var shape=shapes[i];shape.updateBoundingSphereRadius();var offset=shapeOffsets[i].length(),r=shape.boundingSphereRadius;offset+r>radius&&(radius=offset+r)}this.boundingRadius=radius},_proto.computeAABB=function(){for(var shapes=this.shapes,shapeOffsets=this.shapeOffsets,shapeOrientations=this.shapeOrientations,N=shapes.length,offset=tmpVec,orientation=tmpQuat$1,bodyQuat=this.quaternion,aabb=this.aabb,shapeAABB=computeAABB_shapeAABB,i=0;i!==N;i++){var shape=shapes[i];bodyQuat.vmult(shapeOffsets[i],offset),offset.vadd(this.position,offset),bodyQuat.mult(shapeOrientations[i],orientation),shape.calculateWorldAABB(offset,orientation,shapeAABB.lowerBound,shapeAABB.upperBound),0===i?aabb.copy(shapeAABB):aabb.extend(shapeAABB)}this.aabbNeedsUpdate=!1},_proto.updateInertiaWorld=function(force){var I=this.invInertia;if(I.x!==I.y||I.y!==I.z||force){var m1=uiw_m1,m2=uiw_m2;m1.setRotationFromQuaternion(this.quaternion),m1.transpose(m2),m1.scale(I,m1),m1.mmult(m2,this.invInertiaWorld)}else;},_proto.applyForce=function(force,relativePoint){if(this.type===Body.DYNAMIC){var rotForce=Body_applyForce_rotForce;relativePoint.cross(force,rotForce),this.force.vadd(force,this.force),this.torque.vadd(rotForce,this.torque)}},_proto.applyLocalForce=function(localForce,localPoint){if(this.type===Body.DYNAMIC){var worldForce=Body_applyLocalForce_worldForce,relativePointWorld=Body_applyLocalForce_relativePointWorld;this.vectorToWorldFrame(localForce,worldForce),this.vectorToWorldFrame(localPoint,relativePointWorld),this.applyForce(worldForce,relativePointWorld)}},_proto.applyImpulse=function(impulse,relativePoint){if(this.type===Body.DYNAMIC){var r=relativePoint,velo=Body_applyImpulse_velo;velo.copy(impulse),velo.scale(this.invMass,velo),this.velocity.vadd(velo,this.velocity);var rotVelo=Body_applyImpulse_rotVelo;r.cross(impulse,rotVelo),this.invInertiaWorld.vmult(rotVelo,rotVelo),this.angularVelocity.vadd(rotVelo,this.angularVelocity)}},_proto.applyLocalImpulse=function(localImpulse,localPoint){if(this.type===Body.DYNAMIC){var worldImpulse=Body_applyLocalImpulse_worldImpulse,relativePointWorld=Body_applyLocalImpulse_relativePoint;this.vectorToWorldFrame(localImpulse,worldImpulse),this.vectorToWorldFrame(localPoint,relativePointWorld),this.applyImpulse(worldImpulse,relativePointWorld)}},_proto.updateMassProperties=function(){var halfExtents=Body_updateMassProperties_halfExtents;this.invMass=this.mass>0?1/this.mass:0;var I=this.inertia,fixed=this.fixedRotation;this.computeAABB(),halfExtents.set((this.aabb.upperBound.x-this.aabb.lowerBound.x)/2,(this.aabb.upperBound.y-this.aabb.lowerBound.y)/2,(this.aabb.upperBound.z-this.aabb.lowerBound.z)/2),Box.calculateInertia(halfExtents,this.mass,I),this.invInertia.set(I.x>0&&!fixed?1/I.x:0,I.y>0&&!fixed?1/I.y:0,I.z>0&&!fixed?1/I.z:0),this.updateInertiaWorld(!0)},_proto.getVelocityAtWorldPoint=function(worldPoint,result){var r=new Vec3;return worldPoint.vsub(this.position,r),this.angularVelocity.cross(r,result),this.velocity.vadd(result,result),result},_proto.integrate=function(dt,quatNormalize,quatNormalizeFast){if(this.previousPosition.copy(this.position),this.previousQuaternion.copy(this.quaternion),(this.type===Body.DYNAMIC||this.type===Body.KINEMATIC)&&this.sleepState!==Body.SLEEPING){var velo=this.velocity,angularVelo=this.angularVelocity,pos=this.position,force=this.force,torque=this.torque,quat=this.quaternion,invMass=this.invMass,invInertia=this.invInertiaWorld,linearFactor=this.linearFactor,iMdt=invMass*dt;velo.x+=force.x*iMdt*linearFactor.x,velo.y+=force.y*iMdt*linearFactor.y,velo.z+=force.z*iMdt*linearFactor.z;var e=invInertia.elements,angularFactor=this.angularFactor,tx=torque.x*angularFactor.x,ty=torque.y*angularFactor.y,tz=torque.z*angularFactor.z;angularVelo.x+=dt*(e[0]*tx+e[1]*ty+e[2]*tz),angularVelo.y+=dt*(e[3]*tx+e[4]*ty+e[5]*tz),angularVelo.z+=dt*(e[6]*tx+e[7]*ty+e[8]*tz),pos.x+=velo.x*dt,pos.y+=velo.y*dt,pos.z+=velo.z*dt,quat.integrate(this.angularVelocity,dt,this.angularFactor,quat),quatNormalize&&(quatNormalizeFast?quat.normalizeFast():quat.normalize()),this.aabbNeedsUpdate=!0,this.updateInertiaWorld()}},Body}(EventTarget);Body.COLLIDE_EVENT_NAME="collide",Body.DYNAMIC=1,Body.STATIC=2,Body.KINEMATIC=4,Body.AWAKE=BODY_SLEEP_STATES.AWAKE,Body.SLEEPY=BODY_SLEEP_STATES.SLEEPY,Body.SLEEPING=BODY_SLEEP_STATES.SLEEPING,Body.idCounter=0,Body.wakeupEvent={type:"wakeup"},Body.sleepyEvent={type:"sleepy"},Body.sleepEvent={type:"sleep"};var tmpVec=new Vec3,tmpQuat$1=new Quaternion,computeAABB_shapeAABB=new AABB,uiw_m1=new Mat3,uiw_m2=new Mat3,Body_applyForce_rotForce=(new Mat3,new Vec3),Body_applyLocalForce_worldForce=new Vec3,Body_applyLocalForce_relativePointWorld=new Vec3,Body_applyImpulse_velo=new Vec3,Body_applyImpulse_rotVelo=new Vec3,Body_applyLocalImpulse_worldImpulse=new Vec3,Body_applyLocalImpulse_relativePoint=new Vec3,Body_updateMassProperties_halfExtents=new Vec3,Broadphase=function(){function Broadphase(){this.world=null,this.useBoundingBoxes=!1,this.dirty=!0}var _proto=Broadphase.prototype;return _proto.collisionPairs=function(world,p1,p2){throw new Error("collisionPairs not implemented for this BroadPhase class!")},_proto.needBroadphaseCollision=function(bodyA,bodyB){return 0!=(bodyA.collisionFilterGroup&bodyB.collisionFilterMask)&&0!=(bodyB.collisionFilterGroup&bodyA.collisionFilterMask)&&(0==(bodyA.type&Body.STATIC)&&bodyA.sleepState!==Body.SLEEPING||0==(bodyB.type&Body.STATIC)&&bodyB.sleepState!==Body.SLEEPING)},_proto.intersectionTest=function(bodyA,bodyB,pairs1,pairs2){this.useBoundingBoxes?this.doBoundingBoxBroadphase(bodyA,bodyB,pairs1,pairs2):this.doBoundingSphereBroadphase(bodyA,bodyB,pairs1,pairs2)},_proto.doBoundingSphereBroadphase=function(bodyA,bodyB,pairs1,pairs2){var r=Broadphase_collisionPairs_r;bodyB.position.vsub(bodyA.position,r);var boundingRadiusSum2=Math.pow(bodyA.boundingRadius+bodyB.boundingRadius,2);r.lengthSquared()dist.lengthSquared()};var GridBroadphase=function(_Broadphase){function GridBroadphase(aabbMin,aabbMax,nx,ny,nz){var _this;void 0===aabbMin&&(aabbMin=new Vec3(100,100,100)),void 0===aabbMax&&(aabbMax=new Vec3(-100,-100,-100)),void 0===nx&&(nx=10),void 0===ny&&(ny=10),void 0===nz&&(nz=10),(_this=_Broadphase.call(this)||this).nx=nx,_this.ny=ny,_this.nz=nz,_this.aabbMin=aabbMin,_this.aabbMax=aabbMax;var nbins=_this.nx*_this.ny*_this.nz;if(nbins<=0)throw"GridBroadphase: Each dimension's n must be >0";_this.bins=[],_this.binLengths=[],_this.bins.length=nbins,_this.binLengths.length=nbins;for(var i=0;i=nx&&(xoff0=nx-1),yoff0<0?yoff0=0:yoff0>=ny&&(yoff0=ny-1),zoff0<0?zoff0=0:zoff0>=nz&&(zoff0=nz-1),xoff1<0?xoff1=0:xoff1>=nx&&(xoff1=nx-1),yoff1<0?yoff1=0:yoff1>=ny&&(yoff1=ny-1),zoff1<0?zoff1=0:zoff1>=nz&&(zoff1=nz-1),yoff0*=ystep,zoff0*=zstep,xoff1*=xstep,yoff1*=ystep,zoff1*=zstep;for(var xoff=xoff0*=xstep;xoff<=xoff1;xoff+=xstep)for(var yoff=yoff0;yoff<=yoff1;yoff+=ystep)for(var zoff=zoff0;zoff<=zoff1;zoff+=zstep){var idx=xoff+yoff+zoff;bins[idx][binLengths[idx]++]=bi}}for(var _i=0;_i!==N;_i++){var bi=bodies[_i],si=bi.shapes[0];switch(si.type){case SPHERE:var shape=si,x=bi.position.x,y=bi.position.y,z=bi.position.z,r=shape.radius;addBoxToBins(x-r,y-r,z-r,x+r,y+r,z+r,bi);break;case PLANE:var _shape=si;_shape.worldNormalNeedsUpdate&&_shape.computeWorldNormal(bi.quaternion);var planeNormal=_shape.worldNormal,xreset=xmin+.5*binsizeX-bi.position.x,yreset=ymin+.5*binsizeY-bi.position.y,zreset=zmin+.5*binsizeZ-bi.position.z,d=GridBroadphase_collisionPairs_d;d.set(xreset,yreset,zreset);for(var xi=0,xoff=0;xi!==nx;xi++,xoff+=xstep,d.y=yreset,d.x+=binsizeX)for(var yi=0,yoff=0;yi!==ny;yi++,yoff+=ystep,d.z=zreset,d.y+=binsizeY)for(var zi=0,zoff=0;zi!==nz;zi++,zoff+=zstep,d.z+=binsizeZ)if(d.dot(planeNormal)1)for(var bin=bins[_i2],_xi=0;_xi!==binLength;_xi++)for(var _bi=bin[_xi],_yi=0;_yi!==_xi;_yi++){var bj=bin[_yi];this.needBroadphaseCollision(_bi,bj)&&this.intersectionTest(_bi,bj,pairs1,pairs2)}}this.makePairsUnique(pairs1,pairs2)},GridBroadphase}(Broadphase),GridBroadphase_collisionPairs_d=new Vec3,NaiveBroadphase=(new Vec3,function(_Broadphase){function NaiveBroadphase(){return _Broadphase.call(this)||this}_inheritsLoose(NaiveBroadphase,_Broadphase);var _proto=NaiveBroadphase.prototype;return _proto.collisionPairs=function(world,pairs1,pairs2){for(var bi,bj,bodies=world.bodies,n=bodies.length,i=0;i!==n;i++)for(var j=0;j!==i;j++)bi=bodies[i],bj=bodies[j],this.needBroadphaseCollision(bi,bj)&&this.intersectionTest(bi,bj,pairs1,pairs2)},_proto.aabbQuery=function(world,aabb,result){void 0===result&&(result=[]);for(var i=0;ishape.boundingSphereRadius)){var intersectMethod=this[shape.type];intersectMethod&&intersectMethod.call(this,shape,quat,position,body,shape)}},_proto._intersectBox=function(box,quat,position,body,reportedShape){return this._intersectConvex(box.convexPolyhedronRepresentation,quat,position,body,reportedShape)},_proto._intersectPlane=function(shape,quat,position,body,reportedShape){var from=this.from,to=this.to,direction=this.direction,worldNormal=new Vec3(0,0,1);quat.vmult(worldNormal,worldNormal);var len=new Vec3;from.vsub(position,len);var planeToFrom=len.dot(worldNormal);if(to.vsub(position,len),!(planeToFrom*len.dot(worldNormal)>0||from.distanceTo(to)=0&&d1<=1&&(from.lerp(to,d1,intersectionPoint),intersectionPoint.vsub(position,normal),normal.normalize(),this.reportIntersection(normal,intersectionPoint,reportedShape,body,-1)),this.result.shouldStop)return;d2>=0&&d2<=1&&(from.lerp(to,d2,intersectionPoint),intersectionPoint.vsub(position,normal),normal.normalize(),this.reportIntersection(normal,intersectionPoint,reportedShape,body,-1))}},_proto._intersectConvex=function(shape,quat,position,body,reportedShape,options){for(var normal=intersectConvex_normal,vector=intersectConvex_vector,faceList=options&&options.faceList||null,faces=shape.faces,vertices=shape.vertices,normals=shape.faceNormals,direction=this.direction,from=this.from,to=this.to,fromToDistance=from.distanceTo(to),Nfaces=faceList?faceList.length:faces.length,result=this.result,j=0;!result.shouldStop&&jfromToDistance||this.reportIntersection(normal,intersectPoint,reportedShape,body,fi)}}}}},_proto._intersectTrimesh=function(mesh,quat,position,body,reportedShape,options){var normal=intersectTrimesh_normal,triangles=intersectTrimesh_triangles,treeTransform=intersectTrimesh_treeTransform,vector=intersectConvex_vector,localDirection=intersectTrimesh_localDirection,localFrom=intersectTrimesh_localFrom,localTo=intersectTrimesh_localTo,worldIntersectPoint=intersectTrimesh_worldIntersectPoint,worldNormal=intersectTrimesh_worldNormal,indices=(options&&options.faceList,mesh.indices),from=(mesh.vertices,this.from),to=this.to,direction=this.direction;treeTransform.position.copy(position),treeTransform.quaternion.copy(quat),Transform.vectorToLocalFrame(position,quat,direction,localDirection),Transform.pointToLocalFrame(position,quat,from,localFrom),Transform.pointToLocalFrame(position,quat,to,localTo),localTo.x*=mesh.scale.x,localTo.y*=mesh.scale.y,localTo.z*=mesh.scale.z,localFrom.x*=mesh.scale.x,localFrom.y*=mesh.scale.y,localFrom.z*=mesh.scale.z,localTo.vsub(localFrom,localDirection),localDirection.normalize();var fromToDistanceSquared=localFrom.distanceSquared(localTo);mesh.tree.rayQuery(this,treeTransform,triangles);for(var i=0,N=triangles.length;!this.result.shouldStop&&i!==N;i++){var trianglesIndex=triangles[i];mesh.getNormal(trianglesIndex,normal),mesh.getVertex(indices[3*trianglesIndex],a),a.vsub(localFrom,vector);var dot=localDirection.dot(normal),scalar=normal.dot(vector)/dot;if(!(scalar<0)){localDirection.scale(scalar,intersectPoint),intersectPoint.vadd(localFrom,intersectPoint),mesh.getVertex(indices[3*trianglesIndex+1],b),mesh.getVertex(indices[3*trianglesIndex+2],c);var squaredDistance=intersectPoint.distanceSquared(localFrom);!pointInTriangle(intersectPoint,b,a,c)&&!pointInTriangle(intersectPoint,a,b,c)||squaredDistance>fromToDistanceSquared||(Transform.vectorToWorldFrame(quat,normal,worldNormal),Transform.pointToWorldFrame(position,quat,intersectPoint,worldIntersectPoint),this.reportIntersection(worldNormal,worldIntersectPoint,reportedShape,body,trianglesIndex))}}triangles.length=0},_proto.reportIntersection=function(normal,hitPointWorld,shape,body,hitFaceIndex){var from=this.from,to=this.to,distance=from.distanceTo(hitPointWorld),result=this.result;if(!(this.skipBackfaces&&normal.dot(this.direction)>0))switch(result.hitFaceIndex=void 0!==hitFaceIndex?hitFaceIndex:-1,this.mode){case Ray.ALL:this.hasHit=!0,result.set(from,to,normal,hitPointWorld,shape,body,distance),result.hasHit=!0,this.callback(result);break;case Ray.CLOSEST:(distance=0&&(v=dot00*dot12-dot01*dot02)>=0&&u+vvarianceY?varianceX>varianceZ?0:2:varianceY>varianceZ?1:2},_proto.aabbQuery=function(world,aabb,result){void 0===result&&(result=[]),this.dirty&&(this.sortList(),this.dirty=!1);var axisIndex=this.axisIndex,axis="x";1===axisIndex&&(axis="y"),2===axisIndex&&(axis="z");for(var axisList=this.axisList,i=(aabb.lowerBound[axis],aabb.upperBound[axis],0);i=0&&!(a[j].aabb.lowerBound.x<=v.aabb.lowerBound.x);j--)a[j+1]=a[j];a[j+1]=v}return a},SAPBroadphase.insertionSortY=function(a){for(var i=1,l=a.length;i=0&&!(a[j].aabb.lowerBound.y<=v.aabb.lowerBound.y);j--)a[j+1]=a[j];a[j+1]=v}return a},SAPBroadphase.insertionSortZ=function(a){for(var i=1,l=a.length;i=0&&!(a[j].aabb.lowerBound.z<=v.aabb.lowerBound.z);j--)a[j+1]=a[j];a[j+1]=v}return a},SAPBroadphase.checkBounds=function(bi,bj,axisIndex){var biPos,bjPos;0===axisIndex?(biPos=bi.position.x,bjPos=bj.position.x):1===axisIndex?(biPos=bi.position.y,bjPos=bj.position.y):2===axisIndex&&(biPos=bi.position.z,bjPos=bj.position.z);var ri=bi.boundingRadius;return bjPos-bj.boundingRadius=-.1)this.suspensionRelativeVelocity=0,this.clippedInvContactDotSuspension=10;else{var inv=-1/project;this.suspensionRelativeVelocity=projVel*inv,this.clippedInvContactDotSuspension=inv}}else raycastResult.suspensionLength=this.suspensionRestLength,this.suspensionRelativeVelocity=0,raycastResult.directionWorld.scale(-1,raycastResult.hitNormalWorld),this.clippedInvContactDotSuspension=1},WheelInfo}(),chassis_velocity_at_contactPoint=new Vec3,relpos=new Vec3,RaycastVehicle=function(){function RaycastVehicle(options){this.chassisBody=options.chassisBody,this.wheelInfos=[],this.sliding=!1,this.world=null,this.indexRightAxis=void 0!==options.indexRightAxis?options.indexRightAxis:1,this.indexForwardAxis=void 0!==options.indexForwardAxis?options.indexForwardAxis:0,this.indexUpAxis=void 0!==options.indexUpAxis?options.indexUpAxis:2,this.constraints=[],this.preStepCallback=function(){},this.currentVehicleSpeedKmHour=0}var _proto=RaycastVehicle.prototype;return _proto.addWheel=function(options){void 0===options&&(options={});var info=new WheelInfo(options),index=this.wheelInfos.length;return this.wheelInfos.push(info),index},_proto.setSteeringValue=function(value,wheelIndex){this.wheelInfos[wheelIndex].steering=value},_proto.applyEngineForce=function(value,wheelIndex){this.wheelInfos[wheelIndex].engineForce=value},_proto.setBrake=function(brake,wheelIndex){this.wheelInfos[wheelIndex].brake=brake},_proto.addToWorld=function(world){this.constraints;world.addBody(this.chassisBody);var that=this;this.preStepCallback=function(){that.updateVehicle(world.dt)},world.addEventListener("preStep",this.preStepCallback),this.world=world},_proto.getVehicleAxisWorld=function(axisIndex,result){result.set(0===axisIndex?1:0,1===axisIndex?1:0,2===axisIndex?1:0),this.chassisBody.vectorToWorldFrame(result,result)},_proto.updateVehicle=function(timeStep){for(var wheelInfos=this.wheelInfos,numWheels=wheelInfos.length,chassisBody=this.chassisBody,i=0;iwheel.maxSuspensionForce&&(suspensionForce=wheel.maxSuspensionForce),wheel.raycastResult.hitNormalWorld.scale(suspensionForce*timeStep,impulse),wheel.raycastResult.hitPointWorld.vsub(chassisBody.position,relpos),chassisBody.applyImpulse(impulse,relpos)}this.updateFriction(timeStep);for(var hitNormalWorldScaledWithProj=new Vec3,fwd=new Vec3,vel=new Vec3,_i3=0;_i30?1:-1)*_wheel.customSlidingRotationalSpeed*timeStep),Math.abs(_wheel.brake)>Math.abs(_wheel.engineForce)&&(_wheel.deltaRotation=0),_wheel.rotation+=_wheel.deltaRotation,_wheel.deltaRotation*=.99}},_proto.updateSuspension=function(deltaTime){for(var chassisMass=this.chassisBody.mass,wheelInfos=this.wheelInfos,numWheels=wheelInfos.length,w_it=0;w_itmaxSuspensionLength&&(wheel.suspensionLength=maxSuspensionLength,wheel.raycastResult.reset());var denominator=wheel.raycastResult.hitNormalWorld.dot(wheel.directionWorld),chassis_velocity_at_contactPoint=new Vec3;chassisBody.getVelocityAtWorldPoint(wheel.raycastResult.hitPointWorld,chassis_velocity_at_contactPoint);var projVel=wheel.raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint);if(denominator>=-.1)wheel.suspensionRelativeVelocity=0,wheel.clippedInvContactDotSuspension=10;else{var inv=-1/denominator;wheel.suspensionRelativeVelocity=projVel*inv,wheel.clippedInvContactDotSuspension=inv}}else wheel.suspensionLength=wheel.suspensionRestLength+0*wheel.maxSuspensionTravel,wheel.suspensionRelativeVelocity=0,wheel.directionWorld.scale(-1,wheel.raycastResult.hitNormalWorld),wheel.clippedInvContactDotSuspension=1;return depth},_proto.updateWheelTransformWorld=function(wheel){wheel.isInContact=!1;var chassisBody=this.chassisBody;chassisBody.pointToWorldFrame(wheel.chassisConnectionPointLocal,wheel.chassisConnectionPointWorld),chassisBody.vectorToWorldFrame(wheel.directionLocal,wheel.directionWorld),chassisBody.vectorToWorldFrame(wheel.axleLocal,wheel.axleWorld)},_proto.updateWheelTransform=function(wheelIndex){var up=tmpVec4,right=tmpVec5,fwd=tmpVec6,wheel=this.wheelInfos[wheelIndex];this.updateWheelTransformWorld(wheel),wheel.directionLocal.scale(-1,up),right.copy(wheel.axleLocal),up.cross(right,fwd),fwd.normalize(),right.normalize();var steering=wheel.steering,steeringOrn=new Quaternion;steeringOrn.setFromAxisAngle(up,steering);var rotatingOrn=new Quaternion;rotatingOrn.setFromAxisAngle(right,wheel.rotation);var q=wheel.worldTransform.quaternion;this.chassisBody.quaternion.mult(steeringOrn,q),q.mult(rotatingOrn,q),q.normalize();var p=wheel.worldTransform.position;p.copy(wheel.directionWorld),p.scale(wheel.suspensionLength,p),p.vadd(wheel.chassisConnectionPointWorld,p)},_proto.getWheelTransformWorld=function(wheelIndex){return this.wheelInfos[wheelIndex].worldTransform},_proto.updateFriction=function(timeStep){for(var surfNormalWS_scaled_proj=updateFriction_surfNormalWS_scaled_proj,wheelInfos=this.wheelInfos,numWheels=wheelInfos.length,chassisBody=this.chassisBody,forwardWS=updateFriction_forwardWS,axle=updateFriction_axle,i=0;imaximpSquared){this.sliding=!0,_wheel3.sliding=!0;var _factor=maximp/Math.sqrt(impulseSquared);_wheel3.skidInfo*=_factor}}}if(this.sliding)for(var _i6=0;_i61.1)return 0;var vel1=resolveSingleBilateral_vel1,vel2=resolveSingleBilateral_vel2,vel=resolveSingleBilateral_vel;body1.getVelocityAtWorldPoint(pos1,vel1),body2.getVelocityAtWorldPoint(pos2,vel2),vel1.vsub(vel2,vel);return-.2*normal.dot(vel)*(1/(body1.invMass+body2.invMass))}var Sphere=function(_Shape){function Sphere(radius){var _this;if((_this=_Shape.call(this,{type:Shape.types.SPHERE})||this).radius=void 0!==radius?radius:1,_this.radius<0)throw new Error("The sphere radius cannot be negative.");return _this.updateBoundingSphereRadius(),_this}_inheritsLoose(Sphere,_Shape);var _proto=Sphere.prototype;return _proto.calculateLocalInertia=function(mass,target){void 0===target&&(target=new Vec3);var I=2*mass*this.radius*this.radius/5;return target.x=I,target.y=I,target.z=I,target},_proto.volume=function(){return 4*Math.PI*Math.pow(this.radius,3)/3},_proto.updateBoundingSphereRadius=function(){this.boundingSphereRadius=this.radius},_proto.calculateWorldAABB=function(pos,quat,min,max){for(var r=this.radius,axes=["x","y","z"],i=0;ithis.particles.length&&this.neighbors.pop())},_proto.getNeighbors=function(particle,neighbors){for(var N=this.particles.length,id=particle.id,R2=this.smoothingRadius*this.smoothingRadius,dist=SPHSystem_getNeighbors_dist,i=0;i!==N;i++){var p=this.particles[i];p.position.vsub(particle.position,dist),id!==p.id&&dist.lengthSquared()maxValue&&(maxValue=v)}this.maxValue=maxValue},_proto.setHeightValueAtIndex=function(xi,yi,value){this.data[xi][yi]=value,this.clearCachedConvexTrianglePillar(xi,yi,!1),xi>0&&(this.clearCachedConvexTrianglePillar(xi-1,yi,!0),this.clearCachedConvexTrianglePillar(xi-1,yi,!1)),yi>0&&(this.clearCachedConvexTrianglePillar(xi,yi-1,!0),this.clearCachedConvexTrianglePillar(xi,yi-1,!1)),yi>0&&xi>0&&this.clearCachedConvexTrianglePillar(xi-1,yi-1,!0)},_proto.getRectMinMax=function(iMinX,iMinY,iMaxX,iMaxY,result){void 0===result&&(result=[]);for(var data=this.data,max=this.minValue,i=iMinX;i<=iMaxX;i++)for(var j=iMinY;j<=iMaxY;j++){var height=data[i][j];height>max&&(max=height)}result[0]=this.minValue,result[1]=max},_proto.getIndexOfPosition=function(x,y,result,clamp){var w=this.elementSize,data=this.data,xi=Math.floor(x/w),yi=Math.floor(y/w);return result[0]=xi,result[1]=yi,clamp&&(xi<0&&(xi=0),yi<0&&(yi=0),xi>=data.length-1&&(xi=data.length-1),yi>=data[0].length-1&&(yi=data[0].length-1)),!(xi<0||yi<0||xi>=data.length-1||yi>=data[0].length-1)},_proto.getTriangleAt=function(x,y,edgeClamp,a,b,c){var idx=getHeightAt_idx;this.getIndexOfPosition(x,y,idx,edgeClamp);var xi=idx[0],yi=idx[1],data=this.data;edgeClamp&&(xi=Math.min(data.length-2,Math.max(0,xi)),yi=Math.min(data[0].length-2,Math.max(0,yi)));var elementSize=this.elementSize,upper=Math.pow(x/elementSize-xi,2)+Math.pow(y/elementSize-yi,2)>Math.pow(x/elementSize-(xi+1),2)+Math.pow(y/elementSize-(yi+1),2);return this.getTriangle(xi,yi,upper,a,b,c),upper},_proto.getNormalAt=function(x,y,edgeClamp,result){var a=getNormalAt_a,b=getNormalAt_b,c=getNormalAt_c,e0=getNormalAt_e0,e1=getNormalAt_e1;this.getTriangleAt(x,y,edgeClamp,a,b,c),b.vsub(a,e0),c.vsub(a,e1),e0.cross(e1,result),result.normalize()},_proto.getAabbAtIndex=function(xi,yi,_ref){var lowerBound=_ref.lowerBound,upperBound=_ref.upperBound,data=this.data,elementSize=this.elementSize;lowerBound.set(xi*elementSize,yi*elementSize,data[xi][yi]),upperBound.set((xi+1)*elementSize,(yi+1)*elementSize,data[xi+1][yi+1])},_proto.getHeightAt=function(x,y,edgeClamp){var data=this.data,a=getHeightAt_a,b=getHeightAt_b,c=getHeightAt_c,idx=getHeightAt_idx;this.getIndexOfPosition(x,y,idx,edgeClamp);var xi=idx[0],yi=idx[1];edgeClamp&&(xi=Math.min(data.length-2,Math.max(0,xi)),yi=Math.min(data[0].length-2,Math.max(0,yi)));var upper=this.getTriangleAt(x,y,edgeClamp,a,b,c);!function(x,y,ax,ay,bx,by,cx,cy,result){result.x=((by-cy)*(x-cx)+(cx-bx)*(y-cy))/((by-cy)*(ax-cx)+(cx-bx)*(ay-cy)),result.y=((cy-ay)*(x-cx)+(ax-cx)*(y-cy))/((by-cy)*(ax-cx)+(cx-bx)*(ay-cy)),result.z=1-result.x-result.y}(x,y,a.x,a.y,b.x,b.y,c.x,c.y,getHeightAt_weights);var w=getHeightAt_weights;return upper?data[xi+1][yi+1]*w.x+data[xi][yi+1]*w.y+data[xi+1][yi]*w.z:data[xi][yi]*w.x+data[xi+1][yi]*w.y+data[xi][yi+1]*w.z},_proto.getCacheConvexTrianglePillarKey=function(xi,yi,getUpperTriangle){return xi+"_"+yi+"_"+(getUpperTriangle?1:0)},_proto.getCachedConvexTrianglePillar=function(xi,yi,getUpperTriangle){return this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi,yi,getUpperTriangle)]},_proto.setCachedConvexTrianglePillar=function(xi,yi,getUpperTriangle,convex,offset){this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi,yi,getUpperTriangle)]={convex:convex,offset:offset}},_proto.clearCachedConvexTrianglePillar=function(xi,yi,getUpperTriangle){delete this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi,yi,getUpperTriangle)]},_proto.getTriangle=function(xi,yi,upper,a,b,c){var data=this.data,elementSize=this.elementSize;upper?(a.set((xi+1)*elementSize,(yi+1)*elementSize,data[xi+1][yi+1]),b.set(xi*elementSize,(yi+1)*elementSize,data[xi][yi+1]),c.set((xi+1)*elementSize,yi*elementSize,data[xi+1][yi])):(a.set(xi*elementSize,yi*elementSize,data[xi][yi]),b.set((xi+1)*elementSize,yi*elementSize,data[xi+1][yi]),c.set(xi*elementSize,(yi+1)*elementSize,data[xi][yi+1]))},_proto.getConvexTrianglePillar=function(xi,yi,getUpperTriangle){var result=this.pillarConvex,offsetResult=this.pillarOffset;if(this.cacheEnabled){var _data=this.getCachedConvexTrianglePillar(xi,yi,getUpperTriangle);if(_data)return this.pillarConvex=_data.convex,void(this.pillarOffset=_data.offset);result=new ConvexPolyhedron,offsetResult=new Vec3,this.pillarConvex=result,this.pillarOffset=offsetResult}var data=this.data,elementSize=this.elementSize,faces=result.faces;result.vertices.length=6;for(var i=0;i<6;i++)result.vertices[i]||(result.vertices[i]=new Vec3);faces.length=5;for(var _i=0;_i<5;_i++)faces[_i]||(faces[_i]=[]);var verts=result.vertices,h=(Math.min(data[xi][yi],data[xi+1][yi],data[xi][yi+1],data[xi+1][yi+1])-this.minValue)/2+this.minValue;getUpperTriangle?(offsetResult.set((xi+.75)*elementSize,(yi+.75)*elementSize,h),verts[0].set(.25*elementSize,.25*elementSize,data[xi+1][yi+1]-h),verts[1].set(-.75*elementSize,.25*elementSize,data[xi][yi+1]-h),verts[2].set(.25*elementSize,-.75*elementSize,data[xi+1][yi]-h),verts[3].set(.25*elementSize,.25*elementSize,-h-1),verts[4].set(-.75*elementSize,.25*elementSize,-h-1),verts[5].set(.25*elementSize,-.75*elementSize,-h-1),faces[0][0]=0,faces[0][1]=1,faces[0][2]=2,faces[1][0]=5,faces[1][1]=4,faces[1][2]=3,faces[2][0]=2,faces[2][1]=5,faces[2][2]=3,faces[2][3]=0,faces[3][0]=3,faces[3][1]=4,faces[3][2]=1,faces[3][3]=0,faces[4][0]=1,faces[4][1]=4,faces[4][2]=5,faces[4][3]=2):(offsetResult.set((xi+.25)*elementSize,(yi+.25)*elementSize,h),verts[0].set(-.25*elementSize,-.25*elementSize,data[xi][yi]-h),verts[1].set(.75*elementSize,-.25*elementSize,data[xi+1][yi]-h),verts[2].set(-.25*elementSize,.75*elementSize,data[xi][yi+1]-h),verts[3].set(-.25*elementSize,-.25*elementSize,-h-1),verts[4].set(.75*elementSize,-.25*elementSize,-h-1),verts[5].set(-.25*elementSize,.75*elementSize,-h-1),faces[0][0]=0,faces[0][1]=1,faces[0][2]=2,faces[1][0]=5,faces[1][1]=4,faces[1][2]=3,faces[2][0]=0,faces[2][1]=2,faces[2][2]=5,faces[2][3]=3,faces[3][0]=1,faces[3][1]=0,faces[3][2]=3,faces[3][3]=4,faces[4][0]=4,faces[4][1]=5,faces[4][2]=2,faces[4][3]=1),result.computeNormals(),result.computeEdges(),result.updateBoundingSphereRadius(),this.setCachedConvexTrianglePillar(xi,yi,getUpperTriangle,result,offsetResult)},_proto.calculateLocalInertia=function(mass,target){return void 0===target&&(target=new Vec3),target.set(0,0,0),target},_proto.volume=function(){return Number.MAX_VALUE},_proto.calculateWorldAABB=function(pos,quat,min,max){min.set(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE),max.set(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE)},_proto.updateBoundingSphereRadius=function(){var data=this.data,s=this.elementSize;this.boundingSphereRadius=new Vec3(data.length*s,data[0].length*s,Math.max(Math.abs(this.maxValue),Math.abs(this.minValue))).length()},_proto.setHeightsFromImage=function(image,scale){var x=scale.x,z=scale.z,y=scale.y,canvas=document.createElement("canvas");canvas.width=image.width,canvas.height=image.height;var context=canvas.getContext("2d");context.drawImage(image,0,0);var imageData=context.getImageData(0,0,image.width,image.height),matrix=this.data;matrix.length=0,this.elementSize=Math.abs(x)/imageData.width;for(var i=0;i=0;i--)this.children[i].removeEmptyNodes(),this.children[i].children.length||this.children[i].data.length||this.children.splice(i,1)},OctreeNode}()),halfDiagonal=new Vec3,tmpAABB$1=new AABB,Trimesh=function(_Shape){function Trimesh(vertices,indices){var _this;return(_this=_Shape.call(this,{type:Shape.types.TRIMESH})||this).vertices=new Float32Array(vertices),_this.indices=new Int16Array(indices),_this.normals=new Float32Array(indices.length),_this.aabb=new AABB,_this.edges=null,_this.scale=new Vec3(1,1,1),_this.tree=new Octree,_this.updateEdges(),_this.updateNormals(),_this.updateAABB(),_this.updateBoundingSphereRadius(),_this.updateTree(),_this}_inheritsLoose(Trimesh,_Shape);var _proto=Trimesh.prototype;return _proto.updateTree=function(){var tree=this.tree;tree.reset(),tree.aabb.copy(this.aabb);var scale=this.scale;tree.aabb.lowerBound.x*=1/scale.x,tree.aabb.lowerBound.y*=1/scale.y,tree.aabb.lowerBound.z*=1/scale.z,tree.aabb.upperBound.x*=1/scale.x,tree.aabb.upperBound.y*=1/scale.y,tree.aabb.upperBound.z*=1/scale.z;for(var triangleAABB=new AABB,a=new Vec3,b=new Vec3,c=new Vec3,points=[a,b,c],i=0;iu.x&&(u.x=v.x),v.yu.y&&(u.y=v.y),v.zu.z&&(u.z=v.z)},_proto.updateAABB=function(){this.computeLocalAABB(this.aabb)},_proto.updateBoundingSphereRadius=function(){for(var max2=0,vertices=this.vertices,v=new Vec3,i=0,N=vertices.length/3;i!==N;i++){this.getVertex(i,v);var norm2=v.lengthSquared();norm2>max2&&(max2=norm2)}this.boundingSphereRadius=Math.sqrt(max2)},_proto.calculateWorldAABB=function(pos,quat,min,max){var frame=calculateWorldAABB_frame,result=calculateWorldAABB_aabb;frame.position=pos,frame.quaternion=quat,this.aabb.toWorldFrame(frame,result),min.copy(result.lowerBound),max.copy(result.upperBound)},_proto.volume=function(){return 4*Math.PI*this.boundingSphereRadius/3},Trimesh}(Shape),computeNormals_n=new Vec3,unscaledAABB=new AABB,getEdgeVector_va=new Vec3,getEdgeVector_vb=new Vec3,cb=new Vec3,ab=new Vec3;Trimesh.computeNormal=function(va,vb,vc,target){vb.vsub(va,ab),vc.vsub(vb,cb),cb.cross(ab,target),target.isZero()||target.normalize()};var va=new Vec3,vb=new Vec3,vc=new Vec3,cli_aabb=new AABB,computeLocalAABB_worldVert=new Vec3,calculateWorldAABB_frame=new Transform,calculateWorldAABB_aabb=new AABB;Trimesh.createTorus=function(radius,tube,radialSegments,tubularSegments,arc){void 0===radius&&(radius=1),void 0===tube&&(tube=.5),void 0===radialSegments&&(radialSegments=8),void 0===tubularSegments&&(tubularSegments=6),void 0===arc&&(arc=2*Math.PI);for(var vertices=[],indices=[],j=0;j<=radialSegments;j++)for(var i=0;i<=tubularSegments;i++){var u=i/tubularSegments*arc,v=j/radialSegments*Math.PI*2,x=(radius+tube*Math.cos(v))*Math.cos(u),y=(radius+tube*Math.cos(v))*Math.sin(u),z=tube*Math.sin(v);vertices.push(x,y,z)}for(var _j=1;_j<=radialSegments;_j++)for(var _i2=1;_i2<=tubularSegments;_i2++){var a=(tubularSegments+1)*_j+_i2-1,b=(tubularSegments+1)*(_j-1)+_i2-1,c=(tubularSegments+1)*(_j-1)+_i2,d=(tubularSegments+1)*_j+_i2;indices.push(a,b,d),indices.push(b,c,d)}return new Trimesh(vertices,indices)};var Solver=function(){function Solver(){this.equations=[]}var _proto=Solver.prototype;return _proto.solve=function(dt,world){return 0},_proto.addEquation=function(eq){eq.enabled&&this.equations.push(eq)},_proto.removeEquation=function(eq){var eqs=this.equations,i=eqs.indexOf(eq);-1!==i&&eqs.splice(i,1)},_proto.removeAllEquations=function(){this.equations.length=0},Solver}(),GSSolver=function(_Solver){function GSSolver(){var _this;return(_this=_Solver.call(this)||this).iterations=10,_this.tolerance=1e-7,_this}return _inheritsLoose(GSSolver,_Solver),GSSolver.prototype.solve=function(dt,world){var B,invC,deltalambda,deltalambdaTot,lambdaj,iter=0,maxIter=this.iterations,tolSquared=this.tolerance*this.tolerance,equations=this.equations,Neq=equations.length,bodies=world.bodies,Nbodies=bodies.length,h=dt;if(0!==Neq)for(var i=0;i!==Nbodies;i++)bodies[i].updateSolveMassProperties();var invCs=GSSolver_solve_invCs,Bs=GSSolver_solve_Bs,lambda=GSSolver_solve_lambda;invCs.length=Neq,Bs.length=Neq,lambda.length=Neq;for(var _i=0;_i!==Neq;_i++){var c=equations[_i];lambda[_i]=0,Bs[_i]=c.computeB(h),invCs[_i]=1/c.computeC()}if(0!==Neq){for(var _i2=0;_i2!==Nbodies;_i2++){var b=bodies[_i2],vlambda=b.vlambda,wlambda=b.wlambda;vlambda.set(0,0,0),wlambda.set(0,0,0)}for(iter=0;iter!==maxIter;iter++){deltalambdaTot=0;for(var j=0;j!==Neq;j++){var _c=equations[j];B=Bs[j],invC=invCs[j],(lambdaj=lambda[j])+(deltalambda=invC*(B-_c.computeGWlambda()-_c.eps*lambdaj))<_c.minForce?deltalambda=_c.minForce-lambdaj:lambdaj+deltalambda>_c.maxForce&&(deltalambda=_c.maxForce-lambdaj),lambda[j]+=deltalambda,deltalambdaTot+=deltalambda>0?deltalambda:-deltalambda,_c.addToWlambda(deltalambda)}if(deltalambdaTot*deltalambdaTotsize;)objects.pop();for(;objects.length=0&&matB.restitution>=0&&(c.restitution=matA.restitution*matB.restitution),c.si=overrideShapeA||si,c.sj=overrideShapeB||sj,c},_proto.createFrictionEquationsFromContact=function(contactEquation,outArray){var bodyA=contactEquation.bi,bodyB=contactEquation.bj,shapeA=contactEquation.si,shapeB=contactEquation.sj,world=this.world,cm=this.currentContactMaterial,friction=cm.friction,matA=shapeA.material||bodyA.material,matB=shapeB.material||bodyB.material;if(matA&&matB&&matA.friction>=0&&matB.friction>=0&&(friction=matA.friction*matB.friction),friction>0){var mug=friction*world.gravity.length(),reducedMass=bodyA.invMass+bodyB.invMass;reducedMass>0&&(reducedMass=1/reducedMass);var pool=this.frictionEquationPool,c1=pool.length?pool.pop():new FrictionEquation(bodyA,bodyB,mug*reducedMass),c2=pool.length?pool.pop():new FrictionEquation(bodyA,bodyB,mug*reducedMass);return c1.bi=c2.bi=bodyA,c1.bj=c2.bj=bodyB,c1.minForce=c2.minForce=-mug*reducedMass,c1.maxForce=c2.maxForce=mug*reducedMass,c1.ri.copy(contactEquation.ri),c1.rj.copy(contactEquation.rj),c2.ri.copy(contactEquation.ri),c2.rj.copy(contactEquation.rj),contactEquation.ni.tangents(c1.t,c2.t),c1.setSpookParams(cm.frictionEquationStiffness,cm.frictionEquationRelaxation,world.dt),c2.setSpookParams(cm.frictionEquationStiffness,cm.frictionEquationRelaxation,world.dt),c1.enabled=c2.enabled=contactEquation.enabled,outArray.push(c1,c2),!0}return!1},_proto.createFrictionFromAverage=function(numContacts){var c=this.result[this.result.length-1];if(this.createFrictionEquationsFromContact(c,this.frictionResult)&&1!==numContacts){var f1=this.frictionResult[this.frictionResult.length-2],f2=this.frictionResult[this.frictionResult.length-1];averageNormal.setZero(),averageContactPointA.setZero(),averageContactPointB.setZero();for(var bodyA=c.bi,i=(c.bj,0);i!==numContacts;i++)(c=this.result[this.result.length-1-i]).bi!==bodyA?(averageNormal.vadd(c.ni,averageNormal),averageContactPointA.vadd(c.ri,averageContactPointA),averageContactPointB.vadd(c.rj,averageContactPointB)):(averageNormal.vsub(c.ni,averageNormal),averageContactPointA.vadd(c.rj,averageContactPointA),averageContactPointB.vadd(c.ri,averageContactPointB));var invNumContacts=1/numContacts;averageContactPointA.scale(invNumContacts,f1.ri),averageContactPointB.scale(invNumContacts,f1.rj),f2.ri.copy(f1.ri),f2.rj.copy(f1.rj),averageNormal.normalize(),averageNormal.tangents(f1.t,f2.t)}},_proto.getContacts=function(p1,p2,world,result,oldcontacts,frictionResult,frictionPool){this.contactPointPool=oldcontacts,this.frictionEquationPool=frictionPool,this.result=result,this.frictionResult=frictionResult;for(var qi=tmpQuat1,qj=tmpQuat2,xi=tmpVec1$3,xj=tmpVec2$3,k=0,N=p1.length;k!==N;k++){var bi=p1[k],bj=p2[k],bodyContactMaterial=null;bi.material&&bj.material&&(bodyContactMaterial=world.getContactMaterial(bi.material,bj.material)||null);for(var justTest=bi.type&Body.KINEMATIC&&bj.type&Body.STATIC||bi.type&Body.STATIC&&bj.type&Body.KINEMATIC||bi.type&Body.KINEMATIC&&bj.type&Body.KINEMATIC,i=0;isi.boundingSphereRadius+sj.boundingSphereRadius)){var shapeContactMaterial=null;si.material&&sj.material&&(shapeContactMaterial=world.getContactMaterial(si.material,sj.material)||null),this.currentContactMaterial=shapeContactMaterial||bodyContactMaterial||world.defaultContactMaterial;var resolver=this[si.type|sj.type];if(resolver){(si.type0){var ns1=sphereBox_ns1,ns2=sphereBox_ns2;ns1.copy(sides[(idx+1)%3]),ns2.copy(sides[(idx+2)%3]);var h1=ns1.length(),h2=ns2.length();ns1.normalize(),ns2.normalize();var dot1=box_to_sphere.dot(ns1),dot2=box_to_sphere.dot(ns2);if(dot1-h1&&dot2-h2){var _dist=Math.abs(dot-h-R);if((null===side_distance||_distsi.boundingSphereRadius+sj.boundingSphereRadius)&&si.findSeparatingAxis(sj,xi,qi,xj,qj,sepAxis,faceListA,faceListB)){var res=[],q=convexConvex_q;si.clipAgainstHull(xi,qi,sj,xj,qj,sepAxis,-100,100,res);for(var numContacts=0,j=0;j!==res.length;j++){if(justTest)return!0;var r=this.createContactEquation(bi,bj,si,sj,rsi,rsj),ri=r.ri,rj=r.rj;sepAxis.negate(r.ni),res[j].normal.negate(q),q.scale(res[j].depth,q),res[j].point.vadd(q,ri),rj.copy(res[j].point),ri.vsub(xi,ri),rj.vsub(xj,rj),ri.vadd(xi,ri),ri.vsub(bi.position,ri),rj.vadd(xj,rj),rj.vsub(bj.position,rj),this.result.push(r),numContacts++,this.enableFrictionReduction||this.createFrictionEquationsFromContact(r,this.frictionResult)}this.enableFrictionReduction&&numContacts&&this.createFrictionFromAverage(numContacts)}},_proto.sphereConvex=function(si,sj,xi,xj,qi,qj,bi,bj,rsi,rsj,justTest){var v3pool=this.v3pool;xi.vsub(xj,convex_to_sphere);for(var normals=sj.faceNormals,faces=sj.faces,verts=sj.vertices,R=si.radius,found=!1,i=0;i!==verts.length;i++){var v=verts[i],worldCorner=sphereConvex_worldCorner;qj.vmult(v,worldCorner),xj.vadd(worldCorner,worldCorner);var sphere_to_corner=sphereConvex_sphereToCorner;if(worldCorner.vsub(xi,sphere_to_corner),sphere_to_corner.lengthSquared()0){for(var faceVerts=[],j=0,Nverts=face.length;j!==Nverts;j++){var worldVertex=v3pool.get();qj.vmult(verts[face[j]],worldVertex),xj.vadd(worldVertex,worldVertex),faceVerts.push(worldVertex)}if(pointInPolygon(faceVerts,worldNormal,xi)){if(justTest)return!0;found=!0;var _r3=this.createContactEquation(bi,bj,si,sj,rsi,rsj);worldNormal.scale(-R,_r3.ri),worldNormal.negate(_r3.ni);var penetrationVec2=v3pool.get();worldNormal.scale(-penetration,penetrationVec2);var penetrationSpherePoint=v3pool.get();worldNormal.scale(-R,penetrationSpherePoint),xi.vsub(xj,_r3.rj),_r3.rj.vadd(penetrationSpherePoint,_r3.rj),_r3.rj.vadd(penetrationVec2,_r3.rj),_r3.rj.vadd(xj,_r3.rj),_r3.rj.vsub(bj.position,_r3.rj),_r3.ri.vadd(xi,_r3.ri),_r3.ri.vsub(bi.position,_r3.ri),v3pool.release(penetrationVec2),v3pool.release(penetrationSpherePoint),this.result.push(_r3),this.createFrictionEquationsFromContact(_r3,this.frictionResult);for(var _j2=0,Nfaceverts=faceVerts.length;_j2!==Nfaceverts;_j2++)v3pool.release(faceVerts[_j2]);return}for(var _j3=0;_j3!==face.length;_j3++){var v1=v3pool.get(),v2=v3pool.get();qj.vmult(verts[face[(_j3+1)%face.length]],v1),qj.vmult(verts[face[(_j3+2)%face.length]],v2),xj.vadd(v1,v1),xj.vadd(v2,v2);var edge=sphereConvex_edge;v2.vsub(v1,edge);var edgeUnit=sphereConvex_edgeUnit;edge.unit(edgeUnit);var p=v3pool.get(),v1_to_xi=v3pool.get();xi.vsub(v1,v1_to_xi);var dot=v1_to_xi.dot(edgeUnit);edgeUnit.scale(dot,p),p.vadd(v1,p);var xi_to_p=v3pool.get();if(p.vsub(xi,xi_to_p),dot>0&&dot*dotdata.length||iMinY>data[0].length)){iMinX<0&&(iMinX=0),iMaxX<0&&(iMaxX=0),iMinY<0&&(iMinY=0),iMaxY<0&&(iMaxY=0),iMinX>=data.length&&(iMinX=data.length-1),iMaxX>=data.length&&(iMaxX=data.length-1),iMaxY>=data[0].length&&(iMaxY=data[0].length-1),iMinY>=data[0].length&&(iMinY=data[0].length-1);var minMax=[];hfShape.getRectMinMax(iMinX,iMinY,iMaxX,iMaxY,minMax);var min=minMax[0],max=minMax[1];if(!(localSpherePos.z-radius>max||localSpherePos.z+radius2)return}}},_proto.boxHeightfield=function(si,sj,xi,xj,qi,qj,bi,bj,rsi,rsj,justTest){return si.convexPolyhedronRepresentation.material=si.material,si.convexPolyhedronRepresentation.collisionResponse=si.collisionResponse,this.convexHeightfield(si.convexPolyhedronRepresentation,sj,xi,xj,qi,qj,bi,bj,si,sj,justTest)},_proto.convexHeightfield=function(convexShape,hfShape,convexPos,hfPos,convexQuat,hfQuat,convexBody,hfBody,rsi,rsj,justTest){var data=hfShape.data,w=hfShape.elementSize,radius=convexShape.boundingSphereRadius,worldPillarOffset=convexHeightfield_tmp2,faceList=convexHeightfield_faceList,localConvexPos=convexHeightfield_tmp1;Transform.pointToLocalFrame(hfPos,hfQuat,convexPos,localConvexPos);var iMinX=Math.floor((localConvexPos.x-radius)/w)-1,iMaxX=Math.ceil((localConvexPos.x+radius)/w)+1,iMinY=Math.floor((localConvexPos.y-radius)/w)-1,iMaxY=Math.ceil((localConvexPos.y+radius)/w)+1;if(!(iMaxX<0||iMaxY<0||iMinX>data.length||iMinY>data[0].length)){iMinX<0&&(iMinX=0),iMaxX<0&&(iMaxX=0),iMinY<0&&(iMinY=0),iMaxY<0&&(iMaxY=0),iMinX>=data.length&&(iMinX=data.length-1),iMaxX>=data.length&&(iMaxX=data.length-1),iMaxY>=data[0].length&&(iMaxY=data[0].length-1),iMinY>=data[0].length&&(iMinY=data[0].length-1);var minMax=[];hfShape.getRectMinMax(iMinX,iMinY,iMaxX,iMaxY,minMax);var min=minMax[0],max=minMax[1];if(!(localConvexPos.z-radius>max||localConvexPos.z+radius0&&positionAlongEdgeB<0)if(localSpherePos.vsub(edgeVertexA,tmp),edgeVectorUnit.copy(edgeVector),edgeVectorUnit.normalize(),positionAlongEdgeA=tmp.dot(edgeVectorUnit),edgeVectorUnit.scale(positionAlongEdgeA,tmp),tmp.vadd(edgeVertexA,tmp),tmp.distanceTo(localSpherePos)0&&!0===positiveResult||r<=0&&!1===positiveResult))return!1;null===positiveResult&&(positiveResult=r>0)}return!0}var box_to_sphere=new Vec3,sphereBox_ns=new Vec3,sphereBox_ns1=new Vec3,sphereBox_ns2=new Vec3,sphereBox_sides=[new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3],sphereBox_sphere_to_corner=new Vec3,sphereBox_side_ns=new Vec3,sphereBox_side_ns1=new Vec3,sphereBox_side_ns2=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereBox]=Narrowphase.prototype.sphereBox;var convex_to_sphere=new Vec3,sphereConvex_edge=new Vec3,sphereConvex_edgeUnit=new Vec3,sphereConvex_sphereToCorner=new Vec3,sphereConvex_worldCorner=new Vec3,sphereConvex_worldNormal=new Vec3,sphereConvex_worldPoint=new Vec3,sphereConvex_worldSpherePointClosestToPlane=new Vec3,sphereConvex_penetrationVec=new Vec3,sphereConvex_sphereToWorldPoint=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereConvex]=Narrowphase.prototype.sphereConvex;new Vec3,new Vec3;Narrowphase.prototype[COLLISION_TYPES.planeBox]=Narrowphase.prototype.planeBox;var planeConvex_v=new Vec3,planeConvex_normal=new Vec3,planeConvex_relpos=new Vec3,planeConvex_projected=new Vec3;Narrowphase.prototype[COLLISION_TYPES.planeConvex]=Narrowphase.prototype.planeConvex;var convexConvex_sepAxis=new Vec3,convexConvex_q=new Vec3;Narrowphase.prototype[COLLISION_TYPES.convexConvex]=Narrowphase.prototype.convexConvex;var particlePlane_normal=new Vec3,particlePlane_relpos=new Vec3,particlePlane_projected=new Vec3;Narrowphase.prototype[COLLISION_TYPES.planeParticle]=Narrowphase.prototype.planeParticle;var particleSphere_normal=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereParticle]=Narrowphase.prototype.sphereParticle;var cqj=new Quaternion,convexParticle_local=new Vec3,convexParticle_penetratedFaceNormal=(new Vec3,new Vec3),convexParticle_vertexToParticle=new Vec3,convexParticle_worldPenetrationVec=new Vec3;Narrowphase.prototype[COLLISION_TYPES.convexParticle]=Narrowphase.prototype.convexParticle,Narrowphase.prototype[COLLISION_TYPES.boxHeightfield]=Narrowphase.prototype.boxHeightfield;var convexHeightfield_tmp1=new Vec3,convexHeightfield_tmp2=new Vec3,convexHeightfield_faceList=[0];Narrowphase.prototype[COLLISION_TYPES.convexHeightfield]=Narrowphase.prototype.convexHeightfield;var sphereHeightfield_tmp1=new Vec3,sphereHeightfield_tmp2=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereHeightfield]=Narrowphase.prototype.sphereHeightfield;var OverlapKeeper=function(){function OverlapKeeper(){this.current=[],this.previous=[]}var _proto=OverlapKeeper.prototype;return _proto.getKey=function(i,j){if(jcurrent[index];)index++;if(key!==current[index]){for(var _j=current.length-1;_j>=index;_j--)current[_j+1]=current[_j];current[index]=key}},_proto.tick=function(){var tmp=this.current;this.current=this.previous,this.previous=tmp,this.current.length=0},_proto.getDiff=function(additions,removals){for(var a=this.current,b=this.previous,al=a.length,bl=b.length,j=0,i=0;ib[j];)j++;keyA===b[j]||unpackAndPush(additions,keyA)}j=0;for(var _i=0;_ia[j];)j++;a[j]===keyB||unpackAndPush(removals,keyB)}},OverlapKeeper}();function unpackAndPush(array,key){array.push((4294901760&key)>>16,65535&key)}var TupleDictionary=function(){function TupleDictionary(){this.data={keys:[]}}var _proto=TupleDictionary.prototype;return _proto.get=function(i,j){if(i>j){var temp=j;j=i,i=temp}return this.data[i+"-"+j]},_proto.set=function(i,j,value){if(i>j){var temp=j;j=i,i=temp}var key=i+"-"+j;this.get(i,j)||this.data.keys.push(key),this.data[key]=value},_proto.reset=function(){for(var data=this.data,keys=data.keys;keys.length>0;){delete data[keys.pop()]}},TupleDictionary}(),World=function(_EventTarget){function World(options){var _this;return void 0===options&&(options={}),(_this=_EventTarget.call(this)||this).dt=-1,_this.allowSleep=!!options.allowSleep,_this.contacts=[],_this.frictionEquations=[],_this.quatNormalizeSkip=void 0!==options.quatNormalizeSkip?options.quatNormalizeSkip:0,_this.quatNormalizeFast=void 0!==options.quatNormalizeFast&&options.quatNormalizeFast,_this.time=0,_this.stepnumber=0,_this.default_dt=1/60,_this.nextId=0,_this.gravity=new Vec3,options.gravity&&_this.gravity.copy(options.gravity),_this.broadphase=void 0!==options.broadphase?options.broadphase:new NaiveBroadphase,_this.bodies=[],_this.hasActiveBodies=!1,_this.solver=void 0!==options.solver?options.solver:new GSSolver,_this.constraints=[],_this.narrowphase=new Narrowphase(_assertThisInitialized(_this)),_this.collisionMatrix=new ArrayCollisionMatrix,_this.collisionMatrixPrevious=new ArrayCollisionMatrix,_this.bodyOverlapKeeper=new OverlapKeeper,_this.shapeOverlapKeeper=new OverlapKeeper,_this.materials=[],_this.contactmaterials=[],_this.contactMaterialTable=new TupleDictionary,_this.defaultMaterial=new Material("default"),_this.defaultContactMaterial=new ContactMaterial(_this.defaultMaterial,_this.defaultMaterial,{friction:.3,restitution:0}),_this.doProfiling=!1,_this.profile={solve:0,makeContactConstraints:0,broadphase:0,integrate:0,narrowphase:0},_this.accumulator=0,_this.subsystems=[],_this.addBodyEvent={type:"addBody",body:null},_this.removeBodyEvent={type:"removeBody",body:null},_this.idToBodyMap={},_this.broadphase.setWorld(_assertThisInitialized(_this)),_this}_inheritsLoose(World,_EventTarget);var _proto=World.prototype;return _proto.getContactMaterial=function(m1,m2){return this.contactMaterialTable.get(m1.id,m2.id)},_proto.numObjects=function(){return this.bodies.length},_proto.collisionMatrixTick=function(){var temp=this.collisionMatrixPrevious;this.collisionMatrixPrevious=this.collisionMatrix,this.collisionMatrix=temp,this.collisionMatrix.reset(),this.bodyOverlapKeeper.tick(),this.shapeOverlapKeeper.tick()},_proto.addConstraint=function(c){this.constraints.push(c)},_proto.removeConstraint=function(c){var idx=this.constraints.indexOf(c);-1!==idx&&this.constraints.splice(idx,1)},_proto.rayTest=function(from,to,result){result instanceof RaycastResult?this.raycastClosest(from,to,{skipBackfaces:!0},result):this.raycastAll(from,to,{skipBackfaces:!0},result)},_proto.raycastAll=function(from,to,options,callback){return void 0===options&&(options={}),options.mode=Ray.ALL,options.from=from,options.to=to,options.callback=callback,tmpRay$1.intersectWorld(this,options)},_proto.raycastAny=function(from,to,options,result){return void 0===options&&(options={}),options.mode=Ray.ANY,options.from=from,options.to=to,options.result=result,tmpRay$1.intersectWorld(this,options)},_proto.raycastClosest=function(from,to,options,result){return void 0===options&&(options={}),options.mode=Ray.CLOSEST,options.from=from,options.to=to,options.result=result,tmpRay$1.intersectWorld(this,options)},_proto.addBody=function(body){this.bodies.includes(body)||(body.index=this.bodies.length,this.bodies.push(body),body.world=this,body.initPosition.copy(body.position),body.initVelocity.copy(body.velocity),body.timeLastSleepy=this.time,body instanceof Body&&(body.initAngularVelocity.copy(body.angularVelocity),body.initQuaternion.copy(body.quaternion)),this.collisionMatrix.setNumObjects(this.bodies.length),this.addBodyEvent.body=body,this.idToBodyMap[body.id]=body,this.dispatchEvent(this.addBodyEvent))},_proto.removeBody=function(body){body.world=null;var n=this.bodies.length-1,bodies=this.bodies,idx=bodies.indexOf(body);if(-1!==idx){bodies.splice(idx,1);for(var i=0;i!==bodies.length;i++)bodies[i].index=i;this.collisionMatrix.setNumObjects(n),this.removeBodyEvent.body=body,delete this.idToBodyMap[body.id],this.dispatchEvent(this.removeBodyEvent)}},_proto.getBodyById=function(id){return this.idToBodyMap[id]},_proto.getShapeById=function(id){for(var bodies=this.bodies,i=0,bl=bodies.length;i=dt&&substeps=0;j-=1)(c.bodyA===p1[j]&&c.bodyB===p2[j]||c.bodyB===p1[j]&&c.bodyA===p2[j])&&(p1.splice(j,1),p2.splice(j,1))}this.collisionMatrixTick(),doProfiling&&(profilingStart=performance.now());var oldcontacts=World_step_oldContacts,NoldContacts=contacts.length;for(i=0;i!==NoldContacts;i++)oldcontacts.push(contacts[i]);contacts.length=0;var NoldFrictionEquations=this.frictionEquations.length;for(i=0;i!==NoldFrictionEquations;i++)frictionEquationPool.push(this.frictionEquations[i]);for(this.frictionEquations.length=0,this.narrowphase.getContacts(p1,p2,this,contacts,oldcontacts,this.frictionEquations,frictionEquationPool),doProfiling&&(profile.narrowphase=performance.now()-profilingStart),doProfiling&&(profilingStart=performance.now()),i=0;i=0&&bj.material.friction>=0&&_bi.material.friction*bj.material.friction,_bi.material.restitution>=0&&bj.material.restitution>=0&&(_c.restitution=_bi.material.restitution*bj.material.restitution)),solver.addEquation(_c),_bi.allowSleep&&_bi.type===Body.DYNAMIC&&_bi.sleepState===Body.SLEEPING&&bj.sleepState===Body.AWAKE&&bj.type!==Body.STATIC)bj.velocity.lengthSquared()+bj.angularVelocity.lengthSquared()>=2*Math.pow(bj.sleepSpeedLimit,2)&&(_bi.wakeUpAfterNarrowphase=!0);if(bj.allowSleep&&bj.type===Body.DYNAMIC&&bj.sleepState===Body.SLEEPING&&_bi.sleepState===Body.AWAKE&&_bi.type!==Body.STATIC)_bi.velocity.lengthSquared()+_bi.angularVelocity.lengthSquared()>=2*Math.pow(_bi.sleepSpeedLimit,2)&&(bj.wakeUpAfterNarrowphase=!0);this.collisionMatrix.set(_bi,bj,!0),this.collisionMatrixPrevious.get(_bi,bj)||(World_step_collideEvent.body=bj,World_step_collideEvent.contact=_c,_bi.dispatchEvent(World_step_collideEvent),World_step_collideEvent.body=_bi,bj.dispatchEvent(World_step_collideEvent)),this.bodyOverlapKeeper.set(_bi.id,bj.id),this.shapeOverlapKeeper.set(si.id,sj.id)}for(this.emitContactEvents(),doProfiling&&(profile.makeContactConstraints=performance.now()-profilingStart,profilingStart=performance.now()),i=0;i!==N;i++){var _bi2=bodies[i];_bi2.wakeUpAfterNarrowphase&&(_bi2.wakeUp(),_bi2.wakeUpAfterNarrowphase=!1)}for(Nconstraints=constraints.length,i=0;i!==Nconstraints;i++){var _c2=constraints[i];_c2.update();for(var _j=0,Neq=_c2.equations.length;_j!==Neq;_j++){var eq=_c2.equations[_j];solver.addEquation(eq)}}solver.solve(dt,this),doProfiling&&(profile.solve=performance.now()-profilingStart),solver.removeAllEquations();var pow=Math.pow;for(i=0;i!==N;i++){var _bi3=bodies[i];if(_bi3.type&DYNAMIC){var ld=pow(1-_bi3.linearDamping,dt),v=_bi3.velocity;v.scale(ld,v);var av=_bi3.angularVelocity;if(av){var ad=pow(1-_bi3.angularDamping,dt);av.scale(ad,av)}}}for(this.dispatchEvent(World_step_preStepEvent),i=0;i!==N;i++){var _bi4=bodies[i];_bi4.preStep&&_bi4.preStep.call(_bi4)}doProfiling&&(profilingStart=performance.now());var quatNormalize=this.stepnumber%(this.quatNormalizeSkip+1)==0,quatNormalizeFast=this.quatNormalizeFast;for(i=0;i!==N;i++)bodies[i].integrate(dt,quatNormalize,quatNormalizeFast);for(this.clearForces(),this.broadphase.dirty=!0,doProfiling&&(profile.integrate=performance.now()-profilingStart),this.time+=dt,this.stepnumber+=1,this.dispatchEvent(World_step_postStepEvent),i=0;i!==N;i++){var _bi5=bodies[i],postStep=_bi5.postStep;postStep&&postStep.call(_bi5)}var hasActiveBodies=!0;if(this.allowSleep)for(hasActiveBodies=!1,i=0;i!==N;i++){var _bi6=bodies[i];_bi6.sleepTick(this.time),_bi6.sleepState!==Body.SLEEPING&&(hasActiveBodies=!0)}this.hasActiveBodies=hasActiveBodies},_proto.clearForces=function(){for(var bodies=this.bodies,N=bodies.length,i=0;i!==N;i++){var b=bodies[i];b.force,b.torque;b.force.set(0,0,0),b.torque.set(0,0,0)}},World}(EventTarget),tmpRay$1=(new AABB,new Ray);if("undefined"==typeof performance&&(performance={}),!performance.now){var nowOffset=Date.now();performance.timing&&performance.timing.navigationStart&&(nowOffset=performance.timing.navigationStart),performance.now=function(){return Date.now()-nowOffset}}new Vec3;var additions,removals,beginContactEvent,endContactEvent,beginShapeContactEvent,endShapeContactEvent,World_step_postStepEvent={type:"postStep"},World_step_preStepEvent={type:"preStep"},World_step_collideEvent={type:Body.COLLIDE_EVENT_NAME,body:null,contact:null},World_step_oldContacts=[],World_step_frictionEquationPool=[],World_step_p1=[],World_step_p2=[];World.prototype.emitContactEvents=(additions=[],removals=[],beginContactEvent={type:"beginContact",bodyA:null,bodyB:null},endContactEvent={type:"endContact",bodyA:null,bodyB:null},beginShapeContactEvent={type:"beginShapeContact",bodyA:null,bodyB:null,shapeA:null,shapeB:null},endShapeContactEvent={type:"endShapeContact",bodyA:null,bodyB:null,shapeA:null,shapeB:null},function(){var hasBeginContact=this.hasAnyEventListener("beginContact"),hasEndContact=this.hasAnyEventListener("endContact");if((hasBeginContact||hasEndContact)&&this.bodyOverlapKeeper.getDiff(additions,removals),hasBeginContact){for(var i=0,l=additions.length;i{switch(options.cylinderAxis){case"y":return new Ammo.btCylinderShape(btHalfExtents);case"x":return new Ammo.btCylinderShapeX(btHalfExtents);case"z":return new Ammo.btCylinderShapeZ(btHalfExtents)}return null})();return Ammo.destroy(btHalfExtents),_finishCollisionShape(collisionShape,options,_computeScale(root,options)),collisionShape},exports.createCapsuleShape=function(root,options){options.type=TYPE.CAPSULE,_setOptions(options),options.fit===FIT.ALL&&(options.halfExtents=_computeHalfExtents(root,_computeBounds(root,options),options.minHalfExtent,options.maxHalfExtent));const{x:x,y:y,z:z}=options.halfExtents,collisionShape=(()=>{switch(options.cylinderAxis){case"y":return new Ammo.btCapsuleShape(Math.max(x,z),2*y);case"x":return new Ammo.btCapsuleShapeX(Math.max(y,z),2*x);case"z":return new Ammo.btCapsuleShapeZ(Math.max(x,y),2*z)}return null})();return _finishCollisionShape(collisionShape,options,_computeScale(root,options)),collisionShape},exports.createConeShape=function(root,options){options.type=TYPE.CONE,_setOptions(options),options.fit===FIT.ALL&&(options.halfExtents=_computeHalfExtents(root,_computeBounds(root,options),options.minHalfExtent,options.maxHalfExtent));const{x:x,y:y,z:z}=options.halfExtents,collisionShape=(()=>{switch(options.cylinderAxis){case"y":return new Ammo.btConeShape(Math.max(x,z),2*y);case"x":return new Ammo.btConeShapeX(Math.max(y,z),2*x);case"z":return new Ammo.btConeShapeZ(Math.max(x,y),2*z)}return null})();return _finishCollisionShape(collisionShape,options,_computeScale(root,options)),collisionShape},exports.createSphereShape=function(root,options){let radius;options.type=TYPE.SPHERE,_setOptions(options),radius=options.fit!==FIT.MANUAL||isNaN(options.sphereRadius)?_computeRadius(root,options,_computeBounds(root,options)):options.sphereRadius;const collisionShape=new Ammo.btSphereShape(radius);return _finishCollisionShape(collisionShape,options,_computeScale(root,options)),collisionShape},exports.createHullShape=function(){const vertex=new THREE.Vector3,center=new THREE.Vector3;return function(root,options){if(options.type=TYPE.HULL,_setOptions(options),options.fit===FIT.MANUAL)return console.warn("cannot use fit: manual with type: hull"),null;const bounds=_computeBounds(root,options),btVertex=new Ammo.btVector3,originalHull=new Ammo.btConvexHullShape;originalHull.setMargin(options.margin),center.addVectors(bounds.max,bounds.min).multiplyScalar(.5);let vertexCount=0;_iterateGeometries(root,options,geo=>{vertexCount+=geo.attributes.position.array.length/3});const maxVertices=options.hullMaxVertices||1e5;vertexCount>maxVertices&&console.warn(`too many vertices for hull shape; sampling ~${maxVertices} from ~${vertexCount} vertices`);const p=Math.min(1,maxVertices/vertexCount);_iterateGeometries(root,options,(geo,transform)=>{const components=geo.attributes.position.array;for(let i=0;i=100){const shapeHull=new Ammo.btShapeHull(originalHull);shapeHull.buildHull(options.margin),Ammo.destroy(originalHull),collisionShape=new Ammo.btConvexHullShape(Ammo.getPointer(shapeHull.getVertexPointer()),shapeHull.numVertices()),Ammo.destroy(shapeHull)}return Ammo.destroy(btVertex),_finishCollisionShape(collisionShape,options,_computeScale(root,options)),collisionShape}}(),exports.createHACDShapes=function(){const v=new THREE.Vector3,center=new THREE.Vector3;return function(root,options){if(options.type=TYPE.HACD,_setOptions(options),options.fit===FIT.MANUAL)return console.warn("cannot use fit: manual with type: hacd"),[];if(!Ammo.hasOwnProperty("HACD"))return console.warn("HACD unavailable in included build of Ammo.js. Visit https://github.com/mozillareality/ammo.js for the latest version."),[];const bounds=_computeBounds(root,options),scale=_computeScale(root,options);let vertexCount=0,triCount=0;center.addVectors(bounds.max,bounds.min).multiplyScalar(.5),_iterateGeometries(root,options,geo=>{vertexCount+=geo.attributes.position.array.length/3,geo.index?triCount+=geo.index.array.length/3:triCount+=geo.attributes.position.array.length/9});const hacd=new Ammo.HACD;options.hasOwnProperty("compacityWeight")&&hacd.SetCompacityWeight(options.compacityWeight),options.hasOwnProperty("volumeWeight")&&hacd.SetVolumeWeight(options.volumeWeight),options.hasOwnProperty("nClusters")&&hacd.SetNClusters(options.nClusters),options.hasOwnProperty("nVerticesPerCH")&&hacd.SetNVerticesPerCH(options.nVerticesPerCH),options.hasOwnProperty("concavity")&&hacd.SetConcavity(options.concavity);const points=Ammo._malloc(3*vertexCount*8),triangles=Ammo._malloc(3*triCount*4);hacd.SetPoints(points),hacd.SetTriangles(triangles),hacd.SetNPoints(vertexCount),hacd.SetNTriangles(triCount);const pptr=points/8,tptr=triangles/4;_iterateGeometries(root,options,(geo,transform)=>{const components=geo.attributes.position.array,indices=geo.index?geo.index.array:null;for(let i=0;i{vertexCount+=geo.attributes.position.count,geo.index?triCount+=geo.index.count/3:triCount+=geo.attributes.position.count/3});const vhacd=new Ammo.VHACD,params=new Ammo.Parameters;options.hasOwnProperty("resolution")&¶ms.set_m_resolution(options.resolution),options.hasOwnProperty("depth")&¶ms.set_m_depth(options.depth),options.hasOwnProperty("concavity")&¶ms.set_m_concavity(options.concavity),options.hasOwnProperty("planeDownsampling")&¶ms.set_m_planeDownsampling(options.planeDownsampling),options.hasOwnProperty("convexhullDownsampling")&¶ms.set_m_convexhullDownsampling(options.convexhullDownsampling),options.hasOwnProperty("alpha")&¶ms.set_m_alpha(options.alpha),options.hasOwnProperty("beta")&¶ms.set_m_beta(options.beta),options.hasOwnProperty("gamma")&¶ms.set_m_gamma(options.gamma),options.hasOwnProperty("pca")&¶ms.set_m_pca(options.pca),options.hasOwnProperty("mode")&¶ms.set_m_mode(options.mode),options.hasOwnProperty("maxNumVerticesPerCH")&¶ms.set_m_maxNumVerticesPerCH(options.maxNumVerticesPerCH),options.hasOwnProperty("minVolumePerCH")&¶ms.set_m_minVolumePerCH(options.minVolumePerCH),options.hasOwnProperty("convexhullApproximation")&¶ms.set_m_convexhullApproximation(options.convexhullApproximation),options.hasOwnProperty("oclAcceleration")&¶ms.set_m_oclAcceleration(options.oclAcceleration);const points=Ammo._malloc(3*vertexCount*8),triangles=Ammo._malloc(3*triCount*4);let pptr=points/8,tptr=triangles/4;_iterateGeometries(root,options,(geo,transform)=>{const components=geo.attributes.position.array,indices=geo.index?geo.index.array:null;for(let i=0;i{const components=geo.attributes.position.array;if(geo.index)for(let i=0;i{switch(options.heightDataType){case"short":return Ammo.PHY_SHORT;case"float":default:return Ammo.PHY_FLOAT}})(),flipQuadEdges=!options.hasOwnProperty("flipQuadEdges")||options.flipQuadEdges,heightStickLength=heightfieldData.length,heightStickWidth=heightStickLength>0?heightfieldData[0].length:0,data=Ammo._malloc(heightStickLength*heightStickWidth*4),ptr=data/4;let minHeight=Number.POSITIVE_INFINITY,maxHeight=Number.NEGATIVE_INFINITY,index=0;for(let l=0;l{for(let res of collisionShape.resources||[])Ammo.destroy(res);collisionShape.heightfieldData&&Ammo._free(collisionShape.heightfieldData),Ammo.destroy(collisionShape)});const localTransform=new Ammo.btTransform,rotation=new Ammo.btQuaternion;if(localTransform.setIdentity(),localTransform.getOrigin().setValue(options.offset.x,options.offset.y,options.offset.z),rotation.setValue(options.orientation.x,options.orientation.y,options.orientation.z,options.orientation.w),localTransform.setRotation(rotation),Ammo.destroy(rotation),scale){const localScale=new Ammo.btVector3(scale.x,scale.y,scale.z);collisionShape.setLocalScaling(localScale),Ammo.destroy(localScale)}collisionShape.localTransform=localTransform},_iterateGeometries=function(){const transform=new THREE.Matrix4,inverse=new THREE.Matrix4,bufferGeometry=new THREE.BufferGeometry;return function(root,options,cb){inverse.copy(root.matrixWorld).invert(),root.traverse(mesh=>{!mesh.isMesh||THREE.Sky&&mesh.__proto__==THREE.Sky.prototype||!(options.includeInvisible||mesh.el&&mesh.el.object3D.visible||mesh.visible)||(mesh===root?transform.identity():(hasUpdateMatricesFunction&&mesh.updateMatrices(),transform.multiplyMatrices(inverse,mesh.matrixWorld)),cb(mesh.geometry.isBufferGeometry?mesh.geometry:bufferGeometry.fromGeometry(mesh.geometry),transform))})}}(),_computeScale=function(root,options){const scale=new THREE.Vector3(1,1,1);return options.fit===FIT.ALL&&scale.setFromMatrixScale(root.matrixWorld),scale},_computeRadius=function(){const v=new THREE.Vector3,center=new THREE.Vector3;return function(root,options,bounds){let maxRadiusSq=0,{x:cx,y:cy,z:cz}=bounds.getCenter(center);return _iterateGeometries(root,options,(geo,transform)=>{const components=geo.attributes.position.array;for(let i=0;i{const components=geo.attributes.position.array;for(let i=0;imaxX&&(maxX=v.x),v.y>maxY&&(maxY=v.y),v.z>maxZ&&(maxZ=v.z)}),bounds.min.set(minX,minY,minZ),bounds.max.set(maxX,maxY,maxZ),bounds}}()},{}],7:[function(require,module,exports){(function(global){var cannonEs=require("cannon-es"),three="undefined"!=typeof window?window.THREE:void 0!==global?global.THREE:null,ConvexHull=function(){var line3,plane,closestPoint,triangle,Visible=0,v1=new three.Vector3;function ConvexHull(){this.tolerance=-1,this.faces=[],this.newFaces=[],this.assigned=new VertexList,this.unassigned=new VertexList,this.vertices=[]}function Face(){this.normal=new three.Vector3,this.midpoint=new three.Vector3,this.area=0,this.constant=0,this.outside=null,this.mark=Visible,this.edge=null}function HalfEdge(vertex,face){this.vertex=vertex,this.prev=null,this.next=null,this.twin=null,this.face=face}function VertexNode(point){this.point=point,this.prev=null,this.next=null,this.face=null}function VertexList(){this.head=null,this.tail=null}return Object.assign(ConvexHull.prototype,{setFromPoints:function(points){!0!==Array.isArray(points)&&console.error("THREE.ConvexHull: Points parameter is not an array."),points.length<4&&console.error("THREE.ConvexHull: The algorithm needs at least four points."),this.makeEmpty();for(var i=0,l=points.length;ithis.tolerance)return!1}return!0},intersectRay:function(ray,target){for(var faces=this.faces,tNear=-1/0,tFar=1/0,i=0,l=faces.length;i0&&vD>=0)return null;var t=0!==vD?-vN/vD:0;if(!(t<=0)&&(vD>0?tFar=Math.min(t,tFar):tNear=Math.max(t,tNear),tNear>tFar))return null}return tNear!==-1/0?ray.at(tNear,target):ray.at(tFar,target),target},intersectsRay:function(ray){return null!==this.intersectRay(ray,v1)},makeEmpty:function(){return this.faces=[],this.vertices=[],this},addVertexToFace:function(vertex,face){return vertex.face=face,null===face.outside?this.assigned.append(vertex):this.assigned.insertBefore(face.outside,vertex),face.outside=vertex,this},removeVertexFromFace:function(vertex,face){return vertex===face.outside&&(null!==vertex.next&&vertex.next.face===face?face.outside=vertex.next:face.outside=null),this.assigned.remove(vertex),this},removeAllVerticesFromFace:function(face){if(null!==face.outside){for(var start=face.outside,end=face.outside;null!==end.next&&end.next.face===face;)end=end.next;return this.assigned.removeSubList(start,end),start.prev=end.next=null,face.outside=null,start}},deleteFaceVertices:function(face,absorbingFace){var faceVertices=this.removeAllVerticesFromFace(face);if(void 0!==faceVertices)if(void 0===absorbingFace)this.unassigned.appendChain(faceVertices);else{var vertex=faceVertices;do{var nextVertex=vertex.next;absorbingFace.distanceToPoint(vertex.point)>this.tolerance?this.addVertexToFace(vertex,absorbingFace):this.unassigned.append(vertex),vertex=nextVertex}while(null!==vertex)}return this},resolveUnassignedPoints:function(newFaces){if(!1===this.unassigned.isEmpty()){var vertex=this.unassigned.first();do{for(var nextVertex=vertex.next,maxDistance=this.tolerance,maxFace=null,i=0;imaxDistance&&(maxDistance=distance,maxFace=face),maxDistance>1e3*this.tolerance)break}}null!==maxFace&&this.addVertexToFace(vertex,maxFace),vertex=nextVertex}while(null!==vertex)}return this},computeExtremes:function(){var i,l,j,min=new three.Vector3,max=new three.Vector3,minVertices=[],maxVertices=[];for(i=0;i<3;i++)minVertices[i]=maxVertices[i]=this.vertices[0];for(min.copy(this.vertices[0].point),max.copy(this.vertices[0].point),i=0,l=this.vertices.length;imax.getComponent(j)&&(max.setComponent(j,point.getComponent(j)),maxVertices[j]=vertex)}return this.tolerance=3*Number.EPSILON*(Math.max(Math.abs(min.x),Math.abs(max.x))+Math.max(Math.abs(min.y),Math.abs(max.y))+Math.max(Math.abs(min.z),Math.abs(max.z))),{min:minVertices,max:maxVertices}},computeInitialHull:function(){void 0===line3&&(line3=new three.Line3,plane=new three.Plane,closestPoint=new three.Vector3);var vertex,v0,v1,v2,v3,i,l,j,distance,vertices=this.vertices,extremes=this.computeExtremes(),min=extremes.min,max=extremes.max,maxDistance=0,index=0;for(i=0;i<3;i++)(distance=max[i].point.getComponent(i)-min[i].point.getComponent(i))>maxDistance&&(maxDistance=distance,index=i);for(v0=min[index],v1=max[index],maxDistance=0,line3.set(v0.point,v1.point),i=0,l=this.vertices.length;imaxDistance&&(maxDistance=distance,v2=vertex));for(maxDistance=-1,plane.setFromCoplanarPoints(v0.point,v1.point,v2.point),i=0,l=this.vertices.length;imaxDistance&&(maxDistance=distance,v3=vertex);var faces=[];if(plane.distanceToPoint(v3.point)<0)for(faces.push(Face.create(v0,v1,v2),Face.create(v3,v1,v0),Face.create(v3,v2,v1),Face.create(v3,v0,v2)),i=0;i<3;i++)j=(i+1)%3,faces[i+1].getEdge(2).setTwin(faces[0].getEdge(j)),faces[i+1].getEdge(1).setTwin(faces[j+1].getEdge(0));else for(faces.push(Face.create(v0,v2,v1),Face.create(v3,v0,v1),Face.create(v3,v1,v2),Face.create(v3,v2,v0)),i=0;i<3;i++)j=(i+1)%3,faces[i+1].getEdge(2).setTwin(faces[0].getEdge((3-i)%3)),faces[i+1].getEdge(0).setTwin(faces[j+1].getEdge(1));for(i=0;i<4;i++)this.faces.push(faces[i]);for(i=0,l=vertices.length;imaxDistance&&(maxDistance=distance,maxFace=this.faces[j]);null!==maxFace&&this.addVertexToFace(vertex,maxFace)}return this},reindexFaces:function(){for(var activeFaces=[],i=0;imaxDistance&&(maxDistance=distance,eyeVertex=vertex),vertex=vertex.next}while(null!==vertex&&vertex.face===eyeFace);return eyeVertex}},computeHorizon:function(eyePoint,crossEdge,face,horizon){var edge;this.deleteFaceVertices(face),face.mark=1,edge=null===crossEdge?crossEdge=face.getEdge(0):crossEdge.next;do{var twinEdge=edge.twin,oppositeFace=twinEdge.face;oppositeFace.mark===Visible&&(oppositeFace.distanceToPoint(eyePoint)>this.tolerance?this.computeHorizon(eyePoint,twinEdge,oppositeFace,horizon):horizon.push(edge)),edge=edge.next}while(edge!==crossEdge);return this},addAdjoiningFace:function(eyeVertex,horizonEdge){var face=Face.create(eyeVertex,horizonEdge.tail(),horizonEdge.head());return this.faces.push(face),face.getEdge(-1).setTwin(horizonEdge.twin),face.getEdge(0)},addNewFaces:function(eyeVertex,horizon){this.newFaces=[];for(var firstSideEdge=null,previousSideEdge=null,i=0;i0;)edge=edge.next,i--;for(;i<0;)edge=edge.prev,i++;return edge},compute:function(){void 0===triangle&&(triangle=new three.Triangle);var a=this.edge.tail(),b=this.edge.head(),c=this.edge.next.head();return triangle.set(a.point,b.point,c.point),triangle.getNormal(this.normal),triangle.getMidpoint(this.midpoint),this.area=triangle.getArea(),this.constant=this.normal.dot(this.midpoint),this},distanceToPoint:function(point){return this.normal.dot(point)-this.constant}}),Object.assign(HalfEdge.prototype,{head:function(){return this.vertex},tail:function(){return this.prev?this.prev.vertex:null},length:function(){var head=this.head(),tail=this.tail();return null!==tail?tail.point.distanceTo(head.point):-1},lengthSquared:function(){var head=this.head(),tail=this.tail();return null!==tail?tail.point.distanceToSquared(head.point):-1},setTwin:function(edge){return this.twin=edge,edge.twin=this,this}}),Object.assign(VertexList.prototype,{first:function(){return this.head},last:function(){return this.tail},clear:function(){return this.head=this.tail=null,this},insertBefore:function(target,vertex){return vertex.prev=target.prev,vertex.next=target,null===vertex.prev?this.head=vertex:vertex.prev.next=vertex,target.prev=vertex,this},insertAfter:function(target,vertex){return vertex.prev=target,vertex.next=target.next,null===vertex.next?this.tail=vertex:vertex.next.prev=vertex,target.next=vertex,this},append:function(vertex){return null===this.head?this.head=vertex:this.tail.next=vertex,vertex.prev=this.tail,vertex.next=null,this.tail=vertex,this},appendChain:function(vertex){for(null===this.head?this.head=vertex:this.tail.next=vertex,vertex.prev=this.tail;null!==vertex.next;)vertex=vertex.next;return this.tail=vertex,this},remove:function(vertex){return null===vertex.prev?this.head=vertex.next:vertex.prev.next=vertex.next,null===vertex.next?this.tail=vertex.prev:vertex.next.prev=vertex.prev,this},removeSubList:function(a,b){return null===a.prev?this.head=b.next:a.prev.next=b.next,null===b.next?this.tail=a.prev:b.next.prev=a.prev,this},isEmpty:function(){return null===this.head}}),ConvexHull}();const _v1=new three.Vector3,_v2=new three.Vector3,_q1=new three.Quaternion;function getGeometry(object){const meshes=function(object){const meshes=[];return object.traverse(function(o){o.isMesh&&meshes.push(o)}),meshes}(object);if(0===meshes.length)return null;if(1===meshes.length)return normalizeGeometry(meshes[0]);let mesh;const geometries=[];for(;mesh=meshes.pop();)geometries.push(simplifyGeometry(normalizeGeometry(mesh)));return function(geometries){let vertexCount=0;for(let i=0;i{this.loadedEventFired=!0},{once:!0}),this.system.initialized&&this.loadedEventFired&&this.initBody()},initBody:function(){const pos=new THREE.Vector3,quat=new THREE.Quaternion;new THREE.Box3;return function(){const el=this.el,data=this.data;this.localScaling=new Ammo.btVector3;const obj=this.el.object3D;obj.getWorldPosition(pos),obj.getWorldQuaternion(quat),this.prevScale=new THREE.Vector3(1,1,1),this.prevNumChildShapes=0,this.msTransform=new Ammo.btTransform,this.msTransform.setIdentity(),this.rotation=new Ammo.btQuaternion(quat.x,quat.y,quat.z,quat.w),this.msTransform.getOrigin().setValue(pos.x,pos.y,pos.z),this.msTransform.setRotation(this.rotation),this.motionState=new Ammo.btDefaultMotionState(this.msTransform),this.localInertia=new Ammo.btVector3(0,0,0),this.compoundShape=new Ammo.btCompoundShape(!0),this.rbInfo=new Ammo.btRigidBodyConstructionInfo(data.mass,this.motionState,this.compoundShape,this.localInertia),this.rbInfo.m_restitution=((num,min,max)=>Math.min(Math.max(num,min),max))(this.data.restitution,0,1),this.body=new Ammo.btRigidBody(this.rbInfo),this.body.setActivationState(ACTIVATION_STATES.indexOf(data.activationState)+1),this.body.setSleepingThresholds(data.linearSleepingThreshold,data.angularSleepingThreshold),this.body.setDamping(data.linearDamping,data.angularDamping);const angularFactor=new Ammo.btVector3(data.angularFactor.x,data.angularFactor.y,data.angularFactor.z);this.body.setAngularFactor(angularFactor),Ammo.destroy(angularFactor),this._updateBodyGravity(data.gravity),this.updateCollisionFlags(),this.el.body=this.body,this.body.el=el,this.isLoaded=!0,this.el.emit("body-loaded",{body:this.el.body}),this._addToSystem()}}(),tick:function(){this.system.initialized&&!this.isLoaded&&this.loadedEventFired&&this.initBody()},_updateBodyGravity(gravity){if(void 0!==gravity.x&&void 0!==gravity.y&&void 0!==gravity.z){const gravityBtVec=new Ammo.btVector3(gravity.x,gravity.y,gravity.z);epsilon=.001,u=gravityBtVec,v=this.system.driver.physicsWorld.getGravity(),Math.abs(u.x()-v.x())0;){const collisionShape=this.collisionShapes.pop();collisionShape.destroy(),Ammo.destroy(collisionShape.localTransform)}}};module.exports.definition=AmmoShape,module.exports.Component=AFRAME.registerComponent("ammo-shape",AmmoShape)},{"../../constants":20,"three-to-ammo":6}],18:[function(require,module,exports){var CANNON=require("cannon-es"),Shape={schema:{shape:{default:"box",oneOf:["box","sphere","cylinder"]},offset:{type:"vec3",default:{x:0,y:0,z:0}},orientation:{type:"vec4",default:{x:0,y:0,z:0,w:1}},radius:{type:"number",default:1,if:{shape:["sphere"]}},halfExtents:{type:"vec3",default:{x:.5,y:.5,z:.5},if:{shape:["box"]}},radiusTop:{type:"number",default:1,if:{shape:["cylinder"]}},radiusBottom:{type:"number",default:1,if:{shape:["cylinder"]}},height:{type:"number",default:1,if:{shape:["cylinder"]}},numSegments:{type:"int",default:8,if:{shape:["cylinder"]}}},multiple:!0,init:function(){this.el.sceneEl.hasLoaded?this.initShape():this.el.sceneEl.addEventListener("loaded",this.initShape.bind(this))},initShape:function(){this.bodyEl=this.el;for(var bodyType=this._findType(this.bodyEl),data=this.data;!bodyType&&this.bodyEl.parentNode!=this.el.sceneEl;)this.bodyEl=this.bodyEl.parentNode,bodyType=this._findType(this.bodyEl);if(bodyType){var shape,offset,orientation,scale=new THREE.Vector3;switch(this.bodyEl.object3D.getWorldScale(scale),data.hasOwnProperty("offset")&&(offset=new CANNON.Vec3(data.offset.x*scale.x,data.offset.y*scale.y,data.offset.z*scale.z)),data.hasOwnProperty("orientation")&&(orientation=new CANNON.Quaternion).copy(data.orientation),data.shape){case"sphere":shape=new CANNON.Sphere(data.radius*scale.x);break;case"box":var halfExtents=new CANNON.Vec3(data.halfExtents.x*scale.x,data.halfExtents.y*scale.y,data.halfExtents.z*scale.z);shape=new CANNON.Box(halfExtents);break;case"cylinder":shape=new CANNON.Cylinder(data.radiusTop*scale.x,data.radiusBottom*scale.x,data.height*scale.y,data.numSegments);var quat=new CANNON.Quaternion;quat.setFromEuler(90*THREE.MathUtils.DEG2RAD,0,0,"XYZ").normalize(),orientation.mult(quat,orientation);break;default:return void console.warn(data.shape+" shape not supported")}this.bodyEl.body?this.bodyEl.components[bodyType].addShape(shape,offset,orientation):this.bodyEl.addEventListener("body-loaded",function(){this.bodyEl.components[bodyType].addShape(shape,offset,orientation)},{once:!0})}else console.warn("body not found")},_findType:function(el){return el.hasAttribute("body")?"body":el.hasAttribute("dynamic-body")?"dynamic-body":el.hasAttribute("static-body")?"static-body":null},remove:function(){this.bodyEl.parentNode&&console.warn("removing shape component not currently supported")}};module.exports.definition=Shape,module.exports.Component=AFRAME.registerComponent("shape",Shape)},{"cannon-es":5}],19:[function(require,module,exports){var CANNON=require("cannon-es");module.exports=AFRAME.registerComponent("spring",{multiple:!0,schema:{target:{type:"selector"},restLength:{default:1,min:0},stiffness:{default:100,min:0},damping:{default:1,min:0},localAnchorA:{type:"vec3",default:{x:0,y:0,z:0}},localAnchorB:{type:"vec3",default:{x:0,y:0,z:0}}},init:function(){this.system=this.el.sceneEl.systems.physics,this.system.addComponent(this),this.isActive=!0,this.spring=null},update:function(oldData){var el=this.el,data=this.data;data.target?el.body&&data.target.body?(this.createSpring(),this.updateSpring(oldData)):(el.body?data.target:el).addEventListener("body-loaded",this.update.bind(this,{})):console.warn("Spring: invalid target specified.")},updateSpring:function(oldData){if(this.spring){var data=this.data,spring=this.spring;Object.keys(data).forEach(function(attr){if(data[attr]!==oldData[attr]){if("target"===attr)return void(spring.bodyB=data.target.body);spring[attr]=data[attr]}})}else console.warn("Spring: Component attempted to change spring before its created. No changes made.")},createSpring:function(){this.spring||(this.spring=new CANNON.Spring(this.el.body))},step:function(t,dt){return this.spring&&this.isActive?this.spring.applyForce():void 0},play:function(){this.isActive=!0},pause:function(){this.isActive=!1},remove:function(){this.spring&&delete this.spring,this.spring=null}})},{"cannon-es":5}],20:[function(require,module,exports){module.exports={GRAVITY:-9.8,MAX_INTERVAL:4/60,ITERATIONS:10,CONTACT_MATERIAL:{friction:.01,restitution:.3,contactEquationStiffness:1e8,contactEquationRelaxation:3,frictionEquationStiffness:1e8,frictionEquationRegularization:3},ACTIVATION_STATE:{ACTIVE_TAG:"active",ISLAND_SLEEPING:"islandSleeping",WANTS_DEACTIVATION:"wantsDeactivation",DISABLE_DEACTIVATION:"disableDeactivation",DISABLE_SIMULATION:"disableSimulation"},COLLISION_FLAG:{STATIC_OBJECT:1,KINEMATIC_OBJECT:2,NO_CONTACT_RESPONSE:4,CUSTOM_MATERIAL_CALLBACK:8,CHARACTER_OBJECT:16,DISABLE_VISUALIZE_OBJECT:32,DISABLE_SPU_COLLISION_PROCESSING:64},TYPE:{STATIC:"static",DYNAMIC:"dynamic",KINEMATIC:"kinematic"},SHAPE:{BOX:"box",CYLINDER:"cylinder",SPHERE:"sphere",CAPSULE:"capsule",CONE:"cone",HULL:"hull",HACD:"hacd",VHACD:"vhacd",MESH:"mesh",HEIGHTFIELD:"heightfield"},FIT:{ALL:"all",MANUAL:"manual"},CONSTRAINT:{LOCK:"lock",FIXED:"fixed",SPRING:"spring",SLIDER:"slider",HINGE:"hinge",CONE_TWIST:"coneTwist",POINT_TO_POINT:"pointToPoint"}}},{}],21:[function(require,module,exports){const Driver=require("./driver");"undefined"!=typeof window&&(window.AmmoModule=window.Ammo,window.Ammo=null);function AmmoDriver(){this.collisionConfiguration=null,this.dispatcher=null,this.broadphase=null,this.solver=null,this.physicsWorld=null,this.debugDrawer=null,this.els=new Map,this.eventListeners=[],this.collisions=new Map,this.collisionKeys=[],this.currentCollisions=new Map}AmmoDriver.prototype=new Driver,AmmoDriver.prototype.constructor=AmmoDriver,module.exports=AmmoDriver,AmmoDriver.prototype.init=function(worldConfig){return new Promise(resolve=>{AmmoModule().then(result=>{Ammo=result,this.epsilon=worldConfig.epsilon||1e-5,this.debugDrawMode=worldConfig.debugDrawMode||THREE.AmmoDebugConstants.NoDebug,this.maxSubSteps=worldConfig.maxSubSteps||4,this.fixedTimeStep=worldConfig.fixedTimeStep||1/60,this.collisionConfiguration=new Ammo.btDefaultCollisionConfiguration,this.dispatcher=new Ammo.btCollisionDispatcher(this.collisionConfiguration),this.broadphase=new Ammo.btDbvtBroadphase,this.solver=new Ammo.btSequentialImpulseConstraintSolver,this.physicsWorld=new Ammo.btDiscreteDynamicsWorld(this.dispatcher,this.broadphase,this.solver,this.collisionConfiguration),this.physicsWorld.setForceUpdateAllAabbs(!1),this.physicsWorld.setGravity(new Ammo.btVector3(0,worldConfig.hasOwnProperty("gravity")?worldConfig.gravity:-9.8,0)),this.physicsWorld.getSolverInfo().set_m_numIterations(worldConfig.solverIterations),resolve()})})},AmmoDriver.prototype.addBody=function(body,group,mask){this.physicsWorld.addRigidBody(body,group,mask),this.els.set(Ammo.getPointer(body),body.el)},AmmoDriver.prototype.removeBody=function(body){this.physicsWorld.removeRigidBody(body),this.removeEventListener(body);const bodyptr=Ammo.getPointer(body);this.els.delete(bodyptr),this.collisions.delete(bodyptr),this.collisionKeys.splice(this.collisionKeys.indexOf(bodyptr),1),this.currentCollisions.delete(bodyptr)},AmmoDriver.prototype.updateBody=function(body){this.els.has(Ammo.getPointer(body))&&this.physicsWorld.updateSingleAabb(body)},AmmoDriver.prototype.step=function(deltaTime){this.physicsWorld.stepSimulation(deltaTime,this.maxSubSteps,this.fixedTimeStep);const numManifolds=this.dispatcher.getNumManifolds();for(let i=0;i=0;j--){const body1ptr=body1ptrs[j];this.currentCollisions.get(body0ptr).has(body1ptr)||(-1!==this.eventListeners.indexOf(body0ptr)&&this.els.get(body0ptr).emit("collideend",{targetEl:this.els.get(body1ptr)}),-1!==this.eventListeners.indexOf(body1ptr)&&this.els.get(body1ptr).emit("collideend",{targetEl:this.els.get(body0ptr)}),body1ptrs.splice(j,1))}this.currentCollisions.get(body0ptr).clear()}this.debugDrawer&&this.debugDrawer.update()},AmmoDriver.prototype.addConstraint=function(constraint){this.physicsWorld.addConstraint(constraint,!1)},AmmoDriver.prototype.removeConstraint=function(constraint){this.physicsWorld.removeConstraint(constraint)},AmmoDriver.prototype.addEventListener=function(body){this.eventListeners.push(Ammo.getPointer(body))},AmmoDriver.prototype.removeEventListener=function(body){const ptr=Ammo.getPointer(body);-1!==this.eventListeners.indexOf(ptr)&&this.eventListeners.splice(this.eventListeners.indexOf(ptr),1)},AmmoDriver.prototype.destroy=function(){Ammo.destroy(this.collisionConfiguration),Ammo.destroy(this.dispatcher),Ammo.destroy(this.broadphase),Ammo.destroy(this.solver),Ammo.destroy(this.physicsWorld),Ammo.destroy(this.debugDrawer)},AmmoDriver.prototype.getDebugDrawer=function(scene,options){return this.debugDrawer||((options=options||{}).debugDrawMode=options.debugDrawMode||this.debugDrawMode,this.debugDrawer=new THREE.AmmoDebugDrawer(scene,this.physicsWorld,options)),this.debugDrawer}},{"./driver":22}],22:[function(require,module,exports){function Driver(){}function abstractMethod(){throw new Error("Method not implemented.")}module.exports=Driver,Driver.prototype.init=abstractMethod,Driver.prototype.step=abstractMethod,Driver.prototype.destroy=abstractMethod,Driver.prototype.addBody=abstractMethod,Driver.prototype.removeBody=abstractMethod,Driver.prototype.applyBodyMethod=abstractMethod,Driver.prototype.updateBodyProperties=abstractMethod,Driver.prototype.addMaterial=abstractMethod,Driver.prototype.addContactMaterial=abstractMethod,Driver.prototype.addConstraint=abstractMethod,Driver.prototype.removeConstraint=abstractMethod,Driver.prototype.getContacts=abstractMethod},{}],23:[function(require,module,exports){module.exports={INIT:"init",STEP:"step",ADD_BODY:"add-body",REMOVE_BODY:"remove-body",APPLY_BODY_METHOD:"apply-body-method",UPDATE_BODY_PROPERTIES:"update-body-properties",ADD_MATERIAL:"add-material",ADD_CONTACT_MATERIAL:"add-contact-material",ADD_CONSTRAINT:"add-constraint",REMOVE_CONSTRAINT:"remove-constraint",COLLIDE:"collide"}},{}],24:[function(require,module,exports){var CANNON=require("cannon-es"),Driver=require("./driver");function LocalDriver(){this.world=null,this.materials={},this.contactMaterial=null}LocalDriver.prototype=new Driver,LocalDriver.prototype.constructor=LocalDriver,module.exports=LocalDriver,LocalDriver.prototype.init=function(worldConfig){var world=new CANNON.World;world.quatNormalizeSkip=worldConfig.quatNormalizeSkip,world.quatNormalizeFast=worldConfig.quatNormalizeFast,world.solver.iterations=worldConfig.solverIterations,world.gravity.set(0,worldConfig.gravity,0),world.broadphase=new CANNON.NaiveBroadphase,this.world=world},LocalDriver.prototype.step=function(deltaMS){this.world.step(deltaMS)},LocalDriver.prototype.destroy=function(){delete this.world,delete this.contactMaterial,this.materials={}},LocalDriver.prototype.addBody=function(body){this.world.addBody(body)},LocalDriver.prototype.removeBody=function(body){this.world.removeBody(body)},LocalDriver.prototype.applyBodyMethod=function(body,methodName,args){body["__"+methodName].apply(body,args)},LocalDriver.prototype.updateBodyProperties=function(){},LocalDriver.prototype.getMaterial=function(name){return this.materials[name]},LocalDriver.prototype.addMaterial=function(materialConfig){this.materials[materialConfig.name]=new CANNON.Material(materialConfig),this.materials[materialConfig.name].name=materialConfig.name},LocalDriver.prototype.addContactMaterial=function(matName1,matName2,contactMaterialConfig){var mat1=this.materials[matName1],mat2=this.materials[matName2];this.contactMaterial=new CANNON.ContactMaterial(mat1,mat2,contactMaterialConfig),this.world.addContactMaterial(this.contactMaterial)},LocalDriver.prototype.addConstraint=function(constraint){constraint.type||(constraint instanceof CANNON.LockConstraint?constraint.type="LockConstraint":constraint instanceof CANNON.DistanceConstraint?constraint.type="DistanceConstraint":constraint instanceof CANNON.HingeConstraint?constraint.type="HingeConstraint":constraint instanceof CANNON.ConeTwistConstraint?constraint.type="ConeTwistConstraint":constraint instanceof CANNON.PointToPointConstraint&&(constraint.type="PointToPointConstraint")),this.world.addConstraint(constraint)},LocalDriver.prototype.removeConstraint=function(constraint){this.world.removeConstraint(constraint)},LocalDriver.prototype.getContacts=function(){return this.world.contacts}},{"./driver":22,"cannon-es":5}],25:[function(require,module,exports){var Driver=require("./driver");function NetworkDriver(){throw new Error("[NetworkDriver] Driver not implemented.")}NetworkDriver.prototype=new Driver,NetworkDriver.prototype.constructor=NetworkDriver,module.exports=NetworkDriver},{"./driver":22}],26:[function(require,module,exports){function EventTarget(){this.listeners=[]}module.exports=function(worker){var targetA=new EventTarget,targetB=new EventTarget;return targetA.setTarget(targetB),targetB.setTarget(targetA),worker(targetA),targetB},EventTarget.prototype.setTarget=function(target){this.target=target},EventTarget.prototype.addEventListener=function(type,fn){this.listeners.push(fn)},EventTarget.prototype.dispatchEvent=function(type,event){for(var i=0;ithis.frameDelay;)this.frameBuffer.shift(),prevFrame=this.frameBuffer[0],nextFrame=this.frameBuffer[1];if(prevFrame&&nextFrame){var mix=(timestamp-prevFrame.timestamp)/this.frameDelay;for(var id in mix=(mix-(1-1/this.interpBufferSize))*this.interpBufferSize,prevFrame.bodies)prevFrame.bodies.hasOwnProperty(id)&&nextFrame.bodies.hasOwnProperty(id)&&protocol.deserializeInterpBodyUpdate(prevFrame.bodies[id],nextFrame.bodies[id],this.bodies[id],mix)}}},WorkerDriver.prototype.destroy=function(){this.worker.terminate(),delete this.worker},WorkerDriver.prototype._onMessage=function(event){if(event.data.type===Event.STEP){var bodies=event.data.bodies;if(this.contacts=event.data.contacts,this.interpolate)this.frameBuffer.push({timestamp:performance.now(),bodies:bodies});else for(var id in bodies)bodies.hasOwnProperty(id)&&protocol.deserializeBodyUpdate(bodies[id],this.bodies[id])}else{if(event.data.type!==Event.COLLIDE)throw new Error("[WorkerDriver] Unexpected message type.");var body=this.bodies[event.data.bodyID],target=this.bodies[event.data.targetID],contact=protocol.deserializeContact(event.data.contact,this.bodies);if(!body._listeners||!body._listeners.collide)return;for(var i=0;ithis.countBodiesAmmo(),local:()=>this.countBodiesCannon(!1),worker:()=>this.countBodiesCannon(!0)},this.bodyTypeToStatsPropertyMap={ammo:{[TYPE.STATIC]:"staticBodies",[TYPE.KINEMATIC]:"kinematicBodies",[TYPE.DYNAMIC]:"dynamicBodies"},cannon:{[CANNON.Body.STATIC]:"staticBodies",[CANNON.Body.DYNAMIC]:"dynamicBodies"}},this.el.sceneEl.setAttribute("stats-collector","inEvent: physics-tick-data;\n properties: before, after, engine, total;\n outputFrequency: 100;\n outEvent: physics-tick-summary;\n outputs: percentile__50, percentile__90, max")}if(this.statsToPanel){const scene=this.el.sceneEl,space="   ";scene.setAttribute("stats-panel",""),scene.setAttribute("stats-group__bodies","label: Physics Bodies"),scene.setAttribute("stats-row__b1","group: bodies;\n event:physics-body-data;\n properties: staticBodies;\n label: Static"),scene.setAttribute("stats-row__b2","group: bodies;\n event:physics-body-data;\n properties: dynamicBodies;\n label: Dynamic"),"local"===this.data.driver||"worker"===this.data.driver?scene.setAttribute("stats-row__b3","group: bodies;\n event:physics-body-data;\n properties: contacts;\n label: Contacts"):"ammo"===this.data.driver&&(scene.setAttribute("stats-row__b3","group: bodies;\n event:physics-body-data;\n properties: kinematicBodies;\n label: Kinematic"),scene.setAttribute("stats-row__b4","group: bodies;\n event: physics-body-data;\n properties: manifolds;\n label: Manifolds"),scene.setAttribute("stats-row__b5","group: bodies;\n event: physics-body-data;\n properties: manifoldContacts;\n label: Contacts"),scene.setAttribute("stats-row__b6","group: bodies;\n event: physics-body-data;\n properties: collisions;\n label: Collisions"),scene.setAttribute("stats-row__b7","group: bodies;\n event: physics-body-data;\n properties: collisionKeys;\n label: Coll Keys")),scene.setAttribute("stats-group__tick",`label: Physics Ticks: Median${space}90th%${space}99th%`),scene.setAttribute("stats-row__1","group: tick;\n event:physics-tick-summary;\n properties: before.percentile__50, \n before.percentile__90, \n before.max;\n label: Before"),scene.setAttribute("stats-row__2","group: tick;\n event:physics-tick-summary;\n properties: after.percentile__50, \n after.percentile__90, \n after.max; \n label: After"),scene.setAttribute("stats-row__3","group: tick; \n event:physics-tick-summary; \n properties: engine.percentile__50, \n engine.percentile__90, \n engine.max;\n label: Engine"),scene.setAttribute("stats-row__4","group: tick;\n event:physics-tick-summary;\n properties: total.percentile__50, \n total.percentile__90, \n total.max;\n label: Total")}},tick:function(t,dt){if(!this.initialized||!dt)return;const beforeStartTime=performance.now();var i,callbacks=this.callbacks;for(i=0;i{const property=this.bodyTypeToStatsPropertyMap.ammo[(el=el,el.components["ammo-body"].data.type)];statsData[property]++})},countBodiesCannon(worker){const statsData=this.statsBodyData;statsData.contacts=worker?this.driver.contacts.length:this.driver.world.contacts.length,statsData.staticBodies=0,statsData.dynamicBodies=0,(worker?Object.values(this.driver.bodies):this.driver.world.bodies).forEach(body=>{const property=this.bodyTypeToStatsPropertyMap.cannon[body.type];statsData[property]++})},setDebug:function(debug){this.debug=debug,"ammo"===this.data.driver&&this.initialized&&(debug&&!this.debugDrawer?(this.debugDrawer=this.driver.getDebugDrawer(this.el.object3D),this.debugDrawer.enable()):this.debugDrawer&&(this.debugDrawer.disable(),this.debugDrawer=null))},addBody:function(body,group,mask){var driver=this.driver;"local"===this.data.driver&&(body.__applyImpulse=body.applyImpulse,body.applyImpulse=function(){driver.applyBodyMethod(body,"applyImpulse",arguments)},body.__applyForce=body.applyForce,body.applyForce=function(){driver.applyBodyMethod(body,"applyForce",arguments)},body.updateProperties=function(){driver.updateBodyProperties(body)},this.listeners[body.id]=function(e){body.el.emit("collide",e)},body.addEventListener("collide",this.listeners[body.id])),this.driver.addBody(body,group,mask)},removeBody:function(body){this.driver.removeBody(body),"local"!==this.data.driver&&"worker"!==this.data.driver||(body.removeEventListener("collide",this.listeners[body.id]),delete this.listeners[body.id],body.applyImpulse=body.__applyImpulse,delete body.__applyImpulse,body.applyForce=body.__applyForce,delete body.__applyForce,delete body.updateProperties)},addConstraint:function(constraint){this.driver.addConstraint(constraint)},removeConstraint:function(constraint){this.driver.removeConstraint(constraint)},addComponent:function(component){var callbacks=this.callbacks;component.beforeStep&&callbacks.beforeStep.push(component),component.step&&callbacks.step.push(component),component.afterStep&&callbacks.afterStep.push(component)},removeComponent:function(component){var callbacks=this.callbacks;component.beforeStep&&callbacks.beforeStep.splice(callbacks.beforeStep.indexOf(component),1),component.step&&callbacks.step.splice(callbacks.step.indexOf(component),1),component.afterStep&&callbacks.afterStep.splice(callbacks.afterStep.indexOf(component),1)},getContacts:function(){return this.driver.getContacts()},getMaterial:function(name){return this.driver.getMaterial(name)}})},{"./constants":20,"./drivers/ammo-driver":21,"./drivers/local-driver":24,"./drivers/network-driver":25,"./drivers/worker-driver":27,"aframe-stats-panel":3,"cannon-es":5}],30:[function(require,module,exports){module.exports.slerp=function(a,b,t){if(t<=0)return a;if(t>=1)return b;var x=a[0],y=a[1],z=a[2],w=a[3],cosHalfTheta=w*b[3]+x*b[0]+y*b[1]+z*b[2];if(!(cosHalfTheta<0))return b;if((a=a.slice())[3]=-b[3],a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],(cosHalfTheta=-cosHalfTheta)>=1)return a[3]=w,a[0]=x,a[1]=y,a[2]=z,this;var sinHalfTheta=Math.sqrt(1-cosHalfTheta*cosHalfTheta);if(Math.abs(sinHalfTheta)<.001)return a[3]=.5*(w+a[3]),a[0]=.5*(x+a[0]),a[1]=.5*(y+a[1]),a[2]=.5*(z+a[2]),this;var halfTheta=Math.atan2(sinHalfTheta,cosHalfTheta),ratioA=Math.sin((1-t)*halfTheta)/sinHalfTheta,ratioB=Math.sin(t*halfTheta)/sinHalfTheta;return a[3]=w*ratioA+a[3]*ratioB,a[0]=x*ratioA+a[0]*ratioB,a[1]=y*ratioA+a[1]*ratioB,a[2]=z*ratioA+a[2]*ratioB,a}},{}],31:[function(require,module,exports){var CANNON=require("cannon-es"),mathUtils=require("./math"),ID="__id";module.exports.ID=ID;var nextID={};function serializeShape(shape){var shapeMsg={type:shape.type};if(shape.type===CANNON.Shape.types.BOX)shapeMsg.halfExtents=serializeVec3(shape.halfExtents);else if(shape.type===CANNON.Shape.types.SPHERE)shapeMsg.radius=shape.radius;else{if(shape._type!==CANNON.Shape.types.CYLINDER)throw new Error("Unimplemented shape type: %s",shape.type);shapeMsg.type=CANNON.Shape.types.CYLINDER,shapeMsg.radiusTop=shape.radiusTop,shapeMsg.radiusBottom=shape.radiusBottom,shapeMsg.height=shape.height,shapeMsg.numSegments=shape.numSegments}return shapeMsg}function deserializeShape(message){var shape;if(message.type===CANNON.Shape.types.BOX)shape=new CANNON.Box(deserializeVec3(message.halfExtents));else if(message.type===CANNON.Shape.types.SPHERE)shape=new CANNON.Sphere(message.radius);else{if(message.type!==CANNON.Shape.types.CYLINDER)throw new Error("Unimplemented shape type: %s",message.type);(shape=new CANNON.Cylinder(message.radiusTop,message.radiusBottom,message.height,message.numSegments))._type=CANNON.Shape.types.CYLINDER}return shape}function serializeVec3(vec3){return vec3.toArray()}function deserializeVec3(message){return new CANNON.Vec3(message[0],message[1],message[2])}function serializeQuaternion(quat){return quat.toArray()}function deserializeQuaternion(message){return new CANNON.Quaternion(message[0],message[1],message[2],message[3])}module.exports.assignID=function(prefix,object){object[ID]||(nextID[prefix]=nextID[prefix]||1,object[ID]=prefix+"_"+nextID[prefix]++)},module.exports.serializeBody=function(body){return{shapes:body.shapes.map(serializeShape),shapeOffsets:body.shapeOffsets.map(serializeVec3),shapeOrientations:body.shapeOrientations.map(serializeQuaternion),position:serializeVec3(body.position),quaternion:body.quaternion.toArray(),velocity:serializeVec3(body.velocity),angularVelocity:serializeVec3(body.angularVelocity),id:body[ID],mass:body.mass,linearDamping:body.linearDamping,angularDamping:body.angularDamping,fixedRotation:body.fixedRotation,allowSleep:body.allowSleep,sleepSpeedLimit:body.sleepSpeedLimit,sleepTimeLimit:body.sleepTimeLimit}},module.exports.deserializeBodyUpdate=function(message,body){return body.position.set(message.position[0],message.position[1],message.position[2]),body.quaternion.set(message.quaternion[0],message.quaternion[1],message.quaternion[2],message.quaternion[3]),body.velocity.set(message.velocity[0],message.velocity[1],message.velocity[2]),body.angularVelocity.set(message.angularVelocity[0],message.angularVelocity[1],message.angularVelocity[2]),body.linearDamping=message.linearDamping,body.angularDamping=message.angularDamping,body.fixedRotation=message.fixedRotation,body.allowSleep=message.allowSleep,body.sleepSpeedLimit=message.sleepSpeedLimit,body.sleepTimeLimit=message.sleepTimeLimit,body.mass!==message.mass&&(body.mass=message.mass,body.updateMassProperties()),body},module.exports.deserializeInterpBodyUpdate=function(message1,message2,body,mix){var weight1=1-mix,weight2=mix;body.position.set(message1.position[0]*weight1+message2.position[0]*weight2,message1.position[1]*weight1+message2.position[1]*weight2,message1.position[2]*weight1+message2.position[2]*weight2);var quaternion=mathUtils.slerp(message1.quaternion,message2.quaternion,mix);return body.quaternion.set(quaternion[0],quaternion[1],quaternion[2],quaternion[3]),body.velocity.set(message1.velocity[0]*weight1+message2.velocity[0]*weight2,message1.velocity[1]*weight1+message2.velocity[1]*weight2,message1.velocity[2]*weight1+message2.velocity[2]*weight2),body.angularVelocity.set(message1.angularVelocity[0]*weight1+message2.angularVelocity[0]*weight2,message1.angularVelocity[1]*weight1+message2.angularVelocity[1]*weight2,message1.angularVelocity[2]*weight1+message2.angularVelocity[2]*weight2),body.linearDamping=message2.linearDamping,body.angularDamping=message2.angularDamping,body.fixedRotation=message2.fixedRotation,body.allowSleep=message2.allowSleep,body.sleepSpeedLimit=message2.sleepSpeedLimit,body.sleepTimeLimit=message2.sleepTimeLimit,body.mass!==message2.mass&&(body.mass=message2.mass,body.updateMassProperties()),body},module.exports.deserializeBody=function(message){for(var shapeMsg,body=new CANNON.Body({mass:message.mass,position:deserializeVec3(message.position),quaternion:deserializeQuaternion(message.quaternion),velocity:deserializeVec3(message.velocity),angularVelocity:deserializeVec3(message.angularVelocity),linearDamping:message.linearDamping,angularDamping:message.angularDamping,fixedRotation:message.fixedRotation,allowSleep:message.allowSleep,sleepSpeedLimit:message.sleepSpeedLimit,sleepTimeLimit:message.sleepTimeLimit}),i=0;shapeMsg=message.shapes[i];i++)body.addShape(deserializeShape(shapeMsg),deserializeVec3(message.shapeOffsets[i]),deserializeQuaternion(message.shapeOrientations[i]));return body[ID]=message.id,body},module.exports.serializeShape=serializeShape,module.exports.deserializeShape=deserializeShape,module.exports.serializeConstraint=function(constraint){var message={id:constraint[ID],type:constraint.type,maxForce:constraint.maxForce,bodyA:constraint.bodyA[ID],bodyB:constraint.bodyB[ID]};switch(constraint.type){case"LockConstraint":break;case"DistanceConstraint":message.distance=constraint.distance;break;case"HingeConstraint":case"ConeTwistConstraint":message.axisA=serializeVec3(constraint.axisA),message.axisB=serializeVec3(constraint.axisB),message.pivotA=serializeVec3(constraint.pivotA),message.pivotB=serializeVec3(constraint.pivotB);break;case"PointToPointConstraint":message.pivotA=serializeVec3(constraint.pivotA),message.pivotB=serializeVec3(constraint.pivotB);break;default:throw new Error("Unexpected constraint type: "+constraint.type+'. You may need to manually set `constraint.type = "FooConstraint";`.')}return message},module.exports.deserializeConstraint=function(message,bodies){var constraint,TypedConstraint=CANNON[message.type],bodyA=bodies[message.bodyA],bodyB=bodies[message.bodyB];switch(message.type){case"LockConstraint":constraint=new CANNON.LockConstraint(bodyA,bodyB,message);break;case"DistanceConstraint":constraint=new CANNON.DistanceConstraint(bodyA,bodyB,message.distance,message.maxForce);break;case"HingeConstraint":case"ConeTwistConstraint":constraint=new TypedConstraint(bodyA,bodyB,{pivotA:deserializeVec3(message.pivotA),pivotB:deserializeVec3(message.pivotB),axisA:deserializeVec3(message.axisA),axisB:deserializeVec3(message.axisB),maxForce:message.maxForce});break;case"PointToPointConstraint":constraint=new CANNON.PointToPointConstraint(bodyA,deserializeVec3(message.pivotA),bodyB,deserializeVec3(message.pivotB),message.maxForce);break;default:throw new Error("Unexpected constraint type: "+message.type)}return constraint[ID]=message.id,constraint},module.exports.serializeContact=function(contact){return{bi:contact.bi[ID],bj:contact.bj[ID],ni:serializeVec3(contact.ni),ri:serializeVec3(contact.ri),rj:serializeVec3(contact.rj)}},module.exports.deserializeContact=function(message,bodies){return{bi:bodies[message.bi],bj:bodies[message.bj],ni:deserializeVec3(message.ni),ri:deserializeVec3(message.ri),rj:deserializeVec3(message.rj)}},module.exports.serializeVec3=serializeVec3,module.exports.deserializeVec3=deserializeVec3,module.exports.serializeQuaternion=serializeQuaternion,module.exports.deserializeQuaternion=deserializeQuaternion},{"./math":30,"cannon-es":5}]},{},[1]); \ No newline at end of file +!function(){return 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){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i{const counterValue=document.createElement("div");counterValue.classList.add("rs-counter-value"),counterValue.innerHTML="...",this.counter.appendChild(counterValue),this.counterValues[property]=counterValue}),this.updateData=this.updateData.bind(this),this.el.addEventListener(this.data.event,this.updateData),this.splitCache={}):console.warn(`Couldn't find stats group ${groupComponentName}`)},updateData(e){this.data.properties.forEach(property=>{const split=this.splitDot(property);let value=e.detail;for(i=0;i{this.outputDetail[property]={}}),this.statsReceived=this.statsReceived.bind(this),this.el.addEventListener(this.data.inEvent,this.statsReceived)},resetData(){this.counter=0,this.data.properties.forEach(property=>{this.statsData[property]=[]})},statsReceived(e){this.updateData(e.detail),this.counter++,this.counter===this.data.outputFrequency&&(this.outputData(),this.resetData())},updateData(detail){this.data.properties.forEach(property=>{let value=detail;value=value[property],this.statsData[property].push(value)})},outputData(){this.data.properties.forEach(property=>{this.data.outputs.forEach(output=>{this.outputDetail[property][output]=this.computeOutput(output,this.statsData[property])})}),this.data.outEvent&&this.el.emit(this.data.outEvent,this.outputDetail),this.data.outputToConsole&&console.log(this.data.outputToConsole,this.outputDetail)},computeOutput(outputInstruction,data){const outputInstructions=outputInstruction.split("__");let output;switch(outputInstructions[0]){case"mean":output=data.reduce((a,b)=>a+b,0)/data.length;break;case"max":output=Math.max(...data);break;case"min":output=Math.min(...data);break;case"percentile":const sorted=data.sort((a,b)=>a-b),proportion=+outputInstructions[1].replace("_",".")/100,position=(data.length-1)*proportion,base=Math.floor(position),delta=position-base;output=void 0!==sorted[base+1]?sorted[base]+delta*(sorted[base+1]-sorted[base]):sorted[base]}return output.toFixed(2)}})},{}],4:[function(require,module,exports){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:2048,DrawConstraintLimits:4096,FastWireframe:8192,DrawNormals:16384,DrawOnTop:32768,MAX_DEBUG_DRAW_MODE:4294967295},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||!1,maxBufferSize=options.maxBufferSize||1e6;this.geometry=new THREE.BufferGeometry;var vertices=new Float32Array(3*maxBufferSize),colors=new Float32Array(3*maxBufferSize);this.geometry.setAttribute("position",new THREE.BufferAttribute(vertices,3).setUsage(THREE.DynamicDrawUsage)),this.geometry.setAttribute("color",new THREE.BufferAttribute(colors,3).setUsage(THREE.DynamicDrawUsage)),this.index=0;var material=new THREE.LineBasicMaterial({vertexColors:!0,depthTest:!drawOnTop});this.mesh=new THREE.LineSegments(this.geometry,material),drawOnTop&&(this.mesh.renderOrder=999),this.mesh.frustumCulled=!1,this.enabled=!1,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=!0,this.scene.add(this.mesh)},THREE.AmmoDebugDrawer.prototype.disable=function(){this.enabled=!1,this.scene.remove(this.mesh)},THREE.AmmoDebugDrawer.prototype.update=function(){this.enabled&&(0!=this.index&&(this.geometry.attributes.position.needsUpdate=!0,this.geometry.attributes.color.needsUpdate=!0),this.index=0,this.world.debugDrawWorld(),this.geometry.setDrawRange(0,this.index))},THREE.AmmoDebugDrawer.prototype.drawLine=function(from,to,color){const heap=Ammo.HEAPF32,r=heap[(color+0)/4],g=heap[(color+4)/4],b=heap[(color+8)/4],fromX=heap[(from+0)/4],fromY=heap[(from+4)/4],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],toY=heap[(to+4)/4],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)},THREE.AmmoDebugDrawer.prototype.drawContactPoint=function(pointOnB,normalOnB,distance,lifeTime,color){const heap=Ammo.HEAPF32,r=heap[(color+0)/4],g=heap[(color+4)/4],b=heap[(color+8)/4],x=heap[(pointOnB+0)/4],y=heap[(pointOnB+4)/4],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,dy=heap[(normalOnB+4)/4]*distance,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){Ammo.hasOwnProperty("Pointer_stringify")?console.warn(Ammo.Pointer_stringify(warningString)):this.warnedOnce||(this.warnedOnce=!0,console.warn("Cannot print warningString, please rebuild Ammo.js using 'debug' flag"))},THREE.AmmoDebugDrawer.prototype.draw3dText=function(location,textString){console.warn("TODO: draw3dText")},THREE.AmmoDebugDrawer.prototype.setDebugMode=function(debugMode){this.debugDrawMode=debugMode},THREE.AmmoDebugDrawer.prototype.getDebugMode=function(){return this.debugDrawMode}},{}],5:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.World=exports.Vec3Pool=exports.Vec3=exports.Trimesh=exports.Transform=exports.Spring=exports.SplitSolver=exports.Sphere=exports.Solver=exports.Shape=exports.SPHSystem=exports.SHAPE_TYPES=exports.SAPBroadphase=exports.RotationalMotorEquation=exports.RotationalEquation=exports.RigidVehicle=exports.RaycastVehicle=exports.RaycastResult=exports.Ray=exports.RAY_MODES=exports.Quaternion=exports.Pool=exports.PointToPointConstraint=exports.Plane=exports.Particle=exports.ObjectCollisionMatrix=exports.Narrowphase=exports.NaiveBroadphase=exports.Material=exports.Mat3=exports.LockConstraint=exports.JacobianElement=exports.HingeConstraint=exports.Heightfield=exports.GridBroadphase=exports.GSSolver=exports.FrictionEquation=exports.EventTarget=exports.Equation=exports.DistanceConstraint=exports.Cylinder=exports.ConvexPolyhedron=exports.ContactMaterial=exports.ContactEquation=exports.Constraint=exports.ConeTwistConstraint=exports.COLLISION_TYPES=exports.Broadphase=exports.Box=exports.Body=exports.BODY_TYPES=exports.BODY_SLEEP_STATES=exports.ArrayCollisionMatrix=exports.AABB=void 0;exports.ObjectCollisionMatrix=class{constructor(){this.matrix={}}get(bi,bj){let{id:i}=bi,{id:j}=bj;if(j>i){const temp=j;j=i,i=temp}return i+"-"+j in this.matrix}set(bi,bj,value){let{id:i}=bi,{id:j}=bj;if(j>i){const temp=j;j=i,i=temp}value?this.matrix[i+"-"+j]=!0:delete this.matrix[i+"-"+j]}reset(){this.matrix={}}setNumObjects(n){}};class Mat3{constructor(elements=[0,0,0,0,0,0,0,0,0]){this.elements=elements}identity(){const 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}setZero(){const 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}setTrace(vector){const e=this.elements;e[0]=vector.x,e[4]=vector.y,e[8]=vector.z}getTrace(target=new Vec3){const e=this.elements;target.x=e[0],target.y=e[4],target.z=e[8]}vmult(v,target=new Vec3){const e=this.elements,x=v.x,y=v.y,z=v.z;return 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,target}smult(s){for(let i=0;i0){const invN=1/n;this.x*=invN,this.y*=invN,this.z*=invN}else this.x=0,this.y=0,this.z=0;return n}unit(target=new Vec3){const x=this.x,y=this.y,z=this.z;let ninv=Math.sqrt(x*x+y*y+z*z);return ninv>0?(ninv=1/ninv,target.x=x*ninv,target.y=y*ninv,target.z=z*ninv):(target.x=1,target.y=0,target.z=0),target}length(){const x=this.x,y=this.y,z=this.z;return Math.sqrt(x*x+y*y+z*z)}lengthSquared(){return this.dot(this)}distanceTo(p){const x=this.x,y=this.y,z=this.z,px=p.x,py=p.y,pz=p.z;return Math.sqrt((px-x)*(px-x)+(py-y)*(py-y)+(pz-z)*(pz-z))}distanceSquared(p){const x=this.x,y=this.y,z=this.z,px=p.x,py=p.y,pz=p.z;return(px-x)*(px-x)+(py-y)*(py-y)+(pz-z)*(pz-z)}scale(scalar,target=new Vec3){const x=this.x,y=this.y,z=this.z;return target.x=scalar*x,target.y=scalar*y,target.z=scalar*z,target}vmul(vector,target=new Vec3){return target.x=vector.x*this.x,target.y=vector.y*this.y,target.z=vector.z*this.z,target}addScaledVector(scalar,vector,target=new Vec3){return target.x=this.x+scalar*vector.x,target.y=this.y+scalar*vector.y,target.z=this.z+scalar*vector.z,target}dot(vector){return this.x*vector.x+this.y*vector.y+this.z*vector.z}isZero(){return 0===this.x&&0===this.y&&0===this.z}negate(target=new Vec3){return target.x=-this.x,target.y=-this.y,target.z=-this.z,target}tangents(t1,t2){const norm=this.length();if(norm>0){const n=Vec3_tangents_n,inorm=1/norm;n.set(this.x*inorm,this.y*inorm,this.z*inorm);const randVec=Vec3_tangents_randVec;Math.abs(n.x)<.9?(randVec.set(1,0,0),n.cross(randVec,t1)):(randVec.set(0,1,0),n.cross(randVec,t1)),n.cross(t1,t2)}else t1.set(1,0,0),t2.set(0,1,0)}toString(){return this.x+","+this.y+","+this.z}toArray(){return[this.x,this.y,this.z]}copy(vector){return this.x=vector.x,this.y=vector.y,this.z=vector.z,this}lerp(vector,t,target){const x=this.x,y=this.y,z=this.z;target.x=x+(vector.x-x)*t,target.y=y+(vector.y-y)*t,target.z=z+(vector.z-z)*t}almostEquals(vector,precision=1e-6){return!(Math.abs(this.x-vector.x)>precision||Math.abs(this.y-vector.y)>precision||Math.abs(this.z-vector.z)>precision)}almostZero(precision=1e-6){return!(Math.abs(this.x)>precision||Math.abs(this.y)>precision||Math.abs(this.z)>precision)}isAntiparallelTo(vector,precision){return this.negate(antip_neg),antip_neg.almostEquals(vector,precision)}clone(){return new Vec3(this.x,this.y,this.z)}}exports.Vec3=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);const Vec3_tangents_n=new Vec3,Vec3_tangents_randVec=new Vec3,antip_neg=new Vec3;class AABB{constructor(options={}){this.lowerBound=new Vec3,this.upperBound=new Vec3,options.lowerBound&&this.lowerBound.copy(options.lowerBound),options.upperBound&&this.upperBound.copy(options.upperBound)}setFromPoints(points,position,quaternion,skinSize){const l=this.lowerBound,u=this.upperBound,q=quaternion;l.copy(points[0]),q&&q.vmult(l,l),u.copy(l);for(let i=1;iu.x&&(u.x=p.x),p.xu.y&&(u.y=p.y),p.yu.z&&(u.z=p.z),p.z=u2.x&&l1.y<=l2.y&&u1.y>=u2.y&&l1.z<=l2.z&&u1.z>=u2.z}getCorners(a,b,c,d,e,f,g,h){const l=this.lowerBound,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)}toLocalFrame(frame,target){const corners=transformIntoFrame_corners,a=corners[0],b=corners[1],c=corners[2],d=corners[3],e=corners[4],f=corners[5],g=corners[6],h=corners[7];this.getCorners(a,b,c,d,e,f,g,h);for(let i=0;8!==i;i++){const corner=corners[i];frame.pointToLocal(corner,corner)}return target.setFromPoints(corners)}toWorldFrame(frame,target){const corners=transformIntoFrame_corners,a=corners[0],b=corners[1],c=corners[2],d=corners[3],e=corners[4],f=corners[5],g=corners[6],h=corners[7];this.getCorners(a,b,c,d,e,f,g,h);for(let i=0;8!==i;i++){const corner=corners[i];frame.pointToWorld(corner,corner)}return target.setFromPoints(corners)}overlapsRay(ray){const{direction:direction,from:from}=ray,dirFracX=1/direction.x,dirFracY=1/direction.y,dirFracZ=1/direction.z,t1=(this.lowerBound.x-from.x)*dirFracX,t2=(this.upperBound.x-from.x)*dirFracX,t3=(this.lowerBound.y-from.y)*dirFracY,t4=(this.upperBound.y-from.y)*dirFracY,t5=(this.lowerBound.z-from.z)*dirFracZ,t6=(this.upperBound.z-from.z)*dirFracZ,tmin=Math.max(Math.max(Math.min(t1,t2),Math.min(t3,t4)),Math.min(t5,t6)),tmax=Math.min(Math.min(Math.max(t1,t2),Math.max(t3,t4)),Math.max(t5,t6));return!(tmax<0)&&!(tmin>tmax)}}exports.AABB=AABB;const tmp=new Vec3,transformIntoFrame_corners=[new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3];class ArrayCollisionMatrix{constructor(){this.matrix=[]}get(bi,bj){let{index:i}=bi,{index:j}=bj;if(j>i){const temp=j;j=i,i=temp}return this.matrix[(i*(i+1)>>1)+j-1]}set(bi,bj,value){let{index:i}=bi,{index:j}=bj;if(j>i){const temp=j;j=i,i=temp}this.matrix[(i*(i+1)>>1)+j-1]=value?1:0}reset(){for(let i=0,l=this.matrix.length;i!==l;i++)this.matrix[i]=0}setNumObjects(n){this.matrix.length=n*(n-1)>>1}}exports.ArrayCollisionMatrix=ArrayCollisionMatrix;class EventTarget{constructor(){}addEventListener(type,listener){void 0===this._listeners&&(this._listeners={});const listeners=this._listeners;return void 0===listeners[type]&&(listeners[type]=[]),listeners[type].includes(listener)||listeners[type].push(listener),this}hasEventListener(type,listener){if(void 0===this._listeners)return!1;const listeners=this._listeners;return!(void 0===listeners[type]||!listeners[type].includes(listener))}hasAnyEventListener(type){if(void 0===this._listeners)return!1;return void 0!==this._listeners[type]}removeEventListener(type,listener){if(void 0===this._listeners)return this;const listeners=this._listeners;if(void 0===listeners[type])return this;const index=listeners[type].indexOf(listener);return-1!==index&&listeners[type].splice(index,1),this}dispatchEvent(event){if(void 0===this._listeners)return this;const listenerArray=this._listeners[event.type];if(void 0!==listenerArray){event.target=this;for(let i=0,l=listenerArray.length;i.499&&(heading=2*Math.atan2(x,w),attitude=Math.PI/2,bank=0),test<-.499&&(heading=-2*Math.atan2(x,w),attitude=-Math.PI/2,bank=0),void 0===heading){const sqx=x*x,sqy=y*y,sqz=z*z;heading=Math.atan2(2*y*w-2*x*z,1-2*sqy-2*sqz),attitude=Math.asin(2*test),bank=Math.atan2(2*x*w-2*y*z,1-2*sqx-2*sqz)}break;default:throw new Error("Euler order "+order+" not supported yet.")}target.y=heading,target.z=attitude,target.x=bank}setFromEuler(x,y,z,order="XYZ"){const c1=Math.cos(x/2),c2=Math.cos(y/2),c3=Math.cos(z/2),s1=Math.sin(x/2),s2=Math.sin(y/2),s3=Math.sin(z/2);return"XYZ"===order?(this.x=s1*c2*c3+c1*s2*s3,this.y=c1*s2*c3-s1*c2*s3,this.z=c1*c2*s3+s1*s2*c3,this.w=c1*c2*c3-s1*s2*s3):"YXZ"===order?(this.x=s1*c2*c3+c1*s2*s3,this.y=c1*s2*c3-s1*c2*s3,this.z=c1*c2*s3-s1*s2*c3,this.w=c1*c2*c3+s1*s2*s3):"ZXY"===order?(this.x=s1*c2*c3-c1*s2*s3,this.y=c1*s2*c3+s1*c2*s3,this.z=c1*c2*s3+s1*s2*c3,this.w=c1*c2*c3-s1*s2*s3):"ZYX"===order?(this.x=s1*c2*c3-c1*s2*s3,this.y=c1*s2*c3+s1*c2*s3,this.z=c1*c2*s3-s1*s2*c3,this.w=c1*c2*c3+s1*s2*s3):"YZX"===order?(this.x=s1*c2*c3+c1*s2*s3,this.y=c1*s2*c3+s1*c2*s3,this.z=c1*c2*s3-s1*s2*c3,this.w=c1*c2*c3-s1*s2*s3):"XZY"===order&&(this.x=s1*c2*c3-c1*s2*s3,this.y=c1*s2*c3-s1*c2*s3,this.z=c1*c2*s3+s1*s2*c3,this.w=c1*c2*c3+s1*s2*s3),this}clone(){return new Quaternion(this.x,this.y,this.z,this.w)}slerp(toQuat,t,target=new Quaternion){const ax=this.x,ay=this.y,az=this.z,aw=this.w;let omega,cosom,sinom,scale0,scale1,bx=toQuat.x,by=toQuat.y,bz=toQuat.z,bw=toQuat.w;return(cosom=ax*bx+ay*by+az*bz+aw*bw)<0&&(cosom=-cosom,bx=-bx,by=-by,bz=-bz,bw=-bw),1-cosom>1e-6?(omega=Math.acos(cosom),sinom=Math.sin(omega),scale0=Math.sin((1-t)*omega)/sinom,scale1=Math.sin(t*omega)/sinom):(scale0=1-t,scale1=t),target.x=scale0*ax+scale1*bx,target.y=scale0*ay+scale1*by,target.z=scale0*az+scale1*bz,target.w=scale0*aw+scale1*bw,target}integrate(angularVelocity,dt,angularFactor,target=new Quaternion){const ax=angularVelocity.x*angularFactor.x,ay=angularVelocity.y*angularFactor.y,az=angularVelocity.z*angularFactor.z,bx=this.x,by=this.y,bz=this.z,bw=this.w,half_dt=.5*dt;return target.x+=half_dt*(ax*bw+ay*bz-az*by),target.y+=half_dt*(ay*bw+az*bx-ax*bz),target.z+=half_dt*(az*bw+ax*by-ay*bx),target.w+=half_dt*(-ax*bx-ay*by-az*bz),target}}exports.Quaternion=Quaternion;const sfv_t1=new Vec3,sfv_t2=new Vec3,SHAPE_TYPES=exports.SHAPE_TYPES={SPHERE:1,PLANE:2,BOX:4,COMPOUND:8,CONVEXPOLYHEDRON:16,HEIGHTFIELD:32,PARTICLE:64,CYLINDER:128,TRIMESH:256};class Shape{constructor(options={}){this.id=Shape.idCounter++,this.type=options.type||0,this.boundingSphereRadius=0,this.collisionResponse=!options.collisionResponse||options.collisionResponse,this.collisionFilterGroup=void 0!==options.collisionFilterGroup?options.collisionFilterGroup:1,this.collisionFilterMask=void 0!==options.collisionFilterMask?options.collisionFilterMask:-1,this.material=options.material?options.material:null,this.body=null}updateBoundingSphereRadius(){throw"computeBoundingSphereRadius() not implemented for shape type "+this.type}volume(){throw"volume() not implemented for shape type "+this.type}calculateLocalInertia(mass,target){throw"calculateLocalInertia() not implemented for shape type "+this.type}calculateWorldAABB(pos,quat,min,max){throw"calculateWorldAABB() not implemented for shape type "+this.type}}exports.Shape=Shape,Shape.idCounter=0,Shape.types=SHAPE_TYPES;class Transform{constructor(options={}){this.position=new Vec3,this.quaternion=new Quaternion,options.position&&this.position.copy(options.position),options.quaternion&&this.quaternion.copy(options.quaternion)}pointToLocal(worldPoint,result){return Transform.pointToLocalFrame(this.position,this.quaternion,worldPoint,result)}pointToWorld(localPoint,result){return Transform.pointToWorldFrame(this.position,this.quaternion,localPoint,result)}vectorToWorldFrame(localVector,result=new Vec3){return this.quaternion.vmult(localVector,result),result}static pointToLocalFrame(position,quaternion,worldPoint,result=new Vec3){return worldPoint.vsub(position,result),quaternion.conjugate(tmpQuat),tmpQuat.vmult(result,result),result}static pointToWorldFrame(position,quaternion,localPoint,result=new Vec3){return quaternion.vmult(localPoint,result),result.vadd(position,result),result}static vectorToWorldFrame(quaternion,localVector,result=new Vec3){return quaternion.vmult(localVector,result),result}static vectorToLocalFrame(position,quaternion,worldVector,result=new Vec3){return quaternion.w*=-1,quaternion.vmult(worldVector,result),quaternion.w*=-1,result}}exports.Transform=Transform;const tmpQuat=new Quaternion;class ConvexPolyhedron extends Shape{constructor(props={}){const{vertices:vertices=[],faces:faces=[],normals:normals=[],axes:axes,boundingSphereRadius:boundingSphereRadius}=props;super({type:Shape.types.CONVEXPOLYHEDRON}),this.vertices=vertices,this.faces=faces,this.faceNormals=normals,0===this.faceNormals.length&&this.computeNormals(),boundingSphereRadius?this.boundingSphereRadius=boundingSphereRadius:this.updateBoundingSphereRadius(),this.worldVertices=[],this.worldVerticesNeedsUpdate=!0,this.worldFaceNormals=[],this.worldFaceNormalsNeedsUpdate=!0,this.uniqueAxes=axes?axes.slice():null,this.uniqueEdges=[],this.computeEdges()}computeEdges(){const faces=this.faces,vertices=this.vertices,edges=this.uniqueEdges;edges.length=0;const edge=new Vec3;for(let i=0;i!==faces.length;i++){const face=faces[i],numVertices=face.length;for(let j=0;j!==numVertices;j++){const k=(j+1)%numVertices;vertices[face[j]].vsub(vertices[face[k]],edge),edge.normalize();let found=!1;for(let p=0;p!==edges.length;p++)if(edges[p].almostEquals(edge)||edges[p].almostEquals(edge)){found=!0;break}found||edges.push(edge.clone())}}}computeNormals(){this.faceNormals.length=this.faces.length;for(let i=0;idmax&&(dmax=d,closestFaceB=face)}const worldVertsB1=[];for(let i=0;i=0&&this.clipFaceAgainstHull(separatingNormal,posA,quatA,worldVertsB1,minDist,maxDist,result)}findSeparatingAxis(hullB,posA,quatA,posB,quatB,target,faceListA,faceListB){const faceANormalWS3=new Vec3,Worldnormal1=new Vec3,deltaC=new Vec3,worldEdge0=new Vec3,worldEdge1=new Vec3,Cross=new Vec3;let dmin=Number.MAX_VALUE;const hullA=this;if(hullA.uniqueAxes)for(let i=0;i!==hullA.uniqueAxes.length;i++){quatA.vmult(hullA.uniqueAxes[i],faceANormalWS3);const d=hullA.testSepAxis(faceANormalWS3,hullB,posA,quatA,posB,quatB);if(!1===d)return!1;d0&&target.negate(target),!0}testSepAxis(axis,hullB,posA,quatA,posB,quatB){ConvexPolyhedron.project(this,axis,posA,quatA,maxminA),ConvexPolyhedron.project(hullB,axis,posB,quatB,maxminB);const maxA=maxminA[0],minA=maxminA[1],maxB=maxminB[0],minB=maxminB[1];if(maxA0?1/mass:0,this.material=options.material||null,this.linearDamping="number"==typeof options.linearDamping?options.linearDamping:.01,this.type=mass<=0?Body.STATIC:Body.DYNAMIC,typeof options.type==typeof Body.STATIC&&(this.type=options.type),this.allowSleep=void 0===options.allowSleep||options.allowSleep,this.sleepState=0,this.sleepSpeedLimit=void 0!==options.sleepSpeedLimit?options.sleepSpeedLimit:.1,this.sleepTimeLimit=void 0!==options.sleepTimeLimit?options.sleepTimeLimit:1,this.timeLastSleepy=0,this.wakeUpAfterNarrowphase=!1,this.torque=new Vec3,this.quaternion=new Quaternion,this.initQuaternion=new Quaternion,this.previousQuaternion=new Quaternion,this.interpolatedQuaternion=new Quaternion,options.quaternion&&(this.quaternion.copy(options.quaternion),this.initQuaternion.copy(options.quaternion),this.previousQuaternion.copy(options.quaternion),this.interpolatedQuaternion.copy(options.quaternion)),this.angularVelocity=new Vec3,options.angularVelocity&&this.angularVelocity.copy(options.angularVelocity),this.initAngularVelocity=new Vec3,this.shapes=[],this.shapeOffsets=[],this.shapeOrientations=[],this.inertia=new Vec3,this.invInertia=new Vec3,this.invInertiaWorld=new Mat3,this.invMassSolve=0,this.invInertiaSolve=new Vec3,this.invInertiaWorldSolve=new Mat3,this.fixedRotation=void 0!==options.fixedRotation&&options.fixedRotation,this.angularDamping=void 0!==options.angularDamping?options.angularDamping:.01,this.linearFactor=new Vec3(1,1,1),options.linearFactor&&this.linearFactor.copy(options.linearFactor),this.angularFactor=new Vec3(1,1,1),options.angularFactor&&this.angularFactor.copy(options.angularFactor),this.aabb=new AABB,this.aabbNeedsUpdate=!0,this.boundingRadius=0,this.wlambda=new Vec3,options.shape&&this.addShape(options.shape),this.updateMassProperties()}wakeUp(){const prevState=this.sleepState;this.sleepState=0,this.wakeUpAfterNarrowphase=!1,prevState===Body.SLEEPING&&this.dispatchEvent(Body.wakeupEvent)}sleep(){this.sleepState=Body.SLEEPING,this.velocity.set(0,0,0),this.angularVelocity.set(0,0,0),this.wakeUpAfterNarrowphase=!1}sleepTick(time){if(this.allowSleep){const sleepState=this.sleepState,speedSquared=this.velocity.lengthSquared()+this.angularVelocity.lengthSquared(),speedLimitSquared=this.sleepSpeedLimit**2;sleepState===Body.AWAKE&&speedSquaredspeedLimitSquared?this.wakeUp():sleepState===Body.SLEEPY&&time-this.timeLastSleepy>this.sleepTimeLimit&&(this.sleep(),this.dispatchEvent(Body.sleepEvent))}}updateSolveMassProperties(){this.sleepState===Body.SLEEPING||this.type===Body.KINEMATIC?(this.invMassSolve=0,this.invInertiaSolve.setZero(),this.invInertiaWorldSolve.setZero()):(this.invMassSolve=this.invMass,this.invInertiaSolve.copy(this.invInertia),this.invInertiaWorldSolve.copy(this.invInertiaWorld))}pointToLocalFrame(worldPoint,result=new Vec3){return worldPoint.vsub(this.position,result),this.quaternion.conjugate().vmult(result,result),result}vectorToLocalFrame(worldVector,result=new Vec3){return this.quaternion.conjugate().vmult(worldVector,result),result}pointToWorldFrame(localPoint,result=new Vec3){return this.quaternion.vmult(localPoint,result),result.vadd(this.position,result),result}vectorToWorldFrame(localVector,result=new Vec3){return this.quaternion.vmult(localVector,result),result}addShape(shape,_offset,_orientation){const offset=new Vec3,orientation=new Quaternion;return _offset&&offset.copy(_offset),_orientation&&orientation.copy(_orientation),this.shapes.push(shape),this.shapeOffsets.push(offset),this.shapeOrientations.push(orientation),this.updateMassProperties(),this.updateBoundingRadius(),this.aabbNeedsUpdate=!0,shape.body=this,this}updateBoundingRadius(){const shapes=this.shapes,shapeOffsets=this.shapeOffsets,N=shapes.length;let radius=0;for(let i=0;i!==N;i++){const shape=shapes[i];shape.updateBoundingSphereRadius();const offset=shapeOffsets[i].length(),r=shape.boundingSphereRadius;offset+r>radius&&(radius=offset+r)}this.boundingRadius=radius}computeAABB(){const shapes=this.shapes,shapeOffsets=this.shapeOffsets,shapeOrientations=this.shapeOrientations,N=shapes.length,offset=tmpVec,orientation=tmpQuat$1,bodyQuat=this.quaternion,aabb=this.aabb,shapeAABB=computeAABB_shapeAABB;for(let i=0;i!==N;i++){const shape=shapes[i];bodyQuat.vmult(shapeOffsets[i],offset),offset.vadd(this.position,offset),bodyQuat.mult(shapeOrientations[i],orientation),shape.calculateWorldAABB(offset,orientation,shapeAABB.lowerBound,shapeAABB.upperBound),0===i?aabb.copy(shapeAABB):aabb.extend(shapeAABB)}this.aabbNeedsUpdate=!1}updateInertiaWorld(force){const I=this.invInertia;if(I.x!==I.y||I.y!==I.z||force){const m1=uiw_m1,m2=uiw_m2;m1.setRotationFromQuaternion(this.quaternion),m1.transpose(m2),m1.scale(I,m1),m1.mmult(m2,this.invInertiaWorld)}else;}applyForce(force,relativePoint){if(this.type!==Body.DYNAMIC)return;const rotForce=Body_applyForce_rotForce;relativePoint.cross(force,rotForce),this.force.vadd(force,this.force),this.torque.vadd(rotForce,this.torque)}applyLocalForce(localForce,localPoint){if(this.type!==Body.DYNAMIC)return;const worldForce=Body_applyLocalForce_worldForce,relativePointWorld=Body_applyLocalForce_relativePointWorld;this.vectorToWorldFrame(localForce,worldForce),this.vectorToWorldFrame(localPoint,relativePointWorld),this.applyForce(worldForce,relativePointWorld)}applyImpulse(impulse,relativePoint){if(this.type!==Body.DYNAMIC)return;const r=relativePoint,velo=Body_applyImpulse_velo;velo.copy(impulse),velo.scale(this.invMass,velo),this.velocity.vadd(velo,this.velocity);const rotVelo=Body_applyImpulse_rotVelo;r.cross(impulse,rotVelo),this.invInertiaWorld.vmult(rotVelo,rotVelo),this.angularVelocity.vadd(rotVelo,this.angularVelocity)}applyLocalImpulse(localImpulse,localPoint){if(this.type!==Body.DYNAMIC)return;const worldImpulse=Body_applyLocalImpulse_worldImpulse,relativePointWorld=Body_applyLocalImpulse_relativePoint;this.vectorToWorldFrame(localImpulse,worldImpulse),this.vectorToWorldFrame(localPoint,relativePointWorld),this.applyImpulse(worldImpulse,relativePointWorld)}updateMassProperties(){const halfExtents=Body_updateMassProperties_halfExtents;this.invMass=this.mass>0?1/this.mass:0;const I=this.inertia,fixed=this.fixedRotation;this.computeAABB(),halfExtents.set((this.aabb.upperBound.x-this.aabb.lowerBound.x)/2,(this.aabb.upperBound.y-this.aabb.lowerBound.y)/2,(this.aabb.upperBound.z-this.aabb.lowerBound.z)/2),Box.calculateInertia(halfExtents,this.mass,I),this.invInertia.set(I.x>0&&!fixed?1/I.x:0,I.y>0&&!fixed?1/I.y:0,I.z>0&&!fixed?1/I.z:0),this.updateInertiaWorld(!0)}getVelocityAtWorldPoint(worldPoint,result){const r=new Vec3;return worldPoint.vsub(this.position,r),this.angularVelocity.cross(r,result),this.velocity.vadd(result,result),result}integrate(dt,quatNormalize,quatNormalizeFast){if(this.previousPosition.copy(this.position),this.previousQuaternion.copy(this.quaternion),this.type!==Body.DYNAMIC&&this.type!==Body.KINEMATIC||this.sleepState===Body.SLEEPING)return;const velo=this.velocity,angularVelo=this.angularVelocity,pos=this.position,force=this.force,torque=this.torque,quat=this.quaternion,invMass=this.invMass,invInertia=this.invInertiaWorld,linearFactor=this.linearFactor,iMdt=invMass*dt;velo.x+=force.x*iMdt*linearFactor.x,velo.y+=force.y*iMdt*linearFactor.y,velo.z+=force.z*iMdt*linearFactor.z;const e=invInertia.elements,angularFactor=this.angularFactor,tx=torque.x*angularFactor.x,ty=torque.y*angularFactor.y,tz=torque.z*angularFactor.z;angularVelo.x+=dt*(e[0]*tx+e[1]*ty+e[2]*tz),angularVelo.y+=dt*(e[3]*tx+e[4]*ty+e[5]*tz),angularVelo.z+=dt*(e[6]*tx+e[7]*ty+e[8]*tz),pos.x+=velo.x*dt,pos.y+=velo.y*dt,pos.z+=velo.z*dt,quat.integrate(this.angularVelocity,dt,this.angularFactor,quat),quatNormalize&&(quatNormalizeFast?quat.normalizeFast():quat.normalize()),this.aabbNeedsUpdate=!0,this.updateInertiaWorld()}}exports.Body=Body,Body.COLLIDE_EVENT_NAME="collide",Body.DYNAMIC=1,Body.STATIC=2,Body.KINEMATIC=4,Body.AWAKE=BODY_SLEEP_STATES.AWAKE,Body.SLEEPY=BODY_SLEEP_STATES.SLEEPY,Body.SLEEPING=BODY_SLEEP_STATES.SLEEPING,Body.idCounter=0,Body.wakeupEvent={type:"wakeup"},Body.sleepyEvent={type:"sleepy"},Body.sleepEvent={type:"sleep"};const tmpVec=new Vec3,tmpQuat$1=new Quaternion,computeAABB_shapeAABB=new AABB,uiw_m1=new Mat3,uiw_m2=new Mat3,Body_applyForce_rotForce=new Vec3,Body_applyLocalForce_worldForce=new Vec3,Body_applyLocalForce_relativePointWorld=new Vec3,Body_applyImpulse_velo=new Vec3,Body_applyImpulse_rotVelo=new Vec3,Body_applyLocalImpulse_worldImpulse=new Vec3,Body_applyLocalImpulse_relativePoint=new Vec3,Body_updateMassProperties_halfExtents=new Vec3;class Broadphase{constructor(){this.world=null,this.useBoundingBoxes=!1,this.dirty=!0}collisionPairs(world,p1,p2){throw new Error("collisionPairs not implemented for this BroadPhase class!")}needBroadphaseCollision(bodyA,bodyB){return 0!=(bodyA.collisionFilterGroup&bodyB.collisionFilterMask)&&0!=(bodyB.collisionFilterGroup&bodyA.collisionFilterMask)&&(0==(bodyA.type&Body.STATIC)&&bodyA.sleepState!==Body.SLEEPING||0==(bodyB.type&Body.STATIC)&&bodyB.sleepState!==Body.SLEEPING)}intersectionTest(bodyA,bodyB,pairs1,pairs2){this.useBoundingBoxes?this.doBoundingBoxBroadphase(bodyA,bodyB,pairs1,pairs2):this.doBoundingSphereBroadphase(bodyA,bodyB,pairs1,pairs2)}doBoundingSphereBroadphase(bodyA,bodyB,pairs1,pairs2){const r=Broadphase_collisionPairs_r;bodyB.position.vsub(bodyA.position,r);const boundingRadiusSum2=(bodyA.boundingRadius+bodyB.boundingRadius)**2;r.lengthSquared(){const dist=new Vec3;bodyA.position.vsub(bodyB.position,dist);const sa=bodyA.shapes[0],sb=bodyB.shapes[0];return Math.pow(sa.boundingSphereRadius+sb.boundingSphereRadius,2)>dist.lengthSquared()});exports.GridBroadphase=class extends Broadphase{constructor(aabbMin=new Vec3(100,100,100),aabbMax=new Vec3(-100,-100,-100),nx=10,ny=10,nz=10){super(),this.nx=nx,this.ny=ny,this.nz=nz,this.aabbMin=aabbMin,this.aabbMax=aabbMax;const nbins=this.nx*this.ny*this.nz;if(nbins<=0)throw"GridBroadphase: Each dimension's n must be >0";this.bins=[],this.binLengths=[],this.bins.length=nbins,this.binLengths.length=nbins;for(let i=0;i=nx&&(xoff0=nx-1),yoff0<0?yoff0=0:yoff0>=ny&&(yoff0=ny-1),zoff0<0?zoff0=0:zoff0>=nz&&(zoff0=nz-1),xoff1<0?xoff1=0:xoff1>=nx&&(xoff1=nx-1),yoff1<0?yoff1=0:yoff1>=ny&&(yoff1=ny-1),zoff1<0?zoff1=0:zoff1>=nz&&(zoff1=nz-1),yoff0*=ystep,zoff0*=zstep,xoff1*=xstep,yoff1*=ystep,zoff1*=zstep;for(let xoff=xoff0*=xstep;xoff<=xoff1;xoff+=xstep)for(let yoff=yoff0;yoff<=yoff1;yoff+=ystep)for(let zoff=zoff0;zoff<=zoff1;zoff+=zstep){const idx=xoff+yoff+zoff;bins[idx][binLengths[idx]++]=bi}}for(let i=0;i!==N;i++){const bi=bodies[i],si=bi.shapes[0];switch(si.type){case SPHERE:{const shape=si,x=bi.position.x,y=bi.position.y,z=bi.position.z,r=shape.radius;addBoxToBins(x-r,y-r,z-r,x+r,y+r,z+r,bi);break}case PLANE:{const shape=si;shape.worldNormalNeedsUpdate&&shape.computeWorldNormal(bi.quaternion);const planeNormal=shape.worldNormal,xreset=xmin+.5*binsizeX-bi.position.x,yreset=ymin+.5*binsizeY-bi.position.y,zreset=zmin+.5*binsizeZ-bi.position.z,d=GridBroadphase_collisionPairs_d;d.set(xreset,yreset,zreset);for(let xi=0,xoff=0;xi!==nx;xi++,xoff+=xstep,d.y=yreset,d.x+=binsizeX)for(let yi=0,yoff=0;yi!==ny;yi++,yoff+=ystep,d.z=zreset,d.y+=binsizeY)for(let zi=0,zoff=0;zi!==nz;zi++,zoff+=zstep,d.z+=binsizeZ)if(d.dot(planeNormal)1){const bin=bins[i];for(let xi=0;xi!==binLength;xi++){const bi=bin[xi];for(let yi=0;yi!==xi;yi++){const bj=bin[yi];this.needBroadphaseCollision(bi,bj)&&this.intersectionTest(bi,bj,pairs1,pairs2)}}}}this.makePairsUnique(pairs1,pairs2)}};const GridBroadphase_collisionPairs_d=new Vec3;class NaiveBroadphase extends Broadphase{constructor(){super()}collisionPairs(world,pairs1,pairs2){const bodies=world.bodies,n=bodies.length;let bi,bj;for(let i=0;i!==n;i++)for(let j=0;j!==i;j++)bi=bodies[i],bj=bodies[j],this.needBroadphaseCollision(bi,bj)&&this.intersectionTest(bi,bj,pairs1,pairs2)}aabbQuery(world,aabb,result=[]){for(let i=0;i{})}intersectWorld(world,options){return this.mode=options.mode||Ray.ANY,this.result=options.result||new RaycastResult,this.skipBackfaces=!!options.skipBackfaces,this.collisionFilterMask=void 0!==options.collisionFilterMask?options.collisionFilterMask:-1,this.collisionFilterGroup=void 0!==options.collisionFilterGroup?options.collisionFilterGroup:-1,this.checkCollisionResponse=void 0===options.checkCollisionResponse||options.checkCollisionResponse,options.from&&this.from.copy(options.from),options.to&&this.to.copy(options.to),this.callback=options.callback||(()=>{}),this.hasHit=!1,this.result.reset(),this.updateDirection(),this.getAABB(tmpAABB),tmpArray.length=0,world.broadphase.aabbQuery(world,tmpAABB,tmpArray),this.intersectBodies(tmpArray),this.hasHit}intersectBody(body,result){result&&(this.result=result,this.updateDirection());const checkCollisionResponse=this.checkCollisionResponse;if(checkCollisionResponse&&!body.collisionResponse)return;if(0==(this.collisionFilterGroup&body.collisionFilterMask)||0==(body.collisionFilterGroup&this.collisionFilterMask))return;const xi=intersectBody_xi,qi=intersectBody_qi;for(let i=0,N=body.shapes.length;ishape.boundingSphereRadius)return;const intersectMethod=this[shape.type];intersectMethod&&intersectMethod.call(this,shape,quat,position,body,shape)}_intersectBox(box,quat,position,body,reportedShape){return this._intersectConvex(box.convexPolyhedronRepresentation,quat,position,body,reportedShape)}_intersectPlane(shape,quat,position,body,reportedShape){const from=this.from,to=this.to,direction=this.direction,worldNormal=new Vec3(0,0,1);quat.vmult(worldNormal,worldNormal);const len=new Vec3;from.vsub(position,len);const planeToFrom=len.dot(worldNormal);if(to.vsub(position,len),planeToFrom*len.dot(worldNormal)>0)return;if(from.distanceTo(to)=0&&d1<=1&&(from.lerp(to,d1,intersectionPoint),intersectionPoint.vsub(position,normal),normal.normalize(),this.reportIntersection(normal,intersectionPoint,reportedShape,body,-1)),this.result.shouldStop)return;d2>=0&&d2<=1&&(from.lerp(to,d2,intersectionPoint),intersectionPoint.vsub(position,normal),normal.normalize(),this.reportIntersection(normal,intersectionPoint,reportedShape,body,-1))}}_intersectConvex(shape,quat,position,body,reportedShape,options){const normal=intersectConvex_normal,vector=intersectConvex_vector,faceList=options&&options.faceList||null,faces=shape.faces,vertices=shape.vertices,normals=shape.faceNormals,direction=this.direction,from=this.from,to=this.to,fromToDistance=from.distanceTo(to),Nfaces=faceList?faceList.length:faces.length,result=this.result;for(let j=0;!result.shouldStop&&jfromToDistance||this.reportIntersection(normal,intersectPoint,reportedShape,body,fi)}}}}_intersectTrimesh(mesh,quat,position,body,reportedShape,options){const normal=intersectTrimesh_normal,triangles=intersectTrimesh_triangles,treeTransform=intersectTrimesh_treeTransform,vector=intersectConvex_vector,localDirection=intersectTrimesh_localDirection,localFrom=intersectTrimesh_localFrom,localTo=intersectTrimesh_localTo,worldIntersectPoint=intersectTrimesh_worldIntersectPoint,worldNormal=intersectTrimesh_worldNormal,indices=(options&&options.faceList,mesh.indices),from=(mesh.vertices,this.from),to=this.to,direction=this.direction;treeTransform.position.copy(position),treeTransform.quaternion.copy(quat),Transform.vectorToLocalFrame(position,quat,direction,localDirection),Transform.pointToLocalFrame(position,quat,from,localFrom),Transform.pointToLocalFrame(position,quat,to,localTo),localTo.x*=mesh.scale.x,localTo.y*=mesh.scale.y,localTo.z*=mesh.scale.z,localFrom.x*=mesh.scale.x,localFrom.y*=mesh.scale.y,localFrom.z*=mesh.scale.z,localTo.vsub(localFrom,localDirection),localDirection.normalize();const fromToDistanceSquared=localFrom.distanceSquared(localTo);mesh.tree.rayQuery(this,treeTransform,triangles);for(let i=0,N=triangles.length;!this.result.shouldStop&&i!==N;i++){const trianglesIndex=triangles[i];mesh.getNormal(trianglesIndex,normal),mesh.getVertex(indices[3*trianglesIndex],a),a.vsub(localFrom,vector);const dot=localDirection.dot(normal),scalar=normal.dot(vector)/dot;if(scalar<0)continue;localDirection.scale(scalar,intersectPoint),intersectPoint.vadd(localFrom,intersectPoint),mesh.getVertex(indices[3*trianglesIndex+1],b),mesh.getVertex(indices[3*trianglesIndex+2],c);const squaredDistance=intersectPoint.distanceSquared(localFrom);!pointInTriangle(intersectPoint,b,a,c)&&!pointInTriangle(intersectPoint,a,b,c)||squaredDistance>fromToDistanceSquared||(Transform.vectorToWorldFrame(quat,normal,worldNormal),Transform.pointToWorldFrame(position,quat,intersectPoint,worldIntersectPoint),this.reportIntersection(worldNormal,worldIntersectPoint,reportedShape,body,trianglesIndex))}triangles.length=0}reportIntersection(normal,hitPointWorld,shape,body,hitFaceIndex){const from=this.from,to=this.to,distance=from.distanceTo(hitPointWorld),result=this.result;if(!(this.skipBackfaces&&normal.dot(this.direction)>0))switch(result.hitFaceIndex=void 0!==hitFaceIndex?hitFaceIndex:-1,this.mode){case Ray.ALL:this.hasHit=!0,result.set(from,to,normal,hitPointWorld,shape,body,distance),result.hasHit=!0,this.callback(result);break;case Ray.CLOSEST:(distance=0&&(v=dot00*dot12-dot01*dot02)>=0&&u+v{axisList.push(event.body)}),this._removeBodyHandler=(event=>{const idx=axisList.indexOf(event.body);-1!==idx&&axisList.splice(idx,1)}),world&&this.setWorld(world)}setWorld(world){this.axisList.length=0;for(let i=0;ivarianceY?varianceX>varianceZ?0:2:varianceY>varianceZ?1:2}aabbQuery(world,aabb,result=[]){this.dirty&&(this.sortList(),this.dirty=!1);const axisIndex=this.axisIndex;let axis="x";1===axisIndex&&(axis="y"),2===axisIndex&&(axis="z");const axisList=this.axisList;aabb.lowerBound[axis],aabb.upperBound[axis];for(let i=0;i{for(let i=1,l=a.length;i=0&&!(a[j].aabb.lowerBound.x<=v.aabb.lowerBound.x);j--)a[j+1]=a[j];a[j+1]=v}return a}),SAPBroadphase.insertionSortY=(a=>{for(let i=1,l=a.length;i=0&&!(a[j].aabb.lowerBound.y<=v.aabb.lowerBound.y);j--)a[j+1]=a[j];a[j+1]=v}return a}),SAPBroadphase.insertionSortZ=(a=>{for(let i=1,l=a.length;i=0&&!(a[j].aabb.lowerBound.z<=v.aabb.lowerBound.z);j--)a[j+1]=a[j];a[j+1]=v}return a}),SAPBroadphase.checkBounds=((bi,bj,axisIndex)=>{let biPos,bjPos;0===axisIndex?(biPos=bi.position.x,bjPos=bj.position.x):1===axisIndex?(biPos=bi.position.y,bjPos=bj.position.y):2===axisIndex&&(biPos=bi.position.z,bjPos=bj.position.z);const ri=bi.boundingRadius;return bjPos-bj.boundingRadius{for(let key in defaults)key in options||(options[key]=defaults[key]);return options});class Constraint{constructor(bodyA,bodyB,options={}){options=Utils.defaults(options,{collideConnected:!0,wakeUpBodies:!0}),this.equations=[],this.bodyA=bodyA,this.bodyB=bodyB,this.id=Constraint.idCounter++,this.collideConnected=options.collideConnected,options.wakeUpBodies&&(bodyA&&bodyA.wakeUp(),bodyB&&bodyB.wakeUp())}update(){throw new Error("method update() not implmemented in this Constraint subclass!")}enable(){const eqs=this.equations;for(let i=0;i=-.1)this.suspensionRelativeVelocity=0,this.clippedInvContactDotSuspension=10;else{const inv=-1/project;this.suspensionRelativeVelocity=projVel*inv,this.clippedInvContactDotSuspension=inv}}else raycastResult.suspensionLength=this.suspensionRestLength,this.suspensionRelativeVelocity=0,raycastResult.directionWorld.scale(-1,raycastResult.hitNormalWorld),this.clippedInvContactDotSuspension=1}}const chassis_velocity_at_contactPoint=new Vec3,relpos=new Vec3;exports.RaycastVehicle=class{constructor(options){this.chassisBody=options.chassisBody,this.wheelInfos=[],this.sliding=!1,this.world=null,this.indexRightAxis=void 0!==options.indexRightAxis?options.indexRightAxis:1,this.indexForwardAxis=void 0!==options.indexForwardAxis?options.indexForwardAxis:0,this.indexUpAxis=void 0!==options.indexUpAxis?options.indexUpAxis:2,this.constraints=[],this.preStepCallback=(()=>{}),this.currentVehicleSpeedKmHour=0}addWheel(options={}){const info=new WheelInfo(options),index=this.wheelInfos.length;return this.wheelInfos.push(info),index}setSteeringValue(value,wheelIndex){this.wheelInfos[wheelIndex].steering=value}applyEngineForce(value,wheelIndex){this.wheelInfos[wheelIndex].engineForce=value}setBrake(brake,wheelIndex){this.wheelInfos[wheelIndex].brake=brake}addToWorld(world){this.constraints,world.addBody(this.chassisBody);const that=this;this.preStepCallback=(()=>{that.updateVehicle(world.dt)}),world.addEventListener("preStep",this.preStepCallback),this.world=world}getVehicleAxisWorld(axisIndex,result){result.set(0===axisIndex?1:0,1===axisIndex?1:0,2===axisIndex?1:0),this.chassisBody.vectorToWorldFrame(result,result)}updateVehicle(timeStep){const wheelInfos=this.wheelInfos,numWheels=wheelInfos.length,chassisBody=this.chassisBody;for(let i=0;iwheel.maxSuspensionForce&&(suspensionForce=wheel.maxSuspensionForce),wheel.raycastResult.hitNormalWorld.scale(suspensionForce*timeStep,impulse),wheel.raycastResult.hitPointWorld.vsub(chassisBody.position,relpos),chassisBody.applyImpulse(impulse,relpos)}this.updateFriction(timeStep);const hitNormalWorldScaledWithProj=new Vec3,fwd=new Vec3,vel=new Vec3;for(let i=0;i0?1:-1)*wheel.customSlidingRotationalSpeed*timeStep),Math.abs(wheel.brake)>Math.abs(wheel.engineForce)&&(wheel.deltaRotation=0),wheel.rotation+=wheel.deltaRotation,wheel.deltaRotation*=.99}}updateSuspension(deltaTime){const chassisMass=this.chassisBody.mass,wheelInfos=this.wheelInfos,numWheels=wheelInfos.length;for(let w_it=0;w_itmaxSuspensionLength&&(wheel.suspensionLength=maxSuspensionLength,wheel.raycastResult.reset());const denominator=wheel.raycastResult.hitNormalWorld.dot(wheel.directionWorld),chassis_velocity_at_contactPoint=new Vec3;chassisBody.getVelocityAtWorldPoint(wheel.raycastResult.hitPointWorld,chassis_velocity_at_contactPoint);const projVel=wheel.raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint);if(denominator>=-.1)wheel.suspensionRelativeVelocity=0,wheel.clippedInvContactDotSuspension=10;else{const inv=-1/denominator;wheel.suspensionRelativeVelocity=projVel*inv,wheel.clippedInvContactDotSuspension=inv}}else wheel.suspensionLength=wheel.suspensionRestLength+0*wheel.maxSuspensionTravel,wheel.suspensionRelativeVelocity=0,wheel.directionWorld.scale(-1,wheel.raycastResult.hitNormalWorld),wheel.clippedInvContactDotSuspension=1;return depth}updateWheelTransformWorld(wheel){wheel.isInContact=!1;const chassisBody=this.chassisBody;chassisBody.pointToWorldFrame(wheel.chassisConnectionPointLocal,wheel.chassisConnectionPointWorld),chassisBody.vectorToWorldFrame(wheel.directionLocal,wheel.directionWorld),chassisBody.vectorToWorldFrame(wheel.axleLocal,wheel.axleWorld)}updateWheelTransform(wheelIndex){const up=tmpVec4,right=tmpVec5,fwd=tmpVec6,wheel=this.wheelInfos[wheelIndex];this.updateWheelTransformWorld(wheel),wheel.directionLocal.scale(-1,up),right.copy(wheel.axleLocal),up.cross(right,fwd),fwd.normalize(),right.normalize();const steering=wheel.steering,steeringOrn=new Quaternion;steeringOrn.setFromAxisAngle(up,steering);const rotatingOrn=new Quaternion;rotatingOrn.setFromAxisAngle(right,wheel.rotation);const q=wheel.worldTransform.quaternion;this.chassisBody.quaternion.mult(steeringOrn,q),q.mult(rotatingOrn,q),q.normalize();const p=wheel.worldTransform.position;p.copy(wheel.directionWorld),p.scale(wheel.suspensionLength,p),p.vadd(wheel.chassisConnectionPointWorld,p)}getWheelTransformWorld(wheelIndex){return this.wheelInfos[wheelIndex].worldTransform}updateFriction(timeStep){const surfNormalWS_scaled_proj=updateFriction_surfNormalWS_scaled_proj,wheelInfos=this.wheelInfos,numWheels=wheelInfos.length,chassisBody=this.chassisBody,forwardWS=updateFriction_forwardWS,axle=updateFriction_axle;for(let i=0;imaximpSquared){this.sliding=!0,wheel.sliding=!0;const factor=maximp/Math.sqrt(impulseSquared);wheel.skidInfo*=factor}}}if(this.sliding)for(let i=0;i1.1)return 0;const vel1=resolveSingleBilateral_vel1,vel2=resolveSingleBilateral_vel2,vel=resolveSingleBilateral_vel;body1.getVelocityAtWorldPoint(pos1,vel1),body2.getVelocityAtWorldPoint(pos2,vel2),vel1.vsub(vel2,vel);return-.2*normal.dot(vel)*(1/(body1.invMass+body2.invMass))}class Sphere extends Shape{constructor(radius){if(super({type:Shape.types.SPHERE}),this.radius=void 0!==radius?radius:1,this.radius<0)throw new Error("The sphere radius cannot be negative.");this.updateBoundingSphereRadius()}calculateLocalInertia(mass,target=new Vec3){const I=2*mass*this.radius*this.radius/5;return target.x=I,target.y=I,target.z=I,target}volume(){return 4*Math.PI*Math.pow(this.radius,3)/3}updateBoundingSphereRadius(){this.boundingSphereRadius=this.radius}calculateWorldAABB(pos,quat,min,max){const r=this.radius,axes=["x","y","z"];for(let i=0;ithis.particles.length&&this.neighbors.pop())}getNeighbors(particle,neighbors){const N=this.particles.length,id=particle.id,R2=this.smoothingRadius*this.smoothingRadius,dist=SPHSystem_getNeighbors_dist;for(let i=0;i!==N;i++){const p=this.particles[i];p.position.vsub(particle.position,dist),id!==p.id&&dist.lengthSquared()maxValue&&(maxValue=v)}this.maxValue=maxValue}setHeightValueAtIndex(xi,yi,value){this.data[xi][yi]=value,this.clearCachedConvexTrianglePillar(xi,yi,!1),xi>0&&(this.clearCachedConvexTrianglePillar(xi-1,yi,!0),this.clearCachedConvexTrianglePillar(xi-1,yi,!1)),yi>0&&(this.clearCachedConvexTrianglePillar(xi,yi-1,!0),this.clearCachedConvexTrianglePillar(xi,yi-1,!1)),yi>0&&xi>0&&this.clearCachedConvexTrianglePillar(xi-1,yi-1,!0)}getRectMinMax(iMinX,iMinY,iMaxX,iMaxY,result=[]){const data=this.data;let max=this.minValue;for(let i=iMinX;i<=iMaxX;i++)for(let j=iMinY;j<=iMaxY;j++){const height=data[i][j];height>max&&(max=height)}result[0]=this.minValue,result[1]=max}getIndexOfPosition(x,y,result,clamp){const w=this.elementSize,data=this.data;let xi=Math.floor(x/w),yi=Math.floor(y/w);return result[0]=xi,result[1]=yi,clamp&&(xi<0&&(xi=0),yi<0&&(yi=0),xi>=data.length-1&&(xi=data.length-1),yi>=data[0].length-1&&(yi=data[0].length-1)),!(xi<0||yi<0||xi>=data.length-1||yi>=data[0].length-1)}getTriangleAt(x,y,edgeClamp,a,b,c){const idx=getHeightAt_idx;this.getIndexOfPosition(x,y,idx,edgeClamp);let xi=idx[0],yi=idx[1];const data=this.data;edgeClamp&&(xi=Math.min(data.length-2,Math.max(0,xi)),yi=Math.min(data[0].length-2,Math.max(0,yi)));const elementSize=this.elementSize,upper=(x/elementSize-xi)**2+(y/elementSize-yi)**2>(x/elementSize-(xi+1))**2+(y/elementSize-(yi+1))**2;return this.getTriangle(xi,yi,upper,a,b,c),upper}getNormalAt(x,y,edgeClamp,result){const a=getNormalAt_a,b=getNormalAt_b,c=getNormalAt_c,e0=getNormalAt_e0,e1=getNormalAt_e1;this.getTriangleAt(x,y,edgeClamp,a,b,c),b.vsub(a,e0),c.vsub(a,e1),e0.cross(e1,result),result.normalize()}getAabbAtIndex(xi,yi,{lowerBound:lowerBound,upperBound:upperBound}){const data=this.data,elementSize=this.elementSize;lowerBound.set(xi*elementSize,yi*elementSize,data[xi][yi]),upperBound.set((xi+1)*elementSize,(yi+1)*elementSize,data[xi+1][yi+1])}getHeightAt(x,y,edgeClamp){const data=this.data,a=getHeightAt_a,b=getHeightAt_b,c=getHeightAt_c,idx=getHeightAt_idx;this.getIndexOfPosition(x,y,idx,edgeClamp);let xi=idx[0],yi=idx[1];edgeClamp&&(xi=Math.min(data.length-2,Math.max(0,xi)),yi=Math.min(data[0].length-2,Math.max(0,yi)));const upper=this.getTriangleAt(x,y,edgeClamp,a,b,c);!function(x,y,ax,ay,bx,by,cx,cy,result){result.x=((by-cy)*(x-cx)+(cx-bx)*(y-cy))/((by-cy)*(ax-cx)+(cx-bx)*(ay-cy)),result.y=((cy-ay)*(x-cx)+(ax-cx)*(y-cy))/((by-cy)*(ax-cx)+(cx-bx)*(ay-cy)),result.z=1-result.x-result.y}(x,y,a.x,a.y,b.x,b.y,c.x,c.y,getHeightAt_weights);const w=getHeightAt_weights;return upper?data[xi+1][yi+1]*w.x+data[xi][yi+1]*w.y+data[xi+1][yi]*w.z:data[xi][yi]*w.x+data[xi+1][yi]*w.y+data[xi][yi+1]*w.z}getCacheConvexTrianglePillarKey(xi,yi,getUpperTriangle){return xi+"_"+yi+"_"+(getUpperTriangle?1:0)}getCachedConvexTrianglePillar(xi,yi,getUpperTriangle){return this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi,yi,getUpperTriangle)]}setCachedConvexTrianglePillar(xi,yi,getUpperTriangle,convex,offset){this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi,yi,getUpperTriangle)]={convex:convex,offset:offset}}clearCachedConvexTrianglePillar(xi,yi,getUpperTriangle){delete this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi,yi,getUpperTriangle)]}getTriangle(xi,yi,upper,a,b,c){const data=this.data,elementSize=this.elementSize;upper?(a.set((xi+1)*elementSize,(yi+1)*elementSize,data[xi+1][yi+1]),b.set(xi*elementSize,(yi+1)*elementSize,data[xi][yi+1]),c.set((xi+1)*elementSize,yi*elementSize,data[xi+1][yi])):(a.set(xi*elementSize,yi*elementSize,data[xi][yi]),b.set((xi+1)*elementSize,yi*elementSize,data[xi+1][yi]),c.set(xi*elementSize,(yi+1)*elementSize,data[xi][yi+1]))}getConvexTrianglePillar(xi,yi,getUpperTriangle){let result=this.pillarConvex,offsetResult=this.pillarOffset;if(this.cacheEnabled){const data=this.getCachedConvexTrianglePillar(xi,yi,getUpperTriangle);if(data)return this.pillarConvex=data.convex,void(this.pillarOffset=data.offset);result=new ConvexPolyhedron,offsetResult=new Vec3,this.pillarConvex=result,this.pillarOffset=offsetResult}const data=this.data,elementSize=this.elementSize,faces=result.faces;result.vertices.length=6;for(let i=0;i<6;i++)result.vertices[i]||(result.vertices[i]=new Vec3);faces.length=5;for(let i=0;i<5;i++)faces[i]||(faces[i]=[]);const verts=result.vertices,h=(Math.min(data[xi][yi],data[xi+1][yi],data[xi][yi+1],data[xi+1][yi+1])-this.minValue)/2+this.minValue;getUpperTriangle?(offsetResult.set((xi+.75)*elementSize,(yi+.75)*elementSize,h),verts[0].set(.25*elementSize,.25*elementSize,data[xi+1][yi+1]-h),verts[1].set(-.75*elementSize,.25*elementSize,data[xi][yi+1]-h),verts[2].set(.25*elementSize,-.75*elementSize,data[xi+1][yi]-h),verts[3].set(.25*elementSize,.25*elementSize,-h-1),verts[4].set(-.75*elementSize,.25*elementSize,-h-1),verts[5].set(.25*elementSize,-.75*elementSize,-h-1),faces[0][0]=0,faces[0][1]=1,faces[0][2]=2,faces[1][0]=5,faces[1][1]=4,faces[1][2]=3,faces[2][0]=2,faces[2][1]=5,faces[2][2]=3,faces[2][3]=0,faces[3][0]=3,faces[3][1]=4,faces[3][2]=1,faces[3][3]=0,faces[4][0]=1,faces[4][1]=4,faces[4][2]=5,faces[4][3]=2):(offsetResult.set((xi+.25)*elementSize,(yi+.25)*elementSize,h),verts[0].set(-.25*elementSize,-.25*elementSize,data[xi][yi]-h),verts[1].set(.75*elementSize,-.25*elementSize,data[xi+1][yi]-h),verts[2].set(-.25*elementSize,.75*elementSize,data[xi][yi+1]-h),verts[3].set(-.25*elementSize,-.25*elementSize,-h-1),verts[4].set(.75*elementSize,-.25*elementSize,-h-1),verts[5].set(-.25*elementSize,.75*elementSize,-h-1),faces[0][0]=0,faces[0][1]=1,faces[0][2]=2,faces[1][0]=5,faces[1][1]=4,faces[1][2]=3,faces[2][0]=0,faces[2][1]=2,faces[2][2]=5,faces[2][3]=3,faces[3][0]=1,faces[3][1]=0,faces[3][2]=3,faces[3][3]=4,faces[4][0]=4,faces[4][1]=5,faces[4][2]=2,faces[4][3]=1),result.computeNormals(),result.computeEdges(),result.updateBoundingSphereRadius(),this.setCachedConvexTrianglePillar(xi,yi,getUpperTriangle,result,offsetResult)}calculateLocalInertia(mass,target=new Vec3){return target.set(0,0,0),target}volume(){return Number.MAX_VALUE}calculateWorldAABB(pos,quat,min,max){min.set(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE),max.set(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE)}updateBoundingSphereRadius(){const data=this.data,s=this.elementSize;this.boundingSphereRadius=new Vec3(data.length*s,data[0].length*s,Math.max(Math.abs(this.maxValue),Math.abs(this.minValue))).length()}setHeightsFromImage(image,scale){const{x:x,z:z,y:y}=scale,canvas=document.createElement("canvas");canvas.width=image.width,canvas.height=image.height;const context=canvas.getContext("2d");context.drawImage(image,0,0);const imageData=context.getImageData(0,0,image.width,image.height),matrix=this.data;matrix.length=0,this.elementSize=Math.abs(x)/imageData.width;for(let i=0;i=0;i--)this.children[i].removeEmptyNodes(),this.children[i].children.length||this.children[i].data.length||this.children.splice(i,1)}}class Octree extends OctreeNode{constructor(aabb,options={}){super({root:null,aabb:aabb}),this.maxDepth=void 0!==options.maxDepth?options.maxDepth:8}}const halfDiagonal=new Vec3,tmpAABB$1=new AABB;class Trimesh extends Shape{constructor(vertices,indices){super({type:Shape.types.TRIMESH}),this.vertices=new Float32Array(vertices),this.indices=new Int16Array(indices),this.normals=new Float32Array(indices.length),this.aabb=new AABB,this.edges=null,this.scale=new Vec3(1,1,1),this.tree=new Octree,this.updateEdges(),this.updateNormals(),this.updateAABB(),this.updateBoundingSphereRadius(),this.updateTree()}updateTree(){const tree=this.tree;tree.reset(),tree.aabb.copy(this.aabb);const scale=this.scale;tree.aabb.lowerBound.x*=1/scale.x,tree.aabb.lowerBound.y*=1/scale.y,tree.aabb.lowerBound.z*=1/scale.z,tree.aabb.upperBound.x*=1/scale.x,tree.aabb.upperBound.y*=1/scale.y,tree.aabb.upperBound.z*=1/scale.z;const triangleAABB=new AABB,a=new Vec3,b=new Vec3,c=new Vec3,points=[a,b,c];for(let i=0;i{edges[au.x&&(u.x=v.x),v.yu.y&&(u.y=v.y),v.zu.z&&(u.z=v.z)}updateAABB(){this.computeLocalAABB(this.aabb)}updateBoundingSphereRadius(){let max2=0;const vertices=this.vertices,v=new Vec3;for(let i=0,N=vertices.length/3;i!==N;i++){this.getVertex(i,v);const norm2=v.lengthSquared();norm2>max2&&(max2=norm2)}this.boundingSphereRadius=Math.sqrt(max2)}calculateWorldAABB(pos,quat,min,max){const frame=calculateWorldAABB_frame,result=calculateWorldAABB_aabb;frame.position=pos,frame.quaternion=quat,this.aabb.toWorldFrame(frame,result),min.copy(result.lowerBound),max.copy(result.upperBound)}volume(){return 4*Math.PI*this.boundingSphereRadius/3}}exports.Trimesh=Trimesh;const computeNormals_n=new Vec3,unscaledAABB=new AABB,getEdgeVector_va=new Vec3,getEdgeVector_vb=new Vec3,cb=new Vec3,ab=new Vec3;Trimesh.computeNormal=((va,vb,vc,target)=>{vb.vsub(va,ab),vc.vsub(vb,cb),cb.cross(ab,target),target.isZero()||target.normalize()});const va=new Vec3,vb=new Vec3,vc=new Vec3,cli_aabb=new AABB,computeLocalAABB_worldVert=new Vec3,calculateWorldAABB_frame=new Transform,calculateWorldAABB_aabb=new AABB;Trimesh.createTorus=((radius=1,tube=.5,radialSegments=8,tubularSegments=6,arc=2*Math.PI)=>{const vertices=[],indices=[];for(let j=0;j<=radialSegments;j++)for(let i=0;i<=tubularSegments;i++){const u=i/tubularSegments*arc,v=j/radialSegments*Math.PI*2,x=(radius+tube*Math.cos(v))*Math.cos(u),y=(radius+tube*Math.cos(v))*Math.sin(u),z=tube*Math.sin(v);vertices.push(x,y,z)}for(let j=1;j<=radialSegments;j++)for(let i=1;i<=tubularSegments;i++){const a=(tubularSegments+1)*j+i-1,b=(tubularSegments+1)*(j-1)+i-1,c=(tubularSegments+1)*(j-1)+i,d=(tubularSegments+1)*j+i;indices.push(a,b,d),indices.push(b,c,d)}return new Trimesh(vertices,indices)});class Solver{constructor(){this.equations=[]}solve(dt,world){return 0}addEquation(eq){eq.enabled&&this.equations.push(eq)}removeEquation(eq){const eqs=this.equations,i=eqs.indexOf(eq);-1!==i&&eqs.splice(i,1)}removeAllEquations(){this.equations.length=0}}exports.Solver=Solver;class GSSolver extends Solver{constructor(){super(),this.iterations=10,this.tolerance=1e-7}solve(dt,world){let iter=0;const maxIter=this.iterations,tolSquared=this.tolerance*this.tolerance,equations=this.equations,Neq=equations.length,bodies=world.bodies,Nbodies=bodies.length,h=dt;let B,invC,deltalambda,deltalambdaTot,GWlambda,lambdaj;if(0!==Neq)for(let i=0;i!==Nbodies;i++)bodies[i].updateSolveMassProperties();const invCs=GSSolver_solve_invCs,Bs=GSSolver_solve_Bs,lambda=GSSolver_solve_lambda;invCs.length=Neq,Bs.length=Neq,lambda.length=Neq;for(let i=0;i!==Neq;i++){const c=equations[i];lambda[i]=0,Bs[i]=c.computeB(h),invCs[i]=1/c.computeC()}if(0!==Neq){for(let i=0;i!==Nbodies;i++){const b=bodies[i],vlambda=b.vlambda,wlambda=b.wlambda;vlambda.set(0,0,0),wlambda.set(0,0,0)}for(iter=0;iter!==maxIter;iter++){deltalambdaTot=0;for(let j=0;j!==Neq;j++){const c=equations[j];B=Bs[j],invC=invCs[j],(lambdaj=lambda[j])+(deltalambda=invC*(B-(GWlambda=c.computeGWlambda())-c.eps*lambdaj))c.maxForce&&(deltalambda=c.maxForce-lambdaj),lambda[j]+=deltalambda,deltalambdaTot+=deltalambda>0?deltalambda:-deltalambda,c.addToWlambda(deltalambda)}if(deltalambdaTot*deltalambdaTotsize;)objects.pop();for(;objects.length=0&&matB.restitution>=0&&(c.restitution=matA.restitution*matB.restitution),c.si=overrideShapeA||si,c.sj=overrideShapeB||sj,c}createFrictionEquationsFromContact(contactEquation,outArray){const bodyA=contactEquation.bi,bodyB=contactEquation.bj,shapeA=contactEquation.si,shapeB=contactEquation.sj,world=this.world,cm=this.currentContactMaterial;let friction=cm.friction;const matA=shapeA.material||bodyA.material,matB=shapeB.material||bodyB.material;if(matA&&matB&&matA.friction>=0&&matB.friction>=0&&(friction=matA.friction*matB.friction),friction>0){const mug=friction*world.gravity.length();let reducedMass=bodyA.invMass+bodyB.invMass;reducedMass>0&&(reducedMass=1/reducedMass);const pool=this.frictionEquationPool,c1=pool.length?pool.pop():new FrictionEquation(bodyA,bodyB,mug*reducedMass),c2=pool.length?pool.pop():new FrictionEquation(bodyA,bodyB,mug*reducedMass);return c1.bi=c2.bi=bodyA,c1.bj=c2.bj=bodyB,c1.minForce=c2.minForce=-mug*reducedMass,c1.maxForce=c2.maxForce=mug*reducedMass,c1.ri.copy(contactEquation.ri),c1.rj.copy(contactEquation.rj),c2.ri.copy(contactEquation.ri),c2.rj.copy(contactEquation.rj),contactEquation.ni.tangents(c1.t,c2.t),c1.setSpookParams(cm.frictionEquationStiffness,cm.frictionEquationRelaxation,world.dt),c2.setSpookParams(cm.frictionEquationStiffness,cm.frictionEquationRelaxation,world.dt),c1.enabled=c2.enabled=contactEquation.enabled,outArray.push(c1,c2),!0}return!1}createFrictionFromAverage(numContacts){let c=this.result[this.result.length-1];if(!this.createFrictionEquationsFromContact(c,this.frictionResult)||1===numContacts)return;const f1=this.frictionResult[this.frictionResult.length-2],f2=this.frictionResult[this.frictionResult.length-1];averageNormal.setZero(),averageContactPointA.setZero(),averageContactPointB.setZero();const bodyA=c.bi;c.bj;for(let i=0;i!==numContacts;i++)(c=this.result[this.result.length-1-i]).bi!==bodyA?(averageNormal.vadd(c.ni,averageNormal),averageContactPointA.vadd(c.ri,averageContactPointA),averageContactPointB.vadd(c.rj,averageContactPointB)):(averageNormal.vsub(c.ni,averageNormal),averageContactPointA.vadd(c.rj,averageContactPointA),averageContactPointB.vadd(c.ri,averageContactPointB));const invNumContacts=1/numContacts;averageContactPointA.scale(invNumContacts,f1.ri),averageContactPointB.scale(invNumContacts,f1.rj),f2.ri.copy(f1.ri),f2.rj.copy(f1.rj),averageNormal.normalize(),averageNormal.tangents(f1.t,f2.t)}getContacts(p1,p2,world,result,oldcontacts,frictionResult,frictionPool){this.contactPointPool=oldcontacts,this.frictionEquationPool=frictionPool,this.result=result,this.frictionResult=frictionResult;const qi=tmpQuat1,qj=tmpQuat2,xi=tmpVec1$2,xj=tmpVec2$2;for(let k=0,N=p1.length;k!==N;k++){const bi=p1[k],bj=p2[k];let bodyContactMaterial=null;bi.material&&bj.material&&(bodyContactMaterial=world.getContactMaterial(bi.material,bj.material)||null);const justTest=bi.type&Body.KINEMATIC&&bj.type&Body.STATIC||bi.type&Body.STATIC&&bj.type&Body.KINEMATIC||bi.type&Body.KINEMATIC&&bj.type&Body.KINEMATIC;for(let i=0;isi.boundingSphereRadius+sj.boundingSphereRadius)continue;let shapeContactMaterial=null;si.material&&sj.material&&(shapeContactMaterial=world.getContactMaterial(si.material,sj.material)||null),this.currentContactMaterial=shapeContactMaterial||bodyContactMaterial||world.defaultContactMaterial;const resolver=this[si.type|sj.type];if(resolver){let retval=!1;(retval=si.type0){const ns1=sphereBox_ns1,ns2=sphereBox_ns2;ns1.copy(sides[(idx+1)%3]),ns2.copy(sides[(idx+2)%3]);const h1=ns1.length(),h2=ns2.length();ns1.normalize(),ns2.normalize();const dot1=box_to_sphere.dot(ns1),dot2=box_to_sphere.dot(ns2);if(dot1-h1&&dot2-h2){const dist=Math.abs(dot-h-R);if((null===side_distance||distsi.boundingSphereRadius+sj.boundingSphereRadius)&&si.findSeparatingAxis(sj,xi,qi,xj,qj,sepAxis,faceListA,faceListB)){const res=[],q=convexConvex_q;si.clipAgainstHull(xi,qi,sj,xj,qj,sepAxis,-100,100,res);let numContacts=0;for(let j=0;j!==res.length;j++){if(justTest)return!0;const r=this.createContactEquation(bi,bj,si,sj,rsi,rsj),ri=r.ri,rj=r.rj;sepAxis.negate(r.ni),res[j].normal.negate(q),q.scale(res[j].depth,q),res[j].point.vadd(q,ri),rj.copy(res[j].point),ri.vsub(xi,ri),rj.vsub(xj,rj),ri.vadd(xi,ri),ri.vsub(bi.position,ri),rj.vadd(xj,rj),rj.vsub(bj.position,rj),this.result.push(r),numContacts++,this.enableFrictionReduction||this.createFrictionEquationsFromContact(r,this.frictionResult)}this.enableFrictionReduction&&numContacts&&this.createFrictionFromAverage(numContacts)}}sphereConvex(si,sj,xi,xj,qi,qj,bi,bj,rsi,rsj,justTest){const v3pool=this.v3pool;xi.vsub(xj,convex_to_sphere);const normals=sj.faceNormals,faces=sj.faces,verts=sj.vertices,R=si.radius;let found=!1;for(let i=0;i!==verts.length;i++){const v=verts[i],worldCorner=sphereConvex_worldCorner;qj.vmult(v,worldCorner),xj.vadd(worldCorner,worldCorner);const sphere_to_corner=sphereConvex_sphereToCorner;if(worldCorner.vsub(xi,sphere_to_corner),sphere_to_corner.lengthSquared()0){const faceVerts=[];for(let j=0,Nverts=face.length;j!==Nverts;j++){const worldVertex=v3pool.get();qj.vmult(verts[face[j]],worldVertex),xj.vadd(worldVertex,worldVertex),faceVerts.push(worldVertex)}if(pointInPolygon(faceVerts,worldNormal,xi)){if(justTest)return!0;found=!0;const r=this.createContactEquation(bi,bj,si,sj,rsi,rsj);worldNormal.scale(-R,r.ri),worldNormal.negate(r.ni);const penetrationVec2=v3pool.get();worldNormal.scale(-penetration,penetrationVec2);const penetrationSpherePoint=v3pool.get();worldNormal.scale(-R,penetrationSpherePoint),xi.vsub(xj,r.rj),r.rj.vadd(penetrationSpherePoint,r.rj),r.rj.vadd(penetrationVec2,r.rj),r.rj.vadd(xj,r.rj),r.rj.vsub(bj.position,r.rj),r.ri.vadd(xi,r.ri),r.ri.vsub(bi.position,r.ri),v3pool.release(penetrationVec2),v3pool.release(penetrationSpherePoint),this.result.push(r),this.createFrictionEquationsFromContact(r,this.frictionResult);for(let j=0,Nfaceverts=faceVerts.length;j!==Nfaceverts;j++)v3pool.release(faceVerts[j]);return}for(let j=0;j!==face.length;j++){const v1=v3pool.get(),v2=v3pool.get();qj.vmult(verts[face[(j+1)%face.length]],v1),qj.vmult(verts[face[(j+2)%face.length]],v2),xj.vadd(v1,v1),xj.vadd(v2,v2);const edge=sphereConvex_edge;v2.vsub(v1,edge);const edgeUnit=sphereConvex_edgeUnit;edge.unit(edgeUnit);const p=v3pool.get(),v1_to_xi=v3pool.get();xi.vsub(v1,v1_to_xi);const dot=v1_to_xi.dot(edgeUnit);edgeUnit.scale(dot,p),p.vadd(v1,p);const xi_to_p=v3pool.get();if(p.vsub(xi,xi_to_p),dot>0&&dot*dotdata.length||iMinY>data[0].length)return;iMinX<0&&(iMinX=0),iMaxX<0&&(iMaxX=0),iMinY<0&&(iMinY=0),iMaxY<0&&(iMaxY=0),iMinX>=data.length&&(iMinX=data.length-1),iMaxX>=data.length&&(iMaxX=data.length-1),iMaxY>=data[0].length&&(iMaxY=data[0].length-1),iMinY>=data[0].length&&(iMinY=data[0].length-1);const minMax=[];hfShape.getRectMinMax(iMinX,iMinY,iMaxX,iMaxY,minMax);const min=minMax[0],max=minMax[1];if(localSpherePos.z-radius>max||localSpherePos.z+radius2)return}}boxHeightfield(si,sj,xi,xj,qi,qj,bi,bj,rsi,rsj,justTest){return si.convexPolyhedronRepresentation.material=si.material,si.convexPolyhedronRepresentation.collisionResponse=si.collisionResponse,this.convexHeightfield(si.convexPolyhedronRepresentation,sj,xi,xj,qi,qj,bi,bj,si,sj,justTest)}convexHeightfield(convexShape,hfShape,convexPos,hfPos,convexQuat,hfQuat,convexBody,hfBody,rsi,rsj,justTest){const data=hfShape.data,w=hfShape.elementSize,radius=convexShape.boundingSphereRadius,worldPillarOffset=convexHeightfield_tmp2,faceList=convexHeightfield_faceList,localConvexPos=convexHeightfield_tmp1;Transform.pointToLocalFrame(hfPos,hfQuat,convexPos,localConvexPos);let iMinX=Math.floor((localConvexPos.x-radius)/w)-1,iMaxX=Math.ceil((localConvexPos.x+radius)/w)+1,iMinY=Math.floor((localConvexPos.y-radius)/w)-1,iMaxY=Math.ceil((localConvexPos.y+radius)/w)+1;if(iMaxX<0||iMaxY<0||iMinX>data.length||iMinY>data[0].length)return;iMinX<0&&(iMinX=0),iMaxX<0&&(iMaxX=0),iMinY<0&&(iMinY=0),iMaxY<0&&(iMaxY=0),iMinX>=data.length&&(iMinX=data.length-1),iMaxX>=data.length&&(iMaxX=data.length-1),iMaxY>=data[0].length&&(iMaxY=data[0].length-1),iMinY>=data[0].length&&(iMinY=data[0].length-1);const minMax=[];hfShape.getRectMinMax(iMinX,iMinY,iMaxX,iMaxY,minMax);const min=minMax[0],max=minMax[1];if(!(localConvexPos.z-radius>max||localConvexPos.z+radius0&&positionAlongEdgeB<0){if(localSpherePos.vsub(edgeVertexA,tmp),edgeVectorUnit.copy(edgeVector),edgeVectorUnit.normalize(),positionAlongEdgeA=tmp.dot(edgeVectorUnit),edgeVectorUnit.scale(positionAlongEdgeA,tmp),tmp.vadd(edgeVertexA,tmp),tmp.distanceTo(localSpherePos)0&&!0===positiveResult||r<=0&&!1===positiveResult))return!1;null===positiveResult&&(positiveResult=r>0)}return!0}const box_to_sphere=new Vec3,sphereBox_ns=new Vec3,sphereBox_ns1=new Vec3,sphereBox_ns2=new Vec3,sphereBox_sides=[new Vec3,new Vec3,new Vec3,new Vec3,new Vec3,new Vec3],sphereBox_sphere_to_corner=new Vec3,sphereBox_side_ns=new Vec3,sphereBox_side_ns1=new Vec3,sphereBox_side_ns2=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereBox]=Narrowphase.prototype.sphereBox;const convex_to_sphere=new Vec3,sphereConvex_edge=new Vec3,sphereConvex_edgeUnit=new Vec3,sphereConvex_sphereToCorner=new Vec3,sphereConvex_worldCorner=new Vec3,sphereConvex_worldNormal=new Vec3,sphereConvex_worldPoint=new Vec3,sphereConvex_worldSpherePointClosestToPlane=new Vec3,sphereConvex_penetrationVec=new Vec3,sphereConvex_sphereToWorldPoint=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereConvex]=Narrowphase.prototype.sphereConvex,Narrowphase.prototype[COLLISION_TYPES.planeBox]=Narrowphase.prototype.planeBox;const planeConvex_v=new Vec3,planeConvex_normal=new Vec3,planeConvex_relpos=new Vec3,planeConvex_projected=new Vec3;Narrowphase.prototype[COLLISION_TYPES.planeConvex]=Narrowphase.prototype.planeConvex;const convexConvex_sepAxis=new Vec3,convexConvex_q=new Vec3;Narrowphase.prototype[COLLISION_TYPES.convexConvex]=Narrowphase.prototype.convexConvex;const particlePlane_normal=new Vec3,particlePlane_relpos=new Vec3,particlePlane_projected=new Vec3;Narrowphase.prototype[COLLISION_TYPES.planeParticle]=Narrowphase.prototype.planeParticle;const particleSphere_normal=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereParticle]=Narrowphase.prototype.sphereParticle;const cqj=new Quaternion,convexParticle_local=new Vec3,convexParticle_penetratedFaceNormal=new Vec3,convexParticle_vertexToParticle=new Vec3,convexParticle_worldPenetrationVec=new Vec3;Narrowphase.prototype[COLLISION_TYPES.convexParticle]=Narrowphase.prototype.convexParticle,Narrowphase.prototype[COLLISION_TYPES.boxHeightfield]=Narrowphase.prototype.boxHeightfield;const convexHeightfield_tmp1=new Vec3,convexHeightfield_tmp2=new Vec3,convexHeightfield_faceList=[0];Narrowphase.prototype[COLLISION_TYPES.convexHeightfield]=Narrowphase.prototype.convexHeightfield;const sphereHeightfield_tmp1=new Vec3,sphereHeightfield_tmp2=new Vec3;Narrowphase.prototype[COLLISION_TYPES.sphereHeightfield]=Narrowphase.prototype.sphereHeightfield;class OverlapKeeper{constructor(){this.current=[],this.previous=[]}getKey(i,j){if(jcurrent[index];)index++;if(key!==current[index]){for(let j=current.length-1;j>=index;j--)current[j+1]=current[j];current[index]=key}}tick(){const tmp=this.current;this.current=this.previous,this.previous=tmp,this.current.length=0}getDiff(additions,removals){const a=this.current,b=this.previous,al=a.length,bl=b.length;let j=0;for(let i=0;ib[j];)j++;(found=keyA===b[j])||unpackAndPush(additions,keyA)}j=0;for(let i=0;ia[j];)j++;(found=a[j]===keyB)||unpackAndPush(removals,keyB)}}}function unpackAndPush(array,key){array.push((4294901760&key)>>16,65535&key)}class TupleDictionary{constructor(){this.data={keys:[]}}get(i,j){if(i>j){const temp=j;j=i,i=temp}return this.data[i+"-"+j]}set(i,j,value){if(i>j){const temp=j;j=i,i=temp}const key=i+"-"+j;this.get(i,j)||this.data.keys.push(key),this.data[key]=value}reset(){const data=this.data,keys=data.keys;for(;keys.length>0;){delete data[keys.pop()]}}}class World extends EventTarget{constructor(options={}){super(),this.dt=-1,this.allowSleep=!!options.allowSleep,this.contacts=[],this.frictionEquations=[],this.quatNormalizeSkip=void 0!==options.quatNormalizeSkip?options.quatNormalizeSkip:0,this.quatNormalizeFast=void 0!==options.quatNormalizeFast&&options.quatNormalizeFast,this.time=0,this.stepnumber=0,this.default_dt=1/60,this.nextId=0,this.gravity=new Vec3,options.gravity&&this.gravity.copy(options.gravity),this.broadphase=void 0!==options.broadphase?options.broadphase:new NaiveBroadphase,this.bodies=[],this.hasActiveBodies=!1,this.solver=void 0!==options.solver?options.solver:new GSSolver,this.constraints=[],this.narrowphase=new Narrowphase(this),this.collisionMatrix=new ArrayCollisionMatrix,this.collisionMatrixPrevious=new ArrayCollisionMatrix,this.bodyOverlapKeeper=new OverlapKeeper,this.shapeOverlapKeeper=new OverlapKeeper,this.materials=[],this.contactmaterials=[],this.contactMaterialTable=new TupleDictionary,this.defaultMaterial=new Material("default"),this.defaultContactMaterial=new ContactMaterial(this.defaultMaterial,this.defaultMaterial,{friction:.3,restitution:0}),this.doProfiling=!1,this.profile={solve:0,makeContactConstraints:0,broadphase:0,integrate:0,narrowphase:0},this.accumulator=0,this.subsystems=[],this.addBodyEvent={type:"addBody",body:null},this.removeBodyEvent={type:"removeBody",body:null},this.idToBodyMap={},this.broadphase.setWorld(this)}getContactMaterial(m1,m2){return this.contactMaterialTable.get(m1.id,m2.id)}numObjects(){return this.bodies.length}collisionMatrixTick(){const temp=this.collisionMatrixPrevious;this.collisionMatrixPrevious=this.collisionMatrix,this.collisionMatrix=temp,this.collisionMatrix.reset(),this.bodyOverlapKeeper.tick(),this.shapeOverlapKeeper.tick()}addConstraint(c){this.constraints.push(c)}removeConstraint(c){const idx=this.constraints.indexOf(c);-1!==idx&&this.constraints.splice(idx,1)}rayTest(from,to,result){result instanceof RaycastResult?this.raycastClosest(from,to,{skipBackfaces:!0},result):this.raycastAll(from,to,{skipBackfaces:!0},result)}raycastAll(from,to,options={},callback){return options.mode=Ray.ALL,options.from=from,options.to=to,options.callback=callback,tmpRay$1.intersectWorld(this,options)}raycastAny(from,to,options={},result){return options.mode=Ray.ANY,options.from=from,options.to=to,options.result=result,tmpRay$1.intersectWorld(this,options)}raycastClosest(from,to,options={},result){return options.mode=Ray.CLOSEST,options.from=from,options.to=to,options.result=result,tmpRay$1.intersectWorld(this,options)}addBody(body){this.bodies.includes(body)||(body.index=this.bodies.length,this.bodies.push(body),body.world=this,body.initPosition.copy(body.position),body.initVelocity.copy(body.velocity),body.timeLastSleepy=this.time,body instanceof Body&&(body.initAngularVelocity.copy(body.angularVelocity),body.initQuaternion.copy(body.quaternion)),this.collisionMatrix.setNumObjects(this.bodies.length),this.addBodyEvent.body=body,this.idToBodyMap[body.id]=body,this.dispatchEvent(this.addBodyEvent))}removeBody(body){body.world=null;const n=this.bodies.length-1,bodies=this.bodies,idx=bodies.indexOf(body);if(-1!==idx){bodies.splice(idx,1);for(let i=0;i!==bodies.length;i++)bodies[i].index=i;this.collisionMatrix.setNumObjects(n),this.removeBodyEvent.body=body,delete this.idToBodyMap[body.id],this.dispatchEvent(this.removeBodyEvent)}}getBodyById(id){return this.idToBodyMap[id]}getShapeById(id){const bodies=this.bodies;for(let i=0,bl=bodies.length;i=dt&&substeps=0;j-=1)(c.bodyA===p1[j]&&c.bodyB===p2[j]||c.bodyB===p1[j]&&c.bodyA===p2[j])&&(p1.splice(j,1),p2.splice(j,1))}this.collisionMatrixTick(),doProfiling&&(profilingStart=performance.now());const oldcontacts=World_step_oldContacts,NoldContacts=contacts.length;for(i=0;i!==NoldContacts;i++)oldcontacts.push(contacts[i]);contacts.length=0;const NoldFrictionEquations=this.frictionEquations.length;for(i=0;i!==NoldFrictionEquations;i++)frictionEquationPool.push(this.frictionEquations[i]);for(this.frictionEquations.length=0,this.narrowphase.getContacts(p1,p2,this,contacts,oldcontacts,this.frictionEquations,frictionEquationPool),doProfiling&&(profile.narrowphase=performance.now()-profilingStart),doProfiling&&(profilingStart=performance.now()),i=0;i=0&&bj.material.friction>=0&&(mu=bi.material.friction*bj.material.friction),bi.material.restitution>=0&&bj.material.restitution>=0&&(c.restitution=bi.material.restitution*bj.material.restitution)),solver.addEquation(c),bi.allowSleep&&bi.type===Body.DYNAMIC&&bi.sleepState===Body.SLEEPING&&bj.sleepState===Body.AWAKE&&bj.type!==Body.STATIC){bj.velocity.lengthSquared()+bj.angularVelocity.lengthSquared()>=2*bj.sleepSpeedLimit**2&&(bi.wakeUpAfterNarrowphase=!0)}if(bj.allowSleep&&bj.type===Body.DYNAMIC&&bj.sleepState===Body.SLEEPING&&bi.sleepState===Body.AWAKE&&bi.type!==Body.STATIC){bi.velocity.lengthSquared()+bi.angularVelocity.lengthSquared()>=2*bi.sleepSpeedLimit**2&&(bj.wakeUpAfterNarrowphase=!0)}this.collisionMatrix.set(bi,bj,!0),this.collisionMatrixPrevious.get(bi,bj)||(World_step_collideEvent.body=bj,World_step_collideEvent.contact=c,bi.dispatchEvent(World_step_collideEvent),World_step_collideEvent.body=bi,bj.dispatchEvent(World_step_collideEvent)),this.bodyOverlapKeeper.set(bi.id,bj.id),this.shapeOverlapKeeper.set(si.id,sj.id)}for(this.emitContactEvents(),doProfiling&&(profile.makeContactConstraints=performance.now()-profilingStart,profilingStart=performance.now()),i=0;i!==N;i++){const bi=bodies[i];bi.wakeUpAfterNarrowphase&&(bi.wakeUp(),bi.wakeUpAfterNarrowphase=!1)}for(Nconstraints=constraints.length,i=0;i!==Nconstraints;i++){const c=constraints[i];c.update();for(let j=0,Neq=c.equations.length;j!==Neq;j++){const eq=c.equations[j];solver.addEquation(eq)}}solver.solve(dt,this),doProfiling&&(profile.solve=performance.now()-profilingStart),solver.removeAllEquations();const pow=Math.pow;for(i=0;i!==N;i++){const bi=bodies[i];if(bi.type&DYNAMIC){const ld=pow(1-bi.linearDamping,dt),v=bi.velocity;v.scale(ld,v);const av=bi.angularVelocity;if(av){const ad=pow(1-bi.angularDamping,dt);av.scale(ad,av)}}}for(this.dispatchEvent(World_step_preStepEvent),i=0;i!==N;i++){const bi=bodies[i];bi.preStep&&bi.preStep.call(bi)}doProfiling&&(profilingStart=performance.now());const quatNormalize=this.stepnumber%(this.quatNormalizeSkip+1)==0,quatNormalizeFast=this.quatNormalizeFast;for(i=0;i!==N;i++)bodies[i].integrate(dt,quatNormalize,quatNormalizeFast);for(this.clearForces(),this.broadphase.dirty=!0,doProfiling&&(profile.integrate=performance.now()-profilingStart),this.time+=dt,this.stepnumber+=1,this.dispatchEvent(World_step_postStepEvent),i=0;i!==N;i++){const bi=bodies[i],postStep=bi.postStep;postStep&&postStep.call(bi)}let hasActiveBodies=!0;if(this.allowSleep)for(hasActiveBodies=!1,i=0;i!==N;i++){const bi=bodies[i];bi.sleepTick(this.time),bi.sleepState!==Body.SLEEPING&&(hasActiveBodies=!0)}this.hasActiveBodies=hasActiveBodies}clearForces(){const bodies=this.bodies,N=bodies.length;for(let i=0;i!==N;i++){const b=bodies[i];b.force,b.torque;b.force.set(0,0,0),b.torque.set(0,0,0)}}}exports.World=World;new AABB;const tmpRay$1=new Ray;if("undefined"==typeof performance&&(performance={}),!performance.now){let nowOffset=Date.now();performance.timing&&performance.timing.navigationStart&&(nowOffset=performance.timing.navigationStart),performance.now=(()=>Date.now()-nowOffset)}const World_step_postStepEvent={type:"postStep"},World_step_preStepEvent={type:"preStep"},World_step_collideEvent={type:Body.COLLIDE_EVENT_NAME,body:null,contact:null},World_step_oldContacts=[],World_step_frictionEquationPool=[],World_step_p1=[],World_step_p2=[];World.prototype.emitContactEvents=(()=>{const additions=[],removals=[],beginContactEvent={type:"beginContact",bodyA:null,bodyB:null},endContactEvent={type:"endContact",bodyA:null,bodyB:null},beginShapeContactEvent={type:"beginShapeContact",bodyA:null,bodyB:null,shapeA:null,shapeB:null},endShapeContactEvent={type:"endShapeContact",bodyA:null,bodyB:null,shapeA:null,shapeB:null};return function(){const hasBeginContact=this.hasAnyEventListener("beginContact"),hasEndContact=this.hasAnyEventListener("endContact");if((hasBeginContact||hasEndContact)&&this.bodyOverlapKeeper.getDiff(additions,removals),hasBeginContact){for(let i=0,l=additions.length;i{switch(options.cylinderAxis){case"y":return new Ammo.btCylinderShape(btHalfExtents);case"x":return new Ammo.btCylinderShapeX(btHalfExtents);case"z":return new Ammo.btCylinderShapeZ(btHalfExtents)}return null})();return Ammo.destroy(btHalfExtents),_finishCollisionShape(collisionShape,options,_computeScale(matrixWorld,options)),collisionShape};exports.createCylinderShape=createCylinderShape;const createCapsuleShape=function(vertices,matrices,matrixWorld,options={}){options.type=TYPE.CAPSULE,_setOptions(options),options.fit===FIT.ALL&&(options.halfExtents=_computeHalfExtents(_computeBounds(vertices,matrices),options.minHalfExtent,options.maxHalfExtent));const{x:x,y:y,z:z}=options.halfExtents,collisionShape=(()=>{switch(options.cylinderAxis){case"y":return new Ammo.btCapsuleShape(Math.max(x,z),2*y);case"x":return new Ammo.btCapsuleShapeX(Math.max(y,z),2*x);case"z":return new Ammo.btCapsuleShapeZ(Math.max(x,y),2*z)}return null})();return _finishCollisionShape(collisionShape,options,_computeScale(matrixWorld,options)),collisionShape};exports.createCapsuleShape=createCapsuleShape;const createConeShape=function(vertices,matrices,matrixWorld,options={}){options.type=TYPE.CONE,_setOptions(options),options.fit===FIT.ALL&&(options.halfExtents=_computeHalfExtents(_computeBounds(vertices,matrices),options.minHalfExtent,options.maxHalfExtent));const{x:x,y:y,z:z}=options.halfExtents,collisionShape=(()=>{switch(options.cylinderAxis){case"y":return new Ammo.btConeShape(Math.max(x,z),2*y);case"x":return new Ammo.btConeShapeX(Math.max(y,z),2*x);case"z":return new Ammo.btConeShapeZ(Math.max(x,y),2*z)}return null})();return _finishCollisionShape(collisionShape,options,_computeScale(matrixWorld,options)),collisionShape};exports.createConeShape=createConeShape;const createSphereShape=function(vertices,matrices,matrixWorld,options={}){let radius;options.type=TYPE.SPHERE,_setOptions(options),radius=options.fit!==FIT.MANUAL||isNaN(options.sphereRadius)?_computeRadius(vertices,matrices,_computeBounds(vertices,matrices)):options.sphereRadius;const collisionShape=new Ammo.btSphereShape(radius);return _finishCollisionShape(collisionShape,options,_computeScale(matrixWorld,options)),collisionShape};exports.createSphereShape=createSphereShape;const createHullShape=exports.createHullShape=function(){const vertex=new THREE.Vector3,center=new THREE.Vector3,matrix=new THREE.Matrix4;return function(vertices,matrices,matrixWorld,options={}){if(options.type=TYPE.HULL,_setOptions(options),options.fit===FIT.MANUAL)return console.warn("cannot use fit: manual with type: hull"),null;const bounds=_computeBounds(vertices,matrices),btVertex=new Ammo.btVector3,originalHull=new Ammo.btConvexHullShape;originalHull.setMargin(options.margin),center.addVectors(bounds.max,bounds.min).multiplyScalar(.5);let vertexCount=0;for(let i=0;imaxVertices&&console.warn(`too many vertices for hull shape; sampling ~${maxVertices} from ~${vertexCount} vertices`);const p=Math.min(1,maxVertices/vertexCount);for(let i=0;i=100){const shapeHull=new Ammo.btShapeHull(originalHull);shapeHull.buildHull(options.margin),Ammo.destroy(originalHull),collisionShape=new Ammo.btConvexHullShape(Ammo.getPointer(shapeHull.getVertexPointer()),shapeHull.numVertices()),Ammo.destroy(shapeHull)}return Ammo.destroy(btVertex),_finishCollisionShape(collisionShape,options,_computeScale(matrixWorld,options)),collisionShape}}(),createHACDShapes=exports.createHACDShapes=function(){const vector=new THREE.Vector3,center=new THREE.Vector3,matrix=new THREE.Matrix4;return function(vertices,matrices,indexes,matrixWorld,options={}){if(options.type=TYPE.HACD,_setOptions(options),options.fit===FIT.MANUAL)return console.warn("cannot use fit: manual with type: hacd"),[];if(!Ammo.hasOwnProperty("HACD"))return console.warn("HACD unavailable in included build of Ammo.js. Visit https://github.com/mozillareality/ammo.js for the latest version."),[];const bounds=_computeBounds(vertices,matrices),scale=_computeScale(matrixWorld,options);let vertexCount=0,triCount=0;center.addVectors(bounds.max,bounds.min).multiplyScalar(.5);for(let i=0;i{switch(options.heightDataType){case"short":return Ammo.PHY_SHORT;case"float":default:return Ammo.PHY_FLOAT}})(),flipQuadEdges=!options.hasOwnProperty("flipQuadEdges")||options.flipQuadEdges,heightStickLength=heightfieldData.length,heightStickWidth=heightStickLength>0?heightfieldData[0].length:0,data=Ammo._malloc(heightStickLength*heightStickWidth*4),ptr=data/4;let minHeight=Number.POSITIVE_INFINITY,maxHeight=Number.NEGATIVE_INFINITY,index=0;for(let l=0;l{for(let res of collisionShape.resources||[])Ammo.destroy(res);collisionShape.heightfieldData&&Ammo._free(collisionShape.heightfieldData),Ammo.destroy(collisionShape)});const localTransform=new Ammo.btTransform,rotation=new Ammo.btQuaternion;if(localTransform.setIdentity(),localTransform.getOrigin().setValue(options.offset.x,options.offset.y,options.offset.z),rotation.setValue(options.orientation.x,options.orientation.y,options.orientation.z,options.orientation.w),localTransform.setRotation(rotation),Ammo.destroy(rotation),scale){const localScale=new Ammo.btVector3(scale.x,scale.y,scale.z);collisionShape.setLocalScaling(localScale),Ammo.destroy(localScale)}collisionShape.localTransform=localTransform},_computeScale=(exports.iterateGeometries=function(){const inverse=new THREE.Matrix4;return function(root,options,cb){inverse.copy(root.matrixWorld).invert(),(new THREE.Vector3).setFromMatrixScale(root.matrixWorld),root.traverse(mesh=>{const transform=new THREE.Matrix4;mesh.isMesh&&"Sky"!==mesh.name&&(options.includeInvisible||mesh.el&&mesh.el.object3D.visible||mesh.visible)&&(mesh===root?transform.identity():(mesh.updateWorldMatrix(!0),transform.multiplyMatrices(inverse,mesh.matrixWorld)),cb(mesh.geometry.isBufferGeometry?mesh.geometry.attributes.position.array:mesh.geometry.vertices,transform.elements,mesh.geometry.index?mesh.geometry.index.array:null))})}}(),function(){const matrix=new THREE.Matrix4;return function(matrixWorld,options={}){const scale=new THREE.Vector3(1,1,1);return options.fit===FIT.ALL&&(matrix.fromArray(matrixWorld),scale.setFromMatrixScale(matrix)),scale}}()),_computeRadius=function(){const center=new THREE.Vector3;return function(vertices,matrices,bounds){let maxRadiusSq=0,{x:cx,y:cy,z:cz}=bounds.getCenter(center);return _iterateVertices(vertices,matrices,v=>{const dx=cx-v.x,dy=cy-v.y,dz=cz-v.z;maxRadiusSq=Math.max(maxRadiusSq,dx*dx+dy*dy+dz*dz)}),Math.sqrt(maxRadiusSq)}}(),_computeHalfExtents=function(bounds,minHalfExtent,maxHalfExtent){return(new THREE.Vector3).subVectors(bounds.max,bounds.min).multiplyScalar(.5).clampScalar(minHalfExtent,maxHalfExtent)},_computeBounds=function(vertices,matrices){const bounds=new THREE.Box3;let minX=1/0,minY=1/0,minZ=1/0,maxX=-1/0,maxY=-1/0,maxZ=-1/0;return bounds.min.set(0,0,0),bounds.max.set(0,0,0),_iterateVertices(vertices,matrices,v=>{v.xmaxX&&(maxX=v.x),v.y>maxY&&(maxY=v.y),v.z>maxZ&&(maxZ=v.z)}),bounds.min.set(minX,minY,minZ),bounds.max.set(maxX,maxY,maxZ),bounds},_iterateVertices=function(){const vertex=new THREE.Vector3,matrix=new THREE.Matrix4;return function(vertices,matrices,cb){for(let i=0;ithis.tolerance)return!1}return!0},intersectRay:function(ray,target){for(var faces=this.faces,tNear=-1/0,tFar=1/0,i=0,l=faces.length;i0&&vD>=0)return null;var t=0!==vD?-vN/vD:0;if(!(t<=0)&&(vD>0?tFar=Math.min(t,tFar):tNear=Math.max(t,tNear),tNear>tFar))return null}return tNear!==-1/0?ray.at(tNear,target):ray.at(tFar,target),target},intersectsRay:function(ray){return null!==this.intersectRay(ray,v1)},makeEmpty:function(){return this.faces=[],this.vertices=[],this},addVertexToFace:function(vertex,face){return vertex.face=face,null===face.outside?this.assigned.append(vertex):this.assigned.insertBefore(face.outside,vertex),face.outside=vertex,this},removeVertexFromFace:function(vertex,face){return vertex===face.outside&&(null!==vertex.next&&vertex.next.face===face?face.outside=vertex.next:face.outside=null),this.assigned.remove(vertex),this},removeAllVerticesFromFace:function(face){if(null!==face.outside){for(var start=face.outside,end=face.outside;null!==end.next&&end.next.face===face;)end=end.next;return this.assigned.removeSubList(start,end),start.prev=end.next=null,face.outside=null,start}},deleteFaceVertices:function(face,absorbingFace){var faceVertices=this.removeAllVerticesFromFace(face);if(void 0!==faceVertices)if(void 0===absorbingFace)this.unassigned.appendChain(faceVertices);else{var vertex=faceVertices;do{var nextVertex=vertex.next;absorbingFace.distanceToPoint(vertex.point)>this.tolerance?this.addVertexToFace(vertex,absorbingFace):this.unassigned.append(vertex),vertex=nextVertex}while(null!==vertex)}return this},resolveUnassignedPoints:function(newFaces){if(!1===this.unassigned.isEmpty()){var vertex=this.unassigned.first();do{for(var nextVertex=vertex.next,maxDistance=this.tolerance,maxFace=null,i=0;imaxDistance&&(maxDistance=distance,maxFace=face),maxDistance>1e3*this.tolerance)break}}null!==maxFace&&this.addVertexToFace(vertex,maxFace),vertex=nextVertex}while(null!==vertex)}return this},computeExtremes:function(){var i,l,j,min=new _three.Vector3,max=new _three.Vector3,minVertices=[],maxVertices=[];for(i=0;i<3;i++)minVertices[i]=maxVertices[i]=this.vertices[0];for(min.copy(this.vertices[0].point),max.copy(this.vertices[0].point),i=0,l=this.vertices.length;imax.getComponent(j)&&(max.setComponent(j,point.getComponent(j)),maxVertices[j]=vertex)}return this.tolerance=3*Number.EPSILON*(Math.max(Math.abs(min.x),Math.abs(max.x))+Math.max(Math.abs(min.y),Math.abs(max.y))+Math.max(Math.abs(min.z),Math.abs(max.z))),{min:minVertices,max:maxVertices}},computeInitialHull:function(){void 0===line3&&(line3=new _three.Line3,plane=new _three.Plane,closestPoint=new _three.Vector3);var vertex,v0,v1,v2,v3,i,l,j,distance,vertices=this.vertices,extremes=this.computeExtremes(),min=extremes.min,max=extremes.max,maxDistance=0,index=0;for(i=0;i<3;i++)(distance=max[i].point.getComponent(i)-min[i].point.getComponent(i))>maxDistance&&(maxDistance=distance,index=i);for(v0=min[index],v1=max[index],maxDistance=0,line3.set(v0.point,v1.point),i=0,l=this.vertices.length;imaxDistance&&(maxDistance=distance,v2=vertex));for(maxDistance=-1,plane.setFromCoplanarPoints(v0.point,v1.point,v2.point),i=0,l=this.vertices.length;imaxDistance&&(maxDistance=distance,v3=vertex);var faces=[];if(plane.distanceToPoint(v3.point)<0)for(faces.push(Face.create(v0,v1,v2),Face.create(v3,v1,v0),Face.create(v3,v2,v1),Face.create(v3,v0,v2)),i=0;i<3;i++)j=(i+1)%3,faces[i+1].getEdge(2).setTwin(faces[0].getEdge(j)),faces[i+1].getEdge(1).setTwin(faces[j+1].getEdge(0));else for(faces.push(Face.create(v0,v2,v1),Face.create(v3,v0,v1),Face.create(v3,v1,v2),Face.create(v3,v2,v0)),i=0;i<3;i++)j=(i+1)%3,faces[i+1].getEdge(2).setTwin(faces[0].getEdge((3-i)%3)),faces[i+1].getEdge(0).setTwin(faces[j+1].getEdge(1));for(i=0;i<4;i++)this.faces.push(faces[i]);for(i=0,l=vertices.length;imaxDistance&&(maxDistance=distance,maxFace=this.faces[j]);null!==maxFace&&this.addVertexToFace(vertex,maxFace)}return this},reindexFaces:function(){for(var activeFaces=[],i=0;imaxDistance&&(maxDistance=distance,eyeVertex=vertex),vertex=vertex.next}while(null!==vertex&&vertex.face===eyeFace);return eyeVertex}},computeHorizon:function(eyePoint,crossEdge,face,horizon){var edge;this.deleteFaceVertices(face),face.mark=1,edge=null===crossEdge?crossEdge=face.getEdge(0):crossEdge.next;do{var twinEdge=edge.twin,oppositeFace=twinEdge.face;oppositeFace.mark===Visible&&(oppositeFace.distanceToPoint(eyePoint)>this.tolerance?this.computeHorizon(eyePoint,twinEdge,oppositeFace,horizon):horizon.push(edge)),edge=edge.next}while(edge!==crossEdge);return this},addAdjoiningFace:function(eyeVertex,horizonEdge){var face=Face.create(eyeVertex,horizonEdge.tail(),horizonEdge.head());return this.faces.push(face),face.getEdge(-1).setTwin(horizonEdge.twin),face.getEdge(0)},addNewFaces:function(eyeVertex,horizon){this.newFaces=[];for(var firstSideEdge=null,previousSideEdge=null,i=0;i0;)edge=edge.next,i--;for(;i<0;)edge=edge.prev,i++;return edge},compute:function(){void 0===triangle&&(triangle=new _three.Triangle);var a=this.edge.tail(),b=this.edge.head(),c=this.edge.next.head();return triangle.set(a.point,b.point,c.point),triangle.getNormal(this.normal),triangle.getMidpoint(this.midpoint),this.area=triangle.getArea(),this.constant=this.normal.dot(this.midpoint),this},distanceToPoint:function(point){return this.normal.dot(point)-this.constant}}),Object.assign(HalfEdge.prototype,{head:function(){return this.vertex},tail:function(){return this.prev?this.prev.vertex:null},length:function(){var head=this.head(),tail=this.tail();return null!==tail?tail.point.distanceTo(head.point):-1},lengthSquared:function(){var head=this.head(),tail=this.tail();return null!==tail?tail.point.distanceToSquared(head.point):-1},setTwin:function(edge){return this.twin=edge,edge.twin=this,this}}),Object.assign(VertexList.prototype,{first:function(){return this.head},last:function(){return this.tail},clear:function(){return this.head=this.tail=null,this},insertBefore:function(target,vertex){return vertex.prev=target.prev,vertex.next=target,null===vertex.prev?this.head=vertex:vertex.prev.next=vertex,target.prev=vertex,this},insertAfter:function(target,vertex){return vertex.prev=target,vertex.next=target.next,null===vertex.next?this.tail=vertex:vertex.next.prev=vertex,target.next=vertex,this},append:function(vertex){return null===this.head?this.head=vertex:this.tail.next=vertex,vertex.prev=this.tail,vertex.next=null,this.tail=vertex,this},appendChain:function(vertex){for(null===this.head?this.head=vertex:this.tail.next=vertex,vertex.prev=this.tail;null!==vertex.next;)vertex=vertex.next;return this.tail=vertex,this},remove:function(vertex){return null===vertex.prev?this.head=vertex.next:vertex.prev.next=vertex.next,null===vertex.next?this.tail=vertex.prev:vertex.next.prev=vertex.prev,this},removeSubList:function(a,b){return null===a.prev?this.head=b.next:a.prev.next=b.next,null===b.next?this.tail=a.prev:b.next.prev=a.prev,this},isEmpty:function(){return null===this.head}}),ConvexHull}();const _v1=new _three.Vector3,_v2=new _three.Vector3,_q1=new _three.Quaternion;function getGeometry(object){const meshes=function(object){const meshes=[];return object.traverse(function(o){o.isMesh&&meshes.push(o)}),meshes}(object);if(0===meshes.length)return null;if(1===meshes.length)return normalizeGeometry(meshes[0]);let mesh;const geometries=[];for(;mesh=meshes.pop();)geometries.push(simplifyGeometry(normalizeGeometry(mesh)));return function(geometries){let vertexCount=0;for(let i=0;i{this.loadedEventFired=!0},{once:!0}),this.system.initialized&&this.loadedEventFired&&this.initBody()},initBody:function(){const pos=new THREE.Vector3,quat=new THREE.Quaternion;new THREE.Box3;return function(){const el=this.el,data=this.data;this.localScaling=new Ammo.btVector3;const obj=this.el.object3D;obj.getWorldPosition(pos),obj.getWorldQuaternion(quat),this.prevScale=new THREE.Vector3(1,1,1),this.prevNumChildShapes=0,this.msTransform=new Ammo.btTransform,this.msTransform.setIdentity(),this.rotation=new Ammo.btQuaternion(quat.x,quat.y,quat.z,quat.w),this.msTransform.getOrigin().setValue(pos.x,pos.y,pos.z),this.msTransform.setRotation(this.rotation),this.motionState=new Ammo.btDefaultMotionState(this.msTransform),this.localInertia=new Ammo.btVector3(0,0,0),this.compoundShape=new Ammo.btCompoundShape(!0),this.rbInfo=new Ammo.btRigidBodyConstructionInfo(data.mass,this.motionState,this.compoundShape,this.localInertia),this.rbInfo.m_restitution=((num,min,max)=>Math.min(Math.max(num,min),max))(this.data.restitution,0,1),this.body=new Ammo.btRigidBody(this.rbInfo),this.body.setActivationState(ACTIVATION_STATES.indexOf(data.activationState)+1),this.body.setSleepingThresholds(data.linearSleepingThreshold,data.angularSleepingThreshold),this.body.setDamping(data.linearDamping,data.angularDamping);const angularFactor=new Ammo.btVector3(data.angularFactor.x,data.angularFactor.y,data.angularFactor.z);this.body.setAngularFactor(angularFactor),Ammo.destroy(angularFactor),this._updateBodyGravity(data.gravity),this.updateCollisionFlags(),this.el.body=this.body,this.body.el=el,this.isLoaded=!0,this.el.emit("body-loaded",{body:this.el.body}),this._addToSystem()}}(),tick:function(){this.system.initialized&&!this.isLoaded&&this.loadedEventFired&&this.initBody()},_updateBodyGravity(gravity){if(void 0!==gravity.x&&void 0!==gravity.y&&void 0!==gravity.z){const gravityBtVec=new Ammo.btVector3(gravity.x,gravity.y,gravity.z);epsilon=.001,u=gravityBtVec,v=this.system.driver.physicsWorld.getGravity(),Math.abs(u.x()-v.x()){vertices.push(vertexArray),matrices.push(matrixArray),indexes.push(indexArray)});const collisionShapes=threeToAmmo.createCollisionShapes(vertices,matrices,indexes,matrixWorld.elements,data);shapeComponent.addShapes(collisionShapes)},play:function(){this.isLoaded&&this._addToSystem()},_addToSystem:function(){this.addedToSystem||(this.system.addBody(this.body,this.data.collisionFilterGroup,this.data.collisionFilterMask),this.data.emitCollisionEvents&&this.system.driver.addEventListener(this.body),this.system.addComponent(this),this.addedToSystem=!0)},pause:function(){this.addedToSystem&&(this.system.removeComponent(this),this.system.removeBody(this.body),this.addedToSystem=!1)},update:function(prevData){if(this.isLoaded){if(!this.hasUpdated)return void(this.hasUpdated=!0);const data=this.data;if(prevData.type===data.type&&prevData.disableCollision===data.disableCollision||this.updateCollisionFlags(),prevData.activationState!==data.activationState&&(this.body.forceActivationState(ACTIVATION_STATES.indexOf(data.activationState)+1),data.activationState===ACTIVATION_STATE.ACTIVE_TAG&&this.body.activate(!0)),prevData.collisionFilterGroup!==data.collisionFilterGroup||prevData.collisionFilterMask!==data.collisionFilterMask){const broadphaseProxy=this.body.getBroadphaseProxy();broadphaseProxy.set_m_collisionFilterGroup(data.collisionFilterGroup),broadphaseProxy.set_m_collisionFilterMask(data.collisionFilterMask),this.system.driver.broadphase.getOverlappingPairCache().removeOverlappingPairsContainingProxy(broadphaseProxy,this.system.driver.dispatcher)}if(prevData.linearDamping==data.linearDamping&&prevData.angularDamping==data.angularDamping||this.body.setDamping(data.linearDamping,data.angularDamping),almostEqualsVector3(.001,prevData.gravity,data.gravity)||this._updateBodyGravity(data.gravity),prevData.linearSleepingThreshold==data.linearSleepingThreshold&&prevData.angularSleepingThreshold==data.angularSleepingThreshold||this.body.setSleepingThresholds(data.linearSleepingThreshold,data.angularSleepingThreshold),!almostEqualsVector3(.001,prevData.angularFactor,data.angularFactor)){const angularFactor=new Ammo.btVector3(data.angularFactor.x,data.angularFactor.y,data.angularFactor.z);this.body.setAngularFactor(angularFactor),Ammo.destroy(angularFactor)}prevData.restitution!=data.restitution&&console.warn("ammo-body restitution cannot be updated from its initial value.")}},remove:function(){this.triMesh&&Ammo.destroy(this.triMesh),this.localScaling&&Ammo.destroy(this.localScaling),this.compoundShape&&Ammo.destroy(this.compoundShape),this.body&&(Ammo.destroy(this.body),delete this.body),Ammo.destroy(this.rbInfo),Ammo.destroy(this.msTransform),Ammo.destroy(this.motionState),Ammo.destroy(this.localInertia),Ammo.destroy(this.rotation)},beforeStep:function(){this._updateShapes(),this.data.type===TYPE.KINEMATIC&&this.syncToPhysics()},step:function(){this.data.type===TYPE.DYNAMIC&&this.syncFromPhysics()},syncToPhysics:function(){const q=new THREE.Quaternion,v=new THREE.Vector3,q2=new THREE.Vector3,v2=new THREE.Vector3;return function(){const el=this.el,parentEl=el.parentEl;if(!this.body)return;this.motionState.getWorldTransform(this.msTransform),parentEl.isScene?(v.copy(el.object3D.position),q.copy(el.object3D.quaternion)):(el.object3D.getWorldPosition(v),el.object3D.getWorldQuaternion(q));const position=this.msTransform.getOrigin();v2.set(position.x(),position.y(),position.z());const quaternion=this.msTransform.getRotation();q2.set(quaternion.x(),quaternion.y(),quaternion.z(),quaternion.w()),almostEqualsVector3(.001,v,v2)&&function(epsilon,u,v){return Math.abs(u.x-v.x)0;){const collisionShape=this.collisionShapes.pop();collisionShape.destroy(),Ammo.destroy(collisionShape.localTransform)}}};module.exports.definition=AmmoShape,module.exports.Component=AFRAME.registerComponent("ammo-shape",AmmoShape)},{"../../constants":20,"three-to-ammo":6}],18:[function(require,module,exports){var CANNON=require("cannon-es"),Shape={schema:{shape:{default:"box",oneOf:["box","sphere","cylinder"]},offset:{type:"vec3",default:{x:0,y:0,z:0}},orientation:{type:"vec4",default:{x:0,y:0,z:0,w:1}},radius:{type:"number",default:1,if:{shape:["sphere"]}},halfExtents:{type:"vec3",default:{x:.5,y:.5,z:.5},if:{shape:["box"]}},radiusTop:{type:"number",default:1,if:{shape:["cylinder"]}},radiusBottom:{type:"number",default:1,if:{shape:["cylinder"]}},height:{type:"number",default:1,if:{shape:["cylinder"]}},numSegments:{type:"int",default:8,if:{shape:["cylinder"]}}},multiple:!0,init:function(){this.el.sceneEl.hasLoaded?this.initShape():this.el.sceneEl.addEventListener("loaded",this.initShape.bind(this))},initShape:function(){this.bodyEl=this.el;for(var bodyType=this._findType(this.bodyEl),data=this.data;!bodyType&&this.bodyEl.parentNode!=this.el.sceneEl;)this.bodyEl=this.bodyEl.parentNode,bodyType=this._findType(this.bodyEl);if(bodyType){var shape,offset,orientation,scale=new THREE.Vector3;switch(this.bodyEl.object3D.getWorldScale(scale),data.hasOwnProperty("offset")&&(offset=new CANNON.Vec3(data.offset.x*scale.x,data.offset.y*scale.y,data.offset.z*scale.z)),data.hasOwnProperty("orientation")&&(orientation=new CANNON.Quaternion).copy(data.orientation),data.shape){case"sphere":shape=new CANNON.Sphere(data.radius*scale.x);break;case"box":var halfExtents=new CANNON.Vec3(data.halfExtents.x*scale.x,data.halfExtents.y*scale.y,data.halfExtents.z*scale.z);shape=new CANNON.Box(halfExtents);break;case"cylinder":shape=new CANNON.Cylinder(data.radiusTop*scale.x,data.radiusBottom*scale.x,data.height*scale.y,data.numSegments);var quat=new CANNON.Quaternion;quat.setFromEuler(90*THREE.MathUtils.DEG2RAD,0,0,"XYZ").normalize(),orientation.mult(quat,orientation);break;default:return void console.warn(data.shape+" shape not supported")}this.bodyEl.body?this.bodyEl.components[bodyType].addShape(shape,offset,orientation):this.bodyEl.addEventListener("body-loaded",function(){this.bodyEl.components[bodyType].addShape(shape,offset,orientation)},{once:!0})}else console.warn("body not found")},_findType:function(el){return el.hasAttribute("body")?"body":el.hasAttribute("dynamic-body")?"dynamic-body":el.hasAttribute("static-body")?"static-body":null},remove:function(){this.bodyEl.parentNode&&console.warn("removing shape component not currently supported")}};module.exports.definition=Shape,module.exports.Component=AFRAME.registerComponent("shape",Shape)},{"cannon-es":5}],19:[function(require,module,exports){var CANNON=require("cannon-es");module.exports=AFRAME.registerComponent("spring",{multiple:!0,schema:{target:{type:"selector"},restLength:{default:1,min:0},stiffness:{default:100,min:0},damping:{default:1,min:0},localAnchorA:{type:"vec3",default:{x:0,y:0,z:0}},localAnchorB:{type:"vec3",default:{x:0,y:0,z:0}}},init:function(){this.system=this.el.sceneEl.systems.physics,this.system.addComponent(this),this.isActive=!0,this.spring=null},update:function(oldData){var el=this.el,data=this.data;data.target?el.body&&data.target.body?(this.createSpring(),this.updateSpring(oldData)):(el.body?data.target:el).addEventListener("body-loaded",this.update.bind(this,{})):console.warn("Spring: invalid target specified.")},updateSpring:function(oldData){if(this.spring){var data=this.data,spring=this.spring;Object.keys(data).forEach(function(attr){if(data[attr]!==oldData[attr]){if("target"===attr)return void(spring.bodyB=data.target.body);spring[attr]=data[attr]}})}else console.warn("Spring: Component attempted to change spring before its created. No changes made.")},createSpring:function(){this.spring||(this.spring=new CANNON.Spring(this.el.body))},step:function(t,dt){return this.spring&&this.isActive?this.spring.applyForce():void 0},play:function(){this.isActive=!0},pause:function(){this.isActive=!1},remove:function(){this.spring&&delete this.spring,this.spring=null}})},{"cannon-es":5}],20:[function(require,module,exports){module.exports={GRAVITY:-9.8,MAX_INTERVAL:4/60,ITERATIONS:10,CONTACT_MATERIAL:{friction:.01,restitution:.3,contactEquationStiffness:1e8,contactEquationRelaxation:3,frictionEquationStiffness:1e8,frictionEquationRegularization:3},ACTIVATION_STATE:{ACTIVE_TAG:"active",ISLAND_SLEEPING:"islandSleeping",WANTS_DEACTIVATION:"wantsDeactivation",DISABLE_DEACTIVATION:"disableDeactivation",DISABLE_SIMULATION:"disableSimulation"},COLLISION_FLAG:{STATIC_OBJECT:1,KINEMATIC_OBJECT:2,NO_CONTACT_RESPONSE:4,CUSTOM_MATERIAL_CALLBACK:8,CHARACTER_OBJECT:16,DISABLE_VISUALIZE_OBJECT:32,DISABLE_SPU_COLLISION_PROCESSING:64},TYPE:{STATIC:"static",DYNAMIC:"dynamic",KINEMATIC:"kinematic"},SHAPE:{BOX:"box",CYLINDER:"cylinder",SPHERE:"sphere",CAPSULE:"capsule",CONE:"cone",HULL:"hull",HACD:"hacd",VHACD:"vhacd",MESH:"mesh",HEIGHTFIELD:"heightfield"},FIT:{ALL:"all",MANUAL:"manual"},CONSTRAINT:{LOCK:"lock",FIXED:"fixed",SPRING:"spring",SLIDER:"slider",HINGE:"hinge",CONE_TWIST:"coneTwist",POINT_TO_POINT:"pointToPoint"}}},{}],21:[function(require,module,exports){const Driver=require("./driver");"undefined"!=typeof window&&(window.AmmoModule=window.Ammo,window.Ammo=null);function AmmoDriver(){this.collisionConfiguration=null,this.dispatcher=null,this.broadphase=null,this.solver=null,this.physicsWorld=null,this.debugDrawer=null,this.els=new Map,this.eventListeners=[],this.collisions=new Map,this.collisionKeys=[],this.currentCollisions=new Map}AmmoDriver.prototype=new Driver,AmmoDriver.prototype.constructor=AmmoDriver,module.exports=AmmoDriver,AmmoDriver.prototype.init=function(worldConfig){return new Promise(resolve=>{AmmoModule().then(result=>{Ammo=result,this.epsilon=worldConfig.epsilon||1e-5,this.debugDrawMode=worldConfig.debugDrawMode||THREE.AmmoDebugConstants.NoDebug,this.maxSubSteps=worldConfig.maxSubSteps||4,this.fixedTimeStep=worldConfig.fixedTimeStep||1/60,this.collisionConfiguration=new Ammo.btDefaultCollisionConfiguration,this.dispatcher=new Ammo.btCollisionDispatcher(this.collisionConfiguration),this.broadphase=new Ammo.btDbvtBroadphase,this.solver=new Ammo.btSequentialImpulseConstraintSolver,this.physicsWorld=new Ammo.btDiscreteDynamicsWorld(this.dispatcher,this.broadphase,this.solver,this.collisionConfiguration),this.physicsWorld.setForceUpdateAllAabbs(!1),this.physicsWorld.setGravity(new Ammo.btVector3(0,worldConfig.hasOwnProperty("gravity")?worldConfig.gravity:-9.8,0)),this.physicsWorld.getSolverInfo().set_m_numIterations(worldConfig.solverIterations),resolve()})})},AmmoDriver.prototype.addBody=function(body,group,mask){this.physicsWorld.addRigidBody(body,group,mask),this.els.set(Ammo.getPointer(body),body.el)},AmmoDriver.prototype.removeBody=function(body){this.physicsWorld.removeRigidBody(body),this.removeEventListener(body);const bodyptr=Ammo.getPointer(body);this.els.delete(bodyptr),this.collisions.delete(bodyptr),this.collisionKeys.splice(this.collisionKeys.indexOf(bodyptr),1),this.currentCollisions.delete(bodyptr)},AmmoDriver.prototype.updateBody=function(body){this.els.has(Ammo.getPointer(body))&&this.physicsWorld.updateSingleAabb(body)},AmmoDriver.prototype.step=function(deltaTime){this.physicsWorld.stepSimulation(deltaTime,this.maxSubSteps,this.fixedTimeStep);const numManifolds=this.dispatcher.getNumManifolds();for(let i=0;i=0;j--){const body1ptr=body1ptrs[j];this.currentCollisions.get(body0ptr).has(body1ptr)||(-1!==this.eventListeners.indexOf(body0ptr)&&this.els.get(body0ptr).emit("collideend",{targetEl:this.els.get(body1ptr)}),-1!==this.eventListeners.indexOf(body1ptr)&&this.els.get(body1ptr).emit("collideend",{targetEl:this.els.get(body0ptr)}),body1ptrs.splice(j,1))}this.currentCollisions.get(body0ptr).clear()}this.debugDrawer&&this.debugDrawer.update()},AmmoDriver.prototype.addConstraint=function(constraint){this.physicsWorld.addConstraint(constraint,!1)},AmmoDriver.prototype.removeConstraint=function(constraint){this.physicsWorld.removeConstraint(constraint)},AmmoDriver.prototype.addEventListener=function(body){this.eventListeners.push(Ammo.getPointer(body))},AmmoDriver.prototype.removeEventListener=function(body){const ptr=Ammo.getPointer(body);-1!==this.eventListeners.indexOf(ptr)&&this.eventListeners.splice(this.eventListeners.indexOf(ptr),1)},AmmoDriver.prototype.destroy=function(){Ammo.destroy(this.collisionConfiguration),Ammo.destroy(this.dispatcher),Ammo.destroy(this.broadphase),Ammo.destroy(this.solver),Ammo.destroy(this.physicsWorld),Ammo.destroy(this.debugDrawer)},AmmoDriver.prototype.getDebugDrawer=function(scene,options){return this.debugDrawer||((options=options||{}).debugDrawMode=options.debugDrawMode||this.debugDrawMode,this.debugDrawer=new THREE.AmmoDebugDrawer(scene,this.physicsWorld,options)),this.debugDrawer}},{"./driver":22}],22:[function(require,module,exports){function Driver(){}function abstractMethod(){throw new Error("Method not implemented.")}module.exports=Driver,Driver.prototype.init=abstractMethod,Driver.prototype.step=abstractMethod,Driver.prototype.destroy=abstractMethod,Driver.prototype.addBody=abstractMethod,Driver.prototype.removeBody=abstractMethod,Driver.prototype.applyBodyMethod=abstractMethod,Driver.prototype.updateBodyProperties=abstractMethod,Driver.prototype.addMaterial=abstractMethod,Driver.prototype.addContactMaterial=abstractMethod,Driver.prototype.addConstraint=abstractMethod,Driver.prototype.removeConstraint=abstractMethod,Driver.prototype.getContacts=abstractMethod},{}],23:[function(require,module,exports){module.exports={INIT:"init",STEP:"step",ADD_BODY:"add-body",REMOVE_BODY:"remove-body",APPLY_BODY_METHOD:"apply-body-method",UPDATE_BODY_PROPERTIES:"update-body-properties",ADD_MATERIAL:"add-material",ADD_CONTACT_MATERIAL:"add-contact-material",ADD_CONSTRAINT:"add-constraint",REMOVE_CONSTRAINT:"remove-constraint",COLLIDE:"collide"}},{}],24:[function(require,module,exports){var CANNON=require("cannon-es"),Driver=require("./driver");function LocalDriver(){this.world=null,this.materials={},this.contactMaterial=null}LocalDriver.prototype=new Driver,LocalDriver.prototype.constructor=LocalDriver,module.exports=LocalDriver,LocalDriver.prototype.init=function(worldConfig){var world=new CANNON.World;world.quatNormalizeSkip=worldConfig.quatNormalizeSkip,world.quatNormalizeFast=worldConfig.quatNormalizeFast,world.solver.iterations=worldConfig.solverIterations,world.gravity.set(0,worldConfig.gravity,0),world.broadphase=new CANNON.NaiveBroadphase,this.world=world},LocalDriver.prototype.step=function(deltaMS){this.world.step(deltaMS)},LocalDriver.prototype.destroy=function(){delete this.world,delete this.contactMaterial,this.materials={}},LocalDriver.prototype.addBody=function(body){this.world.addBody(body)},LocalDriver.prototype.removeBody=function(body){this.world.removeBody(body)},LocalDriver.prototype.applyBodyMethod=function(body,methodName,args){body["__"+methodName].apply(body,args)},LocalDriver.prototype.updateBodyProperties=function(){},LocalDriver.prototype.getMaterial=function(name){return this.materials[name]},LocalDriver.prototype.addMaterial=function(materialConfig){this.materials[materialConfig.name]=new CANNON.Material(materialConfig),this.materials[materialConfig.name].name=materialConfig.name},LocalDriver.prototype.addContactMaterial=function(matName1,matName2,contactMaterialConfig){var mat1=this.materials[matName1],mat2=this.materials[matName2];this.contactMaterial=new CANNON.ContactMaterial(mat1,mat2,contactMaterialConfig),this.world.addContactMaterial(this.contactMaterial)},LocalDriver.prototype.addConstraint=function(constraint){constraint.type||(constraint instanceof CANNON.LockConstraint?constraint.type="LockConstraint":constraint instanceof CANNON.DistanceConstraint?constraint.type="DistanceConstraint":constraint instanceof CANNON.HingeConstraint?constraint.type="HingeConstraint":constraint instanceof CANNON.ConeTwistConstraint?constraint.type="ConeTwistConstraint":constraint instanceof CANNON.PointToPointConstraint&&(constraint.type="PointToPointConstraint")),this.world.addConstraint(constraint)},LocalDriver.prototype.removeConstraint=function(constraint){this.world.removeConstraint(constraint)},LocalDriver.prototype.getContacts=function(){return this.world.contacts}},{"./driver":22,"cannon-es":5}],25:[function(require,module,exports){var Driver=require("./driver");function NetworkDriver(){throw new Error("[NetworkDriver] Driver not implemented.")}NetworkDriver.prototype=new Driver,NetworkDriver.prototype.constructor=NetworkDriver,module.exports=NetworkDriver},{"./driver":22}],26:[function(require,module,exports){function EventTarget(){this.listeners=[]}module.exports=function(worker){var targetA=new EventTarget,targetB=new EventTarget;return targetA.setTarget(targetB),targetB.setTarget(targetA),worker(targetA),targetB},EventTarget.prototype.setTarget=function(target){this.target=target},EventTarget.prototype.addEventListener=function(type,fn){this.listeners.push(fn)},EventTarget.prototype.dispatchEvent=function(type,event){for(var i=0;ithis.frameDelay;)this.frameBuffer.shift(),prevFrame=this.frameBuffer[0],nextFrame=this.frameBuffer[1];if(prevFrame&&nextFrame){var mix=(timestamp-prevFrame.timestamp)/this.frameDelay;for(var id in mix=(mix-(1-1/this.interpBufferSize))*this.interpBufferSize,prevFrame.bodies)prevFrame.bodies.hasOwnProperty(id)&&nextFrame.bodies.hasOwnProperty(id)&&protocol.deserializeInterpBodyUpdate(prevFrame.bodies[id],nextFrame.bodies[id],this.bodies[id],mix)}}},WorkerDriver.prototype.destroy=function(){this.worker.terminate(),delete this.worker},WorkerDriver.prototype._onMessage=function(event){if(event.data.type===Event.STEP){var bodies=event.data.bodies;if(this.contacts=event.data.contacts,this.interpolate)this.frameBuffer.push({timestamp:performance.now(),bodies:bodies});else for(var id in bodies)bodies.hasOwnProperty(id)&&protocol.deserializeBodyUpdate(bodies[id],this.bodies[id])}else{if(event.data.type!==Event.COLLIDE)throw new Error("[WorkerDriver] Unexpected message type.");var body=this.bodies[event.data.bodyID],target=this.bodies[event.data.targetID],contact=protocol.deserializeContact(event.data.contact,this.bodies);if(!body._listeners||!body._listeners.collide)return;for(var i=0;ithis.countBodiesAmmo(),local:()=>this.countBodiesCannon(!1),worker:()=>this.countBodiesCannon(!0)},this.bodyTypeToStatsPropertyMap={ammo:{[TYPE.STATIC]:"staticBodies",[TYPE.KINEMATIC]:"kinematicBodies",[TYPE.DYNAMIC]:"dynamicBodies"},cannon:{[CANNON.Body.STATIC]:"staticBodies",[CANNON.Body.DYNAMIC]:"dynamicBodies"}},this.el.sceneEl.setAttribute("stats-collector","inEvent: physics-tick-data;\n properties: before, after, engine, total;\n outputFrequency: 100;\n outEvent: physics-tick-summary;\n outputs: percentile__50, percentile__90, max")}if(this.statsToPanel){const scene=this.el.sceneEl,space="   ";scene.setAttribute("stats-panel",""),scene.setAttribute("stats-group__bodies","label: Physics Bodies"),scene.setAttribute("stats-row__b1","group: bodies;\n event:physics-body-data;\n properties: staticBodies;\n label: Static"),scene.setAttribute("stats-row__b2","group: bodies;\n event:physics-body-data;\n properties: dynamicBodies;\n label: Dynamic"),"local"===this.data.driver||"worker"===this.data.driver?scene.setAttribute("stats-row__b3","group: bodies;\n event:physics-body-data;\n properties: contacts;\n label: Contacts"):"ammo"===this.data.driver&&(scene.setAttribute("stats-row__b3","group: bodies;\n event:physics-body-data;\n properties: kinematicBodies;\n label: Kinematic"),scene.setAttribute("stats-row__b4","group: bodies;\n event: physics-body-data;\n properties: manifolds;\n label: Manifolds"),scene.setAttribute("stats-row__b5","group: bodies;\n event: physics-body-data;\n properties: manifoldContacts;\n label: Contacts"),scene.setAttribute("stats-row__b6","group: bodies;\n event: physics-body-data;\n properties: collisions;\n label: Collisions"),scene.setAttribute("stats-row__b7","group: bodies;\n event: physics-body-data;\n properties: collisionKeys;\n label: Coll Keys")),scene.setAttribute("stats-group__tick",`label: Physics Ticks: Median${space}90th%${space}99th%`),scene.setAttribute("stats-row__1","group: tick;\n event:physics-tick-summary;\n properties: before.percentile__50, \n before.percentile__90, \n before.max;\n label: Before"),scene.setAttribute("stats-row__2","group: tick;\n event:physics-tick-summary;\n properties: after.percentile__50, \n after.percentile__90, \n after.max; \n label: After"),scene.setAttribute("stats-row__3","group: tick; \n event:physics-tick-summary; \n properties: engine.percentile__50, \n engine.percentile__90, \n engine.max;\n label: Engine"),scene.setAttribute("stats-row__4","group: tick;\n event:physics-tick-summary;\n properties: total.percentile__50, \n total.percentile__90, \n total.max;\n label: Total")}},tick:function(t,dt){if(!this.initialized||!dt)return;const beforeStartTime=performance.now();var i,callbacks=this.callbacks;for(i=0;i{const property=this.bodyTypeToStatsPropertyMap.ammo[(el=el,el.components["ammo-body"].data.type)];statsData[property]++})},countBodiesCannon(worker){const statsData=this.statsBodyData;statsData.contacts=worker?this.driver.contacts.length:this.driver.world.contacts.length,statsData.staticBodies=0,statsData.dynamicBodies=0,(worker?Object.values(this.driver.bodies):this.driver.world.bodies).forEach(body=>{const property=this.bodyTypeToStatsPropertyMap.cannon[body.type];statsData[property]++})},setDebug:function(debug){this.debug=debug,"ammo"===this.data.driver&&this.initialized&&(debug&&!this.debugDrawer?(this.debugDrawer=this.driver.getDebugDrawer(this.el.object3D),this.debugDrawer.enable()):this.debugDrawer&&(this.debugDrawer.disable(),this.debugDrawer=null))},addBody:function(body,group,mask){var driver=this.driver;"local"===this.data.driver&&(body.__applyImpulse=body.applyImpulse,body.applyImpulse=function(){driver.applyBodyMethod(body,"applyImpulse",arguments)},body.__applyForce=body.applyForce,body.applyForce=function(){driver.applyBodyMethod(body,"applyForce",arguments)},body.updateProperties=function(){driver.updateBodyProperties(body)},this.listeners[body.id]=function(e){body.el.emit("collide",e)},body.addEventListener("collide",this.listeners[body.id])),this.driver.addBody(body,group,mask)},removeBody:function(body){this.driver.removeBody(body),"local"!==this.data.driver&&"worker"!==this.data.driver||(body.removeEventListener("collide",this.listeners[body.id]),delete this.listeners[body.id],body.applyImpulse=body.__applyImpulse,delete body.__applyImpulse,body.applyForce=body.__applyForce,delete body.__applyForce,delete body.updateProperties)},addConstraint:function(constraint){this.driver.addConstraint(constraint)},removeConstraint:function(constraint){this.driver.removeConstraint(constraint)},addComponent:function(component){var callbacks=this.callbacks;component.beforeStep&&callbacks.beforeStep.push(component),component.step&&callbacks.step.push(component),component.afterStep&&callbacks.afterStep.push(component)},removeComponent:function(component){var callbacks=this.callbacks;component.beforeStep&&callbacks.beforeStep.splice(callbacks.beforeStep.indexOf(component),1),component.step&&callbacks.step.splice(callbacks.step.indexOf(component),1),component.afterStep&&callbacks.afterStep.splice(callbacks.afterStep.indexOf(component),1)},getContacts:function(){return this.driver.getContacts()},getMaterial:function(name){return this.driver.getMaterial(name)}})},{"./constants":20,"./drivers/ammo-driver":21,"./drivers/local-driver":24,"./drivers/network-driver":25,"./drivers/worker-driver":27,"aframe-stats-panel":3,"cannon-es":5}],30:[function(require,module,exports){module.exports.slerp=function(a,b,t){if(t<=0)return a;if(t>=1)return b;var x=a[0],y=a[1],z=a[2],w=a[3],cosHalfTheta=w*b[3]+x*b[0]+y*b[1]+z*b[2];if(!(cosHalfTheta<0))return b;if((a=a.slice())[3]=-b[3],a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],(cosHalfTheta=-cosHalfTheta)>=1)return a[3]=w,a[0]=x,a[1]=y,a[2]=z,this;var sinHalfTheta=Math.sqrt(1-cosHalfTheta*cosHalfTheta);if(Math.abs(sinHalfTheta)<.001)return a[3]=.5*(w+a[3]),a[0]=.5*(x+a[0]),a[1]=.5*(y+a[1]),a[2]=.5*(z+a[2]),this;var halfTheta=Math.atan2(sinHalfTheta,cosHalfTheta),ratioA=Math.sin((1-t)*halfTheta)/sinHalfTheta,ratioB=Math.sin(t*halfTheta)/sinHalfTheta;return a[3]=w*ratioA+a[3]*ratioB,a[0]=x*ratioA+a[0]*ratioB,a[1]=y*ratioA+a[1]*ratioB,a[2]=z*ratioA+a[2]*ratioB,a}},{}],31:[function(require,module,exports){var CANNON=require("cannon-es"),mathUtils=require("./math"),ID="__id";module.exports.ID=ID;var nextID={};function serializeShape(shape){var shapeMsg={type:shape.type};if(shape.type===CANNON.Shape.types.BOX)shapeMsg.halfExtents=serializeVec3(shape.halfExtents);else if(shape.type===CANNON.Shape.types.SPHERE)shapeMsg.radius=shape.radius;else{if(shape._type!==CANNON.Shape.types.CYLINDER)throw new Error("Unimplemented shape type: %s",shape.type);shapeMsg.type=CANNON.Shape.types.CYLINDER,shapeMsg.radiusTop=shape.radiusTop,shapeMsg.radiusBottom=shape.radiusBottom,shapeMsg.height=shape.height,shapeMsg.numSegments=shape.numSegments}return shapeMsg}function deserializeShape(message){var shape;if(message.type===CANNON.Shape.types.BOX)shape=new CANNON.Box(deserializeVec3(message.halfExtents));else if(message.type===CANNON.Shape.types.SPHERE)shape=new CANNON.Sphere(message.radius);else{if(message.type!==CANNON.Shape.types.CYLINDER)throw new Error("Unimplemented shape type: %s",message.type);(shape=new CANNON.Cylinder(message.radiusTop,message.radiusBottom,message.height,message.numSegments))._type=CANNON.Shape.types.CYLINDER}return shape}function serializeVec3(vec3){return vec3.toArray()}function deserializeVec3(message){return new CANNON.Vec3(message[0],message[1],message[2])}function serializeQuaternion(quat){return quat.toArray()}function deserializeQuaternion(message){return new CANNON.Quaternion(message[0],message[1],message[2],message[3])}module.exports.assignID=function(prefix,object){object[ID]||(nextID[prefix]=nextID[prefix]||1,object[ID]=prefix+"_"+nextID[prefix]++)},module.exports.serializeBody=function(body){return{shapes:body.shapes.map(serializeShape),shapeOffsets:body.shapeOffsets.map(serializeVec3),shapeOrientations:body.shapeOrientations.map(serializeQuaternion),position:serializeVec3(body.position),quaternion:body.quaternion.toArray(),velocity:serializeVec3(body.velocity),angularVelocity:serializeVec3(body.angularVelocity),id:body[ID],mass:body.mass,linearDamping:body.linearDamping,angularDamping:body.angularDamping,fixedRotation:body.fixedRotation,allowSleep:body.allowSleep,sleepSpeedLimit:body.sleepSpeedLimit,sleepTimeLimit:body.sleepTimeLimit}},module.exports.deserializeBodyUpdate=function(message,body){return body.position.set(message.position[0],message.position[1],message.position[2]),body.quaternion.set(message.quaternion[0],message.quaternion[1],message.quaternion[2],message.quaternion[3]),body.velocity.set(message.velocity[0],message.velocity[1],message.velocity[2]),body.angularVelocity.set(message.angularVelocity[0],message.angularVelocity[1],message.angularVelocity[2]),body.linearDamping=message.linearDamping,body.angularDamping=message.angularDamping,body.fixedRotation=message.fixedRotation,body.allowSleep=message.allowSleep,body.sleepSpeedLimit=message.sleepSpeedLimit,body.sleepTimeLimit=message.sleepTimeLimit,body.mass!==message.mass&&(body.mass=message.mass,body.updateMassProperties()),body},module.exports.deserializeInterpBodyUpdate=function(message1,message2,body,mix){var weight1=1-mix,weight2=mix;body.position.set(message1.position[0]*weight1+message2.position[0]*weight2,message1.position[1]*weight1+message2.position[1]*weight2,message1.position[2]*weight1+message2.position[2]*weight2);var quaternion=mathUtils.slerp(message1.quaternion,message2.quaternion,mix);return body.quaternion.set(quaternion[0],quaternion[1],quaternion[2],quaternion[3]),body.velocity.set(message1.velocity[0]*weight1+message2.velocity[0]*weight2,message1.velocity[1]*weight1+message2.velocity[1]*weight2,message1.velocity[2]*weight1+message2.velocity[2]*weight2),body.angularVelocity.set(message1.angularVelocity[0]*weight1+message2.angularVelocity[0]*weight2,message1.angularVelocity[1]*weight1+message2.angularVelocity[1]*weight2,message1.angularVelocity[2]*weight1+message2.angularVelocity[2]*weight2),body.linearDamping=message2.linearDamping,body.angularDamping=message2.angularDamping,body.fixedRotation=message2.fixedRotation,body.allowSleep=message2.allowSleep,body.sleepSpeedLimit=message2.sleepSpeedLimit,body.sleepTimeLimit=message2.sleepTimeLimit,body.mass!==message2.mass&&(body.mass=message2.mass,body.updateMassProperties()),body},module.exports.deserializeBody=function(message){for(var shapeMsg,body=new CANNON.Body({mass:message.mass,position:deserializeVec3(message.position),quaternion:deserializeQuaternion(message.quaternion),velocity:deserializeVec3(message.velocity),angularVelocity:deserializeVec3(message.angularVelocity),linearDamping:message.linearDamping,angularDamping:message.angularDamping,fixedRotation:message.fixedRotation,allowSleep:message.allowSleep,sleepSpeedLimit:message.sleepSpeedLimit,sleepTimeLimit:message.sleepTimeLimit}),i=0;shapeMsg=message.shapes[i];i++)body.addShape(deserializeShape(shapeMsg),deserializeVec3(message.shapeOffsets[i]),deserializeQuaternion(message.shapeOrientations[i]));return body[ID]=message.id,body},module.exports.serializeShape=serializeShape,module.exports.deserializeShape=deserializeShape,module.exports.serializeConstraint=function(constraint){var message={id:constraint[ID],type:constraint.type,maxForce:constraint.maxForce,bodyA:constraint.bodyA[ID],bodyB:constraint.bodyB[ID]};switch(constraint.type){case"LockConstraint":break;case"DistanceConstraint":message.distance=constraint.distance;break;case"HingeConstraint":case"ConeTwistConstraint":message.axisA=serializeVec3(constraint.axisA),message.axisB=serializeVec3(constraint.axisB),message.pivotA=serializeVec3(constraint.pivotA),message.pivotB=serializeVec3(constraint.pivotB);break;case"PointToPointConstraint":message.pivotA=serializeVec3(constraint.pivotA),message.pivotB=serializeVec3(constraint.pivotB);break;default:throw new Error("Unexpected constraint type: "+constraint.type+'. You may need to manually set `constraint.type = "FooConstraint";`.')}return message},module.exports.deserializeConstraint=function(message,bodies){var constraint,TypedConstraint=CANNON[message.type],bodyA=bodies[message.bodyA],bodyB=bodies[message.bodyB];switch(message.type){case"LockConstraint":constraint=new CANNON.LockConstraint(bodyA,bodyB,message);break;case"DistanceConstraint":constraint=new CANNON.DistanceConstraint(bodyA,bodyB,message.distance,message.maxForce);break;case"HingeConstraint":case"ConeTwistConstraint":constraint=new TypedConstraint(bodyA,bodyB,{pivotA:deserializeVec3(message.pivotA),pivotB:deserializeVec3(message.pivotB),axisA:deserializeVec3(message.axisA),axisB:deserializeVec3(message.axisB),maxForce:message.maxForce});break;case"PointToPointConstraint":constraint=new CANNON.PointToPointConstraint(bodyA,deserializeVec3(message.pivotA),bodyB,deserializeVec3(message.pivotB),message.maxForce);break;default:throw new Error("Unexpected constraint type: "+message.type)}return constraint[ID]=message.id,constraint},module.exports.serializeContact=function(contact){return{bi:contact.bi[ID],bj:contact.bj[ID],ni:serializeVec3(contact.ni),ri:serializeVec3(contact.ri),rj:serializeVec3(contact.rj)}},module.exports.deserializeContact=function(message,bodies){return{bi:bodies[message.bi],bj:bodies[message.bj],ni:deserializeVec3(message.ni),ri:deserializeVec3(message.ri),rj:deserializeVec3(message.rj)}},module.exports.serializeVec3=serializeVec3,module.exports.deserializeVec3=deserializeVec3,module.exports.serializeQuaternion=serializeQuaternion,module.exports.deserializeQuaternion=deserializeQuaternion},{"./math":30,"cannon-es":5}]},{},[1]); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 499177e..fefd30b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ammo-debug-drawer": "^0.1.0", "cannon-es": "^0.9.1", "patch-package": "^6.5.0", - "three-to-ammo": "^0.1.0", + "three-to-ammo": "^1.0.1", "three-to-cannon": "^4.0.0", "webworkify": "^1.4.0" }, @@ -27,6 +27,7 @@ "chai": "^3.5.0", "chai-shallow-deep-equal": "^1.4.6", "envify": "^4.1.0", + "esmify": "^2.1.1", "karma": "^4.4.1", "karma-browserify": "^6.1.0", "karma-chai-shallow-deep-equal": "0.0.4", @@ -50,563 +51,1328 @@ "aframe": ">=0.5.0" } }, - "node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "node_modules/@types/three": { - "version": "0.144.0", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.144.0.tgz", - "integrity": "sha512-psvEs6q5rLN50jUYZ3D4pZMfxTbdt3A243blt0my7/NcL6chaCZpHe2csbCtx0SOD9fI/XnF3wnVUAYZGqCSYg==", + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, "dependencies": { - "@types/webxr": "*" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@types/webxr": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.0.tgz", - "integrity": "sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA==" - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" } }, - "node_modules/accessory": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/accessory/-/accessory-1.1.0.tgz", - "integrity": "sha1-eDPpg5oy3tdtJgIfNqQXB6Ug9ZM=", + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { - "ap": "~0.2.0", - "balanced-match": "~0.2.0", - "dot-parts": "~1.0.0" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/accessory/node_modules/balanced-match": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.1.tgz", - "integrity": "sha1-e8ZYtL7WHu5CStdPdfXD4sTfPMc=", - "dev": true - }, - "node_modules/acorn": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", - "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=4" } }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/acorn-node/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", "dev": true, "engines": { - "node": ">=0.4" + "node": ">=6.9.0" } }, - "node_modules/acorn-walk": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", - "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", + "node_modules/@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/aframe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/aframe/-/aframe-1.1.0.tgz", - "integrity": "sha512-/8Lk7DsnSdy0ZnjDvC/0sQ4aALfp7P+EiOO5y9BGBngk9QCXdWPT1onLNwJixWrJNntLTfU5ULxFrkRZb561Hg==", + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { - "custom-event-polyfill": "^1.0.6", - "debug": "github:ngokevin/debug#noTimestamp", - "deep-assign": "^2.0.0", - "document-register-element": "github:dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90", - "load-bmfont": "^1.2.3", - "object-assign": "^4.0.1", - "present": "0.0.6", - "promise-polyfill": "^3.1.0", - "super-animejs": "^3.1.0", - "super-three": "^0.123.1", - "three-bmfont-text": "github:dmarcos/three-bmfont-text#1babdf8507c731a18f8af3b807292e2b9740955e", - "webvr-polyfill": "^0.10.12" + "ms": "2.1.2" }, "engines": { - "node": ">= 4.6.0", - "npm": "^2.15.9" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/aframe-stats-panel": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/aframe-stats-panel/-/aframe-stats-panel-0.2.1.tgz", - "integrity": "sha512-dcDJ4xC6dxt+iRp+4/wdXmXOxzMeRBTC9nEtabOnkQ2OUfOS1cZp3TJV9wF/R+1NaG+9SIj+wsV+4TziiT0riA==" + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, - "node_modules/aframe/node_modules/debug": { - "version": "2.2.0", - "resolved": "git+ssh://git@github.com/ngokevin/debug.git#ef5f8e66d49ce8bc64c6f282c15f8b7164409e3a", - "integrity": "sha512-rUI9wkpSlmwV2QQcE+jDnEdUPyRG+alTguuGlIJHW1PRMycHzpGy24htiAOiBdg6jYFXduQw4JuA1lvKh3DwzA==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT" + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, - "optional": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, "engines": { - "node": ">=0.4.2" + "node": ">=6.9.0" } }, - "node_modules/ammo-debug-drawer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ammo-debug-drawer/-/ammo-debug-drawer-0.1.0.tgz", - "integrity": "sha512-GIfIf748qpfg++iXFzTB1p/M7ncJK5/X2qkg7mAQm4SPyhx93PSEejSEsZiPnk8eUUwlpyPSRMPDnpITMvlJCg==" + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } }, - "node_modules/an-array": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/an-array/-/an-array-1.0.0.tgz", - "integrity": "sha512-M175GYI7RmsYu24Ok383yZQa3eveDfNnmhTe3OQ3bm70bEovz2gWenH+ST/n32M8lrwLWk74hcPds5CDRPe2wg==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=6.9.0" } }, - "node_modules/ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dev": true, "dependencies": { - "remove-trailing-separator": "^1.0.1" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/ap": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ap/-/ap-0.2.0.tgz", - "integrity": "sha1-rglCYAspkS8NKxTsYMRejzMLYRA=", - "dev": true + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/array-shuffle": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-shuffle/-/array-shuffle-1.0.1.tgz", - "integrity": "sha512-PBqgo1Y2XWSksBzq3GFPEb798ZrW2snAcmr4drbVeF/6MT/5aBlkGJEvu5A/CzXHf4EjbHOj/ZowatjlIiVidA==", + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "node_modules/@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "node_modules/as-number": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/as-number/-/as-number-1.0.0.tgz", - "integrity": "sha512-HkI/zLo2AbSRO4fqVkmyf3hms0bJDs3iboHqTrNuwTiCRvdYXM7HFhfhB6Dk51anV2LM/IMB83mtK9mHw4FlAg==", - "dev": true - }, - "node_modules/asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "node_modules/assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { - "object-assign": "^4.1.1", - "util": "0.10.3" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/assert/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "node_modules/assert/node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "inherits": "2.0.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">= 4.5.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "node_modules/@babel/traverse": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, "engines": { - "node": ">= 0.4.0" + "node": ">=6.9.0" } }, - "node_modules/better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "callsite": "1.0.0" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": "*" + "node": ">=6.0.0" } }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, "engines": { - "node": ">= 0.8" + "node": ">=6.0.0" } }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/bole": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bole/-/bole-2.0.0.tgz", - "integrity": "sha1-2KocaQRnv7T+Ebh0rLLoOH44JhU=", - "dev": true, - "dependencies": { + "node_modules/@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "node_modules/@types/three": { + "version": "0.144.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.144.0.tgz", + "integrity": "sha512-psvEs6q5rLN50jUYZ3D4pZMfxTbdt3A243blt0my7/NcL6chaCZpHe2csbCtx0SOD9fI/XnF3wnVUAYZGqCSYg==", + "dependencies": { + "@types/webxr": "*" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.0.tgz", + "integrity": "sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA==" + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accessory": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/accessory/-/accessory-1.1.0.tgz", + "integrity": "sha1-eDPpg5oy3tdtJgIfNqQXB6Ug9ZM=", + "dev": true, + "dependencies": { + "ap": "~0.2.0", + "balanced-match": "~0.2.0", + "dot-parts": "~1.0.0" + } + }, + "node_modules/accessory/node_modules/balanced-match": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.1.tgz", + "integrity": "sha1-e8ZYtL7WHu5CStdPdfXD4sTfPMc=", + "dev": true + }, + "node_modules/acorn": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", + "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/acorn-walk": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", + "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/aframe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/aframe/-/aframe-1.1.0.tgz", + "integrity": "sha512-/8Lk7DsnSdy0ZnjDvC/0sQ4aALfp7P+EiOO5y9BGBngk9QCXdWPT1onLNwJixWrJNntLTfU5ULxFrkRZb561Hg==", + "dev": true, + "dependencies": { + "custom-event-polyfill": "^1.0.6", + "debug": "github:ngokevin/debug#noTimestamp", + "deep-assign": "^2.0.0", + "document-register-element": "github:dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90", + "load-bmfont": "^1.2.3", + "object-assign": "^4.0.1", + "present": "0.0.6", + "promise-polyfill": "^3.1.0", + "super-animejs": "^3.1.0", + "super-three": "^0.123.1", + "three-bmfont-text": "github:dmarcos/three-bmfont-text#1babdf8507c731a18f8af3b807292e2b9740955e", + "webvr-polyfill": "^0.10.12" + }, + "engines": { + "node": ">= 4.6.0", + "npm": "^2.15.9" + } + }, + "node_modules/aframe-stats-panel": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/aframe-stats-panel/-/aframe-stats-panel-0.2.1.tgz", + "integrity": "sha512-dcDJ4xC6dxt+iRp+4/wdXmXOxzMeRBTC9nEtabOnkQ2OUfOS1cZp3TJV9wF/R+1NaG+9SIj+wsV+4TziiT0riA==" + }, + "node_modules/aframe/node_modules/debug": { + "version": "2.2.0", + "resolved": "git+ssh://git@github.com/ngokevin/debug.git#ef5f8e66d49ce8bc64c6f282c15f8b7164409e3a", + "integrity": "sha512-rUI9wkpSlmwV2QQcE+jDnEdUPyRG+alTguuGlIJHW1PRMycHzpGy24htiAOiBdg6jYFXduQw4JuA1lvKh3DwzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ammo-debug-drawer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ammo-debug-drawer/-/ammo-debug-drawer-0.1.0.tgz", + "integrity": "sha512-GIfIf748qpfg++iXFzTB1p/M7ncJK5/X2qkg7mAQm4SPyhx93PSEejSEsZiPnk8eUUwlpyPSRMPDnpITMvlJCg==" + }, + "node_modules/ammo.js": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/ammo.js/-/ammo.js-0.0.10.tgz", + "integrity": "sha512-jOv977u71jrDUzHfmQ99YaW90/y8YLn/3HFTmtLLzf5wJynAfG+/a1Ie5gbn0fE0uSAHxXVsFk4Bzq8qRPWqAA==", + "peer": true + }, + "node_modules/an-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/an-array/-/an-array-1.0.0.tgz", + "integrity": "sha512-M175GYI7RmsYu24Ok383yZQa3eveDfNnmhTe3OQ3bm70bEovz2gWenH+ST/n32M8lrwLWk74hcPds5CDRPe2wg==", + "dev": true + }, + "node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ap": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ap/-/ap-0.2.0.tgz", + "integrity": "sha1-rglCYAspkS8NKxTsYMRejzMLYRA=", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-shuffle": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-shuffle/-/array-shuffle-1.0.1.tgz", + "integrity": "sha512-PBqgo1Y2XWSksBzq3GFPEb798ZrW2snAcmr4drbVeF/6MT/5aBlkGJEvu5A/CzXHf4EjbHOj/ZowatjlIiVidA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "node_modules/as-number": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/as-number/-/as-number-1.0.0.tgz", + "integrity": "sha512-HkI/zLo2AbSRO4fqVkmyf3hms0bJDs3iboHqTrNuwTiCRvdYXM7HFhfhB6Dk51anV2LM/IMB83mtK9mHw4FlAg==", + "dev": true + }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", + "dev": true, + "dependencies": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "node_modules/babel-code-frame/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-code-frame/node_modules/js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==", + "dev": true + }, + "node_modules/babel-code-frame/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-import-to-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-import-to-require/-/babel-plugin-import-to-require-1.0.0.tgz", + "integrity": "sha512-dc843CwrFivjO8AVgxcHvxl0cb7J7Ed8ZGFP8+PjH3X1CnyzYtAU1WL1349m9Wc/+oqk4ETx2+cIEO2jlp3XyQ==", + "dev": true, + "dependencies": { + "babel-template": "^6.26.0" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-traverse/node_modules/globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/babel-types/node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-types/node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true, + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "node_modules/base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "dependencies": { + "callsite": "1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/bole": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bole/-/bole-2.0.0.tgz", + "integrity": "sha1-2KocaQRnv7T+Ebh0rLLoOH44JhU=", + "dev": true, + "dependencies": { "core-util-is": ">=1.0.1 <1.1.0-0", "individual": ">=3.0.0 <3.1.0-0", "json-stringify-safe": ">=5.0.0 <5.1.0-0" @@ -905,6 +1671,38 @@ "node": ">= 0.6.0" } }, + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/budo": { "version": "11.6.3", "resolved": "https://registry.npmjs.org/budo/-/budo-11.6.3.tgz", @@ -1073,6 +1871,26 @@ "node": ">=6" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001541", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz", + "integrity": "sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, "node_modules/cannon-es": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/cannon-es/-/cannon-es-0.9.1.tgz", @@ -1446,6 +2264,14 @@ "node": ">=0.10.0" } }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true + }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1922,6 +2748,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "node_modules/electron-to-chromium": { + "version": "1.4.537", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.537.tgz", + "integrity": "sha512-W1+g9qs9hviII0HAwOdehGYkr+zt7KKdmCcJcjH0mYg6oL8+ioT3Skjmt7BLoAQqXhjf40AXd+HlR4oAWMlXjA==", + "dev": true + }, "node_modules/elliptic": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", @@ -2129,6 +2961,15 @@ "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==", "dev": true }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2191,6 +3032,24 @@ "node": ">=0.8.0" } }, + "node_modules/esmify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/esmify/-/esmify-2.1.1.tgz", + "integrity": "sha512-GyOVgjG7sNyYB5Mbo15Ll4aGrcXZzZ3LI22rbLOjCI7L/wYelzQpBHRZkZkqbPNZ/QIRilcaHqzgNCLcEsi1lQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.2.2", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "babel-plugin-import-to-require": "^1.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "^1.6.2", + "duplexer2": "^0.1.4", + "through2": "^2.0.5" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -2841,6 +3700,15 @@ "garnish": "bin/cmd.js" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -2970,6 +3838,15 @@ "node": ">=0.10.0" } }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/globo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/globo/-/globo-1.1.0.tgz", @@ -3375,6 +4252,15 @@ "node": ">=4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ip-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", @@ -3743,6 +4629,12 @@ "node": ">= 0.8" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "node_modules/js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -3756,6 +4648,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-stable-stringify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", @@ -3771,6 +4675,18 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -4330,6 +5246,18 @@ "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", "dev": true }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -4794,6 +5722,12 @@ "semver": "^5.7.0" } }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5460,6 +6394,12 @@ "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", "dev": true }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -5742,6 +6682,12 @@ "node": ">=0.10" } }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -7239,9 +8185,13 @@ } }, "node_modules/three-to-ammo": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/three-to-ammo/-/three-to-ammo-0.1.0.tgz", - "integrity": "sha512-+XxlQdAlU20NHjA0As7tRUsTy9VutK6bhB+QiQx0vcET5m5t1l4/mmbXPy4aNnLnvRDWE3bepBvT8DC2OX15Jg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/three-to-ammo/-/three-to-ammo-1.0.1.tgz", + "integrity": "sha512-hXT3MM3dqaudL8nIn9IKY7OWR1lNmTRUMuvXM/bSbpGXYGY9t8Bp4M+ri2KSwgAAcB2utf44/Et5uMHkCACSzw==", + "peerDependencies": { + "ammo.js": "*", + "three": "*" + } }, "node_modules/three-to-cannon": { "version": "4.2.0", @@ -7318,6 +8268,15 @@ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -7593,6 +8552,36 @@ "yarn": "*" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -7773,36 +8762,232 @@ "string-width": "^1.0.2 || 2" } }, - "node_modules/word-wrapper": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/word-wrapper/-/word-wrapper-1.0.7.tgz", - "integrity": "sha512-VOPBFCm9b6FyYKQYfn9AVn2dQvdR/YOVFV6IBRA1TBMJWKffvhEX1af6FMGrttILs2Q9ikCRhLqkbY2weW6dOQ==", - "dev": true - }, - "node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "node_modules/word-wrapper": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/word-wrapper/-/word-wrapper-1.0.7.tgz", + "integrity": "sha512-VOPBFCm9b6FyYKQYfn9AVn2dQvdR/YOVFV6IBRA1TBMJWKffvhEX1af6FMGrttILs2Q9ikCRhLqkbY2weW6dOQ==", + "dev": true + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "dev": true, + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "dev": true, + "dependencies": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=", + "dev": true + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, - "engines": { - "node": ">=0.4.0" + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" }, "engines": { "node": ">=6" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { + "node_modules/yargs/node_modules/ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", @@ -7811,19 +8996,7 @@ "node": ">=6" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { + "node_modules/yargs/node_modules/string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", @@ -7837,7 +9010,7 @@ "node": ">=6" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { + "node_modules/yargs/node_modules/strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", @@ -7849,198 +9022,453 @@ "node": ">=6" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "node_modules/yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } }, - "node_modules/ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, "dependencies": { - "async-limiter": "~1.0.0" + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "node_modules/xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true + }, + "@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, "dependencies": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, - "node_modules/xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, "dependencies": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } } }, - "node_modules/xml-parse-from-string": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", - "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=", + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, - "engines": { - "node": ">=4.0" + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true + }, + "@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + } + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "node_modules/xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "engines": { - "node": ">=0.4.0" + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, - "engines": { - "node": ">=0.4" + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "requires": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" } }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, - "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "@babel/traverse": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", "dev": true, - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" }, - "engines": { - "node": ">=6" + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, - "engines": { - "node": ">=6" + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - } - }, - "dependencies": { "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -8176,6 +9604,12 @@ "resolved": "https://registry.npmjs.org/ammo-debug-drawer/-/ammo-debug-drawer-0.1.0.tgz", "integrity": "sha512-GIfIf748qpfg++iXFzTB1p/M7ncJK5/X2qkg7mAQm4SPyhx93PSEejSEsZiPnk8eUUwlpyPSRMPDnpITMvlJCg==" }, + "ammo.js": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/ammo.js/-/ammo.js-0.0.10.tgz", + "integrity": "sha512-jOv977u71jrDUzHfmQ99YaW90/y8YLn/3HFTmtLLzf5wJynAfG+/a1Ie5gbn0fE0uSAHxXVsFk4Bzq8qRPWqAA==", + "peer": true + }, "an-array": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/an-array/-/an-array-1.0.0.tgz", @@ -8363,6 +9797,169 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true + } + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-import-to-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-import-to-require/-/babel-plugin-import-to-require-1.0.0.tgz", + "integrity": "sha512-dc843CwrFivjO8AVgxcHvxl0cb7J7Ed8ZGFP8+PjH3X1CnyzYtAU1WL1349m9Wc/+oqk4ETx2+cIEO2jlp3XyQ==", + "dev": true, + "requires": { + "babel-template": "^6.26.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", + "dev": true + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -8805,6 +10402,18 @@ "pako": "~1.0.5" } }, + "browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + } + }, "budo": { "version": "11.6.3", "resolved": "https://registry.npmjs.org/budo/-/budo-11.6.3.tgz", @@ -8954,6 +10563,12 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001541", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz", + "integrity": "sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw==", + "dev": true + }, "cannon-es": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/cannon-es/-/cannon-es-0.9.1.tgz", @@ -9270,6 +10885,12 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -9669,6 +11290,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.4.537", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.537.tgz", + "integrity": "sha512-W1+g9qs9hviII0HAwOdehGYkr+zt7KKdmCcJcjH0mYg6oL8+ioT3Skjmt7BLoAQqXhjf40AXd+HlR4oAWMlXjA==", + "dev": true + }, "elliptic": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", @@ -9864,6 +11491,12 @@ "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==", "dev": true }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -9906,6 +11539,24 @@ } } }, + "esmify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/esmify/-/esmify-2.1.1.tgz", + "integrity": "sha512-GyOVgjG7sNyYB5Mbo15Ll4aGrcXZzZ3LI22rbLOjCI7L/wYelzQpBHRZkZkqbPNZ/QIRilcaHqzgNCLcEsi1lQ==", + "dev": true, + "requires": { + "@babel/core": "^7.2.2", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "babel-plugin-import-to-require": "^1.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "^1.6.2", + "duplexer2": "^0.1.4", + "through2": "^2.0.5" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -10451,6 +12102,12 @@ "url-trim": "^1.0.0" } }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, "get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -10558,6 +12215,12 @@ "which": "^1.2.14" } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, "globo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/globo/-/globo-1.1.0.tgz", @@ -10891,6 +12554,15 @@ "ipaddr.js": "^1.5.2" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, "ip-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", @@ -11158,6 +12830,12 @@ "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", "dev": true }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -11168,6 +12846,12 @@ "esprima": "^4.0.0" } }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json-stable-stringify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", @@ -11183,6 +12867,12 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -11631,6 +13321,15 @@ "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", "dev": true }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -12025,6 +13724,12 @@ "semver": "^5.7.0" } }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -12550,6 +14255,12 @@ "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", "dev": true }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -12792,6 +14503,12 @@ "readable-stream": "^2.0.2" } }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -14068,9 +15785,10 @@ } }, "three-to-ammo": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/three-to-ammo/-/three-to-ammo-0.1.0.tgz", - "integrity": "sha512-+XxlQdAlU20NHjA0As7tRUsTy9VutK6bhB+QiQx0vcET5m5t1l4/mmbXPy4aNnLnvRDWE3bepBvT8DC2OX15Jg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/three-to-ammo/-/three-to-ammo-1.0.1.tgz", + "integrity": "sha512-hXT3MM3dqaudL8nIn9IKY7OWR1lNmTRUMuvXM/bSbpGXYGY9t8Bp4M+ri2KSwgAAcB2utf44/Et5uMHkCACSzw==", + "requires": {} }, "three-to-cannon": { "version": "4.2.0", @@ -14133,6 +15851,12 @@ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -14356,6 +16080,16 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", diff --git a/package.json b/package.json index a535d8a..c70eaa2 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "Physics system for A-Frame VR, built on Cannon.js & Ammo.js", "main": "index.js", "scripts": { - "dev": "budo index.js:dist/aframe-physics-system.js -d examples --port 8000 -- -g browserify-shim", - "dist": "browserify -g browserify-shim index.js -o dist/aframe-physics-system.js && uglifyjs -c -o dist/aframe-physics-system.min.js -- dist/aframe-physics-system.js", + "dev": "budo index.js:dist/aframe-physics-system.js -d examples --port 8000 -- -g browserify-shim -p esmify", + "dist": "browserify -g browserify-shim index.js -o dist/aframe-physics-system.js -p esmify && uglifyjs -c -o dist/aframe-physics-system.min.js -- dist/aframe-physics-system.js", "test": "karma start ./tests/karma.conf.js", "test:once": "karma start ./tests/karma.conf.js --single-run", "test:firefox": "karma start ./tests/karma.conf.js --browsers Firefox", @@ -44,9 +44,9 @@ "aframe-stats-panel": "^0.2.1", "ammo-debug-drawer": "^0.1.0", "cannon-es": "^0.9.1", - "three-to-ammo": "^0.1.0", - "three-to-cannon": "^4.0.0", "patch-package": "^6.5.0", + "three-to-ammo": "^1.0.1", + "three-to-cannon": "^4.0.0", "webworkify": "^1.4.0" }, "peerDependencies": { @@ -61,6 +61,7 @@ "chai": "^3.5.0", "chai-shallow-deep-equal": "^1.4.6", "envify": "^4.1.0", + "esmify": "^2.1.1", "karma": "^4.4.1", "karma-browserify": "^6.1.0", "karma-chai-shallow-deep-equal": "0.0.4", diff --git a/patches/three-to-ammo+0.1.0.patch b/patches/three-to-ammo+0.1.0.patch deleted file mode 100644 index 7b71537..0000000 --- a/patches/three-to-ammo+0.1.0.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/node_modules/three-to-ammo/index.js b/node_modules/three-to-ammo/index.js -index 62df76e..6ae1b31 100644 ---- a/node_modules/three-to-ammo/index.js -+++ b/node_modules/three-to-ammo/index.js -@@ -269,7 +269,7 @@ exports.createHACDShapes = (function() { - return []; - } - -- const bounds = _computeBounds(root); -+ const bounds = _computeBounds(root, options); - const scale = _computeScale(root, options); - - let vertexCount = 0; -@@ -662,7 +662,7 @@ const _iterateGeometries = (function() { - const inverse = new THREE.Matrix4(); - const bufferGeometry = new THREE.BufferGeometry(); - return function(root, options, cb) { -- inverse.getInverse(root.matrixWorld); -+ inverse.copy(root.matrixWorld).invert(); - root.traverse(mesh => { - if ( - mesh.isMesh && diff --git a/src/components/body/ammo-body.js b/src/components/body/ammo-body.js index d286322..0e83dd7 100644 --- a/src/components/body/ammo-body.js +++ b/src/components/body/ammo-body.js @@ -241,7 +241,20 @@ let AmmoBody = { _createCollisionShape: function(shapeComponent) { const data = shapeComponent.data; - const collisionShapes = threeToAmmo.createCollisionShapes(shapeComponent.getMesh(), data); + const vertices = []; + const matrices = []; + const indexes = []; + + const root = shapeComponent.el.object3D; + const matrixWorld = root.matrixWorld; + + threeToAmmo.iterateGeometries(root, data, (vertexArray, matrixArray, indexArray) => { + vertices.push(vertexArray); + matrices.push(matrixArray); + indexes.push(indexArray); + }); + + const collisionShapes = threeToAmmo.createCollisionShapes(vertices, matrices, indexes, matrixWorld.elements, data); shapeComponent.addShapes(collisionShapes); return; }, diff --git a/tests/karma.conf.js b/tests/karma.conf.js index 2fbef24..0a00594 100644 --- a/tests/karma.conf.js +++ b/tests/karma.conf.js @@ -3,7 +3,8 @@ module.exports = function (config) { basePath: '../', browserify: { debug: true, - paths: ['src'] + paths: ['src'], + plugin: [ 'esmify' ] }, browsers: ['Firefox', 'Chrome'], client: {