UNPKG

planck

Version:

2D JavaScript/TypeScript physics engine for cross-platform HTML5 game development

1,542 lines (1,540 loc) 429 kB
(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) {