planck-js
Version:
2D JavaScript/TypeScript physics engine for cross-platform HTML5 game development
1,525 lines (1,522 loc) • 588 kB
JavaScript
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.planck = {}));
})(this, function(exports2) {
"use strict";/**
* Planck.js v1.3.0
* @license The MIT license
* @copyright Copyright (c) 2024 Erin Catto, Ali Shakiba
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var extendStatics$1 = function(d2, b2) {
extendStatics$1 = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d3, b3) {
d3.__proto__ = b3;
} || function(d3, b3) {
for (var p in b3) if (Object.prototype.hasOwnProperty.call(b3, p)) d3[p] = b3[p];
};
return extendStatics$1(d2, b2);
};
function __extends$1(d2, b2) {
if (typeof b2 !== "function" && b2 !== null)
throw new TypeError("Class extends value " + String(b2) + " is not a constructor or null");
extendStatics$1(d2, b2);
function __() {
this.constructor = d2;
}
d2.prototype = b2 === null ? Object.create(b2) : (__.prototype = b2.prototype, new __());
}
var __assign$1 = function() {
__assign$1 = Object.assign || function __assign2(t) {
for (var s2, i = 1, n2 = arguments.length; i < n2; i++) {
s2 = arguments[i];
for (var p in s2) if (Object.prototype.hasOwnProperty.call(s2, p)) t[p] = s2[p];
}
return t;
};
return __assign$1.apply(this, arguments);
};
var options = function(input2, defaults) {
if (input2 === null || typeof input2 === "undefined") {
input2 = {};
}
var output2 = __assign$1({}, input2);
for (var key in defaults) {
if (defaults.hasOwnProperty(key) && typeof input2[key] === "undefined") {
output2[key] = defaults[key];
}
}
if (typeof Object.getOwnPropertySymbols === "function") {
var symbols = Object.getOwnPropertySymbols(defaults);
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if (defaults.propertyIsEnumerable(symbol) && typeof input2[symbol] === "undefined") {
output2[symbol] = defaults[symbol];
}
}
}
return output2;
};
var math_random$1 = Math.random;
var EPSILON = 1e-9;
var isFinite = Number.isFinite;
function nextPowerOfTwo(x2) {
x2 |= x2 >> 1;
x2 |= x2 >> 2;
x2 |= x2 >> 4;
x2 |= x2 >> 8;
x2 |= x2 >> 16;
return x2 + 1;
}
function isPowerOfTwo(x2) {
return x2 > 0 && (x2 & x2 - 1) === 0;
}
function mod(num, min, max) {
if (typeof min === "undefined") {
max = 1;
min = 0;
} else if (typeof max === "undefined") {
max = min;
min = 0;
}
if (max > min) {
num = (num - min) % (max - min);
return num + (num < 0 ? max : min);
} else {
num = (num - max) % (min - max);
return num + (num <= 0 ? min : max);
}
}
function clamp$1(num, min, max) {
if (num < min) {
return min;
} else if (num > max) {
return max;
} else {
return num;
}
}
function random$1(min, max) {
if (typeof min === "undefined") {
max = 1;
min = 0;
} else if (typeof max === "undefined") {
max = min;
min = 0;
}
return min === max ? min : math_random$1() * (max - min) + min;
}
var math$1 = Object.create(Math);
math$1.EPSILON = EPSILON;
math$1.isFinite = isFinite;
math$1.nextPowerOfTwo = nextPowerOfTwo;
math$1.isPowerOfTwo = isPowerOfTwo;
math$1.mod = mod;
math$1.clamp = clamp$1;
math$1.random = random$1;
var math_abs$a = Math.abs;
var math_sqrt$8 = Math.sqrt;
var math_max$b = Math.max;
var math_min$d = Math.min;
var Vec2 = (
/** @class */
function() {
function Vec22(x2, y) {
if (!(this instanceof Vec22)) {
return new Vec22(x2, y);
}
if (typeof x2 === "undefined") {
this.x = 0;
this.y = 0;
} else if (typeof x2 === "object") {
this.x = x2.x;
this.y = x2.y;
} else {
this.x = x2;
this.y = y;
}
}
Vec22.prototype._serialize = function() {
return {
x: this.x,
y: this.y
};
};
Vec22._deserialize = function(data) {
var obj = Object.create(Vec22.prototype);
obj.x = data.x;
obj.y = data.y;
return obj;
};
Vec22.zero = function() {
var obj = Object.create(Vec22.prototype);
obj.x = 0;
obj.y = 0;
return obj;
};
Vec22.neo = function(x2, y) {
var obj = Object.create(Vec22.prototype);
obj.x = x2;
obj.y = y;
return obj;
};
Vec22.clone = function(v3) {
return Vec22.neo(v3.x, v3.y);
};
Vec22.prototype.toString = function() {
return JSON.stringify(this);
};
Vec22.isValid = function(obj) {
if (obj === null || typeof obj === "undefined") {
return false;
}
return Number.isFinite(obj.x) && Number.isFinite(obj.y);
};
Vec22.assert = function(o) {
};
Vec22.prototype.clone = function() {
return Vec22.clone(this);
};
Vec22.prototype.setZero = function() {
this.x = 0;
this.y = 0;
return this;
};
Vec22.prototype.set = function(x2, y) {
if (typeof x2 === "object") {
this.x = x2.x;
this.y = x2.y;
} else {
this.x = x2;
this.y = y;
}
return this;
};
Vec22.prototype.setNum = function(x2, y) {
this.x = x2;
this.y = y;
return this;
};
Vec22.prototype.setVec2 = function(value) {
this.x = value.x;
this.y = value.y;
return this;
};
Vec22.prototype.wSet = function(a2, v3, b2, w) {
if (typeof b2 !== "undefined" || typeof w !== "undefined") {
return this.setCombine(a2, v3, b2, w);
} else {
return this.setMul(a2, v3);
}
};
Vec22.prototype.setCombine = function(a2, v3, b2, w) {
var x2 = a2 * v3.x + b2 * w.x;
var y = a2 * v3.y + b2 * w.y;
this.x = x2;
this.y = y;
return this;
};
Vec22.prototype.setMul = function(a2, v3) {
var x2 = a2 * v3.x;
var y = a2 * v3.y;
this.x = x2;
this.y = y;
return this;
};
Vec22.prototype.add = function(w) {
this.x += w.x;
this.y += w.y;
return this;
};
Vec22.prototype.wAdd = function(a2, v3, b2, w) {
if (typeof b2 !== "undefined" || typeof w !== "undefined") {
return this.addCombine(a2, v3, b2, w);
} else {
return this.addMul(a2, v3);
}
};
Vec22.prototype.addCombine = function(a2, v3, b2, w) {
var x2 = a2 * v3.x + b2 * w.x;
var y = a2 * v3.y + b2 * w.y;
this.x += x2;
this.y += y;
return this;
};
Vec22.prototype.addMul = function(a2, v3) {
var x2 = a2 * v3.x;
var y = a2 * v3.y;
this.x += x2;
this.y += y;
return this;
};
Vec22.prototype.wSub = function(a2, v3, b2, w) {
if (typeof b2 !== "undefined" || typeof w !== "undefined") {
return this.subCombine(a2, v3, b2, w);
} else {
return this.subMul(a2, v3);
}
};
Vec22.prototype.subCombine = function(a2, v3, b2, w) {
var x2 = a2 * v3.x + b2 * w.x;
var y = a2 * v3.y + b2 * w.y;
this.x -= x2;
this.y -= y;
return this;
};
Vec22.prototype.subMul = function(a2, v3) {
var x2 = a2 * v3.x;
var y = a2 * v3.y;
this.x -= x2;
this.y -= y;
return this;
};
Vec22.prototype.sub = function(w) {
this.x -= w.x;
this.y -= w.y;
return this;
};
Vec22.prototype.mul = function(m) {
this.x *= m;
this.y *= m;
return this;
};
Vec22.prototype.length = function() {
return Vec22.lengthOf(this);
};
Vec22.prototype.lengthSquared = function() {
return Vec22.lengthSquared(this);
};
Vec22.prototype.normalize = function() {
var length2 = this.length();
if (length2 < EPSILON) {
return 0;
}
var invLength = 1 / length2;
this.x *= invLength;
this.y *= invLength;
return length2;
};
Vec22.normalize = function(v3) {
var length2 = Vec22.lengthOf(v3);
if (length2 < EPSILON) {
return Vec22.zero();
}
var invLength = 1 / length2;
return Vec22.neo(v3.x * invLength, v3.y * invLength);
};
Vec22.lengthOf = function(v3) {
return math_sqrt$8(v3.x * v3.x + v3.y * v3.y);
};
Vec22.lengthSquared = function(v3) {
return v3.x * v3.x + v3.y * v3.y;
};
Vec22.distance = function(v3, w) {
var dx = v3.x - w.x;
var dy = v3.y - w.y;
return math_sqrt$8(dx * dx + dy * dy);
};
Vec22.distanceSquared = function(v3, w) {
var dx = v3.x - w.x;
var dy = v3.y - w.y;
return dx * dx + dy * dy;
};
Vec22.areEqual = function(v3, w) {
return v3 === w || typeof w === "object" && w !== null && v3.x === w.x && v3.y === w.y;
};
Vec22.skew = function(v3) {
return Vec22.neo(-v3.y, v3.x);
};
Vec22.dot = function(v3, w) {
return v3.x * w.x + v3.y * w.y;
};
Vec22.cross = function(v3, w) {
if (typeof w === "number") {
return Vec22.neo(w * v3.y, -w * v3.x);
} else if (typeof v3 === "number") {
return Vec22.neo(-v3 * w.y, v3 * w.x);
} else {
return v3.x * w.y - v3.y * w.x;
}
};
Vec22.crossVec2Vec2 = function(v3, w) {
return v3.x * w.y - v3.y * w.x;
};
Vec22.crossVec2Num = function(v3, w) {
return Vec22.neo(w * v3.y, -w * v3.x);
};
Vec22.crossNumVec2 = function(v3, w) {
return Vec22.neo(-v3 * w.y, v3 * w.x);
};
Vec22.addCross = function(a2, v3, w) {
if (typeof w === "number") {
return Vec22.neo(w * v3.y + a2.x, -w * v3.x + a2.y);
} else if (typeof v3 === "number") {
return Vec22.neo(-v3 * w.y + a2.x, v3 * w.x + a2.y);
}
};
Vec22.addCrossVec2Num = function(a2, v3, w) {
return Vec22.neo(w * v3.y + a2.x, -w * v3.x + a2.y);
};
Vec22.addCrossNumVec2 = function(a2, v3, w) {
return Vec22.neo(-v3 * w.y + a2.x, v3 * w.x + a2.y);
};
Vec22.add = function(v3, w) {
return Vec22.neo(v3.x + w.x, v3.y + w.y);
};
Vec22.wAdd = function(a2, v3, b2, w) {
if (typeof b2 !== "undefined" || typeof w !== "undefined") {
return Vec22.combine(a2, v3, b2, w);
} else {
return Vec22.mulNumVec2(a2, v3);
}
};
Vec22.combine = function(a2, v3, b2, w) {
return Vec22.zero().setCombine(a2, v3, b2, w);
};
Vec22.sub = function(v3, w) {
return Vec22.neo(v3.x - w.x, v3.y - w.y);
};
Vec22.mul = function(a2, b2) {
if (typeof a2 === "object") {
return Vec22.neo(a2.x * b2, a2.y * b2);
} else if (typeof b2 === "object") {
return Vec22.neo(a2 * b2.x, a2 * b2.y);
}
};
Vec22.mulVec2Num = function(a2, b2) {
return Vec22.neo(a2.x * b2, a2.y * b2);
};
Vec22.mulNumVec2 = function(a2, b2) {
return Vec22.neo(a2 * b2.x, a2 * b2.y);
};
Vec22.prototype.neg = function() {
this.x = -this.x;
this.y = -this.y;
return this;
};
Vec22.neg = function(v3) {
return Vec22.neo(-v3.x, -v3.y);
};
Vec22.abs = function(v3) {
return Vec22.neo(math_abs$a(v3.x), math_abs$a(v3.y));
};
Vec22.mid = function(v3, w) {
return Vec22.neo((v3.x + w.x) * 0.5, (v3.y + w.y) * 0.5);
};
Vec22.upper = function(v3, w) {
return Vec22.neo(math_max$b(v3.x, w.x), math_max$b(v3.y, w.y));
};
Vec22.lower = function(v3, w) {
return Vec22.neo(math_min$d(v3.x, w.x), math_min$d(v3.y, w.y));
};
Vec22.prototype.clamp = function(max) {
var lengthSqr = this.x * this.x + this.y * this.y;
if (lengthSqr > max * max) {
var scale = max / math_sqrt$8(lengthSqr);
this.x *= scale;
this.y *= scale;
}
return this;
};
Vec22.clamp = function(v3, max) {
var r = Vec22.neo(v3.x, v3.y);
r.clamp(max);
return r;
};
Vec22.clampVec2 = function(v3, min, max) {
return {
x: clamp$1(v3.x, min === null || min === void 0 ? void 0 : min.x, max === null || max === void 0 ? void 0 : max.x),
y: clamp$1(v3.y, min === null || min === void 0 ? void 0 : min.y, max === null || max === void 0 ? void 0 : max.y)
};
};
Vec22.scaleFn = function(x2, y) {
return function(v3) {
return Vec22.neo(v3.x * x2, v3.y * y);
};
};
Vec22.translateFn = function(x2, y) {
return function(v3) {
return Vec22.neo(v3.x + x2, v3.y + y);
};
};
return Vec22;
}()
);
var math_max$a = Math.max;
var math_min$c = Math.min;
var AABB = (
/** @class */
function() {
function AABB2(lower, upper) {
if (!(this instanceof AABB2)) {
return new AABB2(lower, upper);
}
this.lowerBound = Vec2.zero();
this.upperBound = Vec2.zero();
if (typeof lower === "object") {
this.lowerBound.setVec2(lower);
}
if (typeof upper === "object") {
this.upperBound.setVec2(upper);
} else if (typeof lower === "object") {
this.upperBound.setVec2(lower);
}
}
AABB2.prototype.isValid = function() {
return AABB2.isValid(this);
};
AABB2.isValid = function(obj) {
if (obj === null || typeof obj === "undefined") {
return false;
}
return Vec2.isValid(obj.lowerBound) && Vec2.isValid(obj.upperBound) && Vec2.sub(obj.upperBound, obj.lowerBound).lengthSquared() >= 0;
};
AABB2.assert = function(o) {
};
AABB2.prototype.getCenter = function() {
return Vec2.neo((this.lowerBound.x + this.upperBound.x) * 0.5, (this.lowerBound.y + this.upperBound.y) * 0.5);
};
AABB2.prototype.getExtents = function() {
return Vec2.neo((this.upperBound.x - this.lowerBound.x) * 0.5, (this.upperBound.y - this.lowerBound.y) * 0.5);
};
AABB2.prototype.getPerimeter = function() {
return 2 * (this.upperBound.x - this.lowerBound.x + this.upperBound.y - this.lowerBound.y);
};
AABB2.prototype.combine = function(a2, b2) {
b2 = b2 || this;
var lowerA = a2.lowerBound;
var upperA = a2.upperBound;
var lowerB = b2.lowerBound;
var upperB = b2.upperBound;
var lowerX = math_min$c(lowerA.x, lowerB.x);
var lowerY = math_min$c(lowerA.y, lowerB.y);
var upperX = math_max$a(upperB.x, upperA.x);
var upperY = math_max$a(upperB.y, upperA.y);
this.lowerBound.setNum(lowerX, lowerY);
this.upperBound.setNum(upperX, upperY);
};
AABB2.prototype.combinePoints = function(a2, b2) {
this.lowerBound.setNum(math_min$c(a2.x, b2.x), math_min$c(a2.y, b2.y));
this.upperBound.setNum(math_max$a(a2.x, b2.x), math_max$a(a2.y, b2.y));
};
AABB2.prototype.set = function(aabb) {
this.lowerBound.setNum(aabb.lowerBound.x, aabb.lowerBound.y);
this.upperBound.setNum(aabb.upperBound.x, aabb.upperBound.y);
};
AABB2.prototype.contains = function(aabb) {
var result = true;
result = result && this.lowerBound.x <= aabb.lowerBound.x;
result = result && this.lowerBound.y <= aabb.lowerBound.y;
result = result && aabb.upperBound.x <= this.upperBound.x;
result = result && aabb.upperBound.y <= this.upperBound.y;
return result;
};
AABB2.prototype.extend = function(value) {
AABB2.extend(this, value);
return this;
};
AABB2.extend = function(out, value) {
out.lowerBound.x -= value;
out.lowerBound.y -= value;
out.upperBound.x += value;
out.upperBound.y += value;
return out;
};
AABB2.testOverlap = function(a2, b2) {
var d1x = b2.lowerBound.x - a2.upperBound.x;
var d2x = a2.lowerBound.x - b2.upperBound.x;
var d1y = b2.lowerBound.y - a2.upperBound.y;
var d2y = a2.lowerBound.y - b2.upperBound.y;
if (d1x > 0 || d1y > 0 || d2x > 0 || d2y > 0) {
return false;
}
return true;
};
AABB2.areEqual = function(a2, b2) {
return Vec2.areEqual(a2.lowerBound, b2.lowerBound) && Vec2.areEqual(a2.upperBound, b2.upperBound);
};
AABB2.diff = function(a2, b2) {
var wD = math_max$a(0, math_min$c(a2.upperBound.x, b2.upperBound.x) - math_max$a(b2.lowerBound.x, a2.lowerBound.x));
var hD = math_max$a(0, math_min$c(a2.upperBound.y, b2.upperBound.y) - math_max$a(b2.lowerBound.y, a2.lowerBound.y));
var wA = a2.upperBound.x - a2.lowerBound.x;
var hA = a2.upperBound.y - a2.lowerBound.y;
var wB = b2.upperBound.x - b2.lowerBound.x;
var hB = b2.upperBound.y - b2.lowerBound.y;
return wA * hA + wB * hB - wD * hD;
};
AABB2.prototype.rayCast = function(output2, input2) {
var tmin = -Infinity;
var tmax = Infinity;
var p = input2.p1;
var d2 = Vec2.sub(input2.p2, input2.p1);
var absD = Vec2.abs(d2);
var normal3 = Vec2.zero();
for (var f = "x"; f !== null; f = f === "x" ? "y" : null) {
if (absD.x < EPSILON) {
if (p[f] < this.lowerBound[f] || this.upperBound[f] < p[f]) {
return false;
}
} else {
var inv_d = 1 / d2[f];
var t1 = (this.lowerBound[f] - p[f]) * inv_d;
var t2 = (this.upperBound[f] - p[f]) * inv_d;
var s2 = -1;
if (t1 > t2) {
var temp3 = t1;
t1 = t2;
t2 = temp3;
s2 = 1;
}
if (t1 > tmin) {
normal3.setZero();
normal3[f] = s2;
tmin = t1;
}
tmax = math_min$c(tmax, t2);
if (tmin > tmax) {
return false;
}
}
}
if (tmin < 0 || input2.maxFraction < tmin) {
return false;
}
output2.fraction = tmin;
output2.normal = normal3;
return true;
};
AABB2.prototype.toString = function() {
return JSON.stringify(this);
};
AABB2.combinePoints = function(out, a2, b2) {
out.lowerBound.x = math_min$c(a2.x, b2.x);
out.lowerBound.y = math_min$c(a2.y, b2.y);
out.upperBound.x = math_max$a(a2.x, b2.x);
out.upperBound.y = math_max$a(a2.y, b2.y);
return out;
};
AABB2.combinedPerimeter = function(a2, b2) {
var lx = math_min$c(a2.lowerBound.x, b2.lowerBound.x);
var ly = math_min$c(a2.lowerBound.y, b2.lowerBound.y);
var ux = math_max$a(a2.upperBound.x, b2.upperBound.x);
var uy = math_max$a(a2.upperBound.y, b2.upperBound.y);
return 2 * (ux - lx + uy - ly);
};
return AABB2;
}()
);
var math_PI$8 = Math.PI;
var Settings = (
/** @class */
function() {
function Settings2() {
}
Object.defineProperty(Settings2, "polygonRadius", {
/**
* The radius of the polygon/edge shape skin. This should not be modified.
* Making this smaller means polygons will have an insufficient buffer for
* continuous collision. Making it larger may create artifacts for vertex
* collision.
*/
get: function() {
return 2 * Settings2.linearSlop;
},
enumerable: false,
configurable: true
});
Settings2.lengthUnitsPerMeter = 1;
Settings2.maxManifoldPoints = 2;
Settings2.maxPolygonVertices = 12;
Settings2.aabbExtension = 0.1;
Settings2.aabbMultiplier = 2;
Settings2.linearSlop = 5e-3;
Settings2.angularSlop = 2 / 180 * math_PI$8;
Settings2.maxSubSteps = 8;
Settings2.maxTOIContacts = 32;
Settings2.maxTOIIterations = 20;
Settings2.maxDistanceIterations = 20;
Settings2.velocityThreshold = 1;
Settings2.maxLinearCorrection = 0.2;
Settings2.maxAngularCorrection = 8 / 180 * math_PI$8;
Settings2.maxTranslation = 2;
Settings2.maxRotation = 0.5 * math_PI$8;
Settings2.baumgarte = 0.2;
Settings2.toiBaugarte = 0.75;
Settings2.timeToSleep = 0.5;
Settings2.linearSleepTolerance = 0.01;
Settings2.angularSleepTolerance = 2 / 180 * math_PI$8;
return Settings2;
}()
);
var SettingsInternal = (
/** @class */
function() {
function SettingsInternal2() {
}
Object.defineProperty(SettingsInternal2, "maxManifoldPoints", {
get: function() {
return Settings.maxManifoldPoints;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxPolygonVertices", {
get: function() {
return Settings.maxPolygonVertices;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "aabbExtension", {
get: function() {
return Settings.aabbExtension * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "aabbMultiplier", {
get: function() {
return Settings.aabbMultiplier;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "linearSlop", {
get: function() {
return Settings.linearSlop * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "linearSlopSquared", {
get: function() {
return Settings.linearSlop * Settings.lengthUnitsPerMeter * Settings.linearSlop * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "angularSlop", {
get: function() {
return Settings.angularSlop;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "polygonRadius", {
get: function() {
return 2 * Settings.linearSlop;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxSubSteps", {
get: function() {
return Settings.maxSubSteps;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxTOIContacts", {
get: function() {
return Settings.maxTOIContacts;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxTOIIterations", {
get: function() {
return Settings.maxTOIIterations;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxDistanceIterations", {
get: function() {
return Settings.maxDistanceIterations;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "velocityThreshold", {
get: function() {
return Settings.velocityThreshold * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxLinearCorrection", {
get: function() {
return Settings.maxLinearCorrection * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxAngularCorrection", {
get: function() {
return Settings.maxAngularCorrection;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxTranslation", {
get: function() {
return Settings.maxTranslation * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxTranslationSquared", {
get: function() {
return Settings.maxTranslation * Settings.lengthUnitsPerMeter * Settings.maxTranslation * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxRotation", {
get: function() {
return Settings.maxRotation;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "maxRotationSquared", {
get: function() {
return Settings.maxRotation * Settings.maxRotation;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "baumgarte", {
get: function() {
return Settings.baumgarte;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "toiBaugarte", {
get: function() {
return Settings.toiBaugarte;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "timeToSleep", {
get: function() {
return Settings.timeToSleep;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "linearSleepTolerance", {
get: function() {
return Settings.linearSleepTolerance * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "linearSleepToleranceSqr", {
get: function() {
return Settings.linearSleepTolerance * Settings.lengthUnitsPerMeter * Settings.linearSleepTolerance * Settings.lengthUnitsPerMeter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "angularSleepTolerance", {
get: function() {
return Settings.angularSleepTolerance;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SettingsInternal2, "angularSleepToleranceSqr", {
get: function() {
return Settings.angularSleepTolerance * Settings.angularSleepTolerance;
},
enumerable: false,
configurable: true
});
return SettingsInternal2;
}()
);
var Pool = (
/** @class */
function() {
function Pool2(opts) {
this._list = [];
this._max = Infinity;
this._hasCreateFn = false;
this._createCount = 0;
this._hasAllocateFn = false;
this._allocateCount = 0;
this._hasReleaseFn = false;
this._releaseCount = 0;
this._hasDisposeFn = false;
this._disposeCount = 0;
this._list = [];
this._max = opts.max || this._max;
this._createFn = opts.create;
this._hasCreateFn = typeof this._createFn === "function";
this._allocateFn = opts.allocate;
this._hasAllocateFn = typeof this._allocateFn === "function";
this._releaseFn = opts.release;
this._hasReleaseFn = typeof this._releaseFn === "function";
this._disposeFn = opts.dispose;
this._hasDisposeFn = typeof this._disposeFn === "function";
}
Pool2.prototype.max = function(n2) {
if (typeof n2 === "number") {
this._max = n2;
return this;
}
return this._max;
};
Pool2.prototype.size = function() {
return this._list.length;
};
Pool2.prototype.allocate = function() {
var item;
if (this._list.length > 0) {
item = this._list.shift();
} else {
this._createCount++;
if (this._hasCreateFn) {
item = this._createFn();
} else {
item = {};
}
}
this._allocateCount++;
if (this._hasAllocateFn) {
this._allocateFn(item);
}
return item;
};
Pool2.prototype.release = function(item) {
if (this._list.length < this._max) {
this._releaseCount++;
if (this._hasReleaseFn) {
this._releaseFn(item);
}
this._list.push(item);
} else {
this._disposeCount++;
if (this._hasDisposeFn) {
item = this._disposeFn(item);
}
}
};
Pool2.prototype.toString = function() {
return " +" + this._createCount + " >" + this._allocateCount + " <" + this._releaseCount + " -" + this._disposeCount + " =" + this._list.length + "/" + this._max;
};
return Pool2;
}()
);
var math_abs$9 = Math.abs;
var math_max$9 = Math.max;
var TreeNode = (
/** @class */
function() {
function TreeNode2(id) {
this.aabb = new AABB();
this.userData = null;
this.parent = null;
this.child1 = null;
this.child2 = null;
this.height = -1;
this.id = id;
}
TreeNode2.prototype.toString = function() {
return this.id + ": " + this.userData;
};
TreeNode2.prototype.isLeaf = function() {
return this.child1 == null;
};
return TreeNode2;
}()
);
var poolTreeNode = new Pool({
create: function() {
return new TreeNode();
},
release: function(node) {
node.userData = null;
node.parent = null;
node.child1 = null;
node.child2 = null;
node.height = -1;
node.id = void 0;
}
});
var DynamicTree = (
/** @class */
function() {
function DynamicTree2() {
this.inputPool = new Pool({
create: function() {
return {};
},
release: function(stack) {
}
});
this.stackPool = new Pool({
create: function() {
return [];
},
release: function(stack) {
stack.length = 0;
}
});
this.iteratorPool = new Pool({
create: function() {
return new Iterator();
},
release: function(iterator) {
iterator.close();
}
});
this.m_root = null;
this.m_nodes = {};
this.m_lastProxyId = 0;
}
DynamicTree2.prototype.getUserData = function(id) {
var node = this.m_nodes[id];
return node.userData;
};
DynamicTree2.prototype.getFatAABB = function(id) {
var node = this.m_nodes[id];
return node.aabb;
};
DynamicTree2.prototype.allocateNode = function() {
var node = poolTreeNode.allocate();
node.id = ++this.m_lastProxyId;
this.m_nodes[node.id] = node;
return node;
};
DynamicTree2.prototype.freeNode = function(node) {
delete this.m_nodes[node.id];
poolTreeNode.release(node);
};
DynamicTree2.prototype.createProxy = function(aabb, userData) {
var node = this.allocateNode();
node.aabb.set(aabb);
AABB.extend(node.aabb, SettingsInternal.aabbExtension);
node.userData = userData;
node.height = 0;
this.insertLeaf(node);
return node.id;
};
DynamicTree2.prototype.destroyProxy = function(id) {
var node = this.m_nodes[id];
this.removeLeaf(node);
this.freeNode(node);
};
DynamicTree2.prototype.moveProxy = function(id, aabb, d2) {
var node = this.m_nodes[id];
if (node.aabb.contains(aabb)) {
return false;
}
this.removeLeaf(node);
node.aabb.set(aabb);
aabb = node.aabb;
AABB.extend(aabb, SettingsInternal.aabbExtension);
if (d2.x < 0) {
aabb.lowerBound.x += d2.x * SettingsInternal.aabbMultiplier;
} else {
aabb.upperBound.x += d2.x * SettingsInternal.aabbMultiplier;
}
if (d2.y < 0) {
aabb.lowerBound.y += d2.y * SettingsInternal.aabbMultiplier;
} else {
aabb.upperBound.y += d2.y * SettingsInternal.aabbMultiplier;
}
this.insertLeaf(node);
return true;
};
DynamicTree2.prototype.insertLeaf = function(leaf) {
if (this.m_root == null) {
this.m_root = leaf;
this.m_root.parent = null;
return;
}
var leafAABB = leaf.aabb;
var index = this.m_root;
while (!index.isLeaf()) {
var child1 = index.child1;
var child2 = index.child2;
var area = index.aabb.getPerimeter();
var combinedArea = AABB.combinedPerimeter(index.aabb, leafAABB);
var cost = 2 * combinedArea;
var inheritanceCost = 2 * (combinedArea - area);
var newArea1 = AABB.combinedPerimeter(leafAABB, child1.aabb);
var cost1 = newArea1 + inheritanceCost;
if (!child1.isLeaf()) {
var oldArea = child1.aabb.getPerimeter();
cost1 -= oldArea;
}
var newArea2 = AABB.combinedPerimeter(leafAABB, child2.aabb);
var cost2 = newArea2 + inheritanceCost;
if (!child2.isLeaf()) {
var oldArea = child2.aabb.getPerimeter();
cost2 -= oldArea;
}
if (cost < cost1 && cost < cost2) {
break;
}
if (cost1 < cost2) {
index = child1;
} else {
index = child2;
}
}
var sibling = index;
var oldParent = sibling.parent;
var newParent = this.allocateNode();
newParent.parent = oldParent;
newParent.userData = null;
newParent.aabb.combine(leafAABB, sibling.aabb);
newParent.height = sibling.height + 1;
if (oldParent != null) {
if (oldParent.child1 === sibling) {
oldParent.child1 = newParent;
} else {
oldParent.child2 = newParent;
}
newParent.child1 = sibling;
newParent.child2 = leaf;
sibling.parent = newParent;
leaf.parent = newParent;
} else {
newParent.child1 = sibling;
newParent.child2 = leaf;
sibling.parent = newParent;
leaf.parent = newParent;
this.m_root = newParent;
}
index = leaf.parent;
while (index != null) {
index = this.balance(index);
var child1 = index.child1;
var child2 = index.child2;
index.height = 1 + math_max$9(child1.height, child2.height);
index.aabb.combine(child1.aabb, child2.aabb);
index = index.parent;
}
};
DynamicTree2.prototype.removeLeaf = function(leaf) {
if (leaf === this.m_root) {
this.m_root = null;
return;
}
var parent = leaf.parent;
var grandParent = parent.parent;
var sibling;
if (parent.child1 === leaf) {
sibling = parent.child2;
} else {
sibling = parent.child1;
}
if (grandParent != null) {
if (grandParent.child1 === parent) {
grandParent.child1 = sibling;
} else {
grandParent.child2 = sibling;
}
sibling.parent = grandParent;
this.freeNode(parent);
var index = grandParent;
while (index != null) {
index = this.balance(index);
var child1 = index.child1;
var child2 = index.child2;
index.aabb.combine(child1.aabb, child2.aabb);
index.height = 1 + math_max$9(child1.height, child2.height);
index = index.parent;
}
} else {
this.m_root = sibling;
sibling.parent = null;
this.freeNode(parent);
}
};
DynamicTree2.prototype.balance = function(iA) {
var A = iA;
if (A.isLeaf() || A.height < 2) {
return iA;
}
var B = A.child1;
var C = A.child2;
var balance = C.height - B.height;
if (balance > 1) {
var F = C.child1;
var G = C.child2;
C.child1 = A;
C.parent = A.parent;
A.parent = C;
if (C.parent != null) {
if (C.parent.child1 === iA) {
C.parent.child1 = C;
} else {
C.parent.child2 = C;
}
} else {
this.m_root = C;
}
if (F.height > G.height) {
C.child2 = F;
A.child2 = G;
G.parent = A;
A.aabb.combine(B.aabb, G.aabb);
C.aabb.combine(A.aabb, F.aabb);
A.height = 1 + math_max$9(B.height, G.height);
C.height = 1 + math_max$9(A.height, F.height);
} else {
C.child2 = G;
A.child2 = F;
F.parent = A;
A.aabb.combine(B.aabb, F.aabb);
C.aabb.combine(A.aabb, G.aabb);
A.height = 1 + math_max$9(B.height, F.height);
C.height = 1 + math_max$9(A.height, G.height);
}
return C;
}
if (balance < -1) {
var D = B.child1;
var E = B.child2;
B.child1 = A;
B.parent = A.parent;
A.parent = B;
if (B.parent != null) {
if (B.parent.child1 === A) {
B.parent.child1 = B;
} else {
B.parent.child2 = B;
}
} else {
this.m_root = B;
}
if (D.height > E.height) {
B.child2 = D;
A.child1 = E;
E.parent = A;
A.aabb.combine(C.aabb, E.aabb);
B.aabb.combine(A.aabb, D.aabb);
A.height = 1 + math_max$9(C.height, E.height);
B.height = 1 + math_max$9(A.height, D.height);
} else {
B.child2 = E;
A.child1 = D;
D.parent = A;
A.aabb.combine(C.aabb, D.aabb);
B.aabb.combine(A.aabb, E.aabb);
A.height = 1 + math_max$9(C.height, D.height);
B.height = 1 + math_max$9(A.height, E.height);
}
return B;
}
return A;
};
DynamicTree2.prototype.getHeight = function() {
if (this.m_root == null) {
return 0;
}
return this.m_root.height;
};
DynamicTree2.prototype.getAreaRatio = function() {
if (this.m_root == null) {
return 0;
}
var root = this.m_root;
var rootArea = root.aabb.getPerimeter();
var totalArea = 0;
var node;
var it = this.iteratorPool.allocate().preorder(this.m_root);
while (node = it.next()) {
if (node.height < 0) {
continue;
}
totalArea += node.aabb.getPerimeter();
}
this.iteratorPool.release(it);
return totalArea / rootArea;
};
DynamicTree2.prototype.computeHeight = function(id) {
var node;
if (typeof id !== "undefined") {
node = this.m_nodes[id];
} else {
node = this.m_root;
}
if (node.isLeaf()) {
return 0;
}
var height1 = this.computeHeight(node.child1.id);
var height2 = this.computeHeight(node.child2.id);
return 1 + math_max$9(height1, height2);
};
DynamicTree2.prototype.validateStructure = function(node) {
if (node == null) {
return;
}
if (node === this.m_root) ;
var child1 = node.child1;
var child2 = node.child2;
if (node.isLeaf()) {
return;
}
this.validateStructure(child1);
this.validateStructure(child2);
};
DynamicTree2.prototype.validateMetrics = function(node) {
if (node == null) {
return;
}
var child1 = node.child1;
var child2 = node.child2;
if (node.isLeaf()) {
return;
}
child1.height;
child2.height;
var aabb = new AABB();
aabb.combine(child1.aabb, child2.aabb);
this.validateMetrics(child1);
this.validateMetrics(child2);
};
DynamicTree2.prototype.validate = function() {
return;
};
DynamicTree2.prototype.getMaxBalance = function() {
var maxBalance = 0;
var node;
var it = this.iteratorPool.allocate().preorder(this.m_root);
while (node = it.next()) {
if (node.height <= 1) {
continue;
}
var balance = math_abs$9(node.child2.height - node.child1.height);
maxBalance = math_max$9(maxBalance, balance);
}
this.iteratorPool.release(it);
return maxBalance;
};
DynamicTree2.prototype.rebuildBottomUp = function() {
var nodes = [];
var count = 0;
var node;
var it = this.iteratorPool.allocate().preorder(this.m_root);
while (node = it.next()) {
if (node.height < 0) {
continue;
}
if (node.isLeaf()) {
node.parent = null;
nodes[count] = node;
++count;
} else {
this.freeNode(node);
}
}
this.iteratorPool.release(it);
while (count > 1) {
var minCost = Infinity;
var iMin = -1;
var jMin = -1;
for (var i = 0; i < count; ++i) {
var aabbi = nodes[i].aabb;
for (var j = i + 1; j < count; ++j) {
var aabbj = nodes[j].aabb;
var cost = AABB.combinedPerimeter(aabbi, aabbj);
if (cost < minCost) {
iMin = i;
jMin = j;
minCost = cost;
}
}
}
var child1 = nodes[iMin];
var child2 = nodes[jMin];
var parent_1 = this.allocateNode();
parent_1.child1 = child1;
parent_1.child2 = child2;
parent_1.height = 1 + math_max$9(child1.height, child2.height);
parent_1.aabb.combine(child1.aabb, child2.aabb);
parent_1.parent = null;
child1.parent = parent_1;
child2.parent = parent_1;
nodes[jMin] = nodes[count - 1];
nodes[iMin] = parent_1;
--count;
}
this.m_root = nodes[0];
};
DynamicTree2.prototype.shiftOrigin = function(newOrigin) {
var node;
var it = this.iteratorPool.allocate().preorder(this.m_root);
while (node = it.next()) {
var aabb = node.aabb;
aabb.lowerBound.x -= newOrigin.x;
aabb.lowerBound.y -= newOrigin.y;
aabb.upperBound.x -= newOrigin.x;
aabb.upperBound.y -= newOrigin.y;
}
this.iteratorPool.release(it);
};
DynamicTree2.prototype.query = function(aabb, queryCallback) {
var stack = this.stackPool.allocate();
stack.push(this.m_root);
while (stack.length > 0) {
var node = stack.pop();
if (node == null) {
continue;
}
if (AABB.testOverlap(node.aabb, aabb)) {
if (node.isLeaf()) {
var proceed = queryCallback(node.id);
if (proceed === false) {
return;
}
} else {
stack.push(node.child1);
stack.push(node.child2);
}
}
}
this.stackPool.release(stack);
};
DynamicTree2.prototype.rayCast = function(input2, rayCastCallback) {
var p1 = input2.p1;
var p2 = input2.p2;
var r = Vec2.sub(p2, p1);
r.normalize();
var v3 = Vec2.crossNumVec2(1, r);
var abs_v = Vec2.abs(v3);
var maxFraction = input2.maxFraction;
var segmentAABB = new AABB();
var t = Vec2.combine(1 - maxFraction, p1, maxFraction, p2);
segmentAABB.combinePoints(p1, t);
var stack = this.stackPool.allocate();
var subInput = this.inputPool.allocate();
stack.push(this.m_root);
while (stack.length > 0) {
var node = stack.pop();
if (node == null) {
continue;
}
if (AABB.testOverlap(node.aabb, segmentAABB) === false) {
continue;
}
var c2 = node.aabb.getCenter();
var h = node.aabb.getExtents();
var separation = math_abs$9(Vec2.dot(v3, Vec2.sub(p1, c2))) - Vec2.dot(abs_v, h);
if (separation > 0) {
continue;
}
if (node.isLeaf()) {
subInput.p1 = Vec2.clone(input2.p1);
subInput.p2 = Vec2.clone(input2.p2);
subInput.maxFraction = maxFraction;
var value = rayCastCallback(subInput, node.id);
if (value === 0) {
break;
} else if (value > 0) {
maxFraction = value;
t = Vec2.combine(1 - maxFraction, p1, maxFraction, p2);
segmentAABB.combinePoints(p1, t);
}
} else {
stack.push(node.child1);
stack.push(node.child2);
}
}
this.stackPool.release(stack);
this.inputPool.release(subInput);
};
return DynamicTree2;
}()
);
var Iterator = (
/** @class */
function() {
function Iterator2() {
this.parents = [];
this.states = [];
}
Iterator2.prototype.preorder = function(root) {
this.parents.length = 0;
this.parents.push(root);
this.states.length = 0;
this.states.push(0);
return this;
};
Iterator2.prototype.next = function() {
while (this.parents.length > 0) {
var i = this.parents.length - 1;
var node = this.parents[i];
if (this.states[i] === 0) {
this.states[i] = 1;
return node;
}
if (this.states[i] === 1) {
this.states[i] = 2;
if (node.child1) {
this.parents.push(node.child1);
this.states.push(1);
return node.child1;
}
}
if (this.states[i] === 2) {
this.states[i] = 3;
if (node.child2) {
this.parents.push(node.child2);
this.states.push(1);
return node.child2;
}
}
this.parents.pop();
this.states.pop();
}
};
Iterator2.prototype.close = function() {
this.parents.length = 0;
};
return Iterator2;
}()
);
var math_max$8 = Math.max;
var math_min$b = Math.min;
var BroadPhase = (
/** @class */
function() {
function BroadPhase2() {
var _this = this;
this.m_tree = new DynamicTree();
this.m_moveBuffer = [];
this.query = function(aabb, queryC