UNPKG

planck-js

Version:

2D physics engine for JavaScript/HTML5 game development

163 lines (132 loc) 4.81 kB
/* * Copyright (c) 2016 Ali Shakiba http://shakiba.me/planck.js * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ module.exports = CircleShape; var create = require('../util/create'); var options = require('../util/options'); var Settings = require('../Settings'); var Shape = require('../Shape'); var Math = require('../common/Math'); var Transform = require('../common/Transform'); var Rot = require('../common/Rot'); var Vec2 = require('../common/Vec2'); var AABB = require('../collision/AABB'); CircleShape._super = Shape; CircleShape.prototype = create(CircleShape._super.prototype); CircleShape.TYPE = 'circle'; function CircleShape(p, r) { if (!(this instanceof CircleShape)) { return new CircleShape(p, r); } CircleShape._super.call(this); this.m_type = CircleShape.TYPE; this.m_p = Vec2(); this.m_radius = 1; if (typeof p === 'object' && Vec2.IsValid(p)) { this.m_p.Set(p); } else if (typeof p === 'number') { this.m_radius = p; } else if (typeof r === 'number') { this.m_radius = r; } } CircleShape.prototype.GetRadius = function() { return this.m_radius; } CircleShape.prototype.SetRadius = function(r) { this.m_radius = r; return this; } CircleShape.prototype.GetCenter = function() { return this.m_p; } CircleShape.prototype.SetCenter = function(p) { this.m_p.Set(p); return this; } CircleShape.prototype.GetSupportVertex = function(d) { return this.m_p; } CircleShape.prototype.GetVertex = function(index) { Assert(index == 0); return this.m_p; } CircleShape.prototype.GetVertexCount = function(index) { return 1; } CircleShape.prototype.Clone = function() { var clone = new CircleShape(); clone.m_type = this.m_type; clone.m_radius = this.m_radius; clone.m_p = this.m_p.Clone(); return clone; } CircleShape.prototype.GetChildCount = function() { return 1; } CircleShape.prototype.TestPoint = function(xf, p) { var center = Vec2.Add(xf.p, Rot.Mul(xf.q, this.m_p)); var d = Vec2.Sub(p, center); return Vec2.Dot(d, d) <= this.m_radius * this.m_radius; } // Collision Detection in Interactive 3D Environments by Gino van den Bergen // From Section 3.1.2 // x = s + a * r // norm(x) = radius CircleShape.prototype.RayCast = function(output, input, xf, childIndex) { var position = Vec2.Add(xf.p, Vec2.Mul(xf.q, this.m_p)); var s = Vec2.Sub(input.p1, position); var b = Vec2.Dot(s, s) - this.m_radius * this.m_radius; // Solve quadratic equation. var r = Vec2.Sub(input.p2, input.p1); var c = Vec2.Dot(s, r); var rr = Vec2.Dot(r, r); var sigma = c * c - rr * b; // Check for negative discriminant and short segment. if (sigma < 0.0 || rr < Math.EPSILON) { return false; } // Find the point of intersection of the line with the circle. var a = -(c + Math.sqrt(sigma)); // Is the intersection point on the segment? if (0.0 <= a && a <= input.maxFraction * rr) { a /= rr; output.fraction = a; output.normal = Vec2.Add(s, Vec2.Mul(a, r)); output.normal.Normalize(); return true; } return false; } CircleShape.prototype.ComputeAABB = function(aabb, xf, childIndex) { var p = Vec2.Add(xf.p, Rot.Mul(xf.q, this.m_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); } CircleShape.prototype.ComputeMass = function(massData, density) { massData.mass = density * Math.PI * this.m_radius * this.m_radius; massData.center = this.m_p; // inertia about the local origin massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + Vec2.Dot(this.m_p, this.m_p)); } CircleShape.prototype.ComputeDistanceProxy = function(proxy) { proxy.m_vertices.push(this.m_p); proxy.m_count = 1; proxy.m_radius = this.m_radius; };