planck-js
Version:
2D physics engine for JavaScript/HTML5 game development
163 lines (132 loc) • 4.81 kB
JavaScript
/*
* 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;
};