UNPKG

@box2d/debug-draw

Version:

Debug drawing helper for @box2d

192 lines (191 loc) 7.46 kB
"use strict"; // MIT License Object.defineProperty(exports, "__esModule", { value: true }); exports.b2EdgeShape = 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_common_1 = require("../common/b2_common"); const b2_math_1 = require("../common/b2_math"); const b2_shape_1 = require("./b2_shape"); /** * A line segment (edge) shape. These can be connected in chains or loops * to other edge shapes. Edges created independently are two-sided and do * no provide smooth movement across junctions. */ class b2EdgeShape extends b2_shape_1.b2Shape { constructor() { super(b2_shape_1.b2ShapeType.e_edge, b2_common_1.b2_polygonRadius); /** These are the edge vertices */ this.m_vertex1 = new b2_math_1.b2Vec2(); this.m_vertex2 = new b2_math_1.b2Vec2(); /** Optional adjacent vertices. These are used for smooth collision. */ this.m_vertex0 = new b2_math_1.b2Vec2(); this.m_vertex3 = new b2_math_1.b2Vec2(); /** Uses m_vertex0 and m_vertex3 to create smooth collision. */ this.m_oneSided = false; } /** * Set this as a part of a sequence. Vertex v0 precedes the edge and vertex v3 * follows. These extra vertices are used to provide smooth movement * across junctions. This also makes the collision one-sided. The edge * normal points to the right looking from v1 to v2. */ SetOneSided(v0, v1, v2, v3) { this.m_vertex0.Copy(v0); this.m_vertex1.Copy(v1); this.m_vertex2.Copy(v2); this.m_vertex3.Copy(v3); this.m_oneSided = true; return this; } /** * Set this as an isolated edge. Collision is two-sided. */ SetTwoSided(v1, v2) { this.m_vertex1.Copy(v1); this.m_vertex2.Copy(v2); this.m_oneSided = false; return this; } /** * Implement b2Shape. */ Clone() { return new b2EdgeShape().Copy(this); } Copy(other) { super.Copy(other); // DEBUG: b2Assert(other instanceof b2EdgeShape); this.m_vertex1.Copy(other.m_vertex1); this.m_vertex2.Copy(other.m_vertex2); this.m_vertex0.Copy(other.m_vertex0); this.m_vertex3.Copy(other.m_vertex3); this.m_oneSided = other.m_oneSided; return this; } /** * @see b2Shape::GetChildCount */ GetChildCount() { return 1; } /** * @see b2Shape::TestPoint */ TestPoint(_xf, _p) { return false; } /** * Implement b2Shape. * * p = p1 + t * d * v = v1 + s * e * p1 + t * d = v1 + s * e * s * e - t * d = p1 - v1 */ RayCast(output, input, xf, _childIndex) { // Put the ray into the edge's frame of reference. const p1 = b2_math_1.b2Transform.TransposeMultiplyVec2(xf, input.p1, b2EdgeShape.RayCast_s_p1); const p2 = b2_math_1.b2Transform.TransposeMultiplyVec2(xf, input.p2, b2EdgeShape.RayCast_s_p2); const d = b2_math_1.b2Vec2.Subtract(p2, p1, b2EdgeShape.RayCast_s_d); const v1 = this.m_vertex1; const v2 = this.m_vertex2; const e = b2_math_1.b2Vec2.Subtract(v2, v1, b2EdgeShape.RayCast_s_e); // Normal points to the right, looking from v1 at v2 const { normal } = output; normal.Set(e.y, -e.x).Normalize(); // q = p1 + t * d // dot(normal, q - v1) = 0 // dot(normal, p1 - v1) + t * dot(normal, d) = 0 const numerator = b2_math_1.b2Vec2.Dot(normal, b2_math_1.b2Vec2.Subtract(v1, p1, b2_math_1.b2Vec2.s_t0)); if (this.m_oneSided && numerator > 0) { return false; } const denominator = b2_math_1.b2Vec2.Dot(normal, d); if (denominator === 0) { return false; } const t = numerator / denominator; if (t < 0 || input.maxFraction < t) { return false; } const q = b2_math_1.b2Vec2.AddScaled(p1, t, d, b2EdgeShape.RayCast_s_q); // q = v1 + s * r // s = dot(q - v1, r) / dot(r, r) const r = b2_math_1.b2Vec2.Subtract(v2, v1, b2EdgeShape.RayCast_s_r); const rr = b2_math_1.b2Vec2.Dot(r, r); if (rr === 0) { return false; } const s = b2_math_1.b2Vec2.Dot(b2_math_1.b2Vec2.Subtract(q, v1, b2_math_1.b2Vec2.s_t0), r) / rr; if (s < 0 || s > 1) { return false; } output.fraction = t; b2_math_1.b2Rot.MultiplyVec2(xf.q, output.normal, output.normal); if (numerator > 0) { output.normal.Negate(); } return true; } /** * @see b2Shape::ComputeAABB */ ComputeAABB(aabb, xf, _childIndex) { const v1 = b2_math_1.b2Transform.MultiplyVec2(xf, this.m_vertex1, b2EdgeShape.ComputeAABB_s_v1); const v2 = b2_math_1.b2Transform.MultiplyVec2(xf, this.m_vertex2, b2EdgeShape.ComputeAABB_s_v2); b2_math_1.b2Vec2.Min(v1, v2, aabb.lowerBound); b2_math_1.b2Vec2.Max(v1, v2, aabb.upperBound); const r = this.m_radius; aabb.lowerBound.SubtractXY(r, r); aabb.upperBound.AddXY(r, r); } /** * @see b2Shape::ComputeMass */ ComputeMass(massData, _density) { massData.mass = 0; b2_math_1.b2Vec2.Mid(this.m_vertex1, this.m_vertex2, massData.center); massData.I = 0; } SetupDistanceProxy(proxy, _index) { proxy.m_vertices = proxy.m_buffer; proxy.m_vertices[0] = this.m_vertex1; proxy.m_vertices[1] = this.m_vertex2; proxy.m_count = 2; proxy.m_radius = this.m_radius; } Draw(draw, color) { const v1 = this.m_vertex1; const v2 = this.m_vertex2; draw.DrawSegment(v1, v2, color); if (this.m_oneSided === false) { draw.DrawPoint(v1, 4, color); draw.DrawPoint(v2, 4, color); } } } exports.b2EdgeShape = b2EdgeShape; b2EdgeShape.RayCast_s_p1 = new b2_math_1.b2Vec2(); b2EdgeShape.RayCast_s_p2 = new b2_math_1.b2Vec2(); b2EdgeShape.RayCast_s_d = new b2_math_1.b2Vec2(); b2EdgeShape.RayCast_s_e = new b2_math_1.b2Vec2(); b2EdgeShape.RayCast_s_q = new b2_math_1.b2Vec2(); b2EdgeShape.RayCast_s_r = new b2_math_1.b2Vec2(); b2EdgeShape.ComputeAABB_s_v1 = new b2_math_1.b2Vec2(); b2EdgeShape.ComputeAABB_s_v2 = new b2_math_1.b2Vec2();