@box2d/debug-draw
Version:
Debug drawing helper for @box2d
136 lines (135 loc) • 5.48 kB
JavaScript
"use strict";
// MIT License
Object.defineProperty(exports, "__esModule", { value: true });
exports.b2CircleShape = 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 solid circle shape
*/
class b2CircleShape extends b2_shape_1.b2Shape {
constructor(radius = 0) {
super(b2_shape_1.b2ShapeType.e_circle, radius);
/** Position */
this.m_p = new b2_math_1.b2Vec2();
}
Set(position, radius = this.m_radius) {
this.m_p.Copy(position);
this.m_radius = radius;
return this;
}
/**
* Implement b2Shape.
*/
Clone() {
return new b2CircleShape().Copy(this);
}
Copy(other) {
super.Copy(other);
// DEBUG: b2Assert(other instanceof b2CircleShape);
this.m_p.Copy(other.m_p);
return this;
}
/**
* @see b2Shape::GetChildCount
*/
GetChildCount() {
return 1;
}
/**
* Implement b2Shape.
*/
TestPoint(transform, p) {
const center = b2_math_1.b2Transform.MultiplyVec2(transform, this.m_p, b2CircleShape.TestPoint_s_center);
const d = b2_math_1.b2Vec2.Subtract(p, center, b2CircleShape.TestPoint_s_d);
return b2_math_1.b2Vec2.Dot(d, d) <= this.m_radius ** 2;
}
/**
* Implement b2Shape.
*
* @note because the circle is solid, rays that start inside do not hit because the normal is
* not defined. Collision Detection in Interactive 3D Environments by Gino van den Bergen
* From Section 3.1.2
* x = s + a * r
* norm(x) = radius
*/
RayCast(output, input, transform, _childIndex) {
const position = b2_math_1.b2Transform.MultiplyVec2(transform, this.m_p, b2CircleShape.RayCast_s_position);
const s = b2_math_1.b2Vec2.Subtract(input.p1, position, b2CircleShape.RayCast_s_s);
const b = b2_math_1.b2Vec2.Dot(s, s) - this.m_radius ** 2;
// Solve quadratic equation.
const r = b2_math_1.b2Vec2.Subtract(input.p2, input.p1, b2CircleShape.RayCast_s_r);
const c = b2_math_1.b2Vec2.Dot(s, r);
const rr = b2_math_1.b2Vec2.Dot(r, r);
const sigma = c * c - rr * b;
// Check for negative discriminant and short segment.
if (sigma < 0 || rr < b2_common_1.b2_epsilon) {
return false;
}
// Find the point of intersection of the line with the circle.
let a = -(c + Math.sqrt(sigma));
// Is the intersection point on the segment?
if (a >= 0 && a <= input.maxFraction * rr) {
a /= rr;
output.fraction = a;
b2_math_1.b2Vec2.AddScaled(s, a, r, output.normal).Normalize();
return true;
}
return false;
}
/**
* @see b2Shape::ComputeAABB
*/
ComputeAABB(aabb, transform, _childIndex) {
const p = b2_math_1.b2Transform.MultiplyVec2(transform, this.m_p, b2CircleShape.ComputeAABB_s_p);
aabb.lowerBound.Set(p.x - this.m_radius, p.y - this.m_radius);
aabb.upperBound.Set(p.x + this.m_radius, p.y + this.m_radius);
}
/**
* @see b2Shape::ComputeMass
*/
ComputeMass(massData, density) {
const radius_sq = this.m_radius ** 2;
massData.mass = density * Math.PI * radius_sq;
massData.center.Copy(this.m_p);
// inertia about the local origin
massData.I = massData.mass * (0.5 * radius_sq + b2_math_1.b2Vec2.Dot(this.m_p, this.m_p));
}
SetupDistanceProxy(proxy, _index) {
proxy.m_vertices = proxy.m_buffer;
proxy.m_vertices[0] = this.m_p;
proxy.m_count = 1;
proxy.m_radius = this.m_radius;
}
Draw(draw, color) {
const center = this.m_p;
const radius = this.m_radius;
const axis = b2_math_1.b2Vec2.UNITX;
draw.DrawSolidCircle(center, radius, axis, color);
}
}
exports.b2CircleShape = b2CircleShape;
b2CircleShape.TestPoint_s_center = new b2_math_1.b2Vec2();
b2CircleShape.TestPoint_s_d = new b2_math_1.b2Vec2();
b2CircleShape.RayCast_s_position = new b2_math_1.b2Vec2();
b2CircleShape.RayCast_s_s = new b2_math_1.b2Vec2();
b2CircleShape.RayCast_s_r = new b2_math_1.b2Vec2();
b2CircleShape.ComputeAABB_s_p = new b2_math_1.b2Vec2();