UNPKG

@box2d/debug-draw

Version:

Debug drawing helper for @box2d

324 lines (323 loc) 11.7 kB
"use strict"; // MIT License Object.defineProperty(exports, "__esModule", { value: true }); exports.b2Fixture = exports.b2FixtureProxy = exports.b2DefaultFilter = void 0; // Copyright (c) 2019 Erin Catto // 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. // DEBUG: import { b2Assert } from "../common/b2_common"; const b2_math_1 = require("../common/b2_math"); const b2_collision_1 = require("../collision/b2_collision"); const b2_shape_1 = require("../collision/b2_shape"); const b2_common_1 = require("../common/b2_common"); const b2_settings_1 = require("../common/b2_settings"); const temp = { c1: new b2_math_1.b2Vec2(), c2: new b2_math_1.b2Vec2(), }; exports.b2DefaultFilter = { categoryBits: 0x0001, maskBits: 0xffff, groupIndex: 0, }; /** * This proxy is used internally to connect fixtures to the broad-phase. */ class b2FixtureProxy { constructor(fixture, broadPhase, xf, childIndex) { this.aabb = new b2_collision_1.b2AABB(); this.fixture = fixture; this.childIndex = childIndex; fixture.m_shape.ComputeAABB(this.aabb, xf, childIndex); this.treeNode = broadPhase.CreateProxy(this.aabb, this); } } exports.b2FixtureProxy = b2FixtureProxy; const Synchronize_s_aabb1 = new b2_collision_1.b2AABB(); const Synchronize_s_aabb2 = new b2_collision_1.b2AABB(); const Synchronize_s_displacement = new b2_math_1.b2Vec2(); /** * A fixture is used to attach a shape to a body for collision detection. A fixture * inherits its transform from its parent. Fixtures hold additional non-geometric data * such as friction, collision filters, etc. * Fixtures are created via b2Body::CreateFixture. * * @warning you cannot reuse fixtures. */ class b2Fixture { /** @internal protected */ get m_proxyCount() { return this.m_proxies.length; } /** @internal protected */ constructor(body, def) { var _a, _b, _c, _d, _e; /** @internal protected */ this.m_density = 0; /** @internal protected */ this.m_next = null; /** @internal protected */ this.m_friction = 0; /** @internal protected */ this.m_restitution = 0; /** @internal protected */ this.m_restitutionThreshold = 0; /** @internal protected */ this.m_proxies = []; /** @internal protected */ this.m_isSensor = false; this.m_userData = {}; this.m_body = body; this.m_shape = def.shape.Clone(); if (def.userData) this.SetUserData(def.userData); this.m_friction = (_a = def.friction) !== null && _a !== void 0 ? _a : 0.2; this.m_restitution = (_b = def.restitution) !== null && _b !== void 0 ? _b : 0; this.m_restitutionThreshold = (_c = def.restitutionThreshold) !== null && _c !== void 0 ? _c : b2_settings_1.b2_lengthUnitsPerMeter; this.m_filter = { ...exports.b2DefaultFilter, ...def.filter, }; this.m_isSensor = (_d = def.isSensor) !== null && _d !== void 0 ? _d : false; this.m_density = (_e = def.density) !== null && _e !== void 0 ? _e : 0; } /** * Get the type of the child shape. You can use this to down cast to the concrete shape. * * @returns The shape type. */ GetType() { return this.m_shape.GetType(); } /** * Get the child shape. You can modify the child shape, however you should not change the * number of vertices because this will crash some collision caching mechanisms. * Manipulating the shape may lead to non-physical behavior. */ GetShape() { return this.m_shape; } /** * Set if this fixture is a sensor. */ SetSensor(sensor) { if (sensor !== this.m_isSensor) { this.m_body.SetAwake(true); this.m_isSensor = sensor; } } /** * Is this fixture a sensor (non-solid)? * * @returns The true if the shape is a sensor. */ IsSensor() { return this.m_isSensor; } /** * Set the contact filtering data. This will not update contacts until the next time * step when either parent body is active and awake. * This automatically calls Refilter. */ SetFilterData(filter) { var _a, _b, _c; this.m_filter.categoryBits = (_a = filter.categoryBits) !== null && _a !== void 0 ? _a : exports.b2DefaultFilter.categoryBits; this.m_filter.groupIndex = (_b = filter.groupIndex) !== null && _b !== void 0 ? _b : exports.b2DefaultFilter.groupIndex; this.m_filter.maskBits = (_c = filter.maskBits) !== null && _c !== void 0 ? _c : exports.b2DefaultFilter.maskBits; this.Refilter(); } /** * Get the contact filtering data. */ GetFilterData() { return this.m_filter; } /** * Call this if you want to establish collision that was previously disabled by b2ContactFilter::ShouldCollide. */ Refilter() { // Flag associated contacts for filtering. let edge = this.m_body.GetContactList(); while (edge) { const { contact } = edge; const fixtureA = contact.GetFixtureA(); const fixtureB = contact.GetFixtureB(); if (fixtureA === this || fixtureB === this) { contact.FlagForFiltering(); } edge = edge.next; } const world = this.m_body.GetWorld(); // Touch each proxy so that new pairs may be created const broadPhase = world.m_contactManager.m_broadPhase; for (const proxy of this.m_proxies) { broadPhase.TouchProxy(proxy.treeNode); } } /** * Get the parent body of this fixture. * * @returns The parent body. */ GetBody() { return this.m_body; } /** * Get the next fixture in the parent body's fixture list. * * @returns The next shape. */ GetNext() { return this.m_next; } /** * Get the user data that was assigned in the fixture definition. Use this to * store your application specific data. */ GetUserData() { return this.m_userData; } /** * Set the user data. Use this to store your application specific data. * This is a merge operation. Only specified keys will be overridden. */ SetUserData(data) { Object.assign(this.m_userData, data); } /** * Test a point for containment in this fixture. * * @param p A point in world coordinates. */ TestPoint(p) { return this.m_shape.TestPoint(this.m_body.GetTransform(), p); } /** * Cast a ray against this shape. * * @param output The ray-cast results. * @param input The ray-cast input parameters. */ RayCast(output, input, childIndex) { return this.m_shape.RayCast(output, input, this.m_body.GetTransform(), childIndex); } /** * Get the mass data for this fixture. The mass data is based on the density and * the shape. The rotational inertia is about the shape's origin. This operation * may be expensive. */ GetMassData(massData = new b2_shape_1.b2MassData()) { this.m_shape.ComputeMass(massData, this.m_density); return massData; } /** * Set the density of this fixture. This will _not_ automatically adjust the mass * of the body. You must call b2Body::ResetMassData to update the body's mass. */ SetDensity(density) { // DEBUG: b2Assert(Number.isFinite(density) && density >= 0); this.m_density = density; } /** * Get the density of this fixture. */ GetDensity() { return this.m_density; } /** * Get the coefficient of friction. */ GetFriction() { return this.m_friction; } /** * Set the coefficient of friction. This will _not_ change the friction of * existing contacts. */ SetFriction(friction) { this.m_friction = friction; } /** * Get the coefficient of restitution. */ GetRestitution() { return this.m_restitution; } /** * Set the coefficient of restitution. This will _not_ change the restitution of * existing contacts. */ SetRestitution(restitution) { this.m_restitution = restitution; } /** Get the restitution velocity threshold. */ GetRestitutionThreshold() { return this.m_restitutionThreshold; } /** * Set the restitution threshold. This will _not_ change the restitution threshold of * existing contacts. */ SetRestitutionThreshold(threshold) { this.m_restitutionThreshold = threshold; } /** * Get the fixture's AABB. This AABB may be enlarge and/or stale. * If you need a more accurate AABB, compute it using the shape and * the body transform. */ GetAABB(childIndex) { // DEBUG: b2Assert(0 <= childIndex && childIndex < this.m_proxyCount); return this.m_proxies[childIndex].aabb; } /** * These support body activation/deactivation. * * @internal protected */ CreateProxies(broadPhase, xf) { (0, b2_common_1.b2Assert)(this.m_proxies.length === 0); // Create proxies in the broad-phase. this.m_proxies.length = this.m_shape.GetChildCount(); for (let i = 0; i < this.m_proxies.length; ++i) { this.m_proxies[i] = new b2FixtureProxy(this, broadPhase, xf, i); } } /** @internal protected */ DestroyProxies(broadPhase) { // Destroy proxies in the broad-phase. for (const proxy of this.m_proxies) { broadPhase.DestroyProxy(proxy.treeNode); } this.m_proxies.length = 0; } /** @internal protected */ Synchronize(broadPhase, transform1, transform2) { const { c1, c2 } = temp; const displacement = Synchronize_s_displacement; for (const proxy of this.m_proxies) { // Compute an AABB that covers the swept shape (may miss some rotation effect). const aabb1 = Synchronize_s_aabb1; const aabb2 = Synchronize_s_aabb2; this.m_shape.ComputeAABB(aabb1, transform1, proxy.childIndex); this.m_shape.ComputeAABB(aabb2, transform2, proxy.childIndex); proxy.aabb.Combine2(aabb1, aabb2); b2_math_1.b2Vec2.Subtract(aabb2.GetCenter(c2), aabb1.GetCenter(c1), displacement); broadPhase.MoveProxy(proxy.treeNode, proxy.aabb, displacement); } } } exports.b2Fixture = b2Fixture;