planck-js
Version:
2D physics engine for JavaScript/HTML5 game development
173 lines (145 loc) • 4.84 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 = EdgeShape;
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');
EdgeShape._super = Shape;
EdgeShape.prototype = create(EdgeShape._super.prototype);
EdgeShape.TYPE = 'edge';
/**
* A line segment (edge) shape. These can be connected in chains or loops to
* other edge shapes. The connectivity information is used to ensure correct
* contact normals.
*/
function EdgeShape(v1, v2) {
if (!(this instanceof EdgeShape)) {
return new EdgeShape(v1, v2);
}
EdgeShape._super.call(this);
this.m_type = EdgeShape.TYPE;
this.m_radius = Settings.polygonRadius;
// These are the edge vertices
this.m_vertex1 = Vec2(v1);
this.m_vertex2 = Vec2(v2);
// Optional adjacent vertices. These are used for smooth collision.
// Used by chain shape.
this.m_vertex0 = Vec2();
this.m_vertex3 = Vec2();
this.m_hasVertex0 = false;
this.m_hasVertex3 = false;
}
/**
* Set this as an isolated edge.
*/
EdgeShape.prototype.Set = function(v1, v2) {
this.m_vertex1.Set(v1);
this.m_vertex2.Set(v2);
this.m_hasVertex0 = false;
this.m_hasVertex3 = false;
return this;
}
EdgeShape.prototype.Clone = function() {
var clone = new EdgeShape();
clone.m_type = this.m_type;
clone.m_radius = this.m_radius;
clone.m_vertex1.Set(this.m_vertex1);
clone.m_vertex2.Set(this.m_vertex2);
clone.m_vertex0.Set(this.m_vertex0);
clone.m_vertex3.Set(this.m_vertex3);
clone.m_hasVertex0 = this.m_hasVertex0;
clone.m_hasVertex3 = this.m_hasVertex3;
return clone;
}
EdgeShape.prototype.GetChildCount = function() {
return 1;
}
EdgeShape.prototype.TestPoint = function(xf, p) {
return false;
}
// p = p1 + t * d
// v = v1 + s * e
// p1 + t * d = v1 + s * e
// s * e - t * d = p1 - v1
EdgeShape.prototype.RayCast = function(output, input, xf, childIndex) {
// NOT_USED(childIndex);
// Put the ray into the edge's frame of reference.
var p1 = Vec2.MulT(xf.q, Vec2.Sub(input.p1, xf.p));
var p2 = Vec2.MulT(xf.q, Vec2.Sub(input.p2, xf.p));
var d = Vec2.Sub(p2, p1);
var v1 = this.m_vertex1;
var v2 = this.m_vertex2;
var e = Vec2.Sub(v2, v1);
var normal = Vec2(e.y, -e.x);
normal.Normalize();
// q = p1 + t * d
// dot(normal, q - v1) = 0
// dot(normal, p1 - v1) + t * dot(normal, d) = 0
var numerator = Vec2.Dot(normal, Vec2.Sub(v1, p1));
var denominator = Vec2.Dot(normal, d);
if (denominator == 0.0) {
return false;
}
var t = numerator / denominator;
if (t < 0.0 || input.maxFraction < t) {
return false;
}
var q = Vec2.Add(p1, Vec2.Mul(t, d));
// q = v1 + s * r
// s = dot(q - v1, r) / dot(r, r)
var r = Vec2.Sub(v2, v1);
var rr = Vec2.Dot(r, r);
if (rr == 0.0) {
return false;
}
var s = Vec2.Dot(Vec2.Sub(q - v1), r) / rr;
if (s < 0.0 || 1.0 < s) {
return false;
}
output.fraction = t;
if (numerator > 0.0) {
output.normal = -Vec2.Mul(xf.q, normal);
} else {
output.normal = Vec2.Mul(xf.q, normal);
}
return true;
}
EdgeShape.prototype.ComputeAABB = function(aabb, xf, childIndex) {
var v1 = Transform.Mul(xf, this.m_vertex1);
var v2 = Transform.Mul(xf, this.m_vertex2);
aabb.CombinePoints(v1, v2);
aabb.Extend(this.m_radius)
}
EdgeShape.prototype.ComputeMass = function(massData, density) {
massData.mass = 0.0;
massData.center.WSet(0.5, this.m_vertex1, 0.5, this.m_vertex2);
massData.I = 0.0;
}
EdgeShape.prototype.ComputeDistanceProxy = function(proxy) {
proxy.m_vertices.push(this.m_vertex1);
proxy.m_vertices.push(this.m_vertex2);
proxy.m_count = 2;
proxy.m_radius = this.m_radius;
};