planck
Version:
2D JavaScript/TypeScript physics engine for cross-platform HTML5 game development
1,542 lines (1,540 loc) • 429 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.5.0
* @license The MIT license
* @copyright Copyright (c) 2026 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.
*/
var extendStatics = function(d2, b2) {
extendStatics = 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(d2, b2);
};
function __extends(d2, b2) {
if (typeof b2 !== "function" && b2 !== null)
throw new TypeError("Class extends value " + String(b2) + " is not a constructor or null");
extendStatics(d2, b2);
function __() {
this.constructor = d2;
}
d2.prototype = b2 === null ? Object.create(b2) : (__.prototype = b2.prototype, new __());
}
var __assign = function() {
__assign = 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.apply(this, arguments);
};
typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
var e3 = new Error(message);
return e3.name = "SuppressedError", e3.error = error, e3.suppressed = suppressed, e3;
};
var options = function(input2, defaults) {
if (input2 === null || typeof input2 === "undefined") {
input2 = {};
}
var output2 = __assign({}, 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 = 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(num, min, max) {
if (num < min) {
return min;
} else if (num > max) {
return max;
} else {
return num;
}
}
function random(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() * (max - min) + min;
}
var math = Object.create(Math);
math.EPSILON = EPSILON;
math.isFinite = isFinite;
math.nextPowerOfTwo = nextPowerOfTwo;
math.isPowerOfTwo = isPowerOfTwo;
math.mod = mod;
math.clamp = clamp;
math.random = random;
var math_abs$9 = Math.abs;
var math_sqrt$5 = Math.sqrt;
var math_max$8 = Math.max;
var math_min$8 = 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 length = this.length();
if (length < EPSILON) {
return 0;
}
var invLength = 1 / length;
this.x *= invLength;
this.y *= invLength;
return length;
};
Vec22.normalize = function(v3) {
var length = Vec22.lengthOf(v3);
if (length < EPSILON) {
return Vec22.zero();
}
var invLength = 1 / length;
return Vec22.neo(v3.x * invLength, v3.y * invLength);
};
Vec22.lengthOf = function(v3) {
return math_sqrt$5(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$5(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$9(v3.x), math_abs$9(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$8(v3.x, w.x), math_max$8(v3.y, w.y));
};
Vec22.lower = function(v3, w) {
return Vec22.neo(math_min$8(v3.x, w.x), math_min$8(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$5(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(v3.x, min === null || min === void 0 ? void 0 : min.x, max === null || max === void 0 ? void 0 : max.x),
y: clamp(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$7 = Math.max;
var math_min$7 = 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$7(lowerA.x, lowerB.x);
var lowerY = math_min$7(lowerA.y, lowerB.y);
var upperX = math_max$7(upperB.x, upperA.x);
var upperY = math_max$7(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$7(a2.x, b2.x), math_min$7(a2.y, b2.y));
this.upperBound.setNum(math_max$7(a2.x, b2.x), math_max$7(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$7(0, math_min$7(a2.upperBound.x, b2.upperBound.x) - math_max$7(b2.lowerBound.x, a2.lowerBound.x));
var hD = math_max$7(0, math_min$7(a2.upperBound.y, b2.upperBound.y) - math_max$7(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();
{
if (absD.x < EPSILON) {
if (p.x < this.lowerBound.x || this.upperBound.x < p.x) {
return false;
}
} else {
var inv_d = 1 / d2.x;
var t1 = (this.lowerBound.x - p.x) * inv_d;
var t2 = (this.upperBound.x - p.x) * inv_d;
var s2 = -1;
if (t1 > t2) {
var temp3 = t1;
t1 = t2;
t2 = temp3;
s2 = 1;
}
if (t1 > tmin) {
normal3.setZero();
normal3.x = s2;
tmin = t1;
}
tmax = math_min$7(tmax, t2);
if (tmin > tmax) {
return false;
}
}
}
{
if (absD.y < EPSILON) {
if (p.y < this.lowerBound.y || this.upperBound.y < p.y) {
return false;
}
} else {
var inv_d = 1 / d2.y;
var t1 = (this.lowerBound.y - p.y) * inv_d;
var t2 = (this.upperBound.y - p.y) * inv_d;
var s2 = -1;
if (t1 > t2) {
var temp3 = t1;
t1 = t2;
t2 = temp3;
s2 = 1;
}
if (t1 > tmin) {
normal3.setZero();
normal3.y = s2;
tmin = t1;
}
tmax = math_min$7(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$7(a2.x, b2.x);
out.lowerBound.y = math_min$7(a2.y, b2.y);
out.upperBound.x = math_max$7(a2.x, b2.x);
out.upperBound.y = math_max$7(a2.y, b2.y);
return out;
};
AABB2.combinedPerimeter = function(a2, b2) {
var lx = math_min$7(a2.lowerBound.x, b2.lowerBound.x);
var ly = math_min$7(a2.lowerBound.y, b2.lowerBound.y);
var ux = math_max$7(a2.upperBound.x, b2.upperBound.x);
var uy = math_max$7(a2.upperBound.y, b2.upperBound.y);
return 2 * (ux - lx + uy - ly);
};
return AABB2;
})()
);
var math_PI$6 = 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$6;
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$6;
Settings2.maxTranslation = 2;
Settings2.maxRotation = 0.5 * math_PI$6;
Settings2.baumgarte = 0.2;
Settings2.toiBaugarte = 0.75;
Settings2.timeToSleep = 0.5;
Settings2.linearSleepTolerance = 0.01;
Settings2.angularSleepTolerance = 2 / 180 * math_PI$6;
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$8 = Math.abs;
var math_max$6 = 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$6(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$6(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$6(B.height, G.height);
C.height = 1 + math_max$6(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$6(B.height, F.height);
C.height = 1 + math_max$6(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$6(C.height, E.height);
B.height = 1 + math_max$6(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$6(C.height, D.height);
B.height = 1 + math_max$6(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$6(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;
}
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$8(node.child2.height - node.child1.height);
maxBalance = math_max$6(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$6(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$8(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$5 = Math.max;
var math_min$6 = Math.min;
var BroadPhase = (
/** @class */
(function() {
function BroadPhase2() {
var _this = this;
this.m_tree = new DynamicTree();
this.m_moveBuffer = [];
this.query = function(aabb, queryCallback) {
_this.m_tree.query(aabb, queryCallback);
};
this.queryCallback = function(proxyId) {