UNPKG

@box2d/core

Version:
208 lines (207 loc) 8.36 kB
"use strict"; // MIT License Object.defineProperty(exports, "__esModule", { value: true }); exports.b2ChainShape = 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, b2_linearSlop } 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"); const b2_edge_shape_1 = require("./b2_edge_shape"); /** * A chain shape is a free form sequence of line segments. * The chain has one-sided collision, with the surface normal pointing to the right of the edge. * This provides a counter-clockwise winding like the polygon shape. * Connectivity information is used to create smooth collisions. * * @warning the chain will not collide properly if there are self-intersections. */ class b2ChainShape extends b2_shape_1.b2Shape { constructor() { super(b2_shape_1.b2ShapeType.e_chain, b2_common_1.b2_polygonRadius); this.m_vertices = []; this.m_prevVertex = new b2_math_1.b2Vec2(); this.m_nextVertex = new b2_math_1.b2Vec2(); } /** * Create a loop. This automatically adjusts connectivity. * * @param vertices An array of vertices, these are copied * @param count The vertex count */ CreateLoop(vertices, count = vertices.length) { // DEBUG: b2Assert(count >= 3); if (count < 3) { return this; } // DEBUG: for (let i = 1; i < count; ++i) { // DEBUG: const v1 = vertices[i - 1]; // DEBUG: const v2 = vertices[i]; // DEBUG: // If the code crashes here, it means your vertices are too close together. // DEBUG: b2Assert(b2Vec2.DistanceSquared(v1, v2) > b2_linearSlop * b2_linearSlop); // DEBUG: } this.m_vertices.length = count + 1; for (let i = 0; i < count; ++i) { const { x, y } = vertices[i]; this.m_vertices[i] = new b2_math_1.b2Vec2(x, y); } this.m_vertices[count] = this.m_vertices[0].Clone(); this.m_prevVertex.Copy(this.m_vertices[this.m_vertices.length - 2]); this.m_nextVertex.Copy(this.m_vertices[1]); return this; } /** * Create a chain with ghost vertices to connect multiple chains together. * * @param vertices An array of vertices, these are copied * @param count The vertex count * @param prevVertex Previous vertex from chain that connects to the start * @param nextVertex Next vertex from chain that connects to the end */ CreateChain(vertices, count, prevVertex, nextVertex) { // DEBUG: b2Assert(count >= 2); // DEBUG: for (let i = 1; i < count; ++i) { // DEBUG: // If the code crashes here, it means your vertices are too close together. // DEBUG: b2Assert(b2Vec2.DistanceSquared(vertices[i-1], vertices[i]) > b2_linearSlop * b2_linearSlop); // DEBUG: } this.m_vertices.length = count; for (let i = 0; i < count; ++i) { const { x, y } = vertices[i]; this.m_vertices[i] = new b2_math_1.b2Vec2(x, y); } this.m_prevVertex.Copy(prevVertex); this.m_nextVertex.Copy(nextVertex); return this; } /** * Implement b2Shape. Vertices are cloned using b2Alloc. */ Clone() { return new b2ChainShape().Copy(this); } Copy(other) { super.Copy(other); // DEBUG: b2Assert(other instanceof b2ChainShape); return this.CreateChain(other.m_vertices, other.m_vertices.length, other.m_prevVertex, other.m_nextVertex); } /** * @see b2Shape::GetChildCount */ GetChildCount() { // edge count = vertex count - 1 return this.m_vertices.length - 1; } /** * Get a child edge. */ GetChildEdge(edge, index) { // DEBUG: b2Assert(0 <= index && index < this.m_vertices.length - 1); edge.m_radius = this.m_radius; edge.m_vertex1.Copy(this.m_vertices[index]); edge.m_vertex2.Copy(this.m_vertices[index + 1]); edge.m_oneSided = true; if (index > 0) { edge.m_vertex0.Copy(this.m_vertices[index - 1]); } else { edge.m_vertex0.Copy(this.m_prevVertex); } if (index < this.m_vertices.length - 2) { edge.m_vertex3.Copy(this.m_vertices[index + 2]); } else { edge.m_vertex3.Copy(this.m_nextVertex); } } /** * This always return false. * * @see b2Shape::TestPoint */ TestPoint(_xf, _p) { return false; } /** * Implement b2Shape. */ RayCast(output, input, xf, childIndex) { // DEBUG: b2Assert(childIndex < this.m_vertices.length); const edgeShape = b2ChainShape.RayCast_s_edgeShape; const i1 = childIndex; let i2 = childIndex + 1; if (i2 === this.m_vertices.length) { i2 = 0; } edgeShape.m_vertex1.Copy(this.m_vertices[i1]); edgeShape.m_vertex2.Copy(this.m_vertices[i2]); return edgeShape.RayCast(output, input, xf, 0); } /** * @see b2Shape::ComputeAABB */ ComputeAABB(aabb, xf, childIndex) { // DEBUG: b2Assert(childIndex < this.m_vertices.length); const i1 = childIndex; let i2 = childIndex + 1; if (i2 === this.m_vertices.length) { i2 = 0; } const v1 = b2_math_1.b2Transform.MultiplyVec2(xf, this.m_vertices[i1], b2ChainShape.ComputeAABB_s_v1); const v2 = b2_math_1.b2Transform.MultiplyVec2(xf, this.m_vertices[i2], b2ChainShape.ComputeAABB_s_v2); const lower = b2_math_1.b2Vec2.Min(v1, v2, b2ChainShape.ComputeAABB_s_lower); const upper = b2_math_1.b2Vec2.Max(v1, v2, b2ChainShape.ComputeAABB_s_upper); aabb.lowerBound.x = lower.x - this.m_radius; aabb.lowerBound.y = lower.y - this.m_radius; aabb.upperBound.x = upper.x + this.m_radius; aabb.upperBound.y = upper.y + this.m_radius; } /** * Chains have zero mass. * * @see b2Shape::ComputeMass */ ComputeMass(massData, _density) { massData.mass = 0; massData.center.SetZero(); massData.I = 0; } SetupDistanceProxy(proxy, index) { // DEBUG: b2Assert(0 <= index && index < this.m_vertices.length); proxy.m_vertices = proxy.m_buffer; proxy.m_vertices[0] = this.m_vertices[index]; const secondIndex = index + 1 < this.m_vertices.length ? index + 1 : 0; proxy.m_vertices[1] = this.m_vertices[secondIndex]; proxy.m_count = 2; proxy.m_radius = this.m_radius; } Draw(draw, color) { const vertices = this.m_vertices; let v1 = vertices[0]; for (let i = 1; i < vertices.length; ++i) { const v2 = vertices[i]; draw.DrawSegment(v1, v2, color); v1 = v2; } } } exports.b2ChainShape = b2ChainShape; b2ChainShape.RayCast_s_edgeShape = new b2_edge_shape_1.b2EdgeShape(); b2ChainShape.ComputeAABB_s_v1 = new b2_math_1.b2Vec2(); b2ChainShape.ComputeAABB_s_v2 = new b2_math_1.b2Vec2(); b2ChainShape.ComputeAABB_s_lower = new b2_math_1.b2Vec2(); b2ChainShape.ComputeAABB_s_upper = new b2_math_1.b2Vec2();