mirror of
https://github.com/logsol/chuck.js.git
synced 2026-05-11 10:37:34 +00:00
11132 lines
275 KiB
JavaScript
11132 lines
275 KiB
JavaScript
/**
|
|
* Copyright 2010 Josh Adell. All rights reserved.
|
|
*
|
|
* Based on Box2d2 - Jonas Wagner
|
|
* http://29a.ch/2010/4/17/box2d-2-flash-ported-javascript
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
function extend(a, b) {
|
|
for(var c in b) {
|
|
a[c] = b[c];
|
|
}
|
|
}
|
|
|
|
|
|
var b2Settings = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Settings.prototype.__constructor = function(){}
|
|
b2Settings.prototype.__varz = function(){
|
|
}
|
|
b2Settings.USHRT_MAX = 0x0000ffff;
|
|
b2Settings.b2_pi = Math.PI;
|
|
b2Settings.b2_maxManifoldPoints = 2;
|
|
b2Settings.b2_maxPolygonVertices = 8;
|
|
b2Settings.b2_maxProxies = 512;
|
|
b2Settings.b2_maxPairs = 8 * b2Settings.b2_maxProxies;
|
|
b2Settings.b2_linearSlop = 0.005;
|
|
b2Settings.b2_angularSlop = 2.0 / 180.0 * b2Settings.b2_pi;
|
|
b2Settings.b2_toiSlop = 8.0 * b2Settings.b2_linearSlop;
|
|
b2Settings.b2_maxTOIContactsPerIsland = 32;
|
|
b2Settings.b2_velocityThreshold = 1.0;
|
|
b2Settings.b2_maxLinearCorrection = 0.2;
|
|
b2Settings.b2_maxAngularCorrection = 8.0 / 180.0 * b2Settings.b2_pi;
|
|
b2Settings.b2_maxLinearVelocity = 200.0;
|
|
b2Settings.b2_maxLinearVelocitySquared = b2Settings.b2_maxLinearVelocity * b2Settings.b2_maxLinearVelocity;
|
|
b2Settings.b2_maxAngularVelocity = 250.0;
|
|
b2Settings.b2_maxAngularVelocitySquared = b2Settings.b2_maxAngularVelocity * b2Settings.b2_maxAngularVelocity;
|
|
b2Settings.b2_contactBaumgarte = 0.2;
|
|
b2Settings.b2_timeToSleep = 0.5;
|
|
b2Settings.b2_linearSleepTolerance = 0.01;
|
|
b2Settings.b2_angularSleepTolerance = 2.0 / 180.0;
|
|
b2Settings.b2Assert = function (a) {
|
|
if (!a){
|
|
var nullVec;
|
|
nullVec.x++;
|
|
}
|
|
}
|
|
exports.b2Settings = b2Settings;
|
|
|
|
|
|
var b2Color = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Color.prototype.__constructor = function (rr, gg, bb) {
|
|
this._r = parseInt(255 * b2Math.b2Clamp(rr, 0.0, 1.0));
|
|
this._g = parseInt(255 * b2Math.b2Clamp(gg, 0.0, 1.0));
|
|
this._b = parseInt(255 * b2Math.b2Clamp(bb, 0.0, 1.0));
|
|
}
|
|
b2Color.prototype.__varz = function(){
|
|
}
|
|
b2Color.prototype._r = 0;
|
|
b2Color.prototype._g = 0;
|
|
b2Color.prototype._b = 0;
|
|
b2Color.prototype.Set = function (rr, gg, bb) {
|
|
this._r = parseInt(255 * b2Math.b2Clamp(rr, 0.0, 1.0));
|
|
this._g = parseInt(255 * b2Math.b2Clamp(gg, 0.0, 1.0));
|
|
this._b = parseInt(255 * b2Math.b2Clamp(bb, 0.0, 1.0));
|
|
}
|
|
b2Color.prototype.set = function (rr) {
|
|
this._r = parseInt(255 * b2Math.b2Clamp(rr, 0.0, 1.0));
|
|
}
|
|
b2Color.prototype.set = function (gg) {
|
|
this._g = parseInt(255 * b2Math.b2Clamp(gg, 0.0, 1.0));
|
|
}
|
|
b2Color.prototype.set = function (bb) {
|
|
this._b = parseInt(255 * b2Math.b2Clamp(bb, 0.0, 1.0));
|
|
}
|
|
b2Color.prototype.get = function () {
|
|
return (this._r) | (this._g << 8) | (this._b << 16);
|
|
}
|
|
exports.b2Color = b2Color;
|
|
|
|
|
|
var b2Vec2 = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Vec2.prototype.__constructor = function (x_, y_) {
|
|
if(arguments.length == 2) {
|
|
this.x=x_; this.y=y_;
|
|
}
|
|
}
|
|
b2Vec2.prototype.__varz = function(){
|
|
}
|
|
b2Vec2.Make = function (x_, y_) {
|
|
return new b2Vec2(x_, y_);
|
|
}
|
|
b2Vec2.prototype.x = 0;
|
|
b2Vec2.prototype.y = 0;
|
|
b2Vec2.prototype.SetZero = function () { this.x = 0.0; this.y = 0.0; }
|
|
b2Vec2.prototype.Set = function (x_, y_) {this.x=x_; this.y=y_;}
|
|
b2Vec2.prototype.SetV = function (v) {this.x=v.x; this.y=v.y;}
|
|
b2Vec2.prototype.Negative = function () { return new b2Vec2(-this.x, -this.y); }
|
|
b2Vec2.prototype.Copy = function () {
|
|
return new b2Vec2(this.x,this.y);
|
|
}
|
|
b2Vec2.prototype.Add = function (v) {
|
|
this.x += v.x; this.y += v.y;
|
|
}
|
|
b2Vec2.prototype.Subtract = function (v) {
|
|
this.x -= v.x; this.y -= v.y;
|
|
}
|
|
b2Vec2.prototype.Multiply = function (a) {
|
|
this.x *= a; this.y *= a;
|
|
}
|
|
b2Vec2.prototype.MulM = function (A) {
|
|
var tX = this.x;
|
|
this.x = A.col1.x * tX + A.col2.x * this.y;
|
|
this.y = A.col1.y * tX + A.col2.y * this.y;
|
|
}
|
|
b2Vec2.prototype.MulTM = function (A) {
|
|
var tX = b2Math.b2Dot(this, A.col1);
|
|
this.y = b2Math.b2Dot(this, A.col2);
|
|
this.x = tX;
|
|
}
|
|
b2Vec2.prototype.CrossVF = function (s) {
|
|
var tX = this.x;
|
|
this.x = s * this.y;
|
|
this.y = -s * tX;
|
|
}
|
|
b2Vec2.prototype.CrossFV = function (s) {
|
|
var tX = this.x;
|
|
this.x = -s * this.y;
|
|
this.y = s * tX;
|
|
}
|
|
b2Vec2.prototype.MinV = function (b) {
|
|
this.x = this.x < b.x ? this.x : b.x;
|
|
this.y = this.y < b.y ? this.y : b.y;
|
|
}
|
|
b2Vec2.prototype.MaxV = function (b) {
|
|
this.x = this.x > b.x ? this.x : b.x;
|
|
this.y = this.y > b.y ? this.y : b.y;
|
|
}
|
|
b2Vec2.prototype.Abs = function () {
|
|
if (this.x < 0) this.x = -this.x;
|
|
if (this.y < 0) this.y = -this.y;
|
|
}
|
|
b2Vec2.prototype.Length = function () {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
}
|
|
b2Vec2.prototype.LengthSquared = function () {
|
|
return (this.x * this.x + this.y * this.y);
|
|
}
|
|
b2Vec2.prototype.Normalize = function () {
|
|
var length = Math.sqrt(this.x * this.x + this.y * this.y);
|
|
if (length < Number.MIN_VALUE)
|
|
{
|
|
return 0.0;
|
|
}
|
|
var invLength = 1.0 / length;
|
|
this.x *= invLength;
|
|
this.y *= invLength;
|
|
|
|
return length;
|
|
}
|
|
b2Vec2.prototype.IsValid = function () {
|
|
return b2Math.b2IsValid(this.x) && b2Math.b2IsValid(this.y);
|
|
}
|
|
exports.b2Vec2 = b2Vec2;
|
|
|
|
|
|
var b2Mat22 = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Mat22.prototype.__constructor = function (angle, c1, c2) {
|
|
if (c1!=null && c2!=null){
|
|
this.col1.SetV(c1);
|
|
this.col2.SetV(c2);
|
|
}
|
|
else{
|
|
var c = Math.cos(angle);
|
|
var s = Math.sin(angle);
|
|
this.col1.x = c; this.col2.x = -s;
|
|
this.col1.y = s; this.col2.y = c;
|
|
}
|
|
}
|
|
b2Mat22.prototype.__varz = function(){
|
|
this.col1 = new b2Vec2();
|
|
this.col2 = new b2Vec2();
|
|
}
|
|
b2Mat22.prototype.col1 = new b2Vec2();
|
|
b2Mat22.prototype.col2 = new b2Vec2();
|
|
b2Mat22.prototype.Set = function (angle) {
|
|
var c = Math.cos(angle);
|
|
var s = Math.sin(angle);
|
|
this.col1.x = c; this.col2.x = -s;
|
|
this.col1.y = s; this.col2.y = c;
|
|
}
|
|
b2Mat22.prototype.SetVV = function (c1, c2) {
|
|
this.col1.SetV(c1);
|
|
this.col2.SetV(c2);
|
|
}
|
|
b2Mat22.prototype.Copy = function () {
|
|
return new b2Mat22(0, this.col1, this.col2);
|
|
}
|
|
b2Mat22.prototype.SetM = function (m) {
|
|
this.col1.SetV(m.col1);
|
|
this.col2.SetV(m.col2);
|
|
}
|
|
b2Mat22.prototype.AddM = function (m) {
|
|
this.col1.x += m.col1.x;
|
|
this.col1.y += m.col1.y;
|
|
this.col2.x += m.col2.x;
|
|
this.col2.y += m.col2.y;
|
|
}
|
|
b2Mat22.prototype.SetIdentity = function () {
|
|
this.col1.x = 1.0; this.col2.x = 0.0;
|
|
this.col1.y = 0.0; this.col2.y = 1.0;
|
|
}
|
|
b2Mat22.prototype.SetZero = function () {
|
|
this.col1.x = 0.0; this.col2.x = 0.0;
|
|
this.col1.y = 0.0; this.col2.y = 0.0;
|
|
}
|
|
b2Mat22.prototype.GetAngle = function () {
|
|
return Math.atan2(this.col1.y, this.col1.x);
|
|
}
|
|
b2Mat22.prototype.Invert = function (out) {
|
|
var a = this.col1.x;
|
|
var b = this.col2.x;
|
|
var c = this.col1.y;
|
|
var d = this.col2.y;
|
|
|
|
var det = a * d - b * c;
|
|
|
|
det = 1.0 / det;
|
|
out.col1.x = det * d; out.col2.x = -det * b;
|
|
out.col1.y = -det * c; out.col2.y = det * a;
|
|
return out;
|
|
}
|
|
b2Mat22.prototype.Solve = function (out, bX, bY) {
|
|
|
|
var a11 = this.col1.x;
|
|
var a12 = this.col2.x;
|
|
var a21 = this.col1.y;
|
|
var a22 = this.col2.y;
|
|
|
|
var det = a11 * a22 - a12 * a21;
|
|
|
|
det = 1.0 / det;
|
|
out.x = det * (a22 * bX - a12 * bY);
|
|
out.y = det * (a11 * bY - a21 * bX);
|
|
|
|
return out;
|
|
}
|
|
b2Mat22.prototype.Abs = function () {
|
|
this.col1.Abs();
|
|
this.col2.Abs();
|
|
}
|
|
exports.b2Mat22 = b2Mat22;
|
|
|
|
|
|
var b2XForm = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2XForm.prototype.__constructor = function (pos, r) {
|
|
if (pos){
|
|
this.position.SetV(pos);
|
|
this.R.SetM(r);
|
|
|
|
}
|
|
}
|
|
b2XForm.prototype.__varz = function(){
|
|
this.position = new b2Vec2;
|
|
this.R = new b2Mat22();
|
|
}
|
|
b2XForm.prototype.position = new b2Vec2;
|
|
b2XForm.prototype.R = new b2Mat22();
|
|
b2XForm.prototype.Initialize = function (pos, r) {
|
|
this.position.SetV(pos);
|
|
this.R.SetM(r);
|
|
}
|
|
b2XForm.prototype.SetIdentity = function () {
|
|
this.position.SetZero();
|
|
this.R.SetIdentity();
|
|
}
|
|
b2XForm.prototype.Set = function (x) {
|
|
|
|
this.position.SetV(x.position);
|
|
|
|
this.R.SetM(x.R);
|
|
|
|
}
|
|
exports.b2XForm = b2XForm;
|
|
|
|
|
|
var b2Math = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Math.prototype.__constructor = function(){}
|
|
b2Math.prototype.__varz = function(){
|
|
}
|
|
b2Math.b2Vec2_zero = new b2Vec2(0.0, 0.0);
|
|
b2Math.b2Mat22_identity = new b2Mat22(0, new b2Vec2(1.0, 0.0), new b2Vec2(0.0, 1.0));
|
|
b2Math.b2XForm_identity = new b2XForm(b2Math.b2Vec2_zero, b2Math.b2Mat22_identity);
|
|
b2Math.b2IsValid = function (x) {
|
|
return isFinite(x);
|
|
}
|
|
b2Math.b2Dot = function (a, b) {
|
|
return a.x * b.x + a.y * b.y;
|
|
}
|
|
b2Math.b2CrossVV = function (a, b) {
|
|
return a.x * b.y - a.y * b.x;
|
|
}
|
|
b2Math.b2CrossVF = function (a, s) {
|
|
var v = new b2Vec2(s * a.y, -s * a.x);
|
|
return v;
|
|
}
|
|
b2Math.b2CrossFV = function (s, a) {
|
|
var v = new b2Vec2(-s * a.y, s * a.x);
|
|
return v;
|
|
}
|
|
b2Math.b2MulMV = function (A, v) {
|
|
|
|
|
|
var u = new b2Vec2(A.col1.x * v.x + A.col2.x * v.y, A.col1.y * v.x + A.col2.y * v.y);
|
|
return u;
|
|
}
|
|
b2Math.b2MulTMV = function (A, v) {
|
|
|
|
|
|
var u = new b2Vec2(b2Math.b2Dot(v, A.col1), b2Math.b2Dot(v, A.col2));
|
|
return u;
|
|
}
|
|
b2Math.b2MulX = function (T, v) {
|
|
var a = b2Math.b2MulMV(T.R, v);
|
|
a.x += T.position.x;
|
|
a.y += T.position.y;
|
|
|
|
return a;
|
|
}
|
|
b2Math.b2MulXT = function (T, v) {
|
|
var a = b2Math.SubtractVV(v, T.position);
|
|
|
|
var tX = (a.x * T.R.col1.x + a.y * T.R.col1.y );
|
|
a.y = (a.x * T.R.col2.x + a.y * T.R.col2.y );
|
|
a.x = tX;
|
|
return a;
|
|
}
|
|
b2Math.AddVV = function (a, b) {
|
|
var v = new b2Vec2(a.x + b.x, a.y + b.y);
|
|
return v;
|
|
}
|
|
b2Math.SubtractVV = function (a, b) {
|
|
var v = new b2Vec2(a.x - b.x, a.y - b.y);
|
|
return v;
|
|
}
|
|
b2Math.b2Distance = function (a, b) {
|
|
var cX = a.x-b.x;
|
|
var cY = a.y-b.y;
|
|
return Math.sqrt(cX*cX + cY*cY);
|
|
}
|
|
b2Math.b2DistanceSquared = function (a, b) {
|
|
var cX = a.x-b.x;
|
|
var cY = a.y-b.y;
|
|
return (cX*cX + cY*cY);
|
|
}
|
|
b2Math.MulFV = function (s, a) {
|
|
var v = new b2Vec2(s * a.x, s * a.y);
|
|
return v;
|
|
}
|
|
b2Math.AddMM = function (A, B) {
|
|
var C = new b2Mat22(0, b2Math.AddVV(A.col1, B.col1), b2Math.AddVV(A.col2, B.col2));
|
|
return C;
|
|
}
|
|
b2Math.b2MulMM = function (A, B) {
|
|
var C = new b2Mat22(0, b2Math.b2MulMV(A, B.col1), b2Math.b2MulMV(A, B.col2));
|
|
return C;
|
|
}
|
|
b2Math.b2MulTMM = function (A, B) {
|
|
var c1 = new b2Vec2(b2Math.b2Dot(A.col1, B.col1), b2Math.b2Dot(A.col2, B.col1));
|
|
var c2 = new b2Vec2(b2Math.b2Dot(A.col1, B.col2), b2Math.b2Dot(A.col2, B.col2));
|
|
var C = new b2Mat22(0, c1, c2);
|
|
return C;
|
|
}
|
|
b2Math.b2Abs = function (a) {
|
|
return a > 0.0 ? a : -a;
|
|
}
|
|
b2Math.b2AbsV = function (a) {
|
|
var b = new b2Vec2(b2Math.b2Abs(a.x), b2Math.b2Abs(a.y));
|
|
return b;
|
|
}
|
|
b2Math.b2AbsM = function (A) {
|
|
var B = new b2Mat22(0, b2Math.b2AbsV(A.col1), b2Math.b2AbsV(A.col2));
|
|
return B;
|
|
}
|
|
b2Math.b2Min = function (a, b) {
|
|
return a < b ? a : b;
|
|
}
|
|
b2Math.b2MinV = function (a, b) {
|
|
var c = new b2Vec2(b2Math.b2Min(a.x, b.x), b2Math.b2Min(a.y, b.y));
|
|
return c;
|
|
}
|
|
b2Math.b2Max = function (a, b) {
|
|
return a > b ? a : b;
|
|
}
|
|
b2Math.b2MaxV = function (a, b) {
|
|
var c = new b2Vec2(b2Math.b2Max(a.x, b.x), b2Math.b2Max(a.y, b.y));
|
|
return c;
|
|
}
|
|
b2Math.b2Clamp = function (a, low, high) {
|
|
return b2Math.b2Max(low, b2Math.b2Min(a, high));
|
|
}
|
|
b2Math.b2ClampV = function (a, low, high) {
|
|
return b2Math.b2MaxV(low, b2Math.b2MinV(a, high));
|
|
}
|
|
b2Math.b2Swap = function (a, b) {
|
|
var tmp = a[0];
|
|
a[0] = b[0];
|
|
b[0] = tmp;
|
|
}
|
|
b2Math.b2Random = function () {
|
|
return Math.random() * 2 - 1;
|
|
}
|
|
b2Math.b2RandomRange = function (lo, hi) {
|
|
var r = Math.random();
|
|
r = (hi - lo) * r + lo;
|
|
return r;
|
|
}
|
|
b2Math.b2NextPowerOfTwo = function (x) {
|
|
x |= (x >> 1) & 0x7FFFFFFF;
|
|
x |= (x >> 2) & 0x3FFFFFFF;
|
|
x |= (x >> 4) & 0x0FFFFFFF;
|
|
x |= (x >> 8) & 0x00FFFFFF;
|
|
x |= (x >> 16)& 0x0000FFFF;
|
|
return x + 1;
|
|
}
|
|
b2Math.b2IsPowerOfTwo = function (x) {
|
|
var result = x > 0 && (x & (x - 1)) == 0;
|
|
return result;
|
|
}
|
|
exports.b2Math = b2Math;
|
|
|
|
|
|
var b2Sweep = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Sweep.prototype.__constructor = function(){}
|
|
b2Sweep.prototype.__varz = function(){
|
|
this.localCenter = new b2Vec2();
|
|
this.c0 = new b2Vec2;
|
|
this.c = new b2Vec2();
|
|
}
|
|
b2Sweep.prototype.localCenter = new b2Vec2();
|
|
b2Sweep.prototype.c0 = new b2Vec2;
|
|
b2Sweep.prototype.c = new b2Vec2();
|
|
b2Sweep.prototype.a0 = null;
|
|
b2Sweep.prototype.a = null;
|
|
b2Sweep.prototype.t0 = null;
|
|
b2Sweep.prototype.GetXForm = function (xf, t) {
|
|
|
|
|
|
if (1.0 - this.t0 > Number.MIN_VALUE)
|
|
{
|
|
var alpha = (t - this.t0) / (1.0 - this.t0);
|
|
xf.position.x = (1.0 - alpha) * this.c0.x + alpha * this.c.x;
|
|
xf.position.y = (1.0 - alpha) * this.c0.y + alpha * this.c.y;
|
|
var angle = (1.0 - alpha) * this.a0 + alpha * this.a;
|
|
xf.R.Set(angle);
|
|
}
|
|
else
|
|
{
|
|
xf.position.SetV(this.c);
|
|
xf.R.Set(this.a);
|
|
}
|
|
|
|
|
|
|
|
var tMat = xf.R;
|
|
xf.position.x -= (tMat.col1.x * this.localCenter.x + tMat.col2.x * this.localCenter.y);
|
|
xf.position.y -= (tMat.col1.y * this.localCenter.x + tMat.col2.y * this.localCenter.y);
|
|
|
|
}
|
|
b2Sweep.prototype.Advance = function (t) {
|
|
if (this.t0 < t && 1.0 - this.t0 > Number.MIN_VALUE)
|
|
{
|
|
var alpha = (t - this.t0) / (1.0 - this.t0);
|
|
|
|
this.c0.x = (1.0 - alpha) * this.c0.x + alpha * this.c.x;
|
|
this.c0.y = (1.0 - alpha) * this.c0.y + alpha * this.c.y;
|
|
this.a0 = (1.0 - alpha) * this.a0 + alpha * this.a;
|
|
this.t0 = t;
|
|
}
|
|
}
|
|
exports.b2Sweep = b2Sweep;
|
|
|
|
|
|
var b2Pair = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Pair.prototype.__constructor = function(){}
|
|
b2Pair.prototype.__varz = function(){
|
|
}
|
|
b2Pair.b2_nullPair = b2Settings.USHRT_MAX;
|
|
b2Pair.b2_nullProxy = b2Settings.USHRT_MAX;
|
|
b2Pair.b2_tableCapacity = b2Settings.b2_maxPairs;
|
|
b2Pair.b2_tableMask = b2Pair.b2_tableCapacity - 1;
|
|
b2Pair.e_pairBuffered = 0x0001;
|
|
b2Pair.e_pairRemoved = 0x0002;
|
|
b2Pair.e_pairFinal = 0x0004;
|
|
b2Pair.prototype.userData = null;
|
|
b2Pair.prototype.proxyId1 = 0;
|
|
b2Pair.prototype.proxyId2 = 0;
|
|
b2Pair.prototype.next = 0;
|
|
b2Pair.prototype.status = 0;
|
|
b2Pair.prototype.SetBuffered = function () { this.status |= b2Pair.e_pairBuffered; }
|
|
b2Pair.prototype.ClearBuffered = function () { this.status &= ~b2Pair.e_pairBuffered; }
|
|
b2Pair.prototype.IsBuffered = function () { return (this.status & b2Pair.e_pairBuffered) == b2Pair.e_pairBuffered; }
|
|
b2Pair.prototype.SetRemoved = function () { this.status |= b2Pair.e_pairRemoved; }
|
|
b2Pair.prototype.ClearRemoved = function () { this.status &= ~b2Pair.e_pairRemoved; }
|
|
b2Pair.prototype.IsRemoved = function () { return (this.status & b2Pair.e_pairRemoved) == b2Pair.e_pairRemoved; }
|
|
b2Pair.prototype.SetFinal = function () { this.status |= b2Pair.e_pairFinal; }
|
|
b2Pair.prototype.IsFinal = function () { return (this.status & b2Pair.e_pairFinal) == b2Pair.e_pairFinal; }
|
|
exports.b2Pair = b2Pair;
|
|
|
|
|
|
var b2PairCallback = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2PairCallback.prototype.__constructor = function(){}
|
|
b2PairCallback.prototype.__varz = function(){
|
|
}
|
|
b2PairCallback.prototype.PairAdded = function (proxyUserData1, proxyUserData2) {return null}
|
|
b2PairCallback.prototype.PairRemoved = function (proxyUserData1, proxyUserData2, pairUserData) {}
|
|
exports.b2PairCallback = b2PairCallback;
|
|
|
|
|
|
var b2PairManager = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2PairManager.prototype.__constructor = function () {
|
|
var i = 0;
|
|
|
|
|
|
this.m_hashTable = new Array(b2Pair.b2_tableCapacity);
|
|
for (i = 0; i < b2Pair.b2_tableCapacity; ++i)
|
|
{
|
|
this.m_hashTable[i] = b2Pair.b2_nullPair;
|
|
}
|
|
this.m_pairs = new Array(b2Settings.b2_maxPairs);
|
|
for (i = 0; i < b2Settings.b2_maxPairs; ++i)
|
|
{
|
|
this.m_pairs[i] = new b2Pair();
|
|
}
|
|
this.m_pairBuffer = new Array(b2Settings.b2_maxPairs);
|
|
for (i = 0; i < b2Settings.b2_maxPairs; ++i)
|
|
{
|
|
this.m_pairBuffer[i] = new b2BufferedPair();
|
|
}
|
|
|
|
for (i = 0; i < b2Settings.b2_maxPairs; ++i)
|
|
{
|
|
this.m_pairs[i].proxyId1 = b2Pair.b2_nullProxy;
|
|
this.m_pairs[i].proxyId2 = b2Pair.b2_nullProxy;
|
|
this.m_pairs[i].userData = null;
|
|
this.m_pairs[i].status = 0;
|
|
this.m_pairs[i].next = (i + 1);
|
|
}
|
|
this.m_pairs[parseInt(b2Settings.b2_maxPairs-1)].next = b2Pair.b2_nullPair;
|
|
this.m_pairCount = 0;
|
|
this.m_pairBufferCount = 0;
|
|
}
|
|
b2PairManager.prototype.__varz = function(){
|
|
}
|
|
b2PairManager.Hash = function (proxyId1, proxyId2) {
|
|
var key = ((proxyId2 << 16) & 0xffff0000) | proxyId1;
|
|
key = ~key + ((key << 15) & 0xFFFF8000);
|
|
key = key ^ ((key >> 12) & 0x000fffff);
|
|
key = key + ((key << 2) & 0xFFFFFFFC);
|
|
key = key ^ ((key >> 4) & 0x0fffffff);
|
|
key = key * 2057;
|
|
key = key ^ ((key >> 16) % 65535);
|
|
return key;
|
|
}
|
|
b2PairManager.Equals = function (pair, proxyId1, proxyId2) {
|
|
return (pair.proxyId1 == proxyId1 && pair.proxyId2 == proxyId2);
|
|
}
|
|
b2PairManager.EqualsPair = function (pair1, pair2) {
|
|
return pair1.proxyId1 == pair2.proxyId1 && pair1.proxyId2 == pair2.proxyId2;
|
|
}
|
|
b2PairManager.prototype.m_broadPhase = null;
|
|
b2PairManager.prototype.m_callback = null;
|
|
b2PairManager.prototype.m_pairs = null;
|
|
b2PairManager.prototype.m_freePair = 0;
|
|
b2PairManager.prototype.m_pairCount = 0;
|
|
b2PairManager.prototype.m_pairBuffer = null;
|
|
b2PairManager.prototype.m_pairBufferCount = 0;
|
|
b2PairManager.prototype.m_hashTable = null;
|
|
b2PairManager.prototype.AddPair = function (proxyId1, proxyId2) {
|
|
|
|
if (proxyId1 > proxyId2){
|
|
var temp = proxyId1;
|
|
proxyId1 = proxyId2;
|
|
proxyId2 = temp;
|
|
|
|
}
|
|
|
|
var hash = b2PairManager.Hash(proxyId1, proxyId2) & b2Pair.b2_tableMask;
|
|
|
|
|
|
var pair = pair = this.FindHash(proxyId1, proxyId2, hash);
|
|
|
|
if (pair != null)
|
|
{
|
|
return pair;
|
|
}
|
|
|
|
|
|
|
|
var pIndex = this.m_freePair;
|
|
pair = this.m_pairs[pIndex];
|
|
this.m_freePair = pair.next;
|
|
|
|
pair.proxyId1 = proxyId1;
|
|
pair.proxyId2 = proxyId2;
|
|
pair.status = 0;
|
|
pair.userData = null;
|
|
pair.next = this.m_hashTable[hash];
|
|
|
|
this.m_hashTable[hash] = pIndex;
|
|
|
|
++this.m_pairCount;
|
|
|
|
return pair;
|
|
}
|
|
b2PairManager.prototype.RemovePair = function (proxyId1, proxyId2) {
|
|
var pair;
|
|
|
|
|
|
|
|
if (proxyId1 > proxyId2){
|
|
var temp = proxyId1;
|
|
proxyId1 = proxyId2;
|
|
proxyId2 = temp;
|
|
|
|
}
|
|
|
|
var hash = b2PairManager.Hash(proxyId1, proxyId2) & b2Pair.b2_tableMask;
|
|
|
|
var node = this.m_hashTable[hash];
|
|
var pNode = null;
|
|
|
|
while (node != b2Pair.b2_nullPair)
|
|
{
|
|
if (b2PairManager.Equals(this.m_pairs[node], proxyId1, proxyId2))
|
|
{
|
|
var index = node;
|
|
|
|
|
|
pair = this.m_pairs[node];
|
|
if (pNode){
|
|
pNode.next = pair.next;
|
|
}
|
|
else{
|
|
this.m_hashTable[hash] = pair.next;
|
|
}
|
|
|
|
pair = this.m_pairs[ index ];
|
|
var userData = pair.userData;
|
|
|
|
|
|
pair.next = this.m_freePair;
|
|
pair.proxyId1 = b2Pair.b2_nullProxy;
|
|
pair.proxyId2 = b2Pair.b2_nullProxy;
|
|
pair.userData = null;
|
|
pair.status = 0;
|
|
|
|
this.m_freePair = index;
|
|
--this.m_pairCount;
|
|
return userData;
|
|
}
|
|
else
|
|
{
|
|
|
|
pNode = this.m_pairs[node];
|
|
node = pNode.next;
|
|
}
|
|
}
|
|
|
|
|
|
return null;
|
|
}
|
|
b2PairManager.prototype.Find = function (proxyId1, proxyId2) {
|
|
|
|
if (proxyId1 > proxyId2){
|
|
var temp = proxyId1;
|
|
proxyId1 = proxyId2;
|
|
proxyId2 = temp;
|
|
|
|
}
|
|
|
|
var hash = b2PairManager.Hash(proxyId1, proxyId2) & b2Pair.b2_tableMask;
|
|
|
|
return this.FindHash(proxyId1, proxyId2, hash);
|
|
}
|
|
b2PairManager.prototype.FindHash = function (proxyId1, proxyId2, hash) {
|
|
var pair;
|
|
var index = this.m_hashTable[hash];
|
|
|
|
pair = this.m_pairs[index];
|
|
while( index != b2Pair.b2_nullPair && b2PairManager.Equals(pair, proxyId1, proxyId2) == false)
|
|
{
|
|
index = pair.next;
|
|
pair = this.m_pairs[index];
|
|
}
|
|
|
|
if ( index == b2Pair.b2_nullPair )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
return pair;
|
|
}
|
|
b2PairManager.prototype.ValidateBuffer = function () {
|
|
|
|
}
|
|
b2PairManager.prototype.ValidateTable = function () {
|
|
|
|
}
|
|
b2PairManager.prototype.Initialize = function (broadPhase, callback) {
|
|
this.m_broadPhase = broadPhase;
|
|
this.m_callback = callback;
|
|
}
|
|
b2PairManager.prototype.AddBufferedPair = function (proxyId1, proxyId2) {
|
|
var bufferedPair;
|
|
|
|
|
|
|
|
var pair = this.AddPair(proxyId1, proxyId2);
|
|
|
|
|
|
if (pair.IsBuffered() == false)
|
|
{
|
|
|
|
|
|
|
|
|
|
pair.SetBuffered();
|
|
bufferedPair = this.m_pairBuffer[this.m_pairBufferCount];
|
|
bufferedPair.proxyId1 = pair.proxyId1;
|
|
bufferedPair.proxyId2 = pair.proxyId2;
|
|
++this.m_pairBufferCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
pair.ClearRemoved();
|
|
|
|
if (b2BroadPhase.s_validate)
|
|
{
|
|
this.ValidateBuffer();
|
|
}
|
|
}
|
|
b2PairManager.prototype.RemoveBufferedPair = function (proxyId1, proxyId2) {
|
|
var bufferedPair;
|
|
|
|
|
|
|
|
|
|
var pair = this.Find(proxyId1, proxyId2);
|
|
|
|
if (pair == null)
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
if (pair.IsBuffered() == false)
|
|
{
|
|
|
|
|
|
|
|
pair.SetBuffered();
|
|
bufferedPair = this.m_pairBuffer[this.m_pairBufferCount];
|
|
bufferedPair.proxyId1 = pair.proxyId1;
|
|
bufferedPair.proxyId2 = pair.proxyId2;
|
|
++this.m_pairBufferCount;
|
|
|
|
|
|
}
|
|
|
|
pair.SetRemoved();
|
|
|
|
if (b2BroadPhase.s_validate)
|
|
{
|
|
this.ValidateBuffer();
|
|
}
|
|
}
|
|
b2PairManager.prototype.Commit = function () {
|
|
var bufferedPair;
|
|
var i = 0;
|
|
|
|
var removeCount = 0;
|
|
|
|
var proxies = this.m_broadPhase.m_proxyPool;
|
|
|
|
for (i = 0; i < this.m_pairBufferCount; ++i)
|
|
{
|
|
bufferedPair = this.m_pairBuffer[i];
|
|
var pair = this.Find(bufferedPair.proxyId1, bufferedPair.proxyId2);
|
|
|
|
pair.ClearBuffered();
|
|
|
|
|
|
|
|
var proxy1 = proxies[ pair.proxyId1 ];
|
|
var proxy2 = proxies[ pair.proxyId2 ];
|
|
|
|
|
|
|
|
|
|
if (pair.IsRemoved())
|
|
{
|
|
|
|
|
|
|
|
if (pair.IsFinal() == true)
|
|
{
|
|
this.m_callback.PairRemoved(proxy1.userData, proxy2.userData, pair.userData);
|
|
}
|
|
|
|
|
|
bufferedPair = this.m_pairBuffer[removeCount];
|
|
bufferedPair.proxyId1 = pair.proxyId1;
|
|
bufferedPair.proxyId2 = pair.proxyId2;
|
|
++removeCount;
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
if (pair.IsFinal() == false)
|
|
{
|
|
pair.userData = this.m_callback.PairAdded(proxy1.userData, proxy2.userData);
|
|
pair.SetFinal();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < removeCount; ++i)
|
|
{
|
|
bufferedPair = this.m_pairBuffer[i]
|
|
this.RemovePair(bufferedPair.proxyId1, bufferedPair.proxyId2);
|
|
}
|
|
|
|
this.m_pairBufferCount = 0;
|
|
|
|
if (b2BroadPhase.s_validate)
|
|
{
|
|
this.ValidateTable();
|
|
}
|
|
}
|
|
exports.b2PairManager = b2PairManager;
|
|
|
|
|
|
var b2BufferedPair = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2BufferedPair.prototype.__constructor = function(){}
|
|
b2BufferedPair.prototype.__varz = function(){
|
|
}
|
|
b2BufferedPair.prototype.proxyId1 = 0;
|
|
b2BufferedPair.prototype.proxyId2 = 0;
|
|
exports.b2BufferedPair = b2BufferedPair;
|
|
|
|
|
|
var b2AABB = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2AABB.prototype.__constructor = function(){}
|
|
b2AABB.prototype.__varz = function(){
|
|
this.lowerBound = new b2Vec2();
|
|
this.upperBound = new b2Vec2();
|
|
}
|
|
b2AABB.prototype.lowerBound = new b2Vec2();
|
|
b2AABB.prototype.upperBound = new b2Vec2();
|
|
b2AABB.prototype.IsValid = function () {
|
|
|
|
var dX = this.upperBound.x - this.lowerBound.x;
|
|
var dY = this.upperBound.y - this.lowerBound.y;
|
|
var valid = dX >= 0.0 && dY >= 0.0;
|
|
valid = valid && this.lowerBound.IsValid() && this.upperBound.IsValid();
|
|
return valid;
|
|
}
|
|
exports.b2AABB = b2AABB;
|
|
|
|
|
|
var b2Manifold = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Manifold.prototype.__constructor = function () {
|
|
this.points = new Array(b2Settings.b2_maxManifoldPoints);
|
|
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++){
|
|
this.points[i] = new b2ManifoldPoint();
|
|
}
|
|
this.normal = new b2Vec2();
|
|
}
|
|
b2Manifold.prototype.__varz = function(){
|
|
}
|
|
b2Manifold.prototype.points = null;
|
|
b2Manifold.prototype.normal = null;
|
|
b2Manifold.prototype.pointCount = 0;
|
|
b2Manifold.prototype.Reset = function () {
|
|
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++){
|
|
(this.points[i]).Reset();
|
|
}
|
|
this.normal.SetZero();
|
|
this.pointCount = 0;
|
|
}
|
|
b2Manifold.prototype.Set = function (m) {
|
|
this.pointCount = m.pointCount;
|
|
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++){
|
|
(this.points[i]).Set(m.points[i]);
|
|
}
|
|
this.normal.SetV(m.normal);
|
|
}
|
|
exports.b2Manifold = b2Manifold;
|
|
|
|
|
|
var Features = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
Features.prototype = {
|
|
get referenceEdge() {
|
|
return this._referenceEdge;
|
|
},
|
|
set referenceEdge(value) {
|
|
this._referenceEdge = value;
|
|
this._m_id._key = (this._m_id._key & 0xffffff00) | (this._referenceEdge & 0x000000ff);
|
|
},
|
|
get incidentEdge() {
|
|
return this._incidentEdge;
|
|
},
|
|
set incidentEdge(value) {
|
|
this._incidentEdge = value;
|
|
this._m_id._key = (this._m_id._key & 0xffff00ff) | ((this._incidentEdge << 8) & 0x0000ff00);
|
|
},
|
|
set incidentVertex(value) {
|
|
this._incidentVertex = value;
|
|
this._m_id._key = (this._m_id._key & 0xff00ffff) | ((this._incidentVertex << 16) & 0x00ff0000);
|
|
},
|
|
get incidentVertex() {
|
|
return this._incidentVertex;
|
|
},
|
|
set flip(value) {
|
|
this._flip = value;
|
|
this._m_id._key = (this._m_id._key & 0x00ffffff) | ((this._flip << 24) & 0xff000000);
|
|
},
|
|
get flip() {
|
|
return this._flip;
|
|
}
|
|
}
|
|
Features.prototype.__constructor = function(){}
|
|
Features.prototype.__varz = function(){
|
|
}
|
|
Features.prototype._referenceEdge = 0;
|
|
Features.prototype._incidentEdge = 0;
|
|
Features.prototype._incidentVertex = 0;
|
|
Features.prototype._flip = 0;
|
|
Features.prototype._m_id = null;
|
|
exports.Features = Features;
|
|
|
|
|
|
var b2ContactID = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactID.prototype = {
|
|
get key() {
|
|
return this._key;
|
|
},
|
|
set key(value) {
|
|
this._key = value;
|
|
this.features._referenceEdge = this._key & 0x000000ff;
|
|
this.features._incidentEdge = ((this._key & 0x0000ff00) >> 8) & 0x000000ff;
|
|
this.features._incidentVertex = ((this._key & 0x00ff0000) >> 16) & 0x000000ff;
|
|
this.features._flip = ((this._key & 0xff000000) >> 24) & 0x000000ff;
|
|
}
|
|
}
|
|
b2ContactID.prototype.__constructor = function () {
|
|
this.features._m_id = this;
|
|
}
|
|
b2ContactID.prototype.__varz = function(){
|
|
this.features = new Features();
|
|
}
|
|
b2ContactID.prototype.features = new Features();
|
|
b2ContactID.prototype._key = 0;
|
|
b2ContactID.prototype.Set = function (id) {
|
|
this.key = id._key;
|
|
}
|
|
b2ContactID.prototype.Copy = function () {
|
|
var id = new b2ContactID();
|
|
id.key = this._key;
|
|
return id;
|
|
}
|
|
exports.b2ContactID = b2ContactID;
|
|
|
|
|
|
var b2ManifoldPoint = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ManifoldPoint.prototype.__constructor = function(){}
|
|
b2ManifoldPoint.prototype.__varz = function(){
|
|
this.localPoint1 = new b2Vec2();
|
|
this.localPoint2 = new b2Vec2();
|
|
this.id = new b2ContactID();
|
|
}
|
|
b2ManifoldPoint.prototype.localPoint1 = new b2Vec2();
|
|
b2ManifoldPoint.prototype.localPoint2 = new b2Vec2();
|
|
b2ManifoldPoint.prototype.separation = null;
|
|
b2ManifoldPoint.prototype.normalImpulse = null;
|
|
b2ManifoldPoint.prototype.tangentImpulse = null;
|
|
b2ManifoldPoint.prototype.id = new b2ContactID();
|
|
b2ManifoldPoint.prototype.Reset = function () {
|
|
this.localPoint1.SetZero();
|
|
this.localPoint2.SetZero();
|
|
this.separation = 0.0;
|
|
this.normalImpulse = 0.0;
|
|
this.tangentImpulse = 0.0;
|
|
this.id.key = 0;
|
|
}
|
|
b2ManifoldPoint.prototype.Set = function (m) {
|
|
this.localPoint1.SetV(m.localPoint1);
|
|
this.localPoint2.SetV(m.localPoint2);
|
|
this.separation = m.separation;
|
|
this.normalImpulse = m.normalImpulse;
|
|
this.tangentImpulse = m.tangentImpulse;
|
|
this.id.key = m.id.key;
|
|
}
|
|
exports.b2ManifoldPoint = b2ManifoldPoint;
|
|
|
|
|
|
var b2Point = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Point.prototype.__constructor = function(){}
|
|
b2Point.prototype.__varz = function(){
|
|
this.p = new b2Vec2();
|
|
}
|
|
b2Point.prototype.p = new b2Vec2();
|
|
b2Point.prototype.Support = function (xf, vX, vY) {
|
|
return this.p;
|
|
}
|
|
b2Point.prototype.GetFirstVertex = function (xf) {
|
|
return this.p;
|
|
}
|
|
exports.b2Point = b2Point;
|
|
|
|
|
|
var b2Bound = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Bound.prototype.__constructor = function(){}
|
|
b2Bound.prototype.__varz = function(){
|
|
}
|
|
b2Bound.prototype.value = 0;
|
|
b2Bound.prototype.proxyId = 0;
|
|
b2Bound.prototype.stabbingCount = 0;
|
|
b2Bound.prototype.IsLower = function () { return (this.value & 1) == 0; }
|
|
b2Bound.prototype.IsUpper = function () { return (this.value & 1) == 1; }
|
|
b2Bound.prototype.Swap = function (b) {
|
|
var tempValue = this.value;
|
|
var tempProxyId = this.proxyId;
|
|
var tempStabbingCount = this.stabbingCount;
|
|
|
|
this.value = b.value;
|
|
this.proxyId = b.proxyId;
|
|
this.stabbingCount = b.stabbingCount;
|
|
|
|
b.value = tempValue;
|
|
b.proxyId = tempProxyId;
|
|
b.stabbingCount = tempStabbingCount;
|
|
}
|
|
exports.b2Bound = b2Bound;
|
|
|
|
|
|
var b2BoundValues = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2BoundValues.prototype.__constructor = function(){}
|
|
b2BoundValues.prototype.__varz = function(){
|
|
this.lowerValues = [0,0];
|
|
this.upperValues = [0,0];
|
|
}
|
|
b2BoundValues.prototype.lowerValues = [0,0];
|
|
b2BoundValues.prototype.upperValues = [0,0];
|
|
exports.b2BoundValues = b2BoundValues;
|
|
|
|
|
|
var b2Collision = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Collision.prototype.__constructor = function(){}
|
|
b2Collision.prototype.__varz = function(){
|
|
}
|
|
b2Collision.b2_nullFeature = 0x000000ff;
|
|
b2Collision.b2CollidePolyTempVec = new b2Vec2();
|
|
b2Collision.ClipSegmentToLine = function (vOut, vIn, normal, offset) {
|
|
var cv;
|
|
|
|
|
|
var numOut = 0;
|
|
|
|
cv = vIn[0];
|
|
var vIn0 = cv.v;
|
|
cv = vIn[1];
|
|
var vIn1 = cv.v;
|
|
|
|
|
|
var distance0 = b2Math.b2Dot(normal, vIn0) - offset;
|
|
var distance1 = b2Math.b2Dot(normal, vIn1) - offset;
|
|
|
|
|
|
if (distance0 <= 0.0) vOut[numOut++] = vIn[0];
|
|
if (distance1 <= 0.0) vOut[numOut++] = vIn[1];
|
|
|
|
|
|
if (distance0 * distance1 < 0.0)
|
|
{
|
|
|
|
var interp = distance0 / (distance0 - distance1);
|
|
|
|
|
|
cv = vOut[numOut];
|
|
var tVec = cv.v;
|
|
tVec.x = vIn0.x + interp * (vIn1.x - vIn0.x);
|
|
tVec.y = vIn0.y + interp * (vIn1.y - vIn0.y);
|
|
cv = vOut[numOut];
|
|
var cv2;
|
|
if (distance0 > 0.0)
|
|
{
|
|
cv2 = vIn[0];
|
|
cv.id = cv2.id;
|
|
}
|
|
else
|
|
{
|
|
cv2 = vIn[1];
|
|
cv.id = cv2.id;
|
|
}
|
|
++numOut;
|
|
}
|
|
|
|
return numOut;
|
|
}
|
|
b2Collision.EdgeSeparation = function ( poly1, xf1, edge1,
|
|
poly2, xf2) {
|
|
var count1 = poly1.m_vertexCount;
|
|
var vertices1 = poly1.m_vertices;
|
|
var normals1 = poly1.m_normals;
|
|
|
|
var count2 = poly2.m_vertexCount;
|
|
var vertices2 = poly2.m_vertices;
|
|
|
|
|
|
|
|
var tMat;
|
|
var tVec;
|
|
|
|
|
|
|
|
tMat = xf1.R;
|
|
tVec = normals1[edge1];
|
|
var normal1WorldX = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var normal1WorldY = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tMat = xf2.R;
|
|
var normal1X = (tMat.col1.x * normal1WorldX + tMat.col1.y * normal1WorldY);
|
|
var normal1Y = (tMat.col2.x * normal1WorldX + tMat.col2.y * normal1WorldY);
|
|
|
|
|
|
var index = 0;
|
|
var minDot = Number.MAX_VALUE;
|
|
for (var i = 0; i < count2; ++i)
|
|
{
|
|
|
|
tVec = vertices2[i];
|
|
var dot = tVec.x * normal1X + tVec.y * normal1Y;
|
|
if (dot < minDot)
|
|
{
|
|
minDot = dot;
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
|
|
tVec = vertices1[edge1];
|
|
tMat = xf1.R;
|
|
var v1X = xf1.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var v1Y = xf1.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tVec = vertices2[index];
|
|
tMat = xf2.R;
|
|
var v2X = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var v2Y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
|
|
v2X -= v1X;
|
|
v2Y -= v1Y;
|
|
|
|
var separation = v2X * normal1WorldX + v2Y * normal1WorldY;
|
|
return separation;
|
|
}
|
|
b2Collision.FindMaxSeparation = function (edgeIndex ,
|
|
poly1, xf1,
|
|
poly2, xf2) {
|
|
var count1 = poly1.m_vertexCount;
|
|
var normals1 = poly1.m_normals;
|
|
|
|
var tVec;
|
|
var tMat;
|
|
|
|
|
|
|
|
tMat = xf2.R;
|
|
tVec = poly2.m_centroid;
|
|
var dX = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var dY = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
tMat = xf1.R;
|
|
tVec = poly1.m_centroid;
|
|
dX -= xf1.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
dY -= xf1.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
|
|
var dLocal1X = (dX * xf1.R.col1.x + dY * xf1.R.col1.y);
|
|
var dLocal1Y = (dX * xf1.R.col2.x + dY * xf1.R.col2.y);
|
|
|
|
|
|
var edge = 0;
|
|
var maxDot = -Number.MAX_VALUE;
|
|
for (var i = 0; i < count1; ++i)
|
|
{
|
|
|
|
tVec = normals1[i];
|
|
var dot = (tVec.x * dLocal1X + tVec.y * dLocal1Y);
|
|
if (dot > maxDot)
|
|
{
|
|
maxDot = dot;
|
|
edge = i;
|
|
}
|
|
}
|
|
|
|
|
|
var s = b2Collision.EdgeSeparation(poly1, xf1, edge, poly2, xf2);
|
|
if (s > 0.0)
|
|
{
|
|
return s;
|
|
}
|
|
|
|
|
|
var prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
|
|
var sPrev = b2Collision.EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
|
|
if (sPrev > 0.0)
|
|
{
|
|
return sPrev;
|
|
}
|
|
|
|
|
|
var nextEdge = edge + 1 < count1 ? edge + 1 : 0;
|
|
var sNext = b2Collision.EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
|
|
if (sNext > 0.0)
|
|
{
|
|
return sNext;
|
|
}
|
|
|
|
|
|
var bestEdge = 0;
|
|
var bestSeparation;
|
|
var increment = 0;
|
|
if (sPrev > s && sPrev > sNext)
|
|
{
|
|
increment = -1;
|
|
bestEdge = prevEdge;
|
|
bestSeparation = sPrev;
|
|
}
|
|
else if (sNext > s)
|
|
{
|
|
increment = 1;
|
|
bestEdge = nextEdge;
|
|
bestSeparation = sNext;
|
|
}
|
|
else
|
|
{
|
|
|
|
edgeIndex[0] = edge;
|
|
return s;
|
|
}
|
|
|
|
|
|
while (true)
|
|
{
|
|
|
|
if (increment == -1)
|
|
edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
|
|
else
|
|
edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
|
|
|
|
s = b2Collision.EdgeSeparation(poly1, xf1, edge, poly2, xf2);
|
|
if (s > 0.0)
|
|
{
|
|
return s;
|
|
}
|
|
|
|
if (s > bestSeparation)
|
|
{
|
|
bestEdge = edge;
|
|
bestSeparation = s;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
edgeIndex[0] = bestEdge;
|
|
return bestSeparation;
|
|
}
|
|
b2Collision.FindIncidentEdge = function (c,
|
|
poly1, xf1, edge1,
|
|
poly2, xf2) {
|
|
var count1 = poly1.m_vertexCount;
|
|
var normals1 = poly1.m_normals;
|
|
|
|
var count2 = poly2.m_vertexCount;
|
|
var vertices2 = poly2.m_vertices;
|
|
var normals2 = poly2.m_normals;
|
|
|
|
|
|
|
|
var tMat;
|
|
var tVec;
|
|
|
|
|
|
|
|
tMat = xf1.R;
|
|
tVec = normals1[edge1];
|
|
var normal1X = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var normal1Y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
tMat = xf2.R;
|
|
var tX = (tMat.col1.x * normal1X + tMat.col1.y * normal1Y);
|
|
normal1Y = (tMat.col2.x * normal1X + tMat.col2.y * normal1Y);
|
|
normal1X = tX;
|
|
|
|
|
|
var index = 0;
|
|
var minDot = Number.MAX_VALUE;
|
|
for (var i = 0; i < count2; ++i)
|
|
{
|
|
|
|
tVec = normals2[i];
|
|
var dot = (normal1X * tVec.x + normal1Y * tVec.y);
|
|
if (dot < minDot)
|
|
{
|
|
minDot = dot;
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
var tClip;
|
|
|
|
var i1 = index;
|
|
var i2 = i1 + 1 < count2 ? i1 + 1 : 0;
|
|
|
|
tClip = c[0];
|
|
|
|
tVec = vertices2[i1];
|
|
tMat = xf2.R;
|
|
tClip.v.x = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
tClip.v.y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tClip.id.features.referenceEdge = edge1;
|
|
tClip.id.features.incidentEdge = i1;
|
|
tClip.id.features.incidentVertex = 0;
|
|
|
|
tClip = c[1];
|
|
|
|
tVec = vertices2[i2];
|
|
tMat = xf2.R;
|
|
tClip.v.x = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
tClip.v.y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tClip.id.features.referenceEdge = edge1;
|
|
tClip.id.features.incidentEdge = i2;
|
|
tClip.id.features.incidentVertex = 1;
|
|
}
|
|
b2Collision.b2CollidePolygons = function (manifold,
|
|
polyA, xfA,
|
|
polyB, xfB) {
|
|
var cv;
|
|
|
|
manifold.pointCount = 0;
|
|
|
|
var edgeA = 0;
|
|
var edgeAO = [edgeA];
|
|
var separationA = b2Collision.FindMaxSeparation(edgeAO, polyA, xfA, polyB, xfB);
|
|
edgeA = edgeAO[0];
|
|
if (separationA > 0.0)
|
|
return;
|
|
|
|
var edgeB = 0;
|
|
var edgeBO = [edgeB];
|
|
var separationB = b2Collision.FindMaxSeparation(edgeBO, polyB, xfB, polyA, xfA);
|
|
edgeB = edgeBO[0];
|
|
if (separationB > 0.0)
|
|
return;
|
|
|
|
var poly1;
|
|
var poly2;
|
|
var xf1 = new b2XForm();
|
|
var xf2 = new b2XForm();
|
|
var edge1 = 0;
|
|
var flip = 0;
|
|
var k_relativeTol = 0.98;
|
|
var k_absoluteTol = 0.001;
|
|
|
|
|
|
if (separationB > k_relativeTol * separationA + k_absoluteTol)
|
|
{
|
|
poly1 = polyB;
|
|
poly2 = polyA;
|
|
xf1.Set(xfB);
|
|
xf2.Set(xfA);
|
|
edge1 = edgeB;
|
|
flip = 1;
|
|
}
|
|
else
|
|
{
|
|
poly1 = polyA;
|
|
poly2 = polyB;
|
|
xf1.Set(xfA);
|
|
xf2.Set(xfB);
|
|
edge1 = edgeA;
|
|
flip = 0;
|
|
}
|
|
|
|
var incidentEdge = [new ClipVertex(), new ClipVertex()];
|
|
b2Collision.FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
|
|
|
|
var count1 = poly1.m_vertexCount;
|
|
var vertices1 = poly1.m_vertices;
|
|
|
|
var tVec = vertices1[edge1];
|
|
var v11 = tVec.Copy();
|
|
if (edge1 + 1 < count1) {
|
|
tVec = vertices1[parseInt(edge1+1)];
|
|
var v12 = tVec.Copy();
|
|
} else {
|
|
tVec = vertices1[0];
|
|
v12 = tVec.Copy();
|
|
}
|
|
|
|
var dv = b2Math.SubtractVV(v12 , v11);
|
|
var sideNormal = b2Math.b2MulMV(xf1.R, b2Math.SubtractVV(v12 , v11));
|
|
sideNormal.Normalize();
|
|
var frontNormal = b2Math.b2CrossVF(sideNormal, 1.0);
|
|
|
|
v11 = b2Math.b2MulX(xf1, v11);
|
|
v12 = b2Math.b2MulX(xf1, v12);
|
|
|
|
var frontOffset = b2Math.b2Dot(frontNormal, v11);
|
|
var sideOffset1 = -b2Math.b2Dot(sideNormal, v11);
|
|
var sideOffset2 = b2Math.b2Dot(sideNormal, v12);
|
|
|
|
|
|
var clipPoints1 = [new ClipVertex(), new ClipVertex()];
|
|
var clipPoints2 = [new ClipVertex(), new ClipVertex()];
|
|
var np = 0;
|
|
|
|
|
|
|
|
np = b2Collision.ClipSegmentToLine(clipPoints1, incidentEdge, sideNormal.Negative(), sideOffset1);
|
|
|
|
if (np < 2)
|
|
return;
|
|
|
|
|
|
np = b2Collision.ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
|
|
|
|
if (np < 2)
|
|
return;
|
|
|
|
|
|
manifold.normal = flip ? frontNormal.Negative() : frontNormal.Copy();
|
|
|
|
var pointCount = 0;
|
|
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; ++i)
|
|
{
|
|
cv = clipPoints2[i];
|
|
var separation = b2Math.b2Dot(frontNormal, cv.v) - frontOffset;
|
|
|
|
if (separation <= 0.0)
|
|
{
|
|
var cp = manifold.points[ pointCount ];
|
|
cp.separation = separation;
|
|
cp.localPoint1 = b2Math.b2MulXT(xfA, cv.v);
|
|
cp.localPoint2 = b2Math.b2MulXT(xfB, cv.v);
|
|
cp.id.key = cv.id._key;
|
|
cp.id.features.flip = flip;
|
|
++pointCount;
|
|
}
|
|
}
|
|
|
|
manifold.pointCount = pointCount;
|
|
}
|
|
b2Collision.b2CollideCircles = function (
|
|
manifold,
|
|
circle1, xf1,
|
|
circle2, xf2) {
|
|
manifold.pointCount = 0;
|
|
|
|
var tMat;
|
|
var tVec;
|
|
|
|
|
|
tMat = xf1.R; tVec = circle1.m_localPosition;
|
|
var p1X = xf1.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var p1Y = xf1.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tMat = xf2.R; tVec = circle2.m_localPosition;
|
|
var p2X = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var p2Y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
var dX = p2X - p1X;
|
|
var dY = p2Y - p1Y;
|
|
|
|
var distSqr = dX * dX + dY * dY;
|
|
var r1 = circle1.m_radius;
|
|
var r2 = circle2.m_radius;
|
|
var radiusSum = r1 + r2;
|
|
if (distSqr > radiusSum * radiusSum)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var separation;
|
|
if (distSqr < Number.MIN_VALUE)
|
|
{
|
|
separation = -radiusSum;
|
|
manifold.normal.Set(0.0, 1.0);
|
|
}
|
|
else
|
|
{
|
|
var dist = Math.sqrt(distSqr);
|
|
separation = dist - radiusSum;
|
|
var a = 1.0 / dist;
|
|
manifold.normal.x = a * dX;
|
|
manifold.normal.y = a * dY;
|
|
}
|
|
|
|
manifold.pointCount = 1;
|
|
var tPoint = manifold.points[0];
|
|
tPoint.id.key = 0;
|
|
tPoint.separation = separation;
|
|
|
|
p1X += r1 * manifold.normal.x;
|
|
p1Y += r1 * manifold.normal.y;
|
|
p2X -= r2 * manifold.normal.x;
|
|
p2Y -= r2 * manifold.normal.y;
|
|
|
|
|
|
var pX = 0.5 * (p1X + p2X);
|
|
var pY = 0.5 * (p1Y + p2Y);
|
|
|
|
|
|
var tX = pX - xf1.position.x;
|
|
var tY = pY - xf1.position.y;
|
|
tPoint.localPoint1.x = (tX * xf1.R.col1.x + tY * xf1.R.col1.y );
|
|
tPoint.localPoint1.y = (tX * xf1.R.col2.x + tY * xf1.R.col2.y );
|
|
|
|
tX = pX - xf2.position.x;
|
|
tY = pY - xf2.position.y;
|
|
tPoint.localPoint2.x = (tX * xf2.R.col1.x + tY * xf2.R.col1.y );
|
|
tPoint.localPoint2.y = (tX * xf2.R.col2.x + tY * xf2.R.col2.y );
|
|
}
|
|
b2Collision.b2CollidePolygonAndCircle = function (
|
|
manifold,
|
|
polygon, xf1,
|
|
circle, xf2) {
|
|
manifold.pointCount = 0;
|
|
var tPoint;
|
|
|
|
var dX;
|
|
var dY;
|
|
var positionX;
|
|
var positionY;
|
|
|
|
var tVec;
|
|
var tMat;
|
|
|
|
|
|
|
|
tMat = xf2.R;
|
|
tVec = circle.m_localPosition;
|
|
var cX = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var cY = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
|
|
dX = cX - xf1.position.x;
|
|
dY = cY - xf1.position.y;
|
|
tMat = xf1.R;
|
|
var cLocalX = (dX * tMat.col1.x + dY * tMat.col1.y);
|
|
var cLocalY = (dX * tMat.col2.x + dY * tMat.col2.y);
|
|
|
|
var dist;
|
|
|
|
|
|
var normalIndex = 0;
|
|
var separation = -Number.MAX_VALUE;
|
|
var radius = circle.m_radius;
|
|
var vertexCount = polygon.m_vertexCount;
|
|
var vertices = polygon.m_vertices;
|
|
var normals = polygon.m_normals;
|
|
|
|
for (var i = 0; i < vertexCount; ++i)
|
|
{
|
|
|
|
tVec = vertices[i];
|
|
dX = cLocalX-tVec.x;
|
|
dY = cLocalY-tVec.y;
|
|
tVec = normals[i];
|
|
var s = tVec.x * dX + tVec.y * dY;
|
|
|
|
if (s > radius)
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
if (s > separation)
|
|
{
|
|
separation = s;
|
|
normalIndex = i;
|
|
}
|
|
}
|
|
|
|
|
|
if (separation < Number.MIN_VALUE)
|
|
{
|
|
manifold.pointCount = 1;
|
|
|
|
tVec = normals[normalIndex];
|
|
tMat = xf1.R;
|
|
manifold.normal.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
manifold.normal.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tPoint = manifold.points[0];
|
|
tPoint.id.features.incidentEdge = normalIndex;
|
|
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
|
|
tPoint.id.features.referenceEdge = 0;
|
|
tPoint.id.features.flip = 0;
|
|
|
|
positionX = cX - radius * manifold.normal.x;
|
|
positionY = cY - radius * manifold.normal.y;
|
|
|
|
dX = positionX - xf1.position.x;
|
|
dY = positionY - xf1.position.y;
|
|
tMat = xf1.R;
|
|
tPoint.localPoint1.x = (dX*tMat.col1.x + dY*tMat.col1.y);
|
|
tPoint.localPoint1.y = (dX*tMat.col2.x + dY*tMat.col2.y);
|
|
|
|
dX = positionX - xf2.position.x;
|
|
dY = positionY - xf2.position.y;
|
|
tMat = xf2.R;
|
|
tPoint.localPoint2.x = (dX*tMat.col1.x + dY*tMat.col1.y);
|
|
tPoint.localPoint2.y = (dX*tMat.col2.x + dY*tMat.col2.y);
|
|
|
|
tPoint.separation = separation - radius;
|
|
return;
|
|
}
|
|
|
|
|
|
var vertIndex1 = normalIndex;
|
|
var vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
|
|
tVec = vertices[vertIndex1];
|
|
var tVec2 = vertices[vertIndex2];
|
|
|
|
var eX = tVec2.x - tVec.x;
|
|
var eY = tVec2.y - tVec.y;
|
|
|
|
|
|
var length = Math.sqrt(eX*eX + eY*eY);
|
|
eX /= length;
|
|
eY /= length;
|
|
|
|
|
|
|
|
|
|
dX = cLocalX - tVec.x;
|
|
dY = cLocalY - tVec.y;
|
|
var u = dX*eX + dY*eY;
|
|
|
|
tPoint = manifold.points[0];
|
|
|
|
var pX, pY;
|
|
if (u <= 0.0)
|
|
{
|
|
pX = tVec.x;
|
|
pY = tVec.y;
|
|
tPoint.id.features.incidentEdge = b2Collision.b2_nullFeature;
|
|
tPoint.id.features.incidentVertex = vertIndex1;
|
|
}
|
|
else if (u >= length)
|
|
{
|
|
pX = tVec2.x;
|
|
pY = tVec2.y;
|
|
tPoint.id.features.incidentEdge = b2Collision.b2_nullFeature;
|
|
tPoint.id.features.incidentVertex = vertIndex2;
|
|
}
|
|
else
|
|
{
|
|
|
|
pX = eX * u + tVec.x;
|
|
pY = eY * u + tVec.y;
|
|
tPoint.id.features.incidentEdge = normalIndex;
|
|
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
|
|
}
|
|
|
|
|
|
dX = cLocalX - pX;
|
|
dY = cLocalY - pY;
|
|
|
|
dist = Math.sqrt(dX*dX + dY*dY);
|
|
dX /= dist;
|
|
dY /= dist;
|
|
if (dist > radius)
|
|
{
|
|
return;
|
|
}
|
|
|
|
manifold.pointCount = 1;
|
|
|
|
tMat = xf1.R;
|
|
manifold.normal.x = tMat.col1.x * dX + tMat.col2.x * dY;
|
|
manifold.normal.y = tMat.col1.y * dX + tMat.col2.y * dY;
|
|
|
|
positionX = cX - radius * manifold.normal.x;
|
|
positionY = cY - radius * manifold.normal.y;
|
|
|
|
dX = positionX - xf1.position.x;
|
|
dY = positionY - xf1.position.y;
|
|
tMat = xf1.R;
|
|
tPoint.localPoint1.x = (dX*tMat.col1.x + dY*tMat.col1.y);
|
|
tPoint.localPoint1.y = (dX*tMat.col2.x + dY*tMat.col2.y);
|
|
|
|
dX = positionX - xf2.position.x;
|
|
dY = positionY - xf2.position.y;
|
|
tMat = xf2.R;
|
|
tPoint.localPoint2.x = (dX*tMat.col1.x + dY*tMat.col1.y);
|
|
tPoint.localPoint2.y = (dX*tMat.col2.x + dY*tMat.col2.y);
|
|
tPoint.separation = dist - radius;
|
|
tPoint.id.features.referenceEdge = 0;
|
|
tPoint.id.features.flip = 0;
|
|
}
|
|
b2Collision.b2TestOverlap = function (a, b) {
|
|
var t1 = b.lowerBound;
|
|
var t2 = a.upperBound;
|
|
|
|
var d1X = t1.x - t2.x;
|
|
var d1Y = t1.y - t2.y;
|
|
|
|
t1 = a.lowerBound;
|
|
t2 = b.upperBound;
|
|
var d2X = t1.x - t2.x;
|
|
var d2Y = t1.y - t2.y;
|
|
|
|
if (d1X > 0.0 || d1Y > 0.0)
|
|
return false;
|
|
|
|
if (d2X > 0.0 || d2Y > 0.0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
exports.b2Collision = b2Collision;
|
|
|
|
|
|
var b2Proxy = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Proxy.prototype.__constructor = function(){}
|
|
b2Proxy.prototype.__varz = function(){
|
|
this.lowerBounds = [parseInt(0), parseInt(0)];
|
|
this.upperBounds = [parseInt(0), parseInt(0)];
|
|
}
|
|
b2Proxy.prototype.lowerBounds = [parseInt(0), parseInt(0)];
|
|
b2Proxy.prototype.upperBounds = [parseInt(0), parseInt(0)];
|
|
b2Proxy.prototype.overlapCount = 0;
|
|
b2Proxy.prototype.timeStamp = 0;
|
|
b2Proxy.prototype.userData = null;
|
|
b2Proxy.prototype.GetNext = function () { return this.lowerBounds[0]; }
|
|
b2Proxy.prototype.SetNext = function (next) { this.lowerBounds[0] = next % 65535; }
|
|
b2Proxy.prototype.IsValid = function () { return this.overlapCount != b2BroadPhase.b2_invalid; }
|
|
exports.b2Proxy = b2Proxy;
|
|
|
|
|
|
var b2Segment = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Segment.prototype.__constructor = function(){}
|
|
b2Segment.prototype.__varz = function(){
|
|
this.p1 = new b2Vec2();
|
|
this.p2 = new b2Vec2();
|
|
}
|
|
b2Segment.prototype.p1 = new b2Vec2();
|
|
b2Segment.prototype.p2 = new b2Vec2();
|
|
b2Segment.prototype.TestSegment = function (lambda,
|
|
normal,
|
|
segment,
|
|
maxLambda) {
|
|
|
|
var s = segment.p1;
|
|
|
|
var rX = segment.p2.x - s.x;
|
|
var rY = segment.p2.y - s.y;
|
|
|
|
var dX = this.p2.x - this.p1.x;
|
|
var dY = this.p2.y - this.p1.y;
|
|
|
|
var nX = dY;
|
|
var nY = -dX;
|
|
|
|
var k_slop = 100.0 * Number.MIN_VALUE;
|
|
|
|
var denom = -(rX*nX + rY*nY);
|
|
|
|
|
|
if (denom > k_slop)
|
|
{
|
|
|
|
|
|
var bX = s.x - this.p1.x;
|
|
var bY = s.y - this.p1.y;
|
|
|
|
var a = (bX*nX + bY*nY);
|
|
|
|
if (0.0 <= a && a <= maxLambda * denom)
|
|
{
|
|
var mu2 = -rX * bY + rY * bX;
|
|
|
|
|
|
if (-k_slop * denom <= mu2 && mu2 <= denom * (1.0 + k_slop))
|
|
{
|
|
a /= denom;
|
|
|
|
var nLen = Math.sqrt(nX*nX + nY*nY);
|
|
nX /= nLen;
|
|
nY /= nLen;
|
|
|
|
lambda[0] = a;
|
|
|
|
normal.Set(nX, nY);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
exports.b2Segment = b2Segment;
|
|
|
|
|
|
var b2Distance = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Distance.prototype.__constructor = function(){}
|
|
b2Distance.prototype.__varz = function(){
|
|
}
|
|
b2Distance.g_GJK_Iterations = 0;
|
|
b2Distance.s_p1s = [new b2Vec2(), new b2Vec2(), new b2Vec2()];
|
|
b2Distance.s_p2s = [new b2Vec2(), new b2Vec2(), new b2Vec2()];
|
|
b2Distance.s_points = [new b2Vec2(), new b2Vec2(), new b2Vec2()];
|
|
b2Distance.gPoint = new b2Point();
|
|
b2Distance.ProcessTwo = function (x1, x2, p1s, p2s, points) {
|
|
var points_0 = points[0];
|
|
var points_1 = points[1];
|
|
var p1s_0 = p1s[0];
|
|
var p1s_1 = p1s[1];
|
|
var p2s_0 = p2s[0];
|
|
var p2s_1 = p2s[1];
|
|
|
|
|
|
|
|
var rX = -points_1.x;
|
|
var rY = -points_1.y;
|
|
|
|
var dX = points_0.x - points_1.x;
|
|
var dY = points_0.y - points_1.y;
|
|
|
|
var length = Math.sqrt(dX*dX + dY*dY);
|
|
dX /= length;
|
|
dY /= length;
|
|
|
|
|
|
var lambda = rX * dX + rY * dY;
|
|
if (lambda <= 0.0 || length < Number.MIN_VALUE)
|
|
{
|
|
|
|
|
|
x1.SetV(p1s_1);
|
|
|
|
x2.SetV(p2s_1);
|
|
|
|
p1s_0.SetV(p1s_1);
|
|
|
|
p2s_0.SetV(p2s_1);
|
|
points_0.SetV(points_1);
|
|
return 1;
|
|
}
|
|
|
|
|
|
lambda /= length;
|
|
|
|
x1.x = p1s_1.x + lambda * (p1s_0.x - p1s_1.x);
|
|
x1.y = p1s_1.y + lambda * (p1s_0.y - p1s_1.y);
|
|
|
|
x2.x = p2s_1.x + lambda * (p2s_0.x - p2s_1.x);
|
|
x2.y = p2s_1.y + lambda * (p2s_0.y - p2s_1.y);
|
|
return 2;
|
|
}
|
|
b2Distance.ProcessThree = function (x1, x2, p1s, p2s, points) {
|
|
var points_0 = points[0];
|
|
var points_1 = points[1];
|
|
var points_2 = points[2];
|
|
var p1s_0 = p1s[0];
|
|
var p1s_1 = p1s[1];
|
|
var p1s_2 = p1s[2];
|
|
var p2s_0 = p2s[0];
|
|
var p2s_1 = p2s[1];
|
|
var p2s_2 = p2s[2];
|
|
|
|
|
|
var aX = points_0.x;
|
|
var aY = points_0.y;
|
|
|
|
var bX = points_1.x;
|
|
var bY = points_1.y;
|
|
|
|
var cX = points_2.x;
|
|
var cY = points_2.y;
|
|
|
|
|
|
var abX = bX - aX;
|
|
var abY = bY - aY;
|
|
|
|
var acX = cX - aX;
|
|
var acY = cY - aY;
|
|
|
|
var bcX = cX - bX;
|
|
var bcY = cY - bY;
|
|
|
|
|
|
var sn = -(aX * abX + aY * abY);
|
|
var sd = (bX * abX + bY * abY);
|
|
|
|
var tn = -(aX * acX + aY * acY);
|
|
var td = (cX * acX + cY * acY);
|
|
|
|
var un = -(bX * bcX + bY * bcY);
|
|
var ud = (cX * bcX + cY * bcY);
|
|
|
|
|
|
if (td <= 0.0 && ud <= 0.0)
|
|
{
|
|
|
|
|
|
x1.SetV(p1s_2);
|
|
|
|
x2.SetV(p2s_2);
|
|
|
|
p1s_0.SetV(p1s_2);
|
|
|
|
p2s_0.SetV(p2s_2);
|
|
points_0.SetV(points_2);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var n = abX * acY - abY * acX;
|
|
|
|
|
|
|
|
var vc = n * (aX * bY - aY * bX);
|
|
|
|
var lambda;
|
|
|
|
|
|
|
|
var va = n * (bX * cY - bY * cX);
|
|
if (va <= 0.0 && un >= 0.0 && ud >= 0.0 && (un+ud) > 0.0)
|
|
{
|
|
|
|
|
|
|
|
lambda = un / (un + ud);
|
|
|
|
x1.x = p1s_1.x + lambda * (p1s_2.x - p1s_1.x);
|
|
x1.y = p1s_1.y + lambda * (p1s_2.y - p1s_1.y);
|
|
|
|
x2.x = p2s_1.x + lambda * (p2s_2.x - p2s_1.x);
|
|
x2.y = p2s_1.y + lambda * (p2s_2.y - p2s_1.y);
|
|
|
|
p1s_0.SetV(p1s_2);
|
|
|
|
p2s_0.SetV(p2s_2);
|
|
|
|
points_0.SetV(points_2);
|
|
return 2;
|
|
}
|
|
|
|
|
|
|
|
var vb = n * (cX * aY - cY * aX);
|
|
if (vb <= 0.0 && tn >= 0.0 && td >= 0.0 && (tn+td) > 0.0)
|
|
{
|
|
|
|
|
|
|
|
lambda = tn / (tn + td);
|
|
|
|
x1.x = p1s_0.x + lambda * (p1s_2.x - p1s_0.x);
|
|
x1.y = p1s_0.y + lambda * (p1s_2.y - p1s_0.y);
|
|
|
|
x2.x = p2s_0.x + lambda * (p2s_2.x - p2s_0.x);
|
|
x2.y = p2s_0.y + lambda * (p2s_2.y - p2s_0.y);
|
|
|
|
p1s_1.SetV(p1s_2);
|
|
|
|
p2s_1.SetV(p2s_2);
|
|
|
|
points_1.SetV(points_2);
|
|
return 2;
|
|
}
|
|
|
|
|
|
|
|
var denom = va + vb + vc;
|
|
|
|
denom = 1.0 / denom;
|
|
|
|
var u = va * denom;
|
|
|
|
var v = vb * denom;
|
|
|
|
var w = 1.0 - u - v;
|
|
|
|
x1.x = u * p1s_0.x + v * p1s_1.x + w * p1s_2.x;
|
|
x1.y = u * p1s_0.y + v * p1s_1.y + w * p1s_2.y;
|
|
|
|
x2.x = u * p2s_0.x + v * p2s_1.x + w * p2s_2.x;
|
|
x2.y = u * p2s_0.y + v * p2s_1.y + w * p2s_2.y;
|
|
return 3;
|
|
}
|
|
b2Distance.InPoints = function (w, points, pointCount) {
|
|
var k_tolerance = 100.0 * Number.MIN_VALUE;
|
|
for (var i = 0; i < pointCount; ++i)
|
|
{
|
|
var points_i = points[i];
|
|
|
|
var dX = Math.abs(w.x - points_i.x);
|
|
var dY = Math.abs(w.y - points_i.y);
|
|
|
|
var mX = Math.max(Math.abs(w.x), Math.abs(points_i.x));
|
|
var mY = Math.max(Math.abs(w.y), Math.abs(points_i.y));
|
|
|
|
if (dX < k_tolerance * (mX + 1.0) &&
|
|
dY < k_tolerance * (mY + 1.0)){
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
b2Distance.DistanceGeneric = function (x1, x2,
|
|
shape1, xf1,
|
|
shape2, xf2) {
|
|
var tVec;
|
|
|
|
|
|
var p1s = b2Distance.s_p1s;
|
|
var p2s = b2Distance.s_p2s;
|
|
|
|
var points = b2Distance.s_points;
|
|
|
|
var pointCount = 0;
|
|
|
|
|
|
x1.SetV(shape1.GetFirstVertex(xf1));
|
|
|
|
x2.SetV(shape2.GetFirstVertex(xf2));
|
|
|
|
var vSqr = 0.0;
|
|
var maxIterations = 20;
|
|
for (var iter = 0; iter < maxIterations; ++iter)
|
|
{
|
|
|
|
var vX = x2.x - x1.x;
|
|
var vY = x2.y - x1.y;
|
|
|
|
var w1 = shape1.Support(xf1, vX, vY);
|
|
|
|
var w2 = shape2.Support(xf2, -vX, -vY);
|
|
|
|
vSqr = (vX*vX + vY*vY);
|
|
|
|
var wX = w2.x - w1.x;
|
|
var wY = w2.y - w1.y;
|
|
|
|
var vw = (vX*wX + vY*wY);
|
|
|
|
if (vSqr - vw <= 0.01 * vSqr)
|
|
{
|
|
if (pointCount == 0)
|
|
{
|
|
|
|
x1.SetV(w1);
|
|
|
|
x2.SetV(w2);
|
|
}
|
|
b2Distance.g_GJK_Iterations = iter;
|
|
return Math.sqrt(vSqr);
|
|
}
|
|
|
|
switch (pointCount)
|
|
{
|
|
case 0:
|
|
|
|
tVec = p1s[0];
|
|
tVec.SetV(w1);
|
|
|
|
tVec = p2s[0];
|
|
tVec.SetV(w2);
|
|
|
|
tVec = points[0];
|
|
tVec.x = wX;
|
|
tVec.y = wY;
|
|
|
|
x1.SetV(p1s[0]);
|
|
|
|
x2.SetV(p2s[0]);
|
|
++pointCount;
|
|
break;
|
|
|
|
case 1:
|
|
|
|
tVec = p1s[1];
|
|
tVec.SetV(w1);
|
|
|
|
tVec = p2s[1];
|
|
tVec.SetV(w2);
|
|
|
|
tVec = points[1];
|
|
tVec.x = wX;
|
|
tVec.y = wY;
|
|
pointCount = b2Distance.ProcessTwo(x1, x2, p1s, p2s, points);
|
|
break;
|
|
|
|
case 2:
|
|
|
|
tVec = p1s[2];
|
|
tVec.SetV(w1);
|
|
|
|
tVec = p2s[2];
|
|
tVec.SetV(w2);
|
|
|
|
tVec = points[2];
|
|
tVec.x = wX;
|
|
tVec.y = wY;
|
|
pointCount = b2Distance.ProcessThree(x1, x2, p1s, p2s, points);
|
|
break;
|
|
}
|
|
|
|
|
|
if (pointCount == 3)
|
|
{
|
|
b2Distance.g_GJK_Iterations = iter;
|
|
return 0.0;
|
|
}
|
|
|
|
|
|
var maxSqr = -Number.MAX_VALUE;
|
|
for (var i = 0; i < pointCount; ++i)
|
|
{
|
|
|
|
tVec = points[i];
|
|
maxSqr = b2Math.b2Max(maxSqr, (tVec.x*tVec.x + tVec.y*tVec.y));
|
|
}
|
|
|
|
if (pointCount == 3 || vSqr <= 100.0 * Number.MIN_VALUE * maxSqr)
|
|
{
|
|
b2Distance.g_GJK_Iterations = iter;
|
|
|
|
vX = x2.x - x1.x;
|
|
vY = x2.y - x1.y;
|
|
|
|
vSqr = (vX*vX + vY*vY);
|
|
return Math.sqrt(vSqr);
|
|
}
|
|
}
|
|
|
|
b2Distance.g_GJK_Iterations = maxIterations;
|
|
return Math.sqrt(vSqr);
|
|
}
|
|
b2Distance.DistanceCC = function (
|
|
x1, x2,
|
|
circle1, xf1,
|
|
circle2, xf2) {
|
|
var tMat;
|
|
var tVec;
|
|
|
|
tMat = xf1.R;
|
|
tVec = circle1.m_localPosition;
|
|
var p1X = xf1.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var p1Y = xf1.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tMat = xf2.R;
|
|
tVec = circle2.m_localPosition;
|
|
var p2X = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var p2Y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
|
|
var dX = p2X - p1X;
|
|
var dY = p2Y - p1Y;
|
|
var dSqr = (dX*dX + dY*dY);
|
|
var r1 = circle1.m_radius - b2Settings.b2_toiSlop;
|
|
var r2 = circle2.m_radius - b2Settings.b2_toiSlop;
|
|
var r = r1 + r2;
|
|
if (dSqr > r * r)
|
|
{
|
|
|
|
var dLen = Math.sqrt(dSqr);
|
|
dX /= dLen;
|
|
dY /= dLen;
|
|
var distance = dLen - r;
|
|
|
|
x1.x = p1X + r1 * dX;
|
|
x1.y = p1Y + r1 * dY;
|
|
|
|
x2.x = p2X - r2 * dX;
|
|
x2.y = p2Y - r2 * dY;
|
|
return distance;
|
|
}
|
|
else if (dSqr > Number.MIN_VALUE * Number.MIN_VALUE)
|
|
{
|
|
|
|
dLen = Math.sqrt(dSqr);
|
|
dX /= dLen;
|
|
dY /= dLen;
|
|
|
|
x1.x = p1X + r1 * dX;
|
|
x1.y = p1Y + r1 * dY;
|
|
|
|
x2.x = x1.x;
|
|
x2.y = x1.y;
|
|
return 0.0;
|
|
}
|
|
|
|
|
|
x1.x = p1X;
|
|
x1.y = p1Y;
|
|
|
|
x2.x = x1.x;
|
|
x2.y = x1.y;
|
|
return 0.0;
|
|
}
|
|
b2Distance.DistancePC = function (
|
|
x1, x2,
|
|
polygon, xf1,
|
|
circle, xf2) {
|
|
|
|
var tMat;
|
|
var tVec;
|
|
|
|
var point = b2Distance.gPoint;
|
|
|
|
tVec = circle.m_localPosition;
|
|
tMat = xf2.R;
|
|
point.p.x = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
point.p.y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
|
|
var distance = b2Distance.DistanceGeneric(x1, x2, polygon, xf1, point, b2Math.b2XForm_identity);
|
|
|
|
var r = circle.m_radius - b2Settings.b2_toiSlop;
|
|
|
|
if (distance > r)
|
|
{
|
|
distance -= r;
|
|
|
|
var dX = x2.x - x1.x;
|
|
var dY = x2.y - x1.y;
|
|
|
|
var dLen = Math.sqrt(dX*dX + dY*dY);
|
|
dX /= dLen;
|
|
dY /= dLen;
|
|
|
|
x2.x -= r * dX;
|
|
x2.y -= r * dY;
|
|
}
|
|
else
|
|
{
|
|
distance = 0.0;
|
|
|
|
x2.x = x1.x;
|
|
x2.y = x1.y;
|
|
}
|
|
|
|
return distance;
|
|
}
|
|
b2Distance.Distance = function (x1, x2,
|
|
shape1, xf1,
|
|
shape2, xf2) {
|
|
|
|
var type1 = shape1.m_type;
|
|
|
|
var type2 = shape2.m_type;
|
|
|
|
if (type1 == b2Shape.e_circleShape && type2 == b2Shape.e_circleShape)
|
|
{
|
|
|
|
return b2Distance.DistanceCC(x1, x2, shape1, xf1, shape2, xf2);
|
|
}
|
|
|
|
if (type1 == b2Shape.e_polygonShape && type2 == b2Shape.e_circleShape)
|
|
{
|
|
|
|
return b2Distance.DistancePC(x1, x2, shape1, xf1, shape2, xf2);
|
|
}
|
|
|
|
if (type1 == b2Shape.e_circleShape && type2 == b2Shape.e_polygonShape)
|
|
{
|
|
return b2Distance.DistancePC(x2, x1, shape2, xf2, shape1, xf1);
|
|
}
|
|
|
|
if (type1 == b2Shape.e_polygonShape && type2 == b2Shape.e_polygonShape)
|
|
{
|
|
return b2Distance.DistanceGeneric(x1, x2, shape1, xf1, shape2, xf2);
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
exports.b2Distance = b2Distance;
|
|
|
|
|
|
var b2OBB = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2OBB.prototype.__constructor = function(){}
|
|
b2OBB.prototype.__varz = function(){
|
|
this.R = new b2Mat22();
|
|
this.center = new b2Vec2();
|
|
this.extents = new b2Vec2();
|
|
}
|
|
b2OBB.prototype.R = new b2Mat22();
|
|
b2OBB.prototype.center = new b2Vec2();
|
|
b2OBB.prototype.extents = new b2Vec2();
|
|
exports.b2OBB = b2OBB;
|
|
|
|
|
|
var b2BroadPhase = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2BroadPhase.prototype.__constructor = function (worldAABB, callback) {
|
|
|
|
var i = 0;
|
|
|
|
this.m_pairManager.Initialize(this, callback);
|
|
|
|
this.m_worldAABB = worldAABB;
|
|
|
|
this.m_proxyCount = 0;
|
|
|
|
|
|
for (i = 0; i < b2Settings.b2_maxProxies; i++){
|
|
this.m_queryResults[i] = 0;
|
|
}
|
|
|
|
|
|
this.m_bounds = new Array(2);
|
|
for (i = 0; i < 2; i++){
|
|
this.m_bounds[i] = new Array(2*b2Settings.b2_maxProxies);
|
|
for (var j = 0; j < 2*b2Settings.b2_maxProxies; j++){
|
|
this.m_bounds[i][j] = new b2Bound();
|
|
}
|
|
}
|
|
|
|
|
|
var dX = worldAABB.upperBound.x - worldAABB.lowerBound.x;;
|
|
var dY = worldAABB.upperBound.y - worldAABB.lowerBound.y;
|
|
|
|
this.m_quantizationFactor.x = b2Settings.USHRT_MAX / dX;
|
|
this.m_quantizationFactor.y = b2Settings.USHRT_MAX / dY;
|
|
|
|
var tProxy;
|
|
for (i = 0; i < b2Settings.b2_maxProxies - 1; ++i)
|
|
{
|
|
tProxy = new b2Proxy();
|
|
this.m_proxyPool[i] = tProxy;
|
|
tProxy.SetNext(i + 1);
|
|
tProxy.timeStamp = 0;
|
|
tProxy.overlapCount = b2BroadPhase.b2_invalid;
|
|
tProxy.userData = null;
|
|
}
|
|
tProxy = new b2Proxy();
|
|
this.m_proxyPool[parseInt(b2Settings.b2_maxProxies-1)] = tProxy;
|
|
tProxy.SetNext(b2Pair.b2_nullProxy);
|
|
tProxy.timeStamp = 0;
|
|
tProxy.overlapCount = b2BroadPhase.b2_invalid;
|
|
tProxy.userData = null;
|
|
this.m_freeProxy = 0;
|
|
|
|
this.m_timeStamp = 1;
|
|
this.m_queryResultCount = 0;
|
|
}
|
|
b2BroadPhase.prototype.__varz = function(){
|
|
this.m_pairManager = new b2PairManager();
|
|
this.m_proxyPool = new Array(b2Settings.b2_maxPairs);
|
|
this.m_bounds = new Array(2*b2Settings.b2_maxProxies);
|
|
this.m_queryResults = new Array(b2Settings.b2_maxProxies);
|
|
this.m_quantizationFactor = new b2Vec2();
|
|
}
|
|
b2BroadPhase.s_validate = false;
|
|
b2BroadPhase.b2_invalid = b2Settings.USHRT_MAX;
|
|
b2BroadPhase.b2_nullEdge = b2Settings.USHRT_MAX;
|
|
b2BroadPhase.BinarySearch = function (bounds, count, value) {
|
|
var low = 0;
|
|
var high = count - 1;
|
|
while (low <= high)
|
|
{
|
|
var mid = Math.round((low + high) / 2);
|
|
var bound = bounds[mid];
|
|
if (bound.value > value)
|
|
{
|
|
high = mid - 1;
|
|
}
|
|
else if (bound.value < value)
|
|
{
|
|
low = mid + 1;
|
|
}
|
|
else
|
|
{
|
|
return parseInt(mid);
|
|
}
|
|
}
|
|
|
|
return parseInt(low);
|
|
}
|
|
b2BroadPhase.prototype.m_pairManager = new b2PairManager();
|
|
b2BroadPhase.prototype.m_proxyPool = new Array(b2Settings.b2_maxPairs);
|
|
b2BroadPhase.prototype.m_freeProxy = 0;
|
|
b2BroadPhase.prototype.m_bounds = new Array(2*b2Settings.b2_maxProxies);
|
|
b2BroadPhase.prototype.m_queryResults = new Array(b2Settings.b2_maxProxies);
|
|
b2BroadPhase.prototype.m_queryResultCount = 0;
|
|
b2BroadPhase.prototype.m_worldAABB = null;
|
|
b2BroadPhase.prototype.m_quantizationFactor = new b2Vec2();
|
|
b2BroadPhase.prototype.m_proxyCount = 0;
|
|
b2BroadPhase.prototype.m_timeStamp = 0;
|
|
b2BroadPhase.prototype.ComputeBounds = function (lowerValues, upperValues, aabb) {
|
|
|
|
|
|
|
|
|
|
var minVertexX = aabb.lowerBound.x;
|
|
var minVertexY = aabb.lowerBound.y;
|
|
minVertexX = b2Math.b2Min(minVertexX, this.m_worldAABB.upperBound.x);
|
|
minVertexY = b2Math.b2Min(minVertexY, this.m_worldAABB.upperBound.y);
|
|
minVertexX = b2Math.b2Max(minVertexX, this.m_worldAABB.lowerBound.x);
|
|
minVertexY = b2Math.b2Max(minVertexY, this.m_worldAABB.lowerBound.y);
|
|
|
|
|
|
var maxVertexX = aabb.upperBound.x;
|
|
var maxVertexY = aabb.upperBound.y;
|
|
maxVertexX = b2Math.b2Min(maxVertexX, this.m_worldAABB.upperBound.x);
|
|
maxVertexY = b2Math.b2Min(maxVertexY, this.m_worldAABB.upperBound.y);
|
|
maxVertexX = b2Math.b2Max(maxVertexX, this.m_worldAABB.lowerBound.x);
|
|
maxVertexY = b2Math.b2Max(maxVertexY, this.m_worldAABB.lowerBound.y);
|
|
|
|
|
|
|
|
|
|
lowerValues[0] = parseInt(this.m_quantizationFactor.x * (minVertexX - this.m_worldAABB.lowerBound.x)) & (b2Settings.USHRT_MAX - 1);
|
|
upperValues[0] = (parseInt(this.m_quantizationFactor.x * (maxVertexX - this.m_worldAABB.lowerBound.x))% 65535) | 1;
|
|
|
|
lowerValues[1] = parseInt(this.m_quantizationFactor.y * (minVertexY - this.m_worldAABB.lowerBound.y)) & (b2Settings.USHRT_MAX - 1);
|
|
upperValues[1] = (parseInt(this.m_quantizationFactor.y * (maxVertexY - this.m_worldAABB.lowerBound.y))% 65535) | 1;
|
|
}
|
|
b2BroadPhase.prototype.TestOverlapValidate = function (p1, p2) {
|
|
|
|
for (var axis = 0; axis < 2; ++axis)
|
|
{
|
|
var bounds = this.m_bounds[axis];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var bound1 = bounds[p1.lowerBounds[axis]];
|
|
var bound2 = bounds[p2.upperBounds[axis]];
|
|
if (bound1.value > bound2.value)
|
|
return false;
|
|
|
|
bound1 = bounds[p1.upperBounds[axis]];
|
|
bound2 = bounds[p2.lowerBounds[axis]];
|
|
if (bound1.value < bound2.value)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
b2BroadPhase.prototype.Query = function (lowerQueryOut, upperQueryOut, lowerValue, upperValue, bounds, boundCount, axis) {
|
|
|
|
var lowerQuery = b2BroadPhase.BinarySearch(bounds, boundCount, lowerValue);
|
|
var upperQuery = b2BroadPhase.BinarySearch(bounds, boundCount, upperValue);
|
|
var bound;
|
|
|
|
|
|
|
|
for (var j = lowerQuery; j < upperQuery; ++j)
|
|
{
|
|
bound = bounds[j];
|
|
if (bound.IsLower())
|
|
{
|
|
this.IncrementOverlapCount(bound.proxyId);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (lowerQuery > 0)
|
|
{
|
|
var i = lowerQuery - 1;
|
|
bound = bounds[i];
|
|
var s = bound.stabbingCount;
|
|
|
|
|
|
while (s)
|
|
{
|
|
|
|
bound = bounds[i];
|
|
if (bound.IsLower())
|
|
{
|
|
var proxy = this.m_proxyPool[ bound.proxyId ];
|
|
if (lowerQuery <= proxy.upperBounds[axis])
|
|
{
|
|
this.IncrementOverlapCount(bound.proxyId);
|
|
--s;
|
|
}
|
|
}
|
|
--i;
|
|
}
|
|
}
|
|
|
|
lowerQueryOut[0] = lowerQuery;
|
|
upperQueryOut[0] = upperQuery;
|
|
}
|
|
b2BroadPhase.prototype.IncrementOverlapCount = function (proxyId) {
|
|
var proxy = this.m_proxyPool[ proxyId ];
|
|
if (proxy.timeStamp < this.m_timeStamp)
|
|
{
|
|
proxy.timeStamp = this.m_timeStamp;
|
|
proxy.overlapCount = 1;
|
|
}
|
|
else
|
|
{
|
|
proxy.overlapCount = 2;
|
|
|
|
this.m_queryResults[this.m_queryResultCount] = proxyId;
|
|
++this.m_queryResultCount;
|
|
}
|
|
}
|
|
b2BroadPhase.prototype.IncrementTimeStamp = function () {
|
|
if (this.m_timeStamp == b2Settings.USHRT_MAX)
|
|
{
|
|
for (var i = 0; i < b2Settings.b2_maxProxies; ++i)
|
|
{
|
|
(this.m_proxyPool[i]).timeStamp = 0;
|
|
}
|
|
this.m_timeStamp = 1;
|
|
}
|
|
else
|
|
{
|
|
++this.m_timeStamp;
|
|
}
|
|
}
|
|
b2BroadPhase.prototype.InRange = function (aabb) {
|
|
|
|
var dX;
|
|
var dY;
|
|
var d2X;
|
|
var d2Y;
|
|
|
|
dX = aabb.lowerBound.x;
|
|
dY = aabb.lowerBound.y;
|
|
dX -= this.m_worldAABB.upperBound.x;
|
|
dY -= this.m_worldAABB.upperBound.y;
|
|
|
|
d2X = this.m_worldAABB.lowerBound.x;
|
|
d2Y = this.m_worldAABB.lowerBound.y;
|
|
d2X -= aabb.upperBound.x;
|
|
d2Y -= aabb.upperBound.y;
|
|
|
|
dX = b2Math.b2Max(dX, d2X);
|
|
dY = b2Math.b2Max(dY, d2Y);
|
|
|
|
return b2Math.b2Max(dX, dY) < 0.0;
|
|
}
|
|
b2BroadPhase.prototype.GetProxy = function (proxyId) {
|
|
var proxy = this.m_proxyPool[proxyId];
|
|
if (proxyId == b2Pair.b2_nullProxy || proxy.IsValid() == false)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return proxy;
|
|
}
|
|
b2BroadPhase.prototype.CreateProxy = function (aabb, userData) {
|
|
var index = 0;
|
|
var proxy;
|
|
|
|
|
|
|
|
|
|
var proxyId = this.m_freeProxy;
|
|
proxy = this.m_proxyPool[ proxyId ];
|
|
this.m_freeProxy = proxy.GetNext();
|
|
|
|
proxy.overlapCount = 0;
|
|
proxy.userData = userData;
|
|
|
|
var boundCount = 2 * this.m_proxyCount;
|
|
|
|
var lowerValues = new Array();
|
|
var upperValues = new Array();
|
|
this.ComputeBounds(lowerValues, upperValues, aabb);
|
|
|
|
for (var axis = 0; axis < 2; ++axis)
|
|
{
|
|
var bounds = this.m_bounds[axis];
|
|
var lowerIndex = 0;
|
|
var upperIndex = 0;
|
|
var lowerIndexOut = [lowerIndex];
|
|
var upperIndexOut = [upperIndex];
|
|
this.Query(lowerIndexOut, upperIndexOut, lowerValues[axis], upperValues[axis], bounds, boundCount, axis);
|
|
lowerIndex = lowerIndexOut[0];
|
|
upperIndex = upperIndexOut[0];
|
|
|
|
|
|
|
|
var tArr = new Array();
|
|
var j = 0;
|
|
var tEnd = boundCount - upperIndex
|
|
var tBound1;
|
|
var tBound2;
|
|
var tBoundAS3;
|
|
|
|
for (j = 0; j < tEnd; j++){
|
|
tArr[j] = new b2Bound();
|
|
tBound1 = tArr[j];
|
|
tBound2 = bounds[parseInt(upperIndex+j)];
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
tEnd = tArr.length;
|
|
var tIndex = upperIndex+2;
|
|
for (j = 0; j < tEnd; j++){
|
|
|
|
tBound2 = tArr[j];
|
|
tBound1 = bounds[parseInt(tIndex+j)]
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
|
|
tArr = new Array();
|
|
tEnd = upperIndex - lowerIndex;
|
|
for (j = 0; j < tEnd; j++){
|
|
tArr[j] = new b2Bound();
|
|
tBound1 = tArr[j];
|
|
tBound2 = bounds[parseInt(lowerIndex+j)];
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
tEnd = tArr.length;
|
|
tIndex = lowerIndex+1;
|
|
for (j = 0; j < tEnd; j++){
|
|
|
|
tBound2 = tArr[j];
|
|
tBound1 = bounds[parseInt(tIndex+j)]
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
|
|
++upperIndex;
|
|
|
|
|
|
tBound1 = bounds[lowerIndex];
|
|
tBound2 = bounds[upperIndex];
|
|
tBound1.value = lowerValues[axis];
|
|
tBound1.proxyId = proxyId;
|
|
tBound2.value = upperValues[axis];
|
|
tBound2.proxyId = proxyId;
|
|
|
|
tBoundAS3 = bounds[parseInt(lowerIndex-1)];
|
|
tBound1.stabbingCount = lowerIndex == 0 ? 0 : tBoundAS3.stabbingCount;
|
|
tBoundAS3 = bounds[parseInt(upperIndex-1)];
|
|
tBound2.stabbingCount = tBoundAS3.stabbingCount;
|
|
|
|
|
|
for (index = lowerIndex; index < upperIndex; ++index)
|
|
{
|
|
tBoundAS3 = bounds[index];
|
|
tBoundAS3.stabbingCount++;
|
|
}
|
|
|
|
|
|
for (index = lowerIndex; index < boundCount + 2; ++index)
|
|
{
|
|
tBound1 = bounds[index];
|
|
var proxy2 = this.m_proxyPool[ tBound1.proxyId ];
|
|
if (tBound1.IsLower())
|
|
{
|
|
proxy2.lowerBounds[axis] = index;
|
|
}
|
|
else
|
|
{
|
|
proxy2.upperBounds[axis] = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
++this.m_proxyCount;
|
|
|
|
|
|
|
|
for (var i = 0; i < this.m_queryResultCount; ++i)
|
|
{
|
|
|
|
|
|
|
|
this.m_pairManager.AddBufferedPair(proxyId, this.m_queryResults[i]);
|
|
}
|
|
|
|
this.m_pairManager.Commit();
|
|
|
|
|
|
this.m_queryResultCount = 0;
|
|
this.IncrementTimeStamp();
|
|
|
|
return proxyId;
|
|
}
|
|
b2BroadPhase.prototype.DestroyProxy = function (proxyId) {
|
|
var tBound1;
|
|
var tBound2;
|
|
|
|
|
|
|
|
var proxy = this.m_proxyPool[ proxyId ];
|
|
|
|
|
|
var boundCount = 2 * this.m_proxyCount;
|
|
|
|
for (var axis = 0; axis < 2; ++axis)
|
|
{
|
|
var bounds = this.m_bounds[axis];
|
|
|
|
var lowerIndex = proxy.lowerBounds[axis];
|
|
var upperIndex = proxy.upperBounds[axis];
|
|
tBound1 = bounds[lowerIndex];
|
|
var lowerValue = tBound1.value;
|
|
tBound2 = bounds[upperIndex];
|
|
var upperValue = tBound2.value;
|
|
|
|
|
|
|
|
var tArr = new Array();
|
|
var j = 0;
|
|
var tEnd = upperIndex - lowerIndex - 1;
|
|
|
|
for (j = 0; j < tEnd; j++){
|
|
tArr[j] = new b2Bound();
|
|
tBound1 = tArr[j];
|
|
tBound2 = bounds[parseInt(lowerIndex+1+j)];
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
tEnd = tArr.length;
|
|
var tIndex = lowerIndex;
|
|
for (j = 0; j < tEnd; j++){
|
|
|
|
tBound2 = tArr[j];
|
|
tBound1 = bounds[parseInt(tIndex+j)]
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
|
|
tArr = new Array();
|
|
tEnd = boundCount - upperIndex - 1;
|
|
for (j = 0; j < tEnd; j++){
|
|
tArr[j] = new b2Bound();
|
|
tBound1 = tArr[j];
|
|
tBound2 = bounds[parseInt(upperIndex+1+j)];
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
tEnd = tArr.length;
|
|
tIndex = upperIndex-1;
|
|
for (j = 0; j < tEnd; j++){
|
|
|
|
tBound2 = tArr[j];
|
|
tBound1 = bounds[parseInt(tIndex+j)]
|
|
tBound1.value = tBound2.value;
|
|
tBound1.proxyId = tBound2.proxyId;
|
|
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
}
|
|
|
|
|
|
tEnd = boundCount - 2;
|
|
for (var index = lowerIndex; index < tEnd; ++index)
|
|
{
|
|
tBound1 = bounds[index];
|
|
var proxy2 = this.m_proxyPool[ tBound1.proxyId ];
|
|
if (tBound1.IsLower())
|
|
{
|
|
proxy2.lowerBounds[axis] = index;
|
|
}
|
|
else
|
|
{
|
|
proxy2.upperBounds[axis] = index;
|
|
}
|
|
}
|
|
|
|
|
|
tEnd = upperIndex - 1;
|
|
for (var index2 = lowerIndex; index2 < tEnd; ++index2)
|
|
{
|
|
tBound1 = bounds[index2];
|
|
tBound1.stabbingCount--;
|
|
}
|
|
|
|
|
|
|
|
this.Query([0], [0], lowerValue, upperValue, bounds, boundCount - 2, axis);
|
|
}
|
|
|
|
|
|
|
|
for (var i = 0; i < this.m_queryResultCount; ++i)
|
|
{
|
|
|
|
|
|
this.m_pairManager.RemoveBufferedPair(proxyId, this.m_queryResults[i]);
|
|
}
|
|
|
|
this.m_pairManager.Commit();
|
|
|
|
|
|
this.m_queryResultCount = 0;
|
|
this.IncrementTimeStamp();
|
|
|
|
|
|
proxy.userData = null;
|
|
proxy.overlapCount = b2BroadPhase.b2_invalid;
|
|
proxy.lowerBounds[0] = b2BroadPhase.b2_invalid;
|
|
proxy.lowerBounds[1] = b2BroadPhase.b2_invalid;
|
|
proxy.upperBounds[0] = b2BroadPhase.b2_invalid;
|
|
proxy.upperBounds[1] = b2BroadPhase.b2_invalid;
|
|
|
|
proxy.SetNext(this.m_freeProxy);
|
|
this.m_freeProxy = proxyId;
|
|
--this.m_proxyCount;
|
|
}
|
|
b2BroadPhase.prototype.MoveProxy = function (proxyId, aabb) {
|
|
var as3arr;
|
|
var as3int;
|
|
|
|
var axis = 0;
|
|
var index = 0;
|
|
var bound;
|
|
var prevBound;
|
|
var nextBound;
|
|
var nextProxyId = 0;
|
|
var nextProxy;
|
|
|
|
if (proxyId == b2Pair.b2_nullProxy || b2Settings.b2_maxProxies <= proxyId)
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
if (aabb.IsValid() == false)
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
var boundCount = 2 * this.m_proxyCount;
|
|
|
|
var proxy = this.m_proxyPool[ proxyId ];
|
|
|
|
var newValues = new b2BoundValues();
|
|
this.ComputeBounds(newValues.lowerValues, newValues.upperValues, aabb);
|
|
|
|
|
|
var oldValues = new b2BoundValues();
|
|
for (axis = 0; axis < 2; ++axis)
|
|
{
|
|
bound = this.m_bounds[axis][proxy.lowerBounds[axis]];
|
|
oldValues.lowerValues[axis] = bound.value;
|
|
bound = this.m_bounds[axis][proxy.upperBounds[axis]];
|
|
oldValues.upperValues[axis] = bound.value;
|
|
}
|
|
|
|
for (axis = 0; axis < 2; ++axis)
|
|
{
|
|
var bounds = this.m_bounds[axis];
|
|
|
|
var lowerIndex = proxy.lowerBounds[axis];
|
|
var upperIndex = proxy.upperBounds[axis];
|
|
|
|
var lowerValue = newValues.lowerValues[axis];
|
|
var upperValue = newValues.upperValues[axis];
|
|
|
|
bound = bounds[lowerIndex];
|
|
var deltaLower = lowerValue - bound.value;
|
|
bound.value = lowerValue;
|
|
|
|
bound = bounds[upperIndex];
|
|
var deltaUpper = upperValue - bound.value;
|
|
bound.value = upperValue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (deltaLower < 0)
|
|
{
|
|
index = lowerIndex;
|
|
while (index > 0 && lowerValue < (bounds[parseInt(index-1)]).value)
|
|
{
|
|
bound = bounds[index];
|
|
prevBound = bounds[parseInt(index - 1)];
|
|
|
|
var prevProxyId = prevBound.proxyId;
|
|
var prevProxy = this.m_proxyPool[ prevBound.proxyId ];
|
|
|
|
prevBound.stabbingCount++;
|
|
|
|
if (prevBound.IsUpper() == true)
|
|
{
|
|
if (this.TestOverlap(newValues, prevProxy))
|
|
{
|
|
this.m_pairManager.AddBufferedPair(proxyId, prevProxyId);
|
|
}
|
|
|
|
|
|
as3arr = prevProxy.upperBounds;
|
|
as3int = as3arr[axis];
|
|
as3int++;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount++;
|
|
}
|
|
else
|
|
{
|
|
|
|
as3arr = prevProxy.lowerBounds;
|
|
as3int = as3arr[axis];
|
|
as3int++;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount--;
|
|
}
|
|
|
|
|
|
as3arr = proxy.lowerBounds;
|
|
as3int = as3arr[axis];
|
|
as3int--;
|
|
as3arr[axis] = as3int;
|
|
|
|
|
|
|
|
|
|
|
|
bound.Swap(prevBound);
|
|
|
|
--index;
|
|
}
|
|
}
|
|
|
|
|
|
if (deltaUpper > 0)
|
|
{
|
|
index = upperIndex;
|
|
while (index < boundCount-1 && (bounds[parseInt(index+1)]).value <= upperValue)
|
|
{
|
|
bound = bounds[ index ];
|
|
nextBound = bounds[ parseInt(index + 1) ];
|
|
nextProxyId = nextBound.proxyId;
|
|
nextProxy = this.m_proxyPool[ nextProxyId ];
|
|
|
|
nextBound.stabbingCount++;
|
|
|
|
if (nextBound.IsLower() == true)
|
|
{
|
|
if (this.TestOverlap(newValues, nextProxy))
|
|
{
|
|
this.m_pairManager.AddBufferedPair(proxyId, nextProxyId);
|
|
}
|
|
|
|
|
|
as3arr = nextProxy.lowerBounds;
|
|
as3int = as3arr[axis];
|
|
as3int--;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount++;
|
|
}
|
|
else
|
|
{
|
|
|
|
as3arr = nextProxy.upperBounds;
|
|
as3int = as3arr[axis];
|
|
as3int--;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount--;
|
|
}
|
|
|
|
|
|
as3arr = proxy.upperBounds;
|
|
as3int = as3arr[axis];
|
|
as3int++;
|
|
as3arr[axis] = as3int;
|
|
|
|
|
|
|
|
|
|
|
|
bound.Swap(nextBound);
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (deltaLower > 0)
|
|
{
|
|
index = lowerIndex;
|
|
while (index < boundCount-1 && (bounds[parseInt(index+1)]).value <= lowerValue)
|
|
{
|
|
bound = bounds[ index ];
|
|
nextBound = bounds[ parseInt(index + 1) ];
|
|
|
|
nextProxyId = nextBound.proxyId;
|
|
nextProxy = this.m_proxyPool[ nextProxyId ];
|
|
|
|
nextBound.stabbingCount--;
|
|
|
|
if (nextBound.IsUpper())
|
|
{
|
|
if (this.TestOverlap(oldValues, nextProxy))
|
|
{
|
|
this.m_pairManager.RemoveBufferedPair(proxyId, nextProxyId);
|
|
}
|
|
|
|
|
|
as3arr = nextProxy.upperBounds;
|
|
as3int = as3arr[axis];
|
|
as3int--;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount--;
|
|
}
|
|
else
|
|
{
|
|
|
|
as3arr = nextProxy.lowerBounds;
|
|
as3int = as3arr[axis];
|
|
as3int--;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount++;
|
|
}
|
|
|
|
|
|
as3arr = proxy.lowerBounds;
|
|
as3int = as3arr[axis];
|
|
as3int++;
|
|
as3arr[axis] = as3int;
|
|
|
|
|
|
|
|
|
|
|
|
bound.Swap(nextBound);
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
|
|
if (deltaUpper < 0)
|
|
{
|
|
index = upperIndex;
|
|
while (index > 0 && upperValue < (bounds[parseInt(index-1)]).value)
|
|
{
|
|
bound = bounds[index];
|
|
prevBound = bounds[parseInt(index - 1)];
|
|
|
|
prevProxyId = prevBound.proxyId;
|
|
prevProxy = this.m_proxyPool[ prevProxyId ];
|
|
|
|
prevBound.stabbingCount--;
|
|
|
|
if (prevBound.IsLower() == true)
|
|
{
|
|
if (this.TestOverlap(oldValues, prevProxy))
|
|
{
|
|
this.m_pairManager.RemoveBufferedPair(proxyId, prevProxyId);
|
|
}
|
|
|
|
|
|
as3arr = prevProxy.lowerBounds;
|
|
as3int = as3arr[axis];
|
|
as3int++;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount--;
|
|
}
|
|
else
|
|
{
|
|
|
|
as3arr = prevProxy.upperBounds;
|
|
as3int = as3arr[axis];
|
|
as3int++;
|
|
as3arr[axis] = as3int;
|
|
|
|
bound.stabbingCount++;
|
|
}
|
|
|
|
|
|
as3arr = proxy.upperBounds;
|
|
as3int = as3arr[axis];
|
|
as3int--;
|
|
as3arr[axis] = as3int;
|
|
|
|
|
|
|
|
|
|
|
|
bound.Swap(prevBound);
|
|
|
|
index--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
b2BroadPhase.prototype.Commit = function () {
|
|
this.m_pairManager.Commit();
|
|
}
|
|
b2BroadPhase.prototype.QueryAABB = function (aabb, userData, maxCount) {
|
|
var lowerValues = new Array();
|
|
var upperValues = new Array();
|
|
this.ComputeBounds(lowerValues, upperValues, aabb);
|
|
|
|
var lowerIndex = 0;
|
|
var upperIndex = 0;
|
|
var lowerIndexOut = [lowerIndex];
|
|
var upperIndexOut = [upperIndex];
|
|
this.Query(lowerIndexOut, upperIndexOut, lowerValues[0], upperValues[0], this.m_bounds[0], 2*this.m_proxyCount, 0);
|
|
this.Query(lowerIndexOut, upperIndexOut, lowerValues[1], upperValues[1], this.m_bounds[1], 2*this.m_proxyCount, 1);
|
|
|
|
|
|
|
|
var count = 0;
|
|
for (var i = 0; i < this.m_queryResultCount && count < maxCount; ++i, ++count)
|
|
{
|
|
|
|
var proxy = this.m_proxyPool[ this.m_queryResults[i] ];
|
|
|
|
userData[i] = proxy.userData;
|
|
}
|
|
|
|
|
|
this.m_queryResultCount = 0;
|
|
this.IncrementTimeStamp();
|
|
|
|
return count;
|
|
}
|
|
b2BroadPhase.prototype.Validate = function () {
|
|
var pair;
|
|
var proxy1;
|
|
var proxy2;
|
|
var overlap;
|
|
|
|
for (var axis = 0; axis < 2; ++axis)
|
|
{
|
|
var bounds = this.m_bounds[axis];
|
|
|
|
var boundCount = 2 * this.m_proxyCount;
|
|
var stabbingCount = 0;
|
|
|
|
for (var i = 0; i < boundCount; ++i)
|
|
{
|
|
var bound = bounds[i];
|
|
|
|
|
|
|
|
|
|
if (bound.IsLower() == true)
|
|
{
|
|
|
|
stabbingCount++;
|
|
}
|
|
else
|
|
{
|
|
|
|
stabbingCount--;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
b2BroadPhase.prototype.TestOverlap = function (b, p) {
|
|
for (var axis = 0; axis < 2; ++axis)
|
|
{
|
|
var bounds = this.m_bounds[axis];
|
|
|
|
|
|
|
|
|
|
var bound = bounds[p.upperBounds[axis]];
|
|
if (b.lowerValues[axis] > bound.value)
|
|
return false;
|
|
|
|
bound = bounds[p.lowerBounds[axis]];
|
|
if (b.upperValues[axis] < bound.value)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
exports.b2BroadPhase = b2BroadPhase;
|
|
|
|
|
|
var b2TimeOfImpact = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2TimeOfImpact.prototype.__constructor = function(){}
|
|
b2TimeOfImpact.prototype.__varz = function(){
|
|
}
|
|
b2TimeOfImpact.s_p1 = new b2Vec2();
|
|
b2TimeOfImpact.s_p2 = new b2Vec2();
|
|
b2TimeOfImpact.s_xf1 = new b2XForm();
|
|
b2TimeOfImpact.s_xf2 = new b2XForm();
|
|
b2TimeOfImpact.TimeOfImpact = function ( shape1, sweep1,
|
|
shape2, sweep2) {
|
|
var math1;
|
|
var math2;
|
|
|
|
var r1 = shape1.m_sweepRadius;
|
|
var r2 = shape2.m_sweepRadius;
|
|
|
|
|
|
|
|
|
|
var t0 = sweep1.t0;
|
|
|
|
var v1X = sweep1.c.x - sweep1.c0.x;
|
|
var v1Y = sweep1.c.y - sweep1.c0.y;
|
|
|
|
var v2X = sweep2.c.x - sweep2.c0.x;
|
|
var v2Y = sweep2.c.y - sweep2.c0.y;
|
|
var omega1 = sweep1.a - sweep1.a0;
|
|
var omega2 = sweep2.a - sweep2.a0;
|
|
|
|
var alpha = 0.0;
|
|
|
|
var p1 = b2TimeOfImpact.s_p1;
|
|
var p2 = b2TimeOfImpact.s_p2;
|
|
var k_maxIterations = 20;
|
|
var iter = 0;
|
|
|
|
var normalX = 0.0;
|
|
var normalY = 0.0;
|
|
var distance = 0.0;
|
|
var targetDistance = 0.0;
|
|
for(;;)
|
|
{
|
|
var t = (1.0 - alpha) * t0 + alpha;
|
|
|
|
var xf1 = b2TimeOfImpact.s_xf1;
|
|
var xf2 = b2TimeOfImpact.s_xf2;
|
|
sweep1.GetXForm(xf1, t);
|
|
sweep2.GetXForm(xf2, t);
|
|
|
|
|
|
distance = b2Distance.Distance(p1, p2, shape1, xf1, shape2, xf2);
|
|
|
|
if (iter == 0)
|
|
{
|
|
|
|
|
|
if (distance > 2.0 * b2Settings.b2_toiSlop)
|
|
{
|
|
targetDistance = 1.5 * b2Settings.b2_toiSlop;
|
|
}
|
|
else
|
|
{
|
|
|
|
math1 = 0.05 * b2Settings.b2_toiSlop;
|
|
math2 = distance - 0.5 * b2Settings.b2_toiSlop;
|
|
targetDistance = math1 > math2 ? math1 : math2;
|
|
}
|
|
}
|
|
|
|
if (distance - targetDistance < 0.05 * b2Settings.b2_toiSlop || iter == k_maxIterations)
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
normalX = p2.x - p1.x;
|
|
normalY = p2.y - p1.y;
|
|
|
|
var nLen = Math.sqrt(normalX*normalX + normalY*normalY);
|
|
normalX /= nLen;
|
|
normalY /= nLen;
|
|
|
|
|
|
|
|
var approachVelocityBound = (normalX*(v1X - v2X) + normalY*(v1Y - v2Y))
|
|
+ (omega1 < 0 ? -omega1 : omega1) * r1
|
|
+ (omega2 < 0 ? -omega2 : omega2) * r2;
|
|
|
|
if (approachVelocityBound == 0)
|
|
{
|
|
alpha = 1.0;
|
|
break;
|
|
}
|
|
|
|
|
|
var dAlpha = (distance - targetDistance) / approachVelocityBound;
|
|
|
|
var newAlpha = alpha + dAlpha;
|
|
|
|
|
|
if (newAlpha < 0.0 || 1.0 < newAlpha)
|
|
{
|
|
alpha = 1.0;
|
|
break;
|
|
}
|
|
|
|
|
|
if (newAlpha < (1.0 + 100.0 * Number.MIN_VALUE) * alpha)
|
|
{
|
|
break;
|
|
}
|
|
|
|
alpha = newAlpha;
|
|
|
|
++iter;
|
|
}
|
|
|
|
return alpha;
|
|
}
|
|
exports.b2TimeOfImpact = b2TimeOfImpact;
|
|
|
|
|
|
var b2ContactPoint = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactPoint.prototype.__constructor = function(){}
|
|
b2ContactPoint.prototype.__varz = function(){
|
|
this.position = new b2Vec2();
|
|
this.velocity = new b2Vec2();
|
|
this.normal = new b2Vec2();
|
|
this.id = new b2ContactID();
|
|
}
|
|
b2ContactPoint.prototype.shape1 = null;
|
|
b2ContactPoint.prototype.shape2 = null;
|
|
b2ContactPoint.prototype.position = new b2Vec2();
|
|
b2ContactPoint.prototype.velocity = new b2Vec2();
|
|
b2ContactPoint.prototype.normal = new b2Vec2();
|
|
b2ContactPoint.prototype.separation = null;
|
|
b2ContactPoint.prototype.friction = null;
|
|
b2ContactPoint.prototype.restitution = null;
|
|
b2ContactPoint.prototype.id = new b2ContactID();
|
|
exports.b2ContactPoint= b2ContactPoint;
|
|
|
|
|
|
var ClipVertex = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
ClipVertex.prototype.__constructor = function(){}
|
|
ClipVertex.prototype.__varz = function(){
|
|
this.v = new b2Vec2();
|
|
this.id = new b2ContactID();
|
|
}
|
|
ClipVertex.prototype.v = new b2Vec2();
|
|
ClipVertex.prototype.id = new b2ContactID();
|
|
exports.ClipVertex = ClipVertex;
|
|
|
|
|
|
var b2MassData = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2MassData.prototype.__constructor = function(){}
|
|
b2MassData.prototype.__varz = function(){
|
|
this.center = new b2Vec2(0,0);
|
|
}
|
|
b2MassData.prototype.mass = 0.0;
|
|
b2MassData.prototype.center = new b2Vec2(0,0);
|
|
b2MassData.prototype.I = 0.0;
|
|
exports.b2MassData = b2MassData;
|
|
|
|
|
|
var b2FilterData = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2FilterData.prototype.__constructor = function(){}
|
|
b2FilterData.prototype.__varz = function(){
|
|
this.categoryBits = 0x0001;
|
|
this.maskBits = 0xFFFF;
|
|
}
|
|
b2FilterData.prototype.categoryBits = 0x0001;
|
|
b2FilterData.prototype.maskBits = 0xFFFF;
|
|
b2FilterData.prototype.groupIndex = 0;
|
|
b2FilterData.prototype.Copy = function () {
|
|
var copy = new b2FilterData();
|
|
copy.categoryBits = this.categoryBits;
|
|
copy.maskBits = this.maskBits;
|
|
copy.groupIndex = this.groupIndex;
|
|
return copy;
|
|
}
|
|
exports.b2FilterData = b2FilterData;
|
|
|
|
|
|
var b2Shape = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Shape.prototype.__constructor = function (def) {
|
|
|
|
this.m_userData = def.userData;
|
|
this.m_friction = def.friction;
|
|
this.m_restitution = def.restitution;
|
|
this.m_density = def.density;
|
|
this.m_body = null;
|
|
this.m_sweepRadius = 0.0;
|
|
|
|
this.m_next = null;
|
|
|
|
this.m_proxyId = b2Pair.b2_nullProxy;
|
|
|
|
this.m_filter = def.filter.Copy();
|
|
|
|
this.m_isSensor = def.isSensor;
|
|
|
|
}
|
|
b2Shape.prototype.__varz = function(){
|
|
}
|
|
b2Shape.e_unknownShape = -1;
|
|
b2Shape.e_circleShape = 0;
|
|
b2Shape.e_polygonShape = 1;
|
|
b2Shape.e_shapeTypeCount = 2;
|
|
b2Shape.s_proxyAABB = new b2AABB();
|
|
b2Shape.s_syncAABB = new b2AABB();
|
|
b2Shape.s_resetAABB = new b2AABB();
|
|
b2Shape.Create = function (def, allocator) {
|
|
switch (def.type)
|
|
{
|
|
case b2Shape.e_circleShape:
|
|
{
|
|
|
|
return new b2CircleShape(def);
|
|
}
|
|
|
|
case b2Shape.e_polygonShape:
|
|
{
|
|
|
|
return new b2PolygonShape(def);
|
|
}
|
|
|
|
default:
|
|
|
|
return null;
|
|
}
|
|
}
|
|
b2Shape.Destroy = function (shape, allocator) {
|
|
|
|
}
|
|
b2Shape.prototype.m_type = 0;
|
|
b2Shape.prototype.m_next = null;
|
|
b2Shape.prototype.m_body = null;
|
|
b2Shape.prototype.m_sweepRadius = null;
|
|
b2Shape.prototype.m_density = null;
|
|
b2Shape.prototype.m_friction = null;
|
|
b2Shape.prototype.m_restitution = null;
|
|
b2Shape.prototype.m_proxyId = 0;
|
|
b2Shape.prototype.m_filter = null;
|
|
b2Shape.prototype.m_isSensor = null;
|
|
b2Shape.prototype.m_userData = null;
|
|
b2Shape.prototype.GetType = function () {
|
|
return this.m_type;
|
|
}
|
|
b2Shape.prototype.IsSensor = function () {
|
|
return this.m_isSensor;
|
|
}
|
|
b2Shape.prototype.SetFilterData = function (filter) {
|
|
this.m_filter = filter.Copy();
|
|
}
|
|
b2Shape.prototype.GetFilterData = function () {
|
|
return this.m_filter.Copy();
|
|
}
|
|
b2Shape.prototype.GetBody = function () {
|
|
return this.m_body;
|
|
}
|
|
b2Shape.prototype.GetNext = function () {
|
|
return this.m_next;
|
|
}
|
|
b2Shape.prototype.GetUserData = function () {
|
|
return this.m_userData;
|
|
}
|
|
b2Shape.prototype.SetUserData = function (data) {
|
|
this.m_userData = data;
|
|
}
|
|
b2Shape.prototype.TestPoint = function (xf, p) {return false}
|
|
b2Shape.prototype.TestSegment = function (xf,
|
|
lambda,
|
|
normal,
|
|
segment,
|
|
maxLambda) {return false}
|
|
b2Shape.prototype.ComputeAABB = function (aabb, xf) {}
|
|
b2Shape.prototype.ComputeSweptAABB = function ( aabb,
|
|
xf1,
|
|
xf2) {}
|
|
b2Shape.prototype.ComputeMass = function (massData) {}
|
|
b2Shape.prototype.GetSweepRadius = function () {
|
|
return this.m_sweepRadius;
|
|
}
|
|
b2Shape.prototype.GetFriction = function () {
|
|
return this.m_friction;
|
|
}
|
|
b2Shape.prototype.GetRestitution = function () {
|
|
return this.m_restitution;
|
|
}
|
|
b2Shape.prototype.CreateProxy = function (broadPhase, transform) {
|
|
|
|
|
|
|
|
var aabb = b2Shape.s_proxyAABB;
|
|
this.ComputeAABB(aabb, transform);
|
|
|
|
var inRange = broadPhase.InRange(aabb);
|
|
|
|
|
|
|
|
|
|
if (inRange)
|
|
{
|
|
this.m_proxyId = broadPhase.CreateProxy(aabb, this);
|
|
}
|
|
else
|
|
{
|
|
this.m_proxyId = b2Pair.b2_nullProxy;
|
|
}
|
|
|
|
}
|
|
b2Shape.prototype.DestroyProxy = function (broadPhase) {
|
|
|
|
if (this.m_proxyId != b2Pair.b2_nullProxy)
|
|
{
|
|
broadPhase.DestroyProxy(this.m_proxyId);
|
|
this.m_proxyId = b2Pair.b2_nullProxy;
|
|
}
|
|
|
|
}
|
|
b2Shape.prototype.Synchronize = function (broadPhase, transform1, transform2) {
|
|
|
|
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
var aabb = b2Shape.s_syncAABB;
|
|
this.ComputeSweptAABB(aabb, transform1, transform2);
|
|
|
|
if (broadPhase.InRange(aabb))
|
|
{
|
|
broadPhase.MoveProxy(this.m_proxyId, aabb);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
}
|
|
b2Shape.prototype.RefilterProxy = function (broadPhase, transform) {
|
|
|
|
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
|
{
|
|
return;
|
|
}
|
|
|
|
broadPhase.DestroyProxy(this.m_proxyId);
|
|
|
|
var aabb = b2Shape.s_resetAABB;
|
|
this.ComputeAABB(aabb, transform);
|
|
|
|
var inRange = broadPhase.InRange(aabb);
|
|
|
|
if (inRange)
|
|
{
|
|
this.m_proxyId = broadPhase.CreateProxy(aabb, this);
|
|
}
|
|
else
|
|
{
|
|
this.m_proxyId = b2Pair.b2_nullProxy;
|
|
}
|
|
|
|
}
|
|
b2Shape.prototype.UpdateSweepRadius = function (center) {}
|
|
exports.b2Shape = b2Shape;
|
|
|
|
|
|
var b2CircleShape = function() {
|
|
b2Shape.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2CircleShape.prototype, b2Shape.prototype)
|
|
b2CircleShape.prototype._super = function(){ b2Shape.prototype.__constructor.apply(this, arguments) }
|
|
b2CircleShape.prototype.__constructor = function (def) {
|
|
this._super(def);
|
|
|
|
|
|
var circleDef = def;
|
|
|
|
this.m_type = b2Shape.e_circleShape;
|
|
this.m_localPosition.SetV(circleDef.localPosition);
|
|
this.m_radius = circleDef.radius;
|
|
|
|
}
|
|
b2CircleShape.prototype.__varz = function(){
|
|
this.m_localPosition = new b2Vec2();
|
|
}
|
|
b2CircleShape.prototype.m_localPosition = new b2Vec2();
|
|
b2CircleShape.prototype.m_radius = null;
|
|
b2CircleShape.prototype.TestPoint = function (transform, p) {
|
|
|
|
var tMat = transform.R;
|
|
var dX = transform.position.x + (tMat.col1.x * this.m_localPosition.x + tMat.col2.x * this.m_localPosition.y);
|
|
var dY = transform.position.y + (tMat.col1.y * this.m_localPosition.x + tMat.col2.y * this.m_localPosition.y);
|
|
|
|
dX = p.x - dX;
|
|
dY = p.y - dY;
|
|
|
|
return (dX*dX + dY*dY) <= this.m_radius * this.m_radius;
|
|
}
|
|
b2CircleShape.prototype.TestSegment = function ( transform,
|
|
lambda,
|
|
normal,
|
|
segment,
|
|
maxLambda) {
|
|
|
|
var tMat = transform.R;
|
|
var positionX = transform.position.x + (tMat.col1.x * this.m_localPosition.x + tMat.col2.x * this.m_localPosition.y);
|
|
var positionY = transform.position.y + (tMat.col1.y * this.m_localPosition.x + tMat.col2.y * this.m_localPosition.y);
|
|
|
|
|
|
var sX = segment.p1.x - positionX;
|
|
var sY = segment.p1.y - positionY;
|
|
|
|
var b = (sX*sX + sY*sY) - this.m_radius * this.m_radius;
|
|
|
|
|
|
if (b < 0.0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
var rX = segment.p2.x - segment.p1.x;
|
|
var rY = segment.p2.y - segment.p1.y;
|
|
|
|
var c = (sX*rX + sY*rY);
|
|
|
|
var rr = (rX*rX + rY*rY);
|
|
var sigma = c * c - rr * b;
|
|
|
|
|
|
if (sigma < 0.0 || rr < Number.MIN_VALUE)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
var a = -(c + Math.sqrt(sigma));
|
|
|
|
|
|
if (0.0 <= a && a <= maxLambda * rr)
|
|
{
|
|
a /= rr;
|
|
|
|
lambda[0] = a;
|
|
|
|
normal.x = sX + a * rX;
|
|
normal.y = sY + a * rY;
|
|
normal.Normalize();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
b2CircleShape.prototype.ComputeAABB = function (aabb, transform) {
|
|
|
|
var tMat = transform.R;
|
|
var pX = transform.position.x + (tMat.col1.x * this.m_localPosition.x + tMat.col2.x * this.m_localPosition.y);
|
|
var pY = transform.position.y + (tMat.col1.y * this.m_localPosition.x + tMat.col2.y * this.m_localPosition.y);
|
|
aabb.lowerBound.Set(pX - this.m_radius, pY - this.m_radius);
|
|
aabb.upperBound.Set(pX + this.m_radius, pY + this.m_radius);
|
|
}
|
|
b2CircleShape.prototype.ComputeSweptAABB = function ( aabb,
|
|
transform1,
|
|
transform2) {
|
|
var tMat;
|
|
|
|
tMat = transform1.R;
|
|
var p1X = transform1.position.x + (tMat.col1.x * this.m_localPosition.x + tMat.col2.x * this.m_localPosition.y);
|
|
var p1Y = transform1.position.y + (tMat.col1.y * this.m_localPosition.x + tMat.col2.y * this.m_localPosition.y);
|
|
|
|
tMat = transform2.R;
|
|
var p2X = transform2.position.x + (tMat.col1.x * this.m_localPosition.x + tMat.col2.x * this.m_localPosition.y);
|
|
var p2Y = transform2.position.y + (tMat.col1.y * this.m_localPosition.x + tMat.col2.y * this.m_localPosition.y);
|
|
|
|
|
|
|
|
|
|
|
|
aabb.lowerBound.Set((p1X < p2X ? p1X : p2X) - this.m_radius, (p1Y < p2Y ? p1Y : p2Y) - this.m_radius);
|
|
|
|
aabb.upperBound.Set((p1X > p2X ? p1X : p2X) + this.m_radius, (p1Y > p2Y ? p1Y : p2Y) + this.m_radius);
|
|
}
|
|
b2CircleShape.prototype.ComputeMass = function (massData) {
|
|
massData.mass = this.m_density * b2Settings.b2_pi * this.m_radius * this.m_radius;
|
|
massData.center.SetV(this.m_localPosition);
|
|
|
|
|
|
|
|
massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + (this.m_localPosition.x*this.m_localPosition.x + this.m_localPosition.y*this.m_localPosition.y));
|
|
}
|
|
b2CircleShape.prototype.GetLocalPosition = function () {
|
|
return this.m_localPosition;
|
|
}
|
|
b2CircleShape.prototype.GetRadius = function () {
|
|
return this.m_radius;
|
|
}
|
|
b2CircleShape.prototype.UpdateSweepRadius = function (center) {
|
|
|
|
|
|
|
|
var dX = this.m_localPosition.x - center.x;
|
|
var dY = this.m_localPosition.y - center.y;
|
|
dX = Math.sqrt(dX*dX + dY*dY);
|
|
|
|
this.m_sweepRadius = dX + this.m_radius - b2Settings.b2_toiSlop;
|
|
}
|
|
exports.b2CircleShape = b2CircleShape;
|
|
|
|
|
|
var b2ShapeDef = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ShapeDef.prototype.__constructor = function(){}
|
|
b2ShapeDef.prototype.__varz = function(){
|
|
this.type = b2Shape.e_unknownShape;
|
|
this.filter = new b2FilterData();
|
|
}
|
|
b2ShapeDef.prototype.type = b2Shape.e_unknownShape;
|
|
b2ShapeDef.prototype.userData = null;
|
|
b2ShapeDef.prototype.friction = 0.2;
|
|
b2ShapeDef.prototype.restitution = 0.0;
|
|
b2ShapeDef.prototype.density = 0.0;
|
|
b2ShapeDef.prototype.isSensor = false;
|
|
b2ShapeDef.prototype.filter = new b2FilterData();
|
|
exports.b2ShapeDef = b2ShapeDef;
|
|
|
|
|
|
var b2PolygonDef = function() {
|
|
b2ShapeDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PolygonDef.prototype, b2ShapeDef.prototype)
|
|
b2PolygonDef.prototype._super = function(){ b2ShapeDef.prototype.__constructor.apply(this, arguments) }
|
|
b2PolygonDef.prototype.__constructor = function () {
|
|
this.type = b2Shape.e_polygonShape;
|
|
this.vertexCount = 0;
|
|
|
|
for (var i = 0; i < b2Settings.b2_maxPolygonVertices; i++){
|
|
this.vertices[i] = new b2Vec2();
|
|
}
|
|
}
|
|
b2PolygonDef.prototype.__varz = function(){
|
|
this.vertices = new Array(b2Settings.b2_maxPolygonVertices);
|
|
}
|
|
b2PolygonDef.s_mat = new b2Mat22();
|
|
b2PolygonDef.prototype.vertices = new Array(b2Settings.b2_maxPolygonVertices);
|
|
b2PolygonDef.prototype.vertexCount = 0;
|
|
b2PolygonDef.prototype.SetAsBox = function (hx, hy) {
|
|
this.vertexCount = 4;
|
|
this.vertices[0].Set(-hx, -hy);
|
|
this.vertices[1].Set( hx, -hy);
|
|
this.vertices[2].Set( hx, hy);
|
|
this.vertices[3].Set(-hx, hy);
|
|
}
|
|
b2PolygonDef.prototype.SetAsOrientedBox = function (hx, hy, center, angle) {
|
|
|
|
{
|
|
this.vertexCount = 4;
|
|
this.vertices[0].Set(-hx, -hy);
|
|
this.vertices[1].Set( hx, -hy);
|
|
this.vertices[2].Set( hx, hy);
|
|
this.vertices[3].Set(-hx, hy);
|
|
}
|
|
|
|
if (center){
|
|
|
|
|
|
var xfPosition = center;
|
|
|
|
var xfR = b2PolygonDef.s_mat;
|
|
xfR.Set(angle);
|
|
|
|
for (var i = 0; i < this.vertexCount; ++i)
|
|
{
|
|
|
|
|
|
center = this.vertices[i];
|
|
hx = xfPosition.x + (xfR.col1.x * center.x + xfR.col2.x * center.y)
|
|
center.y = xfPosition.y + (xfR.col1.y * center.x + xfR.col2.y * center.y)
|
|
center.x = hx;
|
|
}
|
|
}
|
|
}
|
|
exports.b2PolygonDef = b2PolygonDef;
|
|
|
|
|
|
var b2PolygonShape = function() {
|
|
b2Shape.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PolygonShape.prototype, b2Shape.prototype)
|
|
b2PolygonShape.prototype._super = function(){ b2Shape.prototype.__constructor.apply(this, arguments) }
|
|
b2PolygonShape.prototype.__constructor = function (def) {
|
|
this._super(def);
|
|
|
|
|
|
this.m_type = b2Shape.e_polygonShape;
|
|
var poly = def;
|
|
|
|
|
|
this.m_vertexCount = poly.vertexCount;
|
|
|
|
|
|
var i = 0;
|
|
var i1 = i;
|
|
var i2 = i;
|
|
|
|
|
|
for (i = 0; i < this.m_vertexCount; ++i)
|
|
{
|
|
this.m_vertices[i] = poly.vertices[i].Copy();
|
|
}
|
|
|
|
|
|
for (i = 0; i < this.m_vertexCount; ++i)
|
|
{
|
|
i1 = i;
|
|
i2 = i + 1 < this.m_vertexCount ? i + 1 : 0;
|
|
|
|
var edgeX = this.m_vertices[i2].x - this.m_vertices[i1].x;
|
|
var edgeY = this.m_vertices[i2].y - this.m_vertices[i1].y;
|
|
|
|
|
|
var len = Math.sqrt(edgeX*edgeX + edgeY*edgeY);
|
|
|
|
this.m_normals[i] = new b2Vec2(edgeY/len, -edgeX/len);
|
|
}
|
|
|
|
|
|
|
|
|
|
this.m_centroid = b2PolygonShape.ComputeCentroid(poly.vertices, poly.vertexCount);
|
|
|
|
|
|
b2PolygonShape.ComputeOBB(this.m_obb, this.m_vertices, this.m_vertexCount);
|
|
|
|
|
|
|
|
for (i = 0; i < this.m_vertexCount; ++i)
|
|
{
|
|
i1 = i - 1 >= 0 ? i - 1 : this.m_vertexCount - 1;
|
|
i2 = i;
|
|
|
|
|
|
var n1X = this.m_normals[i1].x;
|
|
var n1Y = this.m_normals[i1].y;
|
|
|
|
var n2X = this.m_normals[i2].x;
|
|
var n2Y = this.m_normals[i2].y;
|
|
|
|
var vX = this.m_vertices[i].x - this.m_centroid.x;
|
|
var vY = this.m_vertices[i].y - this.m_centroid.y;
|
|
|
|
|
|
var dX = (n1X*vX + n1Y*vY) - b2Settings.b2_toiSlop;
|
|
var dY = (n2X*vX + n2Y*vY) - b2Settings.b2_toiSlop;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var det = 1.0/(n1X * n2Y - n1Y * n2X);
|
|
|
|
this.m_coreVertices[i] = new b2Vec2( det * (n2Y * dX - n1Y * dY) + this.m_centroid.x,
|
|
det * (n1X * dY - n2X * dX) + this.m_centroid.y);
|
|
}
|
|
}
|
|
b2PolygonShape.prototype.__varz = function(){
|
|
this.s_supportVec = new b2Vec2();
|
|
this.m_obb = new b2OBB();
|
|
this.m_vertices = new Array(b2Settings.b2_maxPolygonVertices);
|
|
this.m_normals = new Array(b2Settings.b2_maxPolygonVertices);
|
|
this.m_coreVertices = new Array(b2Settings.b2_maxPolygonVertices);
|
|
}
|
|
b2PolygonShape.s_computeMat = new b2Mat22();
|
|
b2PolygonShape.s_sweptAABB1 = new b2AABB();
|
|
b2PolygonShape.s_sweptAABB2 = new b2AABB();
|
|
b2PolygonShape.ComputeCentroid = function (vs, count) {
|
|
|
|
|
|
var c = new b2Vec2();
|
|
var area = 0.0;
|
|
|
|
|
|
|
|
|
|
var p1X = 0.0;
|
|
var p1Y = 0.0;
|
|
|
|
|
|
var inv3 = 1.0 / 3.0;
|
|
|
|
for (var i = 0; i < count; ++i)
|
|
{
|
|
|
|
|
|
|
|
|
|
var p2 = vs[i];
|
|
|
|
var p3 = i + 1 < count ? vs[parseInt(i+1)] : vs[0];
|
|
|
|
|
|
var e1X = p2.x - p1X;
|
|
var e1Y = p2.y - p1Y;
|
|
|
|
var e2X = p3.x - p1X;
|
|
var e2Y = p3.y - p1Y;
|
|
|
|
|
|
var D = (e1X * e2Y - e1Y * e2X);
|
|
|
|
|
|
var triangleArea = 0.5 * D;
|
|
area += triangleArea;
|
|
|
|
|
|
|
|
c.x += triangleArea * inv3 * (p1X + p2.x + p3.x);
|
|
c.y += triangleArea * inv3 * (p1Y + p2.y + p3.y);
|
|
}
|
|
|
|
|
|
|
|
|
|
c.x *= 1.0 / area;
|
|
c.y *= 1.0 / area;
|
|
return c;
|
|
}
|
|
b2PolygonShape.ComputeOBB = function (obb, vs, count) {
|
|
var i = 0;
|
|
|
|
var p = new Array(b2Settings.b2_maxPolygonVertices + 1);
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
p[i] = vs[i];
|
|
}
|
|
p[count] = p[0];
|
|
|
|
var minArea = Number.MAX_VALUE;
|
|
|
|
for (i = 1; i <= count; ++i)
|
|
{
|
|
var root = p[parseInt(i-1)];
|
|
|
|
var uxX = p[i].x - root.x;
|
|
var uxY = p[i].y - root.y;
|
|
|
|
var length = Math.sqrt(uxX*uxX + uxY*uxY);
|
|
uxX /= length;
|
|
uxY /= length;
|
|
|
|
|
|
var uyX = -uxY;
|
|
var uyY = uxX;
|
|
|
|
var lowerX = Number.MAX_VALUE;
|
|
var lowerY = Number.MAX_VALUE;
|
|
|
|
var upperX = -Number.MAX_VALUE;
|
|
var upperY = -Number.MAX_VALUE;
|
|
|
|
for (var j = 0; j < count; ++j)
|
|
{
|
|
|
|
var dX = p[j].x - root.x;
|
|
var dY = p[j].y - root.y;
|
|
|
|
|
|
var rX = (uxX*dX + uxY*dY);
|
|
|
|
var rY = (uyX*dX + uyY*dY);
|
|
|
|
if (rX < lowerX) lowerX = rX;
|
|
if (rY < lowerY) lowerY = rY;
|
|
|
|
if (rX > upperX) upperX = rX;
|
|
if (rY > upperY) upperY = rY;
|
|
}
|
|
|
|
var area = (upperX - lowerX) * (upperY - lowerY);
|
|
if (area < 0.95 * minArea)
|
|
{
|
|
minArea = area;
|
|
|
|
obb.R.col1.x = uxX;
|
|
obb.R.col1.y = uxY;
|
|
|
|
obb.R.col2.x = uyX;
|
|
obb.R.col2.y = uyY;
|
|
|
|
var centerX = 0.5 * (lowerX + upperX);
|
|
var centerY = 0.5 * (lowerY + upperY);
|
|
|
|
var tMat = obb.R;
|
|
obb.center.x = root.x + (tMat.col1.x * centerX + tMat.col2.x * centerY);
|
|
obb.center.y = root.y + (tMat.col1.y * centerX + tMat.col2.y * centerY);
|
|
|
|
obb.extents.x = 0.5 * (upperX - lowerX);
|
|
obb.extents.y = 0.5 * (upperY - lowerY);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
b2PolygonShape.prototype.s_supportVec = new b2Vec2();
|
|
b2PolygonShape.prototype.m_centroid = null;
|
|
b2PolygonShape.prototype.m_obb = new b2OBB();
|
|
b2PolygonShape.prototype.m_vertices = new Array(b2Settings.b2_maxPolygonVertices);
|
|
b2PolygonShape.prototype.m_normals = new Array(b2Settings.b2_maxPolygonVertices);
|
|
b2PolygonShape.prototype.m_coreVertices = new Array(b2Settings.b2_maxPolygonVertices);
|
|
b2PolygonShape.prototype.m_vertexCount = 0;
|
|
b2PolygonShape.prototype.TestPoint = function (xf, p) {
|
|
var tVec;
|
|
|
|
|
|
var tMat = xf.R;
|
|
var tX = p.x - xf.position.x;
|
|
var tY = p.y - xf.position.y;
|
|
var pLocalX = (tX*tMat.col1.x + tY*tMat.col1.y);
|
|
var pLocalY = (tX*tMat.col2.x + tY*tMat.col2.y);
|
|
|
|
for (var i = 0; i < this.m_vertexCount; ++i)
|
|
{
|
|
|
|
tVec = this.m_vertices[i];
|
|
tX = pLocalX - tVec.x;
|
|
tY = pLocalY - tVec.y;
|
|
tVec = this.m_normals[i];
|
|
var dot = (tVec.x * tX + tVec.y * tY);
|
|
if (dot > 0.0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
b2PolygonShape.prototype.TestSegment = function ( xf,
|
|
lambda,
|
|
normal,
|
|
segment,
|
|
maxLambda) {
|
|
var lower = 0.0;
|
|
var upper = maxLambda;
|
|
|
|
var tX;
|
|
var tY;
|
|
var tMat;
|
|
var tVec;
|
|
|
|
|
|
tX = segment.p1.x - xf.position.x;
|
|
tY = segment.p1.y - xf.position.y;
|
|
tMat = xf.R;
|
|
var p1X = (tX * tMat.col1.x + tY * tMat.col1.y);
|
|
var p1Y = (tX * tMat.col2.x + tY * tMat.col2.y);
|
|
|
|
tX = segment.p2.x - xf.position.x;
|
|
tY = segment.p2.y - xf.position.y;
|
|
tMat = xf.R;
|
|
var p2X = (tX * tMat.col1.x + tY * tMat.col1.y);
|
|
var p2Y = (tX * tMat.col2.x + tY * tMat.col2.y);
|
|
|
|
var dX = p2X - p1X;
|
|
var dY = p2Y - p1Y;
|
|
var index = -1;
|
|
|
|
for (var i = 0; i < this.m_vertexCount; ++i)
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
tVec = this.m_vertices[i];
|
|
tX = tVec.x - p1X;
|
|
tY = tVec.y - p1Y;
|
|
tVec = this.m_normals[i];
|
|
var numerator = (tVec.x*tX + tVec.y*tY);
|
|
|
|
var denominator = (tVec.x*dX + tVec.y*dY);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (denominator < 0.0 && numerator < lower * denominator)
|
|
{
|
|
|
|
|
|
lower = numerator / denominator;
|
|
index = i;
|
|
}
|
|
else if (denominator > 0.0 && numerator < upper * denominator)
|
|
{
|
|
|
|
|
|
upper = numerator / denominator;
|
|
}
|
|
|
|
if (upper < lower)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (index >= 0)
|
|
{
|
|
|
|
lambda[0] = lower;
|
|
|
|
tMat = xf.R;
|
|
tVec = this.m_normals[index];
|
|
normal.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
normal.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
b2PolygonShape.prototype.ComputeAABB = function (aabb, xf) {
|
|
var tMat;
|
|
var tVec;
|
|
|
|
var R = b2PolygonShape.s_computeMat;
|
|
|
|
tMat = xf.R;
|
|
tVec = this.m_obb.R.col1;
|
|
|
|
R.col1.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
R.col1.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
tVec = this.m_obb.R.col2;
|
|
|
|
R.col2.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
R.col2.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
|
|
R.Abs();
|
|
var absR = R;
|
|
|
|
tVec = this.m_obb.extents;
|
|
var hX = (absR.col1.x * tVec.x + absR.col2.x * tVec.y);
|
|
var hY = (absR.col1.y * tVec.x + absR.col2.y * tVec.y);
|
|
|
|
tMat = xf.R;
|
|
tVec = this.m_obb.center;
|
|
var positionX = xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
var positionY = xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
aabb.lowerBound.Set(positionX - hX, positionY - hY);
|
|
|
|
aabb.upperBound.Set(positionX + hX, positionY + hY);
|
|
}
|
|
b2PolygonShape.prototype.ComputeSweptAABB = function ( aabb,
|
|
transform1,
|
|
transform2) {
|
|
|
|
var aabb1 = b2PolygonShape.s_sweptAABB1;
|
|
var aabb2 = b2PolygonShape.s_sweptAABB2;
|
|
this.ComputeAABB(aabb1, transform1);
|
|
this.ComputeAABB(aabb2, transform2);
|
|
|
|
aabb.lowerBound.Set((aabb1.lowerBound.x < aabb2.lowerBound.x ? aabb1.lowerBound.x : aabb2.lowerBound.x),
|
|
(aabb1.lowerBound.y < aabb2.lowerBound.y ? aabb1.lowerBound.y : aabb2.lowerBound.y));
|
|
|
|
aabb.upperBound.Set((aabb1.upperBound.x > aabb2.upperBound.x ? aabb1.upperBound.x : aabb2.upperBound.x),
|
|
(aabb1.upperBound.y > aabb2.upperBound.y ? aabb1.upperBound.y : aabb2.upperBound.y));
|
|
}
|
|
b2PolygonShape.prototype.ComputeMass = function (massData) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var centerX = 0.0;
|
|
var centerY = 0.0;
|
|
var area = 0.0;
|
|
var I = 0.0;
|
|
|
|
|
|
|
|
|
|
var p1X = 0.0;
|
|
var p1Y = 0.0;
|
|
|
|
|
|
var k_inv3 = 1.0 / 3.0;
|
|
|
|
for (var i = 0; i < this.m_vertexCount; ++i)
|
|
{
|
|
|
|
|
|
|
|
|
|
var p2 = this.m_vertices[i];
|
|
|
|
var p3 = i + 1 < this.m_vertexCount ? this.m_vertices[parseInt(i+1)] : this.m_vertices[0];
|
|
|
|
|
|
var e1X = p2.x - p1X;
|
|
var e1Y = p2.y - p1Y;
|
|
|
|
var e2X = p3.x - p1X;
|
|
var e2Y = p3.y - p1Y;
|
|
|
|
|
|
var D = e1X * e2Y - e1Y * e2X;
|
|
|
|
|
|
var triangleArea = 0.5 * D;
|
|
area += triangleArea;
|
|
|
|
|
|
|
|
centerX += triangleArea * k_inv3 * (p1X + p2.x + p3.x);
|
|
centerY += triangleArea * k_inv3 * (p1Y + p2.y + p3.y);
|
|
|
|
|
|
var px = p1X;
|
|
var py = p1Y;
|
|
|
|
var ex1 = e1X;
|
|
var ey1 = e1Y;
|
|
|
|
var ex2 = e2X;
|
|
var ey2 = e2Y;
|
|
|
|
|
|
var intx2 = k_inv3 * (0.25 * (ex1*ex1 + ex2*ex1 + ex2*ex2) + (px*ex1 + px*ex2)) + 0.5*px*px;
|
|
|
|
var inty2 = k_inv3 * (0.25 * (ey1*ey1 + ey2*ey1 + ey2*ey2) + (py*ey1 + py*ey2)) + 0.5*py*py;
|
|
|
|
I += D * (intx2 + inty2);
|
|
}
|
|
|
|
|
|
massData.mass = this.m_density * area;
|
|
|
|
|
|
|
|
|
|
centerX *= 1.0 / area;
|
|
centerY *= 1.0 / area;
|
|
|
|
massData.center.Set(centerX, centerY);
|
|
|
|
|
|
massData.I = this.m_density * I;
|
|
}
|
|
b2PolygonShape.prototype.GetOBB = function () {
|
|
return this.m_obb;
|
|
}
|
|
b2PolygonShape.prototype.GetCentroid = function () {
|
|
return this.m_centroid;
|
|
}
|
|
b2PolygonShape.prototype.GetVertexCount = function () {
|
|
return this.m_vertexCount;
|
|
}
|
|
b2PolygonShape.prototype.GetVertices = function () {
|
|
return this.m_vertices;
|
|
}
|
|
b2PolygonShape.prototype.GetCoreVertices = function () {
|
|
return this.m_coreVertices;
|
|
}
|
|
b2PolygonShape.prototype.GetNormals = function () {
|
|
return this.m_normals;
|
|
}
|
|
b2PolygonShape.prototype.GetFirstVertex = function (xf) {
|
|
return b2Math.b2MulX(xf, this.m_coreVertices[0]);
|
|
}
|
|
b2PolygonShape.prototype.Centroid = function (xf) {
|
|
return b2Math.b2MulX(xf, this.m_centroid);
|
|
}
|
|
b2PolygonShape.prototype.Support = function (xf, dX, dY) {
|
|
var tVec;
|
|
|
|
var tMat;
|
|
|
|
tMat = xf.R;
|
|
var dLocalX = (dX * tMat.col1.x + dY * tMat.col1.y);
|
|
var dLocalY = (dX * tMat.col2.x + dY * tMat.col2.y);
|
|
|
|
var bestIndex = 0;
|
|
|
|
tVec = this.m_coreVertices[0];
|
|
var bestValue = (tVec.x*dLocalX + tVec.y*dLocalY);
|
|
for (var i = 1; i < this.m_vertexCount; ++i)
|
|
{
|
|
|
|
tVec = this.m_coreVertices[i];
|
|
var value = (tVec.x*dLocalX + tVec.y*dLocalY);
|
|
if (value > bestValue)
|
|
{
|
|
bestIndex = i;
|
|
bestValue = value;
|
|
}
|
|
}
|
|
|
|
|
|
tMat = xf.R;
|
|
tVec = this.m_coreVertices[bestIndex];
|
|
this.s_supportVec.x = xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
this.s_supportVec.y = xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
return this.s_supportVec;
|
|
|
|
}
|
|
b2PolygonShape.prototype.UpdateSweepRadius = function (center) {
|
|
var tVec;
|
|
|
|
|
|
|
|
this.m_sweepRadius = 0.0;
|
|
for (var i = 0; i < this.m_vertexCount; ++i)
|
|
{
|
|
|
|
tVec = this.m_coreVertices[i];
|
|
var dX = tVec.x - center.x;
|
|
var dY = tVec.y - center.y;
|
|
dX = Math.sqrt(dX*dX + dY*dY);
|
|
|
|
if (dX > this.m_sweepRadius) this.m_sweepRadius = dX;
|
|
}
|
|
}
|
|
exports.b2PolygonShape = b2PolygonShape;
|
|
|
|
|
|
var b2CircleDef = function() {
|
|
b2ShapeDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2CircleDef.prototype, b2ShapeDef.prototype)
|
|
b2CircleDef.prototype._super = function(){ b2ShapeDef.prototype.__constructor.apply(this, arguments) }
|
|
b2CircleDef.prototype.__constructor = function () {
|
|
this.type = b2Shape.e_circleShape;
|
|
this.radius = 1.0;
|
|
}
|
|
b2CircleDef.prototype.__varz = function(){
|
|
this.localPosition = new b2Vec2(0.0, 0.0);
|
|
}
|
|
b2CircleDef.prototype.localPosition = new b2Vec2(0.0, 0.0);
|
|
b2CircleDef.prototype.radius = null;
|
|
exports.b2CircleDef = b2CircleDef;
|
|
|
|
|
|
var b2TimeStep = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2TimeStep.prototype.__constructor = function(){}
|
|
b2TimeStep.prototype.__varz = function(){
|
|
}
|
|
b2TimeStep.prototype.dt = null;
|
|
b2TimeStep.prototype.inv_dt = null;
|
|
b2TimeStep.prototype.dtRatio = null;
|
|
b2TimeStep.prototype.maxIterations = 0;
|
|
b2TimeStep.prototype.warmStarting = null;
|
|
b2TimeStep.prototype.positionCorrection = null;
|
|
exports.b2TimeStep = b2TimeStep;
|
|
|
|
|
|
var b2BoundaryListener = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2BoundaryListener.prototype.__constructor = function(){}
|
|
b2BoundaryListener.prototype.__varz = function(){
|
|
}
|
|
b2BoundaryListener.prototype.Violation = function (body) {}
|
|
exports.b2BoundaryListener = b2BoundaryListener;
|
|
|
|
|
|
var b2ContactListener = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactListener.prototype.__constructor = function(){}
|
|
b2ContactListener.prototype.__varz = function(){
|
|
}
|
|
b2ContactListener.prototype.Add = function (point) {}
|
|
b2ContactListener.prototype.Persist = function (point) {}
|
|
b2ContactListener.prototype.Remove = function (point) {}
|
|
b2ContactListener.prototype.Result = function (point) {}
|
|
exports.b2ContactListener = b2ContactListener;
|
|
|
|
|
|
var b2DestructionListener = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2DestructionListener.prototype.__constructor = function(){}
|
|
b2DestructionListener.prototype.__varz = function(){
|
|
}
|
|
b2DestructionListener.prototype.SayGoodbyeJoint = function (joint) {}
|
|
b2DestructionListener.prototype.SayGoodbyeShape = function (shape) {}
|
|
exports.b2DestructionListener = b2DestructionListener;
|
|
|
|
|
|
var b2DebugDraw = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2DebugDraw.prototype.__constructor = function () {
|
|
this.m_drawFlags = 0;
|
|
}
|
|
b2DebugDraw.prototype.__varz = function(){
|
|
}
|
|
b2DebugDraw.e_shapeBit = 0x0001;
|
|
b2DebugDraw.e_jointBit = 0x0002;
|
|
b2DebugDraw.e_coreShapeBit = 0x0004;
|
|
b2DebugDraw.e_aabbBit = 0x0008;
|
|
b2DebugDraw.e_obbBit = 0x0010;
|
|
b2DebugDraw.e_pairBit = 0x0020;
|
|
b2DebugDraw.e_centerOfMassBit = 0x0040;
|
|
b2DebugDraw.prototype.m_drawFlags = 0;
|
|
b2DebugDraw.prototype.m_sprite = null;
|
|
b2DebugDraw.prototype.m_drawScale = 1.0;
|
|
b2DebugDraw.prototype.m_lineThickness = 1.0;
|
|
b2DebugDraw.prototype.m_alpha = 1.0;
|
|
b2DebugDraw.prototype.m_fillAlpha = 1.0;
|
|
b2DebugDraw.prototype.m_xformScale = 1.0;
|
|
b2DebugDraw.prototype.SetFlags = function (flags) {
|
|
this.m_drawFlags = flags;
|
|
}
|
|
b2DebugDraw.prototype.GetFlags = function () {
|
|
return this.m_drawFlags;
|
|
}
|
|
b2DebugDraw.prototype.AppendFlags = function (flags) {
|
|
this.m_drawFlags |= flags;
|
|
}
|
|
b2DebugDraw.prototype.ClearFlags = function (flags) {
|
|
this.m_drawFlags &= ~flags;
|
|
}
|
|
b2DebugDraw.prototype.DrawPolygon = function (vertices, vertexCount, color) {
|
|
|
|
this.m_sprite.graphics.lineStyle(this.m_lineThickness, color.color, this.m_alpha);
|
|
this.m_sprite.graphics.moveTo(vertices[0].x * this.m_drawScale, vertices[0].y * this.m_drawScale);
|
|
for (var i = 1; i < vertexCount; i++){
|
|
this.m_sprite.graphics.lineTo(vertices[i].x * this.m_drawScale, vertices[i].y * this.m_drawScale);
|
|
}
|
|
this.m_sprite.graphics.lineTo(vertices[0].x * this.m_drawScale, vertices[0].y * this.m_drawScale);
|
|
|
|
}
|
|
b2DebugDraw.prototype.DrawSolidPolygon = function (vertices, vertexCount, color) {
|
|
|
|
this.m_sprite.graphics.lineStyle(this.m_lineThickness, color.color, this.m_alpha);
|
|
this.m_sprite.graphics.moveTo(vertices[0].x * this.m_drawScale, vertices[0].y * this.m_drawScale);
|
|
this.m_sprite.graphics.beginFill(color.color, this.m_fillAlpha);
|
|
for (var i = 1; i < vertexCount; i++){
|
|
this.m_sprite.graphics.lineTo(vertices[i].x * this.m_drawScale, vertices[i].y * this.m_drawScale);
|
|
}
|
|
this.m_sprite.graphics.lineTo(vertices[0].x * this.m_drawScale, vertices[0].y * this.m_drawScale);
|
|
this.m_sprite.graphics.endFill();
|
|
|
|
}
|
|
b2DebugDraw.prototype.DrawCircle = function (center, radius, color) {
|
|
|
|
this.m_sprite.graphics.lineStyle(this.m_lineThickness, color.color, this.m_alpha);
|
|
this.m_sprite.graphics.drawCircle(center.x * this.m_drawScale, center.y * this.m_drawScale, radius * this.m_drawScale);
|
|
|
|
}
|
|
b2DebugDraw.prototype.DrawSolidCircle = function (center, radius, axis, color) {
|
|
|
|
this.m_sprite.graphics.lineStyle(this.m_lineThickness, color.color, this.m_alpha);
|
|
this.m_sprite.graphics.moveTo(0,0);
|
|
this.m_sprite.graphics.beginFill(color.color, this.m_fillAlpha);
|
|
this.m_sprite.graphics.drawCircle(center.x * this.m_drawScale, center.y * this.m_drawScale, radius * this.m_drawScale);
|
|
this.m_sprite.graphics.endFill();
|
|
this.m_sprite.graphics.moveTo(center.x * this.m_drawScale, center.y * this.m_drawScale);
|
|
this.m_sprite.graphics.lineTo((center.x + axis.x*radius) * this.m_drawScale, (center.y + axis.y*radius) * this.m_drawScale);
|
|
|
|
}
|
|
b2DebugDraw.prototype.DrawSegment = function (p1, p2, color) {
|
|
|
|
this.m_sprite.graphics.lineStyle(this.m_lineThickness, color.color, this.m_alpha);
|
|
this.m_sprite.graphics.moveTo(p1.x * this.m_drawScale, p1.y * this.m_drawScale);
|
|
this.m_sprite.graphics.lineTo(p2.x * this.m_drawScale, p2.y * this.m_drawScale);
|
|
|
|
}
|
|
b2DebugDraw.prototype.DrawXForm = function (xf) {
|
|
|
|
this.m_sprite.graphics.lineStyle(this.m_lineThickness, 0xff0000, this.m_alpha);
|
|
this.m_sprite.graphics.moveTo(xf.position.x * this.m_drawScale, xf.position.y * this.m_drawScale);
|
|
this.m_sprite.graphics.lineTo((xf.position.x + this.m_xformScale*xf.R.col1.x) * this.m_drawScale, (xf.position.y + this.m_xformScale*xf.R.col1.y) * this.m_drawScale);
|
|
|
|
this.m_sprite.graphics.lineStyle(this.m_lineThickness, 0x00ff00, this.m_alpha);
|
|
this.m_sprite.graphics.moveTo(xf.position.x * this.m_drawScale, xf.position.y * this.m_drawScale);
|
|
this.m_sprite.graphics.lineTo((xf.position.x + this.m_xformScale*xf.R.col2.x) * this.m_drawScale, (xf.position.y + this.m_xformScale*xf.R.col2.y) * this.m_drawScale);
|
|
|
|
}
|
|
exports.b2DebugDraw = b2DebugDraw;
|
|
|
|
|
|
var b2BodyDef = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2BodyDef.prototype.__constructor = function () {
|
|
this.massData.center.SetZero();
|
|
this.massData.mass = 0.0;
|
|
this.massData.I = 0.0;
|
|
this.userData = null;
|
|
this.position.Set(0.0, 0.0);
|
|
this.angle = 0.0;
|
|
this.linearDamping = 0.0;
|
|
this.angularDamping = 0.0;
|
|
this.allowSleep = true;
|
|
this.isSleeping = false;
|
|
this.fixedRotation = false;
|
|
this.isBullet = false;
|
|
}
|
|
b2BodyDef.prototype.__varz = function(){
|
|
this.massData = new b2MassData();
|
|
this.position = new b2Vec2();
|
|
}
|
|
b2BodyDef.prototype.massData = new b2MassData();
|
|
b2BodyDef.prototype.userData = null;
|
|
b2BodyDef.prototype.position = new b2Vec2();
|
|
b2BodyDef.prototype.angle = null;
|
|
b2BodyDef.prototype.linearDamping = null;
|
|
b2BodyDef.prototype.angularDamping = null;
|
|
b2BodyDef.prototype.allowSleep = null;
|
|
b2BodyDef.prototype.isSleeping = null;
|
|
b2BodyDef.prototype.fixedRotation = null;
|
|
b2BodyDef.prototype.isBullet = null;
|
|
exports.b2BodyDef = b2BodyDef;
|
|
|
|
|
|
var b2Body = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Body.prototype.__constructor = function (bd, world) {
|
|
|
|
|
|
this.m_flags = 0;
|
|
|
|
if (bd.isBullet)
|
|
{
|
|
this.m_flags |= b2Body.e_bulletFlag;
|
|
}
|
|
if (bd.fixedRotation)
|
|
{
|
|
this.m_flags |= b2Body.e_fixedRotationFlag;
|
|
}
|
|
if (bd.allowSleep)
|
|
{
|
|
this.m_flags |= b2Body.e_allowSleepFlag;
|
|
}
|
|
if (bd.isSleeping)
|
|
{
|
|
this.m_flags |= b2Body.e_sleepFlag;
|
|
}
|
|
|
|
this.m_world = world;
|
|
|
|
this.m_xf.position.SetV(bd.position);
|
|
this.m_xf.R.Set(bd.angle);
|
|
|
|
this.m_sweep.localCenter.SetV(bd.massData.center);
|
|
this.m_sweep.t0 = 1.0;
|
|
this.m_sweep.a0 = this.m_sweep.a = bd.angle;
|
|
|
|
|
|
|
|
var tMat = this.m_xf.R;
|
|
var tVec = this.m_sweep.localCenter;
|
|
|
|
this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
|
|
this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
this.m_sweep.c.x += this.m_xf.position.x;
|
|
this.m_sweep.c.y += this.m_xf.position.y;
|
|
|
|
this.m_sweep.c0.SetV(this.m_sweep.c);
|
|
|
|
this.m_jointList = null;
|
|
this.m_contactList = null;
|
|
this.m_prev = null;
|
|
this.m_next = null;
|
|
|
|
this.m_linearDamping = bd.linearDamping;
|
|
this.m_angularDamping = bd.angularDamping;
|
|
|
|
this.m_force.Set(0.0, 0.0);
|
|
this.m_torque = 0.0;
|
|
|
|
this.m_linearVelocity.SetZero();
|
|
this.m_angularVelocity = 0.0;
|
|
|
|
this.m_sleepTime = 0.0;
|
|
|
|
this.m_invMass = 0.0;
|
|
this.m_I = 0.0;
|
|
this.m_invI = 0.0;
|
|
|
|
this.m_mass = bd.massData.mass;
|
|
|
|
if (this.m_mass > 0.0)
|
|
{
|
|
this.m_invMass = 1.0 / this.m_mass;
|
|
}
|
|
|
|
if ((this.m_flags & b2Body.e_fixedRotationFlag) == 0)
|
|
{
|
|
this.m_I = bd.massData.I;
|
|
}
|
|
|
|
if (this.m_I > 0.0)
|
|
{
|
|
this.m_invI = 1.0 / this.m_I;
|
|
}
|
|
|
|
if (this.m_invMass == 0.0 && this.m_invI == 0.0)
|
|
{
|
|
this.m_type = b2Body.e_staticType;
|
|
}
|
|
else
|
|
{
|
|
this.m_type = b2Body.e_dynamicType;
|
|
}
|
|
|
|
this.m_userData = bd.userData;
|
|
|
|
this.m_shapeList = null;
|
|
this.m_shapeCount = 0;
|
|
}
|
|
b2Body.prototype.__varz = function(){
|
|
this.m_xf = new b2XForm();
|
|
this.m_sweep = new b2Sweep();
|
|
this.m_linearVelocity = new b2Vec2();
|
|
this.m_force = new b2Vec2();
|
|
}
|
|
b2Body.e_frozenFlag = 0x0002;
|
|
b2Body.e_islandFlag = 0x0004;
|
|
b2Body.e_sleepFlag = 0x0008;
|
|
b2Body.e_allowSleepFlag = 0x0010;
|
|
b2Body.e_bulletFlag = 0x0020;
|
|
b2Body.e_fixedRotationFlag = 0x0040;
|
|
b2Body.e_staticType = 1;
|
|
b2Body.e_dynamicType = 2;
|
|
b2Body.e_maxTypes = 3;
|
|
b2Body.s_massData = new b2MassData();
|
|
b2Body.s_xf1 = new b2XForm();
|
|
b2Body.prototype.m_flags = 0;
|
|
b2Body.prototype.m_type = 0;
|
|
b2Body.prototype.m_xf = new b2XForm();
|
|
b2Body.prototype.m_sweep = new b2Sweep();
|
|
b2Body.prototype.m_linearVelocity = new b2Vec2();
|
|
b2Body.prototype.m_angularVelocity = null;
|
|
b2Body.prototype.m_force = new b2Vec2();
|
|
b2Body.prototype.m_torque = null;
|
|
b2Body.prototype.m_world = null;
|
|
b2Body.prototype.m_prev = null;
|
|
b2Body.prototype.m_next = null;
|
|
b2Body.prototype.m_shapeList = null;
|
|
b2Body.prototype.m_shapeCount = 0;
|
|
b2Body.prototype.m_jointList = null;
|
|
b2Body.prototype.m_contactList = null;
|
|
b2Body.prototype.m_mass = null;
|
|
b2Body.prototype.m_invMass = null;
|
|
b2Body.prototype.m_I = null;
|
|
b2Body.prototype.m_invI = null;
|
|
b2Body.prototype.m_linearDamping = null;
|
|
b2Body.prototype.m_angularDamping = null;
|
|
b2Body.prototype.m_sleepTime = null;
|
|
b2Body.prototype.m_userData = null;
|
|
b2Body.prototype.CreateShape = function (def) {
|
|
|
|
if (this.m_world.m_lock == true)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var s = b2Shape.Create(def, this.m_world.m_blockAllocator);
|
|
|
|
s.m_next = this.m_shapeList;
|
|
this.m_shapeList = s;
|
|
++this.m_shapeCount;
|
|
|
|
s.m_body = this;
|
|
|
|
|
|
s.CreateProxy(this.m_world.m_broadPhase, this.m_xf);
|
|
|
|
|
|
s.UpdateSweepRadius(this.m_sweep.localCenter);
|
|
|
|
return s;
|
|
}
|
|
b2Body.prototype.DestroyShape = function (s) {
|
|
|
|
if (this.m_world.m_lock == true)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
s.DestroyProxy(this.m_world.m_broadPhase);
|
|
|
|
|
|
|
|
var node = this.m_shapeList;
|
|
var ppS = null;
|
|
var found = false;
|
|
while (node != null)
|
|
{
|
|
if (node == s)
|
|
{
|
|
if (ppS)
|
|
ppS.m_next = s.m_next;
|
|
else
|
|
this.m_shapeList = s.m_next;
|
|
|
|
found = true;
|
|
break;
|
|
}
|
|
|
|
ppS = node;
|
|
node = node.m_next;
|
|
}
|
|
|
|
|
|
|
|
|
|
s.m_body = null;
|
|
s.m_next = null;
|
|
|
|
--this.m_shapeCount;
|
|
|
|
b2Shape.Destroy(s, this.m_world.m_blockAllocator);
|
|
}
|
|
b2Body.prototype.SetMass = function (massData) {
|
|
var s;
|
|
|
|
|
|
if (this.m_world.m_lock == true)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this.m_invMass = 0.0;
|
|
this.m_I = 0.0;
|
|
this.m_invI = 0.0;
|
|
|
|
this.m_mass = massData.mass;
|
|
|
|
if (this.m_mass > 0.0)
|
|
{
|
|
this.m_invMass = 1.0 / this.m_mass;
|
|
}
|
|
|
|
if ((this.m_flags & b2Body.e_fixedRotationFlag) == 0)
|
|
{
|
|
this.m_I = massData.I;
|
|
}
|
|
|
|
if (this.m_I > 0.0)
|
|
{
|
|
this.m_invI = 1.0 / this.m_I;
|
|
}
|
|
|
|
|
|
this.m_sweep.localCenter.SetV(massData.center);
|
|
|
|
|
|
var tMat = this.m_xf.R;
|
|
var tVec = this.m_sweep.localCenter;
|
|
|
|
this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
|
|
this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
this.m_sweep.c.x += this.m_xf.position.x;
|
|
this.m_sweep.c.y += this.m_xf.position.y;
|
|
|
|
this.m_sweep.c0.SetV(this.m_sweep.c);
|
|
|
|
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.UpdateSweepRadius(this.m_sweep.localCenter);
|
|
}
|
|
|
|
var oldType = this.m_type;
|
|
if (this.m_invMass == 0.0 && this.m_invI == 0.0)
|
|
{
|
|
this.m_type = b2Body.e_staticType;
|
|
}
|
|
else
|
|
{
|
|
this.m_type = b2Body.e_dynamicType;
|
|
}
|
|
|
|
|
|
if (oldType != this.m_type)
|
|
{
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.RefilterProxy(this.m_world.m_broadPhase, this.m_xf);
|
|
}
|
|
}
|
|
}
|
|
b2Body.prototype.SetMassFromShapes = function () {
|
|
|
|
var s;
|
|
|
|
|
|
if (this.m_world.m_lock == true)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
this.m_mass = 0.0;
|
|
this.m_invMass = 0.0;
|
|
this.m_I = 0.0;
|
|
this.m_invI = 0.0;
|
|
|
|
|
|
var centerX = 0.0;
|
|
var centerY = 0.0;
|
|
var massData = b2Body.s_massData;
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.ComputeMass(massData);
|
|
this.m_mass += massData.mass;
|
|
|
|
centerX += massData.mass * massData.center.x;
|
|
centerY += massData.mass * massData.center.y;
|
|
this.m_I += massData.I;
|
|
}
|
|
|
|
|
|
if (this.m_mass > 0.0)
|
|
{
|
|
this.m_invMass = 1.0 / this.m_mass;
|
|
centerX *= this.m_invMass;
|
|
centerY *= this.m_invMass;
|
|
}
|
|
|
|
if (this.m_I > 0.0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0)
|
|
{
|
|
|
|
|
|
this.m_I -= this.m_mass * (centerX * centerX + centerY * centerY);
|
|
|
|
this.m_invI = 1.0 / this.m_I;
|
|
}
|
|
else
|
|
{
|
|
this.m_I = 0.0;
|
|
this.m_invI = 0.0;
|
|
}
|
|
|
|
|
|
this.m_sweep.localCenter.Set(centerX, centerY);
|
|
|
|
|
|
var tMat = this.m_xf.R;
|
|
var tVec = this.m_sweep.localCenter;
|
|
|
|
this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
|
|
this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
this.m_sweep.c.x += this.m_xf.position.x;
|
|
this.m_sweep.c.y += this.m_xf.position.y;
|
|
|
|
this.m_sweep.c0.SetV(this.m_sweep.c);
|
|
|
|
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.UpdateSweepRadius(this.m_sweep.localCenter);
|
|
}
|
|
|
|
var oldType = this.m_type;
|
|
if (this.m_invMass == 0.0 && this.m_invI == 0.0)
|
|
{
|
|
this.m_type = b2Body.e_staticType;
|
|
}
|
|
else
|
|
{
|
|
this.m_type = b2Body.e_dynamicType;
|
|
}
|
|
|
|
|
|
if (oldType != this.m_type)
|
|
{
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.RefilterProxy(this.m_world.m_broadPhase, this.m_xf);
|
|
}
|
|
}
|
|
}
|
|
b2Body.prototype.SetXForm = function (position, angle) {
|
|
|
|
var s;
|
|
|
|
|
|
if (this.m_world.m_lock == true)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (this.IsFrozen())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
this.m_xf.R.Set(angle);
|
|
this.m_xf.position.SetV(position);
|
|
|
|
|
|
|
|
var tMat = this.m_xf.R;
|
|
var tVec = this.m_sweep.localCenter;
|
|
|
|
this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
|
|
this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
this.m_sweep.c.x += this.m_xf.position.x;
|
|
this.m_sweep.c.y += this.m_xf.position.y;
|
|
|
|
this.m_sweep.c0.SetV(this.m_sweep.c);
|
|
|
|
this.m_sweep.a0 = this.m_sweep.a = angle;
|
|
|
|
var freeze = false;
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
var inRange = s.Synchronize(this.m_world.m_broadPhase, this.m_xf, this.m_xf);
|
|
|
|
if (inRange == false)
|
|
{
|
|
freeze = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (freeze == true)
|
|
{
|
|
this.m_flags |= b2Body.e_frozenFlag;
|
|
this.m_linearVelocity.SetZero();
|
|
this.m_angularVelocity = 0.0;
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.DestroyProxy(this.m_world.m_broadPhase);
|
|
}
|
|
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
this.m_world.m_broadPhase.Commit();
|
|
return true;
|
|
|
|
}
|
|
b2Body.prototype.GetXForm = function () {
|
|
return this.m_xf;
|
|
}
|
|
b2Body.prototype.GetPosition = function () {
|
|
return this.m_xf.position;
|
|
}
|
|
b2Body.prototype.GetAngle = function () {
|
|
return this.m_sweep.a;
|
|
}
|
|
b2Body.prototype.GetWorldCenter = function () {
|
|
return this.m_sweep.c;
|
|
}
|
|
b2Body.prototype.GetLocalCenter = function () {
|
|
return this.m_sweep.localCenter;
|
|
}
|
|
b2Body.prototype.SetLinearVelocity = function (v) {
|
|
this.m_linearVelocity.SetV(v);
|
|
}
|
|
b2Body.prototype.GetLinearVelocity = function () {
|
|
return this.m_linearVelocity;
|
|
}
|
|
b2Body.prototype.SetAngularVelocity = function (omega) {
|
|
this.m_angularVelocity = omega;
|
|
}
|
|
b2Body.prototype.GetAngularVelocity = function () {
|
|
return this.m_angularVelocity;
|
|
}
|
|
b2Body.prototype.ApplyForce = function (force, point) {
|
|
if (this.IsSleeping())
|
|
{
|
|
this.WakeUp();
|
|
}
|
|
|
|
this.m_force.x += force.x;
|
|
this.m_force.y += force.y;
|
|
|
|
this.m_torque += ((point.x - this.m_sweep.c.x) * force.y - (point.y - this.m_sweep.c.y) * force.x);
|
|
}
|
|
b2Body.prototype.ApplyTorque = function (torque) {
|
|
if (this.IsSleeping())
|
|
{
|
|
this.WakeUp();
|
|
}
|
|
this.m_torque += torque;
|
|
}
|
|
b2Body.prototype.ApplyImpulse = function (impulse, point) {
|
|
if (this.IsSleeping())
|
|
{
|
|
this.WakeUp();
|
|
}
|
|
|
|
this.m_linearVelocity.x += this.m_invMass * impulse.x;
|
|
this.m_linearVelocity.y += this.m_invMass * impulse.y;
|
|
|
|
this.m_angularVelocity += this.m_invI * ((point.x - this.m_sweep.c.x) * impulse.y - (point.y - this.m_sweep.c.y) * impulse.x);
|
|
}
|
|
b2Body.prototype.GetMass = function () {
|
|
return this.m_mass;
|
|
}
|
|
b2Body.prototype.GetInertia = function () {
|
|
return this.m_I;
|
|
}
|
|
b2Body.prototype.GetWorldPoint = function (localPoint) {
|
|
|
|
var A = this.m_xf.R;
|
|
var u = new b2Vec2(A.col1.x * localPoint.x + A.col2.x * localPoint.y,
|
|
A.col1.y * localPoint.x + A.col2.y * localPoint.y);
|
|
u.x += this.m_xf.position.x;
|
|
u.y += this.m_xf.position.y;
|
|
return u;
|
|
}
|
|
b2Body.prototype.GetWorldVector = function (localVector) {
|
|
return b2Math.b2MulMV(this.m_xf.R, localVector);
|
|
}
|
|
b2Body.prototype.GetLocalPoint = function (worldPoint) {
|
|
return b2Math.b2MulXT(this.m_xf, worldPoint);
|
|
}
|
|
b2Body.prototype.GetLocalVector = function (worldVector) {
|
|
return b2Math.b2MulTMV(this.m_xf.R, worldVector);
|
|
}
|
|
b2Body.prototype.GetLinearVelocityFromWorldPoint = function (worldPoint) {
|
|
|
|
return new b2Vec2( this.m_linearVelocity.x - this.m_angularVelocity * (worldPoint.y - this.m_sweep.c.y),
|
|
this.m_linearVelocity.y + this.m_angularVelocity * (worldPoint.x - this.m_sweep.c.x));
|
|
}
|
|
b2Body.prototype.GetLinearVelocityFromLocalPoint = function (localPoint) {
|
|
|
|
var A = this.m_xf.R;
|
|
var worldPoint = new b2Vec2(A.col1.x * localPoint.x + A.col2.x * localPoint.y,
|
|
A.col1.y * localPoint.x + A.col2.y * localPoint.y);
|
|
worldPoint.x += this.m_xf.position.x;
|
|
worldPoint.y += this.m_xf.position.y;
|
|
return new b2Vec2(this.m_linearVelocity.x + this.m_angularVelocity * (worldPoint.y - this.m_sweep.c.y),
|
|
this.m_linearVelocity.x - this.m_angularVelocity * (worldPoint.x - this.m_sweep.c.x));
|
|
}
|
|
b2Body.prototype.IsBullet = function () {
|
|
return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag;
|
|
}
|
|
b2Body.prototype.SetBullet = function (flag) {
|
|
if (flag)
|
|
{
|
|
this.m_flags |= b2Body.e_bulletFlag;
|
|
}
|
|
else
|
|
{
|
|
this.m_flags &= ~b2Body.e_bulletFlag;
|
|
}
|
|
}
|
|
b2Body.prototype.IsStatic = function () {
|
|
return this.m_type == b2Body.e_staticType;
|
|
}
|
|
b2Body.prototype.IsDynamic = function () {
|
|
return this.m_type == b2Body.e_dynamicType;
|
|
}
|
|
b2Body.prototype.IsFrozen = function () {
|
|
return (this.m_flags & b2Body.e_frozenFlag) == b2Body.e_frozenFlag;
|
|
}
|
|
b2Body.prototype.IsSleeping = function () {
|
|
return (this.m_flags & b2Body.e_sleepFlag) == b2Body.e_sleepFlag;
|
|
}
|
|
b2Body.prototype.AllowSleeping = function (flag) {
|
|
if (flag)
|
|
{
|
|
this.m_flags |= b2Body.e_allowSleepFlag;
|
|
}
|
|
else
|
|
{
|
|
this.m_flags &= ~b2Body.e_allowSleepFlag;
|
|
this.WakeUp();
|
|
}
|
|
}
|
|
b2Body.prototype.WakeUp = function () {
|
|
this.m_flags &= ~b2Body.e_sleepFlag;
|
|
this.m_sleepTime = 0.0;
|
|
}
|
|
b2Body.prototype.PutToSleep = function () {
|
|
this.m_flags |= b2Body.e_sleepFlag;
|
|
this.m_sleepTime = 0.0;
|
|
this.m_linearVelocity.SetZero();
|
|
this.m_angularVelocity = 0.0;
|
|
this.m_force.SetZero();
|
|
this.m_torque = 0.0;
|
|
}
|
|
b2Body.prototype.GetShapeList = function () {
|
|
return this.m_shapeList;
|
|
}
|
|
b2Body.prototype.GetJointList = function () {
|
|
return this.m_jointList;
|
|
}
|
|
b2Body.prototype.GetNext = function () {
|
|
return this.m_next;
|
|
}
|
|
b2Body.prototype.GetUserData = function () {
|
|
return this.m_userData;
|
|
}
|
|
b2Body.prototype.SetUserData = function (data) {
|
|
this.m_userData = data;
|
|
}
|
|
b2Body.prototype.GetWorld = function () {
|
|
return this.m_world;
|
|
}
|
|
b2Body.prototype.SynchronizeShapes = function () {
|
|
|
|
var xf1 = b2Body.s_xf1;
|
|
xf1.R.Set(this.m_sweep.a0);
|
|
|
|
var tMat = xf1.R;
|
|
var tVec = this.m_sweep.localCenter;
|
|
xf1.position.x = this.m_sweep.c0.x - (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
xf1.position.y = this.m_sweep.c0.y - (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
|
|
var s;
|
|
|
|
var inRange = true;
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
inRange = s.Synchronize(this.m_world.m_broadPhase, xf1, this.m_xf);
|
|
if (inRange == false)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (inRange == false)
|
|
{
|
|
this.m_flags |= b2Body.e_frozenFlag;
|
|
this.m_linearVelocity.SetZero();
|
|
this.m_angularVelocity = 0.0;
|
|
for (s = this.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.DestroyProxy(this.m_world.m_broadPhase);
|
|
}
|
|
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
b2Body.prototype.SynchronizeTransform = function () {
|
|
this.m_xf.R.Set(this.m_sweep.a);
|
|
|
|
var tMat = this.m_xf.R;
|
|
var tVec = this.m_sweep.localCenter;
|
|
this.m_xf.position.x = this.m_sweep.c.x - (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
this.m_xf.position.y = this.m_sweep.c.y - (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
}
|
|
b2Body.prototype.IsConnected = function (other) {
|
|
for (var jn = this.m_jointList; jn; jn = jn.next)
|
|
{
|
|
if (jn.other == other)
|
|
return jn.joint.m_collideConnected == false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
b2Body.prototype.Advance = function (t) {
|
|
|
|
this.m_sweep.Advance(t);
|
|
this.m_sweep.c.SetV(this.m_sweep.c0);
|
|
this.m_sweep.a = this.m_sweep.a0;
|
|
this.SynchronizeTransform();
|
|
}
|
|
exports.b2Body = b2Body;
|
|
|
|
|
|
var b2ContactFilter = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactFilter.prototype.__constructor = function(){}
|
|
b2ContactFilter.prototype.__varz = function(){
|
|
}
|
|
b2ContactFilter.b2_defaultFilter = new b2ContactFilter();
|
|
b2ContactFilter.prototype.ShouldCollide = function (shape1, shape2) {
|
|
var filter1 = shape1.GetFilterData();
|
|
var filter2 = shape2.GetFilterData();
|
|
|
|
if (filter1.groupIndex == filter2.groupIndex && filter1.groupIndex != 0)
|
|
{
|
|
return filter1.groupIndex > 0;
|
|
}
|
|
|
|
var collide = (filter1.maskBits & filter2.categoryBits) != 0 && (filter1.categoryBits & filter2.maskBits) != 0;
|
|
return collide;
|
|
}
|
|
exports.b2ContactFilter = b2ContactFilter;
|
|
|
|
|
|
var b2ContactResult = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactResult.prototype.__constructor = function(){}
|
|
b2ContactResult.prototype.__varz = function(){
|
|
this.position = new b2Vec2();
|
|
this.normal = new b2Vec2();
|
|
this.id = new b2ContactID();
|
|
}
|
|
b2ContactResult.prototype.shape1 = null;
|
|
b2ContactResult.prototype.shape2 = null;
|
|
b2ContactResult.prototype.position = new b2Vec2();
|
|
b2ContactResult.prototype.normal = new b2Vec2();
|
|
b2ContactResult.prototype.normalImpulse = null;
|
|
b2ContactResult.prototype.tangentImpulse = null;
|
|
b2ContactResult.prototype.id = new b2ContactID();
|
|
exports.b2ContactResult = b2ContactResult;
|
|
|
|
|
|
var b2Island = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Island.prototype.__constructor = function (
|
|
bodyCapacity,
|
|
contactCapacity,
|
|
jointCapacity,
|
|
allocator,
|
|
listener) {
|
|
var i = 0;
|
|
|
|
this.m_bodyCapacity = bodyCapacity;
|
|
this.m_contactCapacity = contactCapacity;
|
|
this.m_jointCapacity = jointCapacity;
|
|
this.m_bodyCount = 0;
|
|
this.m_contactCount = 0;
|
|
this.m_jointCount = 0;
|
|
|
|
this.m_allocator = allocator;
|
|
this.m_listener = listener;
|
|
|
|
|
|
this.m_bodies = new Array(bodyCapacity);
|
|
for (i = 0; i < bodyCapacity; i++)
|
|
this.m_bodies[i] = null;
|
|
|
|
|
|
this.m_contacts = new Array(contactCapacity);
|
|
for (i = 0; i < contactCapacity; i++)
|
|
this.m_contacts[i] = null;
|
|
|
|
|
|
this.m_joints = new Array(jointCapacity);
|
|
for (i = 0; i < jointCapacity; i++)
|
|
this.m_joints[i] = null;
|
|
|
|
this.m_positionIterationCount = 0;
|
|
|
|
}
|
|
b2Island.prototype.__varz = function(){
|
|
}
|
|
b2Island.s_reportCR = new b2ContactResult();
|
|
b2Island.prototype.m_allocator = null;
|
|
b2Island.prototype.m_listener = null;
|
|
b2Island.prototype.m_bodies = null;
|
|
b2Island.prototype.m_contacts = null;
|
|
b2Island.prototype.m_joints = null;
|
|
b2Island.prototype.m_bodyCount = 0;
|
|
b2Island.prototype.m_jointCount = 0;
|
|
b2Island.prototype.m_contactCount = 0;
|
|
b2Island.prototype.m_bodyCapacity = 0;
|
|
b2Island.prototype.m_contactCapacity = 0;
|
|
b2Island.prototype.m_jointCapacity = 0;
|
|
b2Island.prototype.m_positionIterationCount = 0;
|
|
b2Island.prototype.Clear = function () {
|
|
this.m_bodyCount = 0;
|
|
this.m_contactCount = 0;
|
|
this.m_jointCount = 0;
|
|
}
|
|
b2Island.prototype.Solve = function (step, gravity, correctPositions, allowSleep) {
|
|
var i = 0;
|
|
var b;
|
|
var joint;
|
|
|
|
|
|
for (i = 0; i < this.m_bodyCount; ++i)
|
|
{
|
|
b = this.m_bodies[i];
|
|
|
|
if (b.IsStatic())
|
|
continue;
|
|
|
|
|
|
|
|
b.m_linearVelocity.x += step.dt * (gravity.x + b.m_invMass * b.m_force.x);
|
|
b.m_linearVelocity.y += step.dt * (gravity.y + b.m_invMass * b.m_force.y);
|
|
b.m_angularVelocity += step.dt * b.m_invI * b.m_torque;
|
|
|
|
|
|
b.m_force.SetZero();
|
|
b.m_torque = 0.0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
b.m_linearVelocity.Multiply( b2Math.b2Clamp(1.0 - step.dt * b.m_linearDamping, 0.0, 1.0) );
|
|
b.m_angularVelocity *= b2Math.b2Clamp(1.0 - step.dt * b.m_angularDamping, 0.0, 1.0);
|
|
|
|
|
|
|
|
if ((b.m_linearVelocity.LengthSquared()) > b2Settings.b2_maxLinearVelocitySquared)
|
|
{
|
|
b.m_linearVelocity.Normalize();
|
|
b.m_linearVelocity.x *= b2Settings.b2_maxLinearVelocity;
|
|
b.m_linearVelocity.y *= b2Settings.b2_maxLinearVelocity;
|
|
}
|
|
|
|
if (b.m_angularVelocity * b.m_angularVelocity > b2Settings.b2_maxAngularVelocitySquared)
|
|
{
|
|
if (b.m_angularVelocity < 0.0)
|
|
{
|
|
b.m_angularVelocity = -b2Settings.b2_maxAngularVelocity;
|
|
}
|
|
else
|
|
{
|
|
b.m_angularVelocity = b2Settings.b2_maxAngularVelocity;
|
|
}
|
|
}
|
|
}
|
|
|
|
var contactSolver = new b2ContactSolver(step, this.m_contacts, this.m_contactCount, this.m_allocator);
|
|
|
|
|
|
contactSolver.InitVelocityConstraints(step);
|
|
|
|
for (i = 0; i < this.m_jointCount; ++i)
|
|
{
|
|
joint = this.m_joints[i];
|
|
joint.InitVelocityConstraints(step);
|
|
}
|
|
|
|
|
|
for (i = 0; i < step.maxIterations; ++i)
|
|
{
|
|
contactSolver.SolveVelocityConstraints();
|
|
|
|
for (var j = 0; j < this.m_jointCount; ++j)
|
|
{
|
|
joint = this.m_joints[j];
|
|
joint.SolveVelocityConstraints(step);
|
|
}
|
|
}
|
|
|
|
|
|
contactSolver.FinalizeVelocityConstraints();
|
|
|
|
|
|
for (i = 0; i < this.m_bodyCount; ++i)
|
|
{
|
|
b = this.m_bodies[i];
|
|
|
|
if (b.IsStatic())
|
|
continue;
|
|
|
|
|
|
b.m_sweep.c0.SetV(b.m_sweep.c);
|
|
b.m_sweep.a0 = b.m_sweep.a;
|
|
|
|
|
|
|
|
b.m_sweep.c.x += step.dt * b.m_linearVelocity.x;
|
|
b.m_sweep.c.y += step.dt * b.m_linearVelocity.y;
|
|
b.m_sweep.a += step.dt * b.m_angularVelocity;
|
|
|
|
|
|
b.SynchronizeTransform();
|
|
|
|
|
|
}
|
|
|
|
if (correctPositions)
|
|
{
|
|
|
|
|
|
for (i = 0; i < this.m_jointCount; ++i)
|
|
{
|
|
joint = this.m_joints[i];
|
|
joint.InitPositionConstraints();
|
|
}
|
|
|
|
|
|
for (this.m_positionIterationCount = 0; this.m_positionIterationCount < step.maxIterations; ++this.m_positionIterationCount)
|
|
{
|
|
var contactsOkay = contactSolver.SolvePositionConstraints(b2Settings.b2_contactBaumgarte);
|
|
|
|
var jointsOkay = true;
|
|
for (i = 0; i < this.m_jointCount; ++i)
|
|
{
|
|
joint = this.m_joints[i];
|
|
var jointOkay = joint.SolvePositionConstraints();
|
|
jointsOkay = jointsOkay && jointOkay;
|
|
}
|
|
|
|
if (contactsOkay && jointsOkay)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.Report(contactSolver.m_constraints);
|
|
|
|
if (allowSleep){
|
|
|
|
var minSleepTime = Number.MAX_VALUE;
|
|
|
|
var linTolSqr = b2Settings.b2_linearSleepTolerance * b2Settings.b2_linearSleepTolerance;
|
|
var angTolSqr = b2Settings.b2_angularSleepTolerance * b2Settings.b2_angularSleepTolerance;
|
|
|
|
for (i = 0; i < this.m_bodyCount; ++i)
|
|
{
|
|
b = this.m_bodies[i];
|
|
if (b.m_invMass == 0.0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ((b.m_flags & b2Body.e_allowSleepFlag) == 0)
|
|
{
|
|
b.m_sleepTime = 0.0;
|
|
minSleepTime = 0.0;
|
|
}
|
|
|
|
if ((b.m_flags & b2Body.e_allowSleepFlag) == 0 ||
|
|
b.m_angularVelocity * b.m_angularVelocity > angTolSqr ||
|
|
b2Math.b2Dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr)
|
|
{
|
|
b.m_sleepTime = 0.0;
|
|
minSleepTime = 0.0;
|
|
}
|
|
else
|
|
{
|
|
b.m_sleepTime += step.dt;
|
|
minSleepTime = b2Math.b2Min(minSleepTime, b.m_sleepTime);
|
|
}
|
|
}
|
|
|
|
if (minSleepTime >= b2Settings.b2_timeToSleep)
|
|
{
|
|
for (i = 0; i < this.m_bodyCount; ++i)
|
|
{
|
|
b = this.m_bodies[i];
|
|
b.m_flags |= b2Body.e_sleepFlag;
|
|
b.m_linearVelocity.SetZero();
|
|
b.m_angularVelocity = 0.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
b2Island.prototype.SolveTOI = function (subStep) {
|
|
var i = 0;
|
|
var contactSolver = new b2ContactSolver(subStep, this.m_contacts, this.m_contactCount, this.m_allocator);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < subStep.maxIterations; ++i)
|
|
{
|
|
contactSolver.SolveVelocityConstraints();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < this.m_bodyCount; ++i)
|
|
{
|
|
var b = this.m_bodies[i];
|
|
|
|
if (b.IsStatic())
|
|
continue;
|
|
|
|
|
|
b.m_sweep.c0.SetV(b.m_sweep.c);
|
|
b.m_sweep.a0 = b.m_sweep.a;
|
|
|
|
|
|
b.m_sweep.c.x += subStep.dt * b.m_linearVelocity.x;
|
|
b.m_sweep.c.y += subStep.dt * b.m_linearVelocity.y;
|
|
b.m_sweep.a += subStep.dt * b.m_angularVelocity;
|
|
|
|
|
|
b.SynchronizeTransform();
|
|
|
|
|
|
}
|
|
|
|
|
|
var k_toiBaumgarte = 0.75;
|
|
for (i = 0; i < subStep.maxIterations; ++i)
|
|
{
|
|
var contactsOkay = contactSolver.SolvePositionConstraints(k_toiBaumgarte);
|
|
if (contactsOkay)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
this.Report(contactSolver.m_constraints);
|
|
}
|
|
b2Island.prototype.Report = function (constraints) {
|
|
var tMat;
|
|
var tVec;
|
|
if (this.m_listener == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < this.m_contactCount; ++i)
|
|
{
|
|
var c = this.m_contacts[i];
|
|
var cc = constraints[ i ];
|
|
var cr = b2Island.s_reportCR;
|
|
cr.shape1 = c.m_shape1;
|
|
cr.shape2 = c.m_shape2;
|
|
var b1 = cr.shape1.m_body;
|
|
var manifoldCount = c.m_manifoldCount;
|
|
var manifolds = c.GetManifolds();
|
|
for (var j = 0; j < manifoldCount; ++j)
|
|
{
|
|
var manifold = manifolds[ j ];
|
|
cr.normal.SetV( manifold.normal );
|
|
for (var k = 0; k < manifold.pointCount; ++k)
|
|
{
|
|
var point = manifold.points[ k ];
|
|
var ccp = cc.points[ k ];
|
|
cr.position = b1.GetWorldPoint(point.localPoint1);
|
|
|
|
|
|
|
|
cr.normalImpulse = ccp.normalImpulse;
|
|
cr.tangentImpulse = ccp.tangentImpulse;
|
|
cr.id.key = point.id.key;
|
|
|
|
this.m_listener.Result(cr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
b2Island.prototype.AddBody = function (body) {
|
|
|
|
this.m_bodies[this.m_bodyCount++] = body;
|
|
}
|
|
b2Island.prototype.AddContact = function (contact) {
|
|
|
|
this.m_contacts[this.m_contactCount++] = contact;
|
|
}
|
|
b2Island.prototype.AddJoint = function (joint) {
|
|
|
|
this.m_joints[this.m_jointCount++] = joint;
|
|
}
|
|
exports.b2Island = b2Island;
|
|
|
|
|
|
var b2ContactEdge = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactEdge.prototype.__constructor = function(){}
|
|
b2ContactEdge.prototype.__varz = function(){
|
|
}
|
|
b2ContactEdge.prototype.other = null;
|
|
b2ContactEdge.prototype.contact = null;
|
|
b2ContactEdge.prototype.prev = null;
|
|
b2ContactEdge.prototype.next = null;
|
|
exports.b2ContactEdge = b2ContactEdge;
|
|
|
|
|
|
var b2Contact = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Contact.prototype.__constructor = function (s1, s2) {
|
|
this.m_flags = 0;
|
|
|
|
if (!s1 || !s2){
|
|
this.m_shape1 = null;
|
|
this.m_shape2 = null;
|
|
return;
|
|
}
|
|
|
|
if (s1.IsSensor() || s2.IsSensor())
|
|
{
|
|
this.m_flags |= b2Contact.e_nonSolidFlag;
|
|
}
|
|
|
|
this.m_shape1 = s1;
|
|
this.m_shape2 = s2;
|
|
|
|
this.m_manifoldCount = 0;
|
|
|
|
this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction);
|
|
this.m_restitution = b2Math.b2Max(this.m_shape1.m_restitution, this.m_shape2.m_restitution);
|
|
|
|
this.m_prev = null;
|
|
this.m_next = null;
|
|
|
|
this.m_node1.contact = null;
|
|
this.m_node1.prev = null;
|
|
this.m_node1.next = null;
|
|
this.m_node1.other = null;
|
|
|
|
this.m_node2.contact = null;
|
|
this.m_node2.prev = null;
|
|
this.m_node2.next = null;
|
|
this.m_node2.other = null;
|
|
}
|
|
b2Contact.prototype.__varz = function(){
|
|
this.m_node1 = new b2ContactEdge();
|
|
this.m_node2 = new b2ContactEdge();
|
|
}
|
|
b2Contact.e_nonSolidFlag = 0x0001;
|
|
b2Contact.e_slowFlag = 0x0002;
|
|
b2Contact.e_islandFlag = 0x0004;
|
|
b2Contact.e_toiFlag = 0x0008;
|
|
b2Contact.s_registers = null;
|
|
b2Contact.s_initialized = false;
|
|
b2Contact.AddType = function (createFcn, destroyFcn, type1, type2) {
|
|
|
|
|
|
|
|
b2Contact.s_registers[type1][type2].createFcn = createFcn;
|
|
b2Contact.s_registers[type1][type2].destroyFcn = destroyFcn;
|
|
b2Contact.s_registers[type1][type2].primary = true;
|
|
|
|
if (type1 != type2)
|
|
{
|
|
b2Contact.s_registers[type2][type1].createFcn = createFcn;
|
|
b2Contact.s_registers[type2][type1].destroyFcn = destroyFcn;
|
|
b2Contact.s_registers[type2][type1].primary = false;
|
|
}
|
|
}
|
|
b2Contact.InitializeRegisters = function () {
|
|
b2Contact.s_registers = new Array(b2Shape.e_shapeTypeCount);
|
|
for (var i = 0; i < b2Shape.e_shapeTypeCount; i++){
|
|
b2Contact.s_registers[i] = new Array(b2Shape.e_shapeTypeCount);
|
|
for (var j = 0; j < b2Shape.e_shapeTypeCount; j++){
|
|
b2Contact.s_registers[i][j] = new b2ContactRegister();
|
|
}
|
|
}
|
|
|
|
b2Contact.AddType(b2CircleContact.Create, b2CircleContact.Destroy, b2Shape.e_circleShape, b2Shape.e_circleShape);
|
|
b2Contact.AddType(b2PolyAndCircleContact.Create, b2PolyAndCircleContact.Destroy, b2Shape.e_polygonShape, b2Shape.e_circleShape);
|
|
b2Contact.AddType(b2PolygonContact.Create, b2PolygonContact.Destroy, b2Shape.e_polygonShape, b2Shape.e_polygonShape);
|
|
|
|
}
|
|
b2Contact.Create = function (shape1, shape2, allocator) {
|
|
if (b2Contact.s_initialized == false)
|
|
{
|
|
b2Contact.InitializeRegisters();
|
|
b2Contact.s_initialized = true;
|
|
}
|
|
|
|
var type1 = shape1.m_type;
|
|
var type2 = shape2.m_type;
|
|
|
|
|
|
|
|
|
|
var reg = b2Contact.s_registers[type1][type2];
|
|
var createFcn = reg.createFcn;
|
|
if (createFcn != null)
|
|
{
|
|
if (reg.primary)
|
|
{
|
|
return createFcn(shape1, shape2, allocator);
|
|
}
|
|
else
|
|
{
|
|
var c = createFcn(shape2, shape1, allocator);
|
|
for (var i = 0; i < c.m_manifoldCount; ++i)
|
|
{
|
|
var m = c.GetManifolds()[ i ];
|
|
m.normal = m.normal.Negative();
|
|
}
|
|
return c;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
b2Contact.Destroy = function (contact, allocator) {
|
|
|
|
|
|
if (contact.m_manifoldCount > 0)
|
|
{
|
|
contact.m_shape1.m_body.WakeUp();
|
|
contact.m_shape2.m_body.WakeUp();
|
|
}
|
|
|
|
var type1 = contact.m_shape1.m_type;
|
|
var type2 = contact.m_shape2.m_type;
|
|
|
|
|
|
|
|
|
|
var reg = b2Contact.s_registers[type1][type2];
|
|
var destroyFcn = reg.destroyFcn;
|
|
destroyFcn(contact, allocator);
|
|
}
|
|
b2Contact.prototype.m_flags = 0;
|
|
b2Contact.prototype.m_prev = null;
|
|
b2Contact.prototype.m_next = null;
|
|
b2Contact.prototype.m_node1 = new b2ContactEdge();
|
|
b2Contact.prototype.m_node2 = new b2ContactEdge();
|
|
b2Contact.prototype.m_shape1 = null;
|
|
b2Contact.prototype.m_shape2 = null;
|
|
b2Contact.prototype.m_manifoldCount = 0;
|
|
b2Contact.prototype.m_friction = null;
|
|
b2Contact.prototype.m_restitution = null;
|
|
b2Contact.prototype.m_toi = null;
|
|
b2Contact.prototype.GetManifolds = function () {return null}
|
|
b2Contact.prototype.GetManifoldCount = function () {
|
|
return this.m_manifoldCount;
|
|
}
|
|
b2Contact.prototype.IsSolid = function () {
|
|
return (this.m_flags & b2Contact.e_nonSolidFlag) == 0;
|
|
}
|
|
b2Contact.prototype.GetNext = function () {
|
|
return this.m_next;
|
|
}
|
|
b2Contact.prototype.GetShape1 = function () {
|
|
return this.m_shape1;
|
|
}
|
|
b2Contact.prototype.GetShape2 = function () {
|
|
return this.m_shape2;
|
|
}
|
|
b2Contact.prototype.Update = function (listener) {
|
|
var oldCount = this.m_manifoldCount;
|
|
|
|
this.Evaluate(listener);
|
|
|
|
var newCount = this.m_manifoldCount;
|
|
|
|
var body1 = this.m_shape1.m_body;
|
|
var body2 = this.m_shape2.m_body;
|
|
|
|
if (newCount == 0 && oldCount > 0)
|
|
{
|
|
body1.WakeUp();
|
|
body2.WakeUp();
|
|
}
|
|
|
|
|
|
if (body1.IsStatic() || body1.IsBullet() || body2.IsStatic() || body2.IsBullet())
|
|
{
|
|
this.m_flags &= ~b2Contact.e_slowFlag;
|
|
}
|
|
else
|
|
{
|
|
this.m_flags |= b2Contact.e_slowFlag;
|
|
}
|
|
}
|
|
b2Contact.prototype.Evaluate = function (listener) {}
|
|
exports.b2Contact = b2Contact;
|
|
|
|
|
|
var b2NullContact = function() {
|
|
b2Contact.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2NullContact.prototype, b2Contact.prototype)
|
|
b2NullContact.prototype._super = function(){ b2Contact.prototype.__constructor.apply(this, arguments) }
|
|
b2NullContact.prototype.__constructor = function () {}
|
|
b2NullContact.prototype.__varz = function(){
|
|
}
|
|
b2NullContact.prototype.Evaluate = function (l) {}
|
|
b2NullContact.prototype.GetManifolds = function () { return null; }
|
|
exports.b2NullContact = b2NullContact;
|
|
|
|
|
|
var b2ContactManager = function() {
|
|
b2PairCallback.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2ContactManager.prototype, b2PairCallback.prototype)
|
|
b2ContactManager.prototype._super = function(){ b2PairCallback.prototype.__constructor.apply(this, arguments) }
|
|
b2ContactManager.prototype.__constructor = function () {
|
|
this.m_world = null;
|
|
this.m_destroyImmediate = false;
|
|
}
|
|
b2ContactManager.prototype.__varz = function(){
|
|
this.m_nullContact = new b2NullContact();
|
|
}
|
|
b2ContactManager.s_evalCP = new b2ContactPoint();
|
|
b2ContactManager.prototype.m_world = null;
|
|
b2ContactManager.prototype.m_nullContact = new b2NullContact();
|
|
b2ContactManager.prototype.m_destroyImmediate = null;
|
|
b2ContactManager.prototype.PairAdded = function (proxyUserData1, proxyUserData2) {
|
|
var shape1 = proxyUserData1;
|
|
var shape2 = proxyUserData2;
|
|
|
|
var body1 = shape1.m_body;
|
|
var body2 = shape2.m_body;
|
|
|
|
if (body1.IsStatic() && body2.IsStatic())
|
|
{
|
|
return this.m_nullContact;
|
|
}
|
|
|
|
if (shape1.m_body == shape2.m_body)
|
|
{
|
|
return this.m_nullContact;
|
|
}
|
|
|
|
if (body2.IsConnected(body1))
|
|
{
|
|
return this.m_nullContact;
|
|
}
|
|
|
|
if (this.m_world.m_contactFilter != null && this.m_world.m_contactFilter.ShouldCollide(shape1, shape2) == false)
|
|
{
|
|
return this.m_nullContact;
|
|
}
|
|
|
|
|
|
var c = b2Contact.Create(shape1, shape2, this.m_world.m_blockAllocator);
|
|
|
|
if (c == null)
|
|
{
|
|
return this.m_nullContact;
|
|
}
|
|
|
|
|
|
shape1 = c.m_shape1;
|
|
shape2 = c.m_shape2;
|
|
body1 = shape1.m_body;
|
|
body2 = shape2.m_body;
|
|
|
|
|
|
c.m_prev = null;
|
|
c.m_next = this.m_world.m_contactList;
|
|
if (this.m_world.m_contactList != null)
|
|
{
|
|
this.m_world.m_contactList.m_prev = c;
|
|
}
|
|
this.m_world.m_contactList = c;
|
|
|
|
|
|
|
|
|
|
|
|
c.m_node1.contact = c;
|
|
c.m_node1.other = body2;
|
|
|
|
c.m_node1.prev = null;
|
|
c.m_node1.next = body1.m_contactList;
|
|
if (body1.m_contactList != null)
|
|
{
|
|
body1.m_contactList.prev = c.m_node1;
|
|
}
|
|
body1.m_contactList = c.m_node1;
|
|
|
|
|
|
c.m_node2.contact = c;
|
|
c.m_node2.other = body1;
|
|
|
|
c.m_node2.prev = null;
|
|
c.m_node2.next = body2.m_contactList;
|
|
if (body2.m_contactList != null)
|
|
{
|
|
body2.m_contactList.prev = c.m_node2;
|
|
}
|
|
body2.m_contactList = c.m_node2;
|
|
|
|
++this.m_world.m_contactCount;
|
|
return c;
|
|
|
|
}
|
|
b2ContactManager.prototype.PairRemoved = function (proxyUserData1, proxyUserData2, pairUserData) {
|
|
|
|
if (pairUserData == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var c = pairUserData;
|
|
if (c == this.m_nullContact)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
this.Destroy(c);
|
|
}
|
|
b2ContactManager.prototype.Destroy = function (c) {
|
|
|
|
var shape1 = c.m_shape1;
|
|
var shape2 = c.m_shape2;
|
|
|
|
|
|
var manifoldCount = c.m_manifoldCount;
|
|
if (manifoldCount > 0 && this.m_world.m_contactListener)
|
|
{
|
|
var b1 = shape1.m_body;
|
|
var b2 = shape2.m_body;
|
|
|
|
var manifolds = c.GetManifolds();
|
|
var cp = b2ContactManager.s_evalCP;
|
|
cp.shape1 = c.m_shape1;
|
|
cp.shape2 = c.m_shape2;
|
|
cp.friction = c.m_friction;
|
|
cp.restitution = c.m_restitution;
|
|
|
|
for (var i = 0; i < manifoldCount; ++i)
|
|
{
|
|
var manifold = manifolds[ i ];
|
|
cp.normal.SetV(manifold.normal);
|
|
|
|
for (var j = 0; j < manifold.pointCount; ++j)
|
|
{
|
|
var mp = manifold.points[j];
|
|
cp.position = b1.GetWorldPoint(mp.localPoint1);
|
|
var v1 = b1.GetLinearVelocityFromLocalPoint(mp.localPoint1);
|
|
var v2 = b2.GetLinearVelocityFromLocalPoint(mp.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.separation = mp.separation;
|
|
cp.id.key = mp.id._key;
|
|
this.m_world.m_contactListener.Remove(cp);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (c.m_prev)
|
|
{
|
|
c.m_prev.m_next = c.m_next;
|
|
}
|
|
|
|
if (c.m_next)
|
|
{
|
|
c.m_next.m_prev = c.m_prev;
|
|
}
|
|
|
|
if (c == this.m_world.m_contactList)
|
|
{
|
|
this.m_world.m_contactList = c.m_next;
|
|
}
|
|
|
|
var body1 = shape1.m_body;
|
|
var body2 = shape2.m_body;
|
|
|
|
|
|
if (c.m_node1.prev)
|
|
{
|
|
c.m_node1.prev.next = c.m_node1.next;
|
|
}
|
|
|
|
if (c.m_node1.next)
|
|
{
|
|
c.m_node1.next.prev = c.m_node1.prev;
|
|
}
|
|
|
|
if (c.m_node1 == body1.m_contactList)
|
|
{
|
|
body1.m_contactList = c.m_node1.next;
|
|
}
|
|
|
|
|
|
if (c.m_node2.prev)
|
|
{
|
|
c.m_node2.prev.next = c.m_node2.next;
|
|
}
|
|
|
|
if (c.m_node2.next)
|
|
{
|
|
c.m_node2.next.prev = c.m_node2.prev;
|
|
}
|
|
|
|
if (c.m_node2 == body2.m_contactList)
|
|
{
|
|
body2.m_contactList = c.m_node2.next;
|
|
}
|
|
|
|
|
|
b2Contact.Destroy(c, this.m_world.m_blockAllocator);
|
|
--this.m_world.m_contactCount;
|
|
}
|
|
b2ContactManager.prototype.Collide = function () {
|
|
|
|
for (var c = this.m_world.m_contactList; c; c = c.m_next)
|
|
{
|
|
var body1 = c.m_shape1.m_body;
|
|
var body2 = c.m_shape2.m_body;
|
|
if (body1.IsSleeping() && body2.IsSleeping())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
c.Update(this.m_world.m_contactListener);
|
|
}
|
|
}
|
|
exports.b2ContactManager = b2ContactManager;
|
|
|
|
|
|
var b2ContactSolver = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactSolver.prototype.__constructor = function (step, contacts, contactCount, allocator) {
|
|
var contact;
|
|
|
|
|
|
this.m_step.dt = step.dt;
|
|
this.m_step.inv_dt = step.inv_dt;
|
|
this.m_step.maxIterations = step.maxIterations;
|
|
|
|
this.m_allocator = allocator;
|
|
|
|
var i = 0;
|
|
var tVec;
|
|
var tMat;
|
|
|
|
this.m_constraintCount = 0;
|
|
for (i = 0; i < contactCount; ++i)
|
|
{
|
|
|
|
contact = contacts[i];
|
|
this.m_constraintCount += contact.m_manifoldCount;
|
|
}
|
|
|
|
|
|
for (i = 0; i < this.m_constraintCount; i++){
|
|
this.m_constraints[i] = new b2ContactConstraint();
|
|
}
|
|
|
|
var count = 0;
|
|
for (i = 0; i < contactCount; ++i)
|
|
{
|
|
contact = contacts[i];
|
|
var b1 = contact.m_shape1.m_body;
|
|
var b2 = contact.m_shape2.m_body;
|
|
var manifoldCount = contact.m_manifoldCount;
|
|
var manifolds = contact.GetManifolds();
|
|
var friction = contact.m_friction;
|
|
var restitution = contact.m_restitution;
|
|
|
|
|
|
var v1X = b1.m_linearVelocity.x;
|
|
var v1Y = b1.m_linearVelocity.y;
|
|
|
|
var v2X = b2.m_linearVelocity.x;
|
|
var v2Y = b2.m_linearVelocity.y;
|
|
var w1 = b1.m_angularVelocity;
|
|
var w2 = b2.m_angularVelocity;
|
|
|
|
for (var j = 0; j < manifoldCount; ++j)
|
|
{
|
|
var manifold = manifolds[ j ];
|
|
|
|
|
|
|
|
|
|
var normalX = manifold.normal.x;
|
|
var normalY = manifold.normal.y;
|
|
|
|
|
|
var c = this.m_constraints[ count ];
|
|
c.body1 = b1;
|
|
c.body2 = b2;
|
|
c.manifold = manifold;
|
|
|
|
c.normal.x = normalX;
|
|
c.normal.y = normalY;
|
|
c.pointCount = manifold.pointCount;
|
|
c.friction = friction;
|
|
c.restitution = restitution;
|
|
|
|
for (var k = 0; k < c.pointCount; ++k)
|
|
{
|
|
var cp = manifold.points[ k ];
|
|
var ccp = c.points[ k ];
|
|
|
|
ccp.normalImpulse = cp.normalImpulse;
|
|
ccp.tangentImpulse = cp.tangentImpulse;
|
|
ccp.separation = cp.separation;
|
|
ccp.positionImpulse = 0.0;
|
|
|
|
ccp.localAnchor1.SetV(cp.localPoint1);
|
|
ccp.localAnchor2.SetV(cp.localPoint2);
|
|
|
|
var tX;
|
|
var tY;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = cp.localPoint1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = cp.localPoint1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
ccp.r1.Set(r1X,r1Y);
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = cp.localPoint2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = cp.localPoint2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
ccp.r2.Set(r2X,r2Y);
|
|
|
|
var r1Sqr = r1X * r1X + r1Y * r1Y;
|
|
var r2Sqr = r2X * r2X + r2Y * r2Y;
|
|
|
|
|
|
var rn1 = r1X*normalX + r1Y*normalY;
|
|
|
|
var rn2 = r2X*normalX + r2Y*normalY;
|
|
var kNormal = b1.m_invMass + b2.m_invMass;
|
|
kNormal += b1.m_invI * (r1Sqr - rn1 * rn1) + b2.m_invI * (r2Sqr - rn2 * rn2);
|
|
|
|
ccp.normalMass = 1.0 / kNormal;
|
|
|
|
var kEqualized = b1.m_mass * b1.m_invMass + b2.m_mass * b2.m_invMass;
|
|
kEqualized += b1.m_mass * b1.m_invI * (r1Sqr - rn1 * rn1) + b2.m_mass * b2.m_invI * (r2Sqr - rn2 * rn2);
|
|
|
|
ccp.equalizedMass = 1.0 / kEqualized;
|
|
|
|
|
|
var tangentX = normalY
|
|
var tangentY = -normalX;
|
|
|
|
|
|
var rt1 = r1X*tangentX + r1Y*tangentY;
|
|
|
|
var rt2 = r2X*tangentX + r2Y*tangentY;
|
|
var kTangent = b1.m_invMass + b2.m_invMass;
|
|
kTangent += b1.m_invI * (r1Sqr - rt1 * rt1) + b2.m_invI * (r2Sqr - rt2 * rt2);
|
|
|
|
ccp.tangentMass = 1.0 / kTangent;
|
|
|
|
|
|
ccp.velocityBias = 0.0;
|
|
if (ccp.separation > 0.0)
|
|
{
|
|
ccp.velocityBias = -60.0 * ccp.separation;
|
|
}
|
|
|
|
tX = v2X + (-w2*r2Y) - v1X - (-w1*r1Y);
|
|
tY = v2Y + (w2*r2X) - v1Y - (w1*r1X);
|
|
|
|
var vRel = c.normal.x*tX + c.normal.y*tY;
|
|
if (vRel < -b2Settings.b2_velocityThreshold)
|
|
{
|
|
ccp.velocityBias += -c.restitution * vRel;
|
|
}
|
|
}
|
|
|
|
++count;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
b2ContactSolver.prototype.__varz = function(){
|
|
this.m_step = new b2TimeStep();
|
|
this.m_constraints = new Array();
|
|
}
|
|
b2ContactSolver.prototype.m_step = new b2TimeStep();
|
|
b2ContactSolver.prototype.m_allocator = null;
|
|
b2ContactSolver.prototype.m_constraints = new Array();
|
|
b2ContactSolver.prototype.m_constraintCount = 0;
|
|
b2ContactSolver.prototype.InitVelocityConstraints = function (step) {
|
|
var tVec;
|
|
var tVec2;
|
|
var tMat;
|
|
|
|
|
|
for (var i = 0; i < this.m_constraintCount; ++i)
|
|
{
|
|
var c = this.m_constraints[ i ];
|
|
|
|
var b1 = c.body1;
|
|
var b2 = c.body2;
|
|
var invMass1 = b1.m_invMass;
|
|
var invI1 = b1.m_invI;
|
|
var invMass2 = b2.m_invMass;
|
|
var invI2 = b2.m_invI;
|
|
|
|
var normalX = c.normal.x;
|
|
var normalY = c.normal.y;
|
|
|
|
var tangentX = normalY;
|
|
var tangentY = -normalX;
|
|
|
|
var tX;
|
|
|
|
var j = 0;
|
|
var tCount = 0;
|
|
if (step.warmStarting)
|
|
{
|
|
tCount = c.pointCount;
|
|
for (j = 0; j < tCount; ++j)
|
|
{
|
|
var ccp = c.points[ j ];
|
|
ccp.normalImpulse *= step.dtRatio;
|
|
ccp.tangentImpulse *= step.dtRatio;
|
|
|
|
var PX = ccp.normalImpulse * normalX + ccp.tangentImpulse * tangentX;
|
|
var PY = ccp.normalImpulse * normalY + ccp.tangentImpulse * tangentY;
|
|
|
|
|
|
b1.m_angularVelocity -= invI1 * (ccp.r1.x * PY - ccp.r1.y * PX);
|
|
|
|
b1.m_linearVelocity.x -= invMass1 * PX;
|
|
b1.m_linearVelocity.y -= invMass1 * PY;
|
|
|
|
b2.m_angularVelocity += invI2 * (ccp.r2.x * PY - ccp.r2.y * PX);
|
|
|
|
b2.m_linearVelocity.x += invMass2 * PX;
|
|
b2.m_linearVelocity.y += invMass2 * PY;
|
|
}
|
|
}
|
|
else{
|
|
tCount = c.pointCount;
|
|
for (j = 0; j < tCount; ++j)
|
|
{
|
|
var ccp2 = c.points[ j ];
|
|
ccp2.normalImpulse = 0.0;
|
|
ccp2.tangentImpulse = 0.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
b2ContactSolver.prototype.SolveVelocityConstraints = function () {
|
|
var j = 0;
|
|
var ccp;
|
|
var r1X;
|
|
var r1Y;
|
|
var r2X;
|
|
var r2Y;
|
|
var dvX;
|
|
var dvY;
|
|
var vn;
|
|
var vt;
|
|
var lambda_n;
|
|
var lambda_t;
|
|
var newImpulse_n;
|
|
var newImpulse_t;
|
|
var PX;
|
|
var PY;
|
|
|
|
var tMat;
|
|
var tVec;
|
|
|
|
for (var i = 0; i < this.m_constraintCount; ++i)
|
|
{
|
|
var c = this.m_constraints[ i ];
|
|
var b1 = c.body1;
|
|
var b2 = c.body2;
|
|
var w1 = b1.m_angularVelocity;
|
|
var w2 = b2.m_angularVelocity;
|
|
var v1 = b1.m_linearVelocity;
|
|
var v2 = b2.m_linearVelocity;
|
|
|
|
var invMass1 = b1.m_invMass;
|
|
var invI1 = b1.m_invI;
|
|
var invMass2 = b2.m_invMass;
|
|
var invI2 = b2.m_invI;
|
|
|
|
var normalX = c.normal.x;
|
|
var normalY = c.normal.y;
|
|
|
|
var tangentX = normalY;
|
|
var tangentY = -normalX;
|
|
var friction = c.friction;
|
|
|
|
var tX;
|
|
|
|
var tCount = c.pointCount;
|
|
for (j = 0; j < tCount; ++j)
|
|
{
|
|
ccp = c.points[ j ];
|
|
|
|
|
|
|
|
dvX = v2.x + (-w2 * ccp.r2.y) - v1.x - (-w1 * ccp.r1.y);
|
|
dvY = v2.y + (w2 * ccp.r2.x) - v1.y - (w1 * ccp.r1.x);
|
|
|
|
|
|
|
|
vn = dvX * normalX + dvY * normalY;
|
|
lambda_n = -ccp.normalMass * (vn - ccp.velocityBias);
|
|
|
|
|
|
vt = dvX*tangentX + dvY*tangentY;
|
|
lambda_t = ccp.tangentMass * (-vt);
|
|
|
|
|
|
newImpulse_n = b2Math.b2Max(ccp.normalImpulse + lambda_n, 0.0);
|
|
lambda_n = newImpulse_n - ccp.normalImpulse;
|
|
|
|
|
|
var maxFriction = friction * ccp.normalImpulse;
|
|
newImpulse_t = b2Math.b2Clamp(ccp.tangentImpulse + lambda_t, -maxFriction, maxFriction);
|
|
lambda_t = newImpulse_t - ccp.tangentImpulse;
|
|
|
|
|
|
|
|
PX = lambda_n * normalX + lambda_t * tangentX;
|
|
PY = lambda_n * normalY + lambda_t * tangentY;
|
|
|
|
|
|
v1.x -= invMass1 * PX;
|
|
v1.y -= invMass1 * PY;
|
|
w1 -= invI1 * (ccp.r1.x * PY - ccp.r1.y * PX);
|
|
|
|
|
|
v2.x += invMass2 * PX;
|
|
v2.y += invMass2 * PY;
|
|
w2 += invI2 * (ccp.r2.x * PY - ccp.r2.y * PX);
|
|
|
|
ccp.normalImpulse = newImpulse_n;
|
|
ccp.tangentImpulse = newImpulse_t;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
b1.m_angularVelocity = w1;
|
|
b2.m_angularVelocity = w2;
|
|
}
|
|
}
|
|
b2ContactSolver.prototype.FinalizeVelocityConstraints = function () {
|
|
for (var i = 0; i < this.m_constraintCount; ++i)
|
|
{
|
|
var c = this.m_constraints[ i ];
|
|
var m = c.manifold;
|
|
|
|
for (var j = 0; j < c.pointCount; ++j)
|
|
{
|
|
var point1 = m.points[j];
|
|
var point2 = c.points[j];
|
|
point1.normalImpulse = point2.normalImpulse;
|
|
point1.tangentImpulse = point2.tangentImpulse;
|
|
}
|
|
}
|
|
}
|
|
b2ContactSolver.prototype.SolvePositionConstraints = function (baumgarte) {
|
|
var minSeparation = 0.0;
|
|
|
|
var tMat;
|
|
var tVec;
|
|
|
|
for (var i = 0; i < this.m_constraintCount; ++i)
|
|
{
|
|
var c = this.m_constraints[ i ];
|
|
var b1 = c.body1;
|
|
var b2 = c.body2;
|
|
var b1_sweep_c = b1.m_sweep.c;
|
|
var b1_sweep_a = b1.m_sweep.a;
|
|
var b2_sweep_c = b2.m_sweep.c;
|
|
var b2_sweep_a = b2.m_sweep.a;
|
|
|
|
var invMass1 = b1.m_mass * b1.m_invMass;
|
|
var invI1 = b1.m_mass * b1.m_invI;
|
|
var invMass2 = b2.m_mass * b2.m_invMass;
|
|
var invI2 = b2.m_mass * b2.m_invI;
|
|
|
|
var normalX = c.normal.x;
|
|
var normalY = c.normal.y;
|
|
|
|
|
|
var tCount = c.pointCount;
|
|
for (var j = 0; j < tCount; ++j)
|
|
{
|
|
var ccp = c.points[ j ];
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
tVec = b1.m_sweep.localCenter;
|
|
var r1X = ccp.localAnchor1.x - tVec.x;
|
|
var r1Y = ccp.localAnchor1.y - tVec.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
|
|
tMat = b2.m_xf.R;
|
|
tVec = b2.m_sweep.localCenter;
|
|
var r2X = ccp.localAnchor2.x - tVec.x;
|
|
var r2Y = ccp.localAnchor2.y - tVec.y;
|
|
var tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var p1X = b1_sweep_c.x + r1X;
|
|
var p1Y = b1_sweep_c.y + r1Y;
|
|
|
|
|
|
var p2X = b2_sweep_c.x + r2X;
|
|
var p2Y = b2_sweep_c.y + r2Y;
|
|
|
|
|
|
var dpX = p2X - p1X;
|
|
var dpY = p2Y - p1Y;
|
|
|
|
|
|
|
|
var separation = (dpX*normalX + dpY*normalY) + ccp.separation;
|
|
|
|
|
|
minSeparation = b2Math.b2Min(minSeparation, separation);
|
|
|
|
|
|
var C = baumgarte * b2Math.b2Clamp(separation + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
|
|
|
|
|
var dImpulse = -ccp.equalizedMass * C;
|
|
|
|
|
|
var impulse0 = ccp.positionImpulse;
|
|
ccp.positionImpulse = b2Math.b2Max(impulse0 + dImpulse, 0.0);
|
|
dImpulse = ccp.positionImpulse - impulse0;
|
|
|
|
|
|
var impulseX = dImpulse * normalX;
|
|
var impulseY = dImpulse * normalY;
|
|
|
|
|
|
b1_sweep_c.x -= invMass1 * impulseX;
|
|
b1_sweep_c.y -= invMass1 * impulseY;
|
|
b1_sweep_a -= invI1 * (r1X * impulseY - r1Y * impulseX);
|
|
b1.m_sweep.a = b1_sweep_a;
|
|
b1.SynchronizeTransform();
|
|
|
|
|
|
b2_sweep_c.x += invMass2 * impulseX;
|
|
b2_sweep_c.y += invMass2 * impulseY;
|
|
b2_sweep_a += invI2 * (r2X * impulseY - r2Y * impulseX);
|
|
b2.m_sweep.a = b2_sweep_a;
|
|
b2.SynchronizeTransform();
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return minSeparation >= -1.5 * b2Settings.b2_linearSlop;
|
|
}
|
|
exports.b2ContactSolver = b2ContactSolver;
|
|
|
|
|
|
var b2ContactConstraintPoint = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactConstraintPoint.prototype.__constructor = function(){}
|
|
b2ContactConstraintPoint.prototype.__varz = function(){
|
|
this.localAnchor1 = new b2Vec2();
|
|
this.localAnchor2 = new b2Vec2();
|
|
this.r1 = new b2Vec2();
|
|
this.r2 = new b2Vec2();
|
|
}
|
|
b2ContactConstraintPoint.prototype.localAnchor1 = new b2Vec2();
|
|
b2ContactConstraintPoint.prototype.localAnchor2 = new b2Vec2();
|
|
b2ContactConstraintPoint.prototype.r1 = new b2Vec2();
|
|
b2ContactConstraintPoint.prototype.r2 = new b2Vec2();
|
|
b2ContactConstraintPoint.prototype.normalImpulse = null;
|
|
b2ContactConstraintPoint.prototype.tangentImpulse = null;
|
|
b2ContactConstraintPoint.prototype.positionImpulse = null;
|
|
b2ContactConstraintPoint.prototype.normalMass = null;
|
|
b2ContactConstraintPoint.prototype.tangentMass = null;
|
|
b2ContactConstraintPoint.prototype.equalizedMass = null;
|
|
b2ContactConstraintPoint.prototype.separation = null;
|
|
b2ContactConstraintPoint.prototype.velocityBias = null;
|
|
exports.b2ContactConstraintPoint = b2ContactConstraintPoint;
|
|
|
|
|
|
var b2ContactRegister = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactRegister.prototype.__constructor = function(){}
|
|
b2ContactRegister.prototype.__varz = function(){
|
|
}
|
|
b2ContactRegister.prototype.createFcn = null;
|
|
b2ContactRegister.prototype.destroyFcn = null;
|
|
b2ContactRegister.prototype.primary = null;
|
|
exports.b2ContactRegister = b2ContactRegister;
|
|
|
|
|
|
var b2ContactConstraint = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2ContactConstraint.prototype.__constructor = function () {
|
|
this.points = new Array(b2Settings.b2_maxManifoldPoints);
|
|
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++){
|
|
this.points[i] = new b2ContactConstraintPoint();
|
|
}
|
|
|
|
|
|
}
|
|
b2ContactConstraint.prototype.__varz = function(){
|
|
this.normal = new b2Vec2();
|
|
}
|
|
b2ContactConstraint.prototype.points = null;
|
|
b2ContactConstraint.prototype.normal = new b2Vec2();
|
|
b2ContactConstraint.prototype.manifold = null;
|
|
b2ContactConstraint.prototype.body1 = null;
|
|
b2ContactConstraint.prototype.body2 = null;
|
|
b2ContactConstraint.prototype.friction = null;
|
|
b2ContactConstraint.prototype.restitution = null;
|
|
b2ContactConstraint.prototype.pointCount = 0;
|
|
exports.b2ContactConstraint = b2ContactConstraint;
|
|
|
|
|
|
var b2PolygonContact = function() {
|
|
b2Contact.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PolygonContact.prototype, b2Contact.prototype)
|
|
b2PolygonContact.prototype._super = function(){ b2Contact.prototype.__constructor.apply(this, arguments) }
|
|
b2PolygonContact.prototype.__constructor = function (shape1, shape2) {
|
|
this._super(shape1, shape2);
|
|
this.m_manifold = this.m_manifolds[0];
|
|
|
|
|
|
this.m_manifold.pointCount = 0;
|
|
}
|
|
b2PolygonContact.prototype.__varz = function(){
|
|
this.m0 = new b2Manifold();
|
|
this.m_manifolds = [new b2Manifold()];
|
|
}
|
|
b2PolygonContact.s_evalCP = new b2ContactPoint();
|
|
b2PolygonContact.Create = function (shape1, shape2, allocator) {
|
|
|
|
return new b2PolygonContact(shape1, shape2);
|
|
}
|
|
b2PolygonContact.Destroy = function (contact, allocator) {
|
|
|
|
|
|
}
|
|
b2PolygonContact.prototype.m0 = new b2Manifold();
|
|
b2PolygonContact.prototype.m_manifolds = [new b2Manifold()];
|
|
b2PolygonContact.prototype.m_manifold = null;
|
|
b2PolygonContact.prototype.Evaluate = function (listener) {
|
|
var v1;
|
|
var v2;
|
|
var mp0;
|
|
|
|
var b1 = this.m_shape1.m_body;
|
|
var b2 = this.m_shape2.m_body;
|
|
|
|
var cp;
|
|
var i = 0;
|
|
|
|
|
|
|
|
|
|
this.m0.Set(this.m_manifold);
|
|
|
|
b2Collision.b2CollidePolygons(this.m_manifold, this.m_shape1, b1.m_xf, this.m_shape2, b2.m_xf);
|
|
var persisted = [false, false];
|
|
|
|
cp = b2PolygonContact.s_evalCP;
|
|
cp.shape1 = this.m_shape1;
|
|
cp.shape2 = this.m_shape2;
|
|
cp.friction = this.m_friction;
|
|
cp.restitution = this.m_restitution;
|
|
|
|
|
|
if (this.m_manifold.pointCount > 0)
|
|
{
|
|
|
|
|
|
|
|
for (i = 0; i < this.m_manifold.pointCount; ++i)
|
|
{
|
|
var mp = this.m_manifold.points[ i ];
|
|
mp.normalImpulse = 0.0;
|
|
mp.tangentImpulse = 0.0;
|
|
var found = false;
|
|
var idKey = mp.id._key;
|
|
|
|
for (var j = 0; j < this.m0.pointCount; ++j)
|
|
{
|
|
if (persisted[j] == true)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
mp0 = this.m0.points[ j ];
|
|
|
|
if (mp0.id._key == idKey)
|
|
{
|
|
persisted[j] = true;
|
|
mp.normalImpulse = mp0.normalImpulse;
|
|
mp.tangentImpulse = mp0.tangentImpulse;
|
|
|
|
|
|
found = true;
|
|
|
|
|
|
if (listener != null)
|
|
{
|
|
cp.position = b1.GetWorldPoint(mp.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m_manifold.normal);
|
|
cp.separation = mp.separation;
|
|
cp.id.key = idKey;
|
|
listener.Persist(cp);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (found == false && listener != null)
|
|
{
|
|
cp.position = b1.GetWorldPoint(mp.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m_manifold.normal);
|
|
cp.separation = mp.separation;
|
|
cp.id.key = idKey;
|
|
listener.Add(cp);
|
|
}
|
|
}
|
|
|
|
this.m_manifoldCount = 1;
|
|
}
|
|
else
|
|
{
|
|
this.m_manifoldCount = 0;
|
|
}
|
|
|
|
if (listener == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
for (i = 0; i < this.m0.pointCount; ++i)
|
|
{
|
|
if (persisted[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
mp0 = this.m0.points[ i ];
|
|
cp.position = b1.GetWorldPoint(mp0.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp0.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp0.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m0.normal);
|
|
cp.separation = mp0.separation;
|
|
cp.id.key = mp0.id._key;
|
|
listener.Remove(cp);
|
|
}
|
|
}
|
|
b2PolygonContact.prototype.GetManifolds = function () {
|
|
return this.m_manifolds;
|
|
}
|
|
exports.b2PolygonContact = b2PolygonContact;
|
|
|
|
|
|
var b2CircleContact = function() {
|
|
b2Contact.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2CircleContact.prototype, b2Contact.prototype)
|
|
b2CircleContact.prototype._super = function(){ b2Contact.prototype.__constructor.apply(this, arguments) }
|
|
b2CircleContact.prototype.__constructor = function (shape1, shape2) {
|
|
this._super(shape1, shape2);
|
|
|
|
this.m_manifold = this.m_manifolds[0];
|
|
|
|
|
|
|
|
this.m_manifold.pointCount = 0;
|
|
var point = this.m_manifold.points[0];
|
|
point.normalImpulse = 0.0;
|
|
point.tangentImpulse = 0.0;
|
|
}
|
|
b2CircleContact.prototype.__varz = function(){
|
|
this.m_manifolds = [new b2Manifold()];
|
|
this.m0 = new b2Manifold();
|
|
}
|
|
b2CircleContact.s_evalCP = new b2ContactPoint();
|
|
b2CircleContact.Create = function (shape1, shape2, allocator) {
|
|
return new b2CircleContact(shape1, shape2);
|
|
}
|
|
b2CircleContact.Destroy = function (contact, allocator) {
|
|
|
|
}
|
|
b2CircleContact.prototype.m_manifolds = [new b2Manifold()];
|
|
b2CircleContact.prototype.m0 = new b2Manifold();
|
|
b2CircleContact.prototype.m_manifold = null;
|
|
b2CircleContact.prototype.Evaluate = function (listener) {
|
|
var v1;
|
|
var v2;
|
|
var mp0;
|
|
|
|
var b1 = this.m_shape1.m_body;
|
|
var b2 = this.m_shape2.m_body;
|
|
|
|
|
|
|
|
|
|
this.m0.Set(this.m_manifold);
|
|
|
|
b2Collision.b2CollideCircles(this.m_manifold, this.m_shape1, b1.m_xf, this.m_shape2, b2.m_xf);
|
|
|
|
var cp = b2CircleContact.s_evalCP;
|
|
cp.shape1 = this.m_shape1;
|
|
cp.shape2 = this.m_shape2;
|
|
cp.friction = this.m_friction;
|
|
cp.restitution = this.m_restitution;
|
|
|
|
if (this.m_manifold.pointCount > 0)
|
|
{
|
|
this.m_manifoldCount = 1;
|
|
var mp = this.m_manifold.points[ 0 ];
|
|
|
|
if (this.m0.pointCount == 0)
|
|
{
|
|
mp.normalImpulse = 0.0;
|
|
mp.tangentImpulse = 0.0;
|
|
|
|
if (listener)
|
|
{
|
|
cp.position = b1.GetWorldPoint(mp.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m_manifold.normal);
|
|
cp.separation = mp.separation;
|
|
cp.id.key = mp.id._key;
|
|
listener.Add(cp);
|
|
}
|
|
} else
|
|
{
|
|
mp0 = this.m0.points[ 0 ];
|
|
mp.normalImpulse = mp0.normalImpulse;
|
|
mp.tangentImpulse = mp0.tangentImpulse;
|
|
|
|
if (listener)
|
|
{
|
|
cp.position = b1.GetWorldPoint(mp.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m_manifold.normal);
|
|
cp.separation = mp.separation;
|
|
cp.id.key = mp.id._key;
|
|
listener.Persist(cp);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.m_manifoldCount = 0;
|
|
if (this.m0.pointCount > 0 && listener)
|
|
{
|
|
mp0 = this.m0.points[ 0 ];
|
|
cp.position = b1.GetWorldPoint(mp0.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp0.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp0.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m0.normal);
|
|
cp.separation = mp0.separation;
|
|
cp.id.key = mp0.id._key;
|
|
listener.Remove(cp);
|
|
}
|
|
}
|
|
}
|
|
b2CircleContact.prototype.GetManifolds = function () {
|
|
return this.m_manifolds;
|
|
}
|
|
exports.b2CircleContact = b2CircleContact;
|
|
|
|
|
|
var b2PolyAndCircleContact = function() {
|
|
b2Contact.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PolyAndCircleContact.prototype, b2Contact.prototype)
|
|
b2PolyAndCircleContact.prototype._super = function(){ b2Contact.prototype.__constructor.apply(this, arguments) }
|
|
b2PolyAndCircleContact.prototype.__constructor = function (shape1, shape2) {
|
|
this._super(shape1, shape2);
|
|
|
|
this.m_manifold = this.m_manifolds[0];
|
|
|
|
b2Settings.b2Assert(this.m_shape1.m_type == b2Shape.e_polygonShape);
|
|
b2Settings.b2Assert(this.m_shape2.m_type == b2Shape.e_circleShape);
|
|
this.m_manifold.pointCount = 0;
|
|
var point = this.m_manifold.points[0];
|
|
point.normalImpulse = 0.0;
|
|
point.tangentImpulse = 0.0;
|
|
}
|
|
b2PolyAndCircleContact.prototype.__varz = function(){
|
|
this.m_manifolds = [new b2Manifold()];
|
|
this.m0 = new b2Manifold();
|
|
}
|
|
b2PolyAndCircleContact.s_evalCP = new b2ContactPoint();
|
|
b2PolyAndCircleContact.Create = function (shape1, shape2, allocator) {
|
|
return new b2PolyAndCircleContact(shape1, shape2);
|
|
}
|
|
b2PolyAndCircleContact.Destroy = function (contact, allocator) {
|
|
}
|
|
b2PolyAndCircleContact.prototype.m_manifolds = [new b2Manifold()];
|
|
b2PolyAndCircleContact.prototype.m0 = new b2Manifold();
|
|
b2PolyAndCircleContact.prototype.m_manifold = null;
|
|
b2PolyAndCircleContact.prototype.Evaluate = function (listener) {
|
|
var i = 0;
|
|
var v1;
|
|
var v2;
|
|
var mp0;
|
|
|
|
var b1 = this.m_shape1.m_body;
|
|
var b2 = this.m_shape2.m_body;
|
|
|
|
|
|
|
|
|
|
this.m0.Set(this.m_manifold);
|
|
|
|
b2Collision.b2CollidePolygonAndCircle(this.m_manifold, this.m_shape1, b1.m_xf, this.m_shape2, b2.m_xf);
|
|
|
|
var persisted = [false, false];
|
|
|
|
var cp = b2PolyAndCircleContact.s_evalCP;
|
|
cp.shape1 = this.m_shape1;
|
|
cp.shape2 = this.m_shape2;
|
|
cp.friction = this.m_friction;
|
|
cp.restitution = this.m_restitution;
|
|
|
|
|
|
if (this.m_manifold.pointCount > 0)
|
|
{
|
|
|
|
|
|
for (i = 0; i < this.m_manifold.pointCount; ++i)
|
|
{
|
|
var mp = this.m_manifold.points[ i ];
|
|
mp.normalImpulse = 0.0;
|
|
mp.tangentImpulse = 0.0;
|
|
var found = false;
|
|
var idKey = mp.id._key;
|
|
|
|
for (var j = 0; j < this.m0.pointCount; ++j)
|
|
{
|
|
if (persisted[j] == true)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
mp0 = this.m0.points[ j ];
|
|
|
|
if (mp0.id._key == idKey)
|
|
{
|
|
persisted[j] = true;
|
|
mp.normalImpulse = mp0.normalImpulse;
|
|
mp.tangentImpulse = mp0.tangentImpulse;
|
|
|
|
|
|
found = true;
|
|
|
|
|
|
if (listener != null)
|
|
{
|
|
cp.position = b1.GetWorldPoint(mp.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m_manifold.normal);
|
|
cp.separation = mp.separation;
|
|
cp.id.key = idKey;
|
|
listener.Persist(cp);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (found == false && listener != null)
|
|
{
|
|
cp.position = b1.GetWorldPoint(mp.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m_manifold.normal);
|
|
cp.separation = mp.separation;
|
|
cp.id.key = idKey;
|
|
listener.Add(cp);
|
|
}
|
|
}
|
|
|
|
this.m_manifoldCount = 1;
|
|
}
|
|
else
|
|
{
|
|
this.m_manifoldCount = 0;
|
|
}
|
|
|
|
if (listener == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
for (i = 0; i < this.m0.pointCount; ++i)
|
|
{
|
|
if (persisted[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
mp0 = this.m0.points[ i ];
|
|
cp.position = b1.GetWorldPoint(mp0.localPoint1);
|
|
v1 = b1.GetLinearVelocityFromLocalPoint(mp0.localPoint1);
|
|
v2 = b2.GetLinearVelocityFromLocalPoint(mp0.localPoint2);
|
|
cp.velocity.Set(v2.x - v1.x, v2.y - v1.y);
|
|
cp.normal.SetV(this.m0.normal);
|
|
cp.separation = mp0.separation;
|
|
cp.id.key = mp0.id._key;
|
|
listener.Remove(cp);
|
|
}
|
|
}
|
|
b2PolyAndCircleContact.prototype.GetManifolds = function () {
|
|
return this.m_manifolds;
|
|
}
|
|
exports.b2PolyAndCircleContact = b2PolyAndCircleContact;
|
|
|
|
|
|
var b2JointEdge = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2JointEdge.prototype.__constructor = function(){}
|
|
b2JointEdge.prototype.__varz = function(){
|
|
}
|
|
b2JointEdge.prototype.other = null;
|
|
b2JointEdge.prototype.joint = null;
|
|
b2JointEdge.prototype.prev = null;
|
|
b2JointEdge.prototype.next = null;
|
|
exports.b2JointEdge = b2JointEdge;
|
|
|
|
|
|
var b2JointDef = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2JointDef.prototype.__constructor = function () {
|
|
this.type = b2Joint.e_unknownJoint;
|
|
this.userData = null;
|
|
this.body1 = null;
|
|
this.body2 = null;
|
|
this.collideConnected = false;
|
|
}
|
|
b2JointDef.prototype.__varz = function(){
|
|
}
|
|
b2JointDef.prototype.type = 0;
|
|
b2JointDef.prototype.userData = null;
|
|
b2JointDef.prototype.body1 = null;
|
|
b2JointDef.prototype.body2 = null;
|
|
b2JointDef.prototype.collideConnected = null;
|
|
exports.b2JointDef = b2JointDef;
|
|
|
|
|
|
var b2MouseJointDef = function() {
|
|
b2JointDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2MouseJointDef.prototype, b2JointDef.prototype)
|
|
b2MouseJointDef.prototype._super = function(){ b2JointDef.prototype.__constructor.apply(this, arguments) }
|
|
b2MouseJointDef.prototype.__constructor = function () {
|
|
this.type = b2Joint.e_mouseJoint;
|
|
this.maxForce = 0.0;
|
|
this.frequencyHz = 5.0;
|
|
this.dampingRatio = 0.7;
|
|
this.timeStep = 1.0 / 60.0;
|
|
}
|
|
b2MouseJointDef.prototype.__varz = function(){
|
|
this.target = new b2Vec2();
|
|
}
|
|
b2MouseJointDef.prototype.target = new b2Vec2();
|
|
b2MouseJointDef.prototype.maxForce = null;
|
|
b2MouseJointDef.prototype.frequencyHz = null;
|
|
b2MouseJointDef.prototype.dampingRatio = null;
|
|
b2MouseJointDef.prototype.timeStep = null;
|
|
exports.b2MouseJointDef = b2MouseJointDef;
|
|
|
|
|
|
var b2PulleyJointDef = function() {
|
|
b2JointDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PulleyJointDef.prototype, b2JointDef.prototype)
|
|
b2PulleyJointDef.prototype._super = function(){ b2JointDef.prototype.__constructor.apply(this, arguments) }
|
|
b2PulleyJointDef.prototype.__constructor = function () {
|
|
this.type = b2Joint.e_pulleyJoint;
|
|
this.groundAnchor1.Set(-1.0, 1.0);
|
|
this.groundAnchor2.Set(1.0, 1.0);
|
|
this.localAnchor1.Set(-1.0, 0.0);
|
|
this.localAnchor2.Set(1.0, 0.0);
|
|
this.length1 = 0.0;
|
|
this.maxLength1 = 0.0;
|
|
this.length2 = 0.0;
|
|
this.maxLength2 = 0.0;
|
|
this.ratio = 1.0;
|
|
this.collideConnected = true;
|
|
}
|
|
b2PulleyJointDef.prototype.__varz = function(){
|
|
this.groundAnchor1 = new b2Vec2();
|
|
this.groundAnchor2 = new b2Vec2();
|
|
this.localAnchor1 = new b2Vec2();
|
|
this.localAnchor2 = new b2Vec2();
|
|
}
|
|
b2PulleyJointDef.prototype.groundAnchor1 = new b2Vec2();
|
|
b2PulleyJointDef.prototype.groundAnchor2 = new b2Vec2();
|
|
b2PulleyJointDef.prototype.localAnchor1 = new b2Vec2();
|
|
b2PulleyJointDef.prototype.localAnchor2 = new b2Vec2();
|
|
b2PulleyJointDef.prototype.length1 = null;
|
|
b2PulleyJointDef.prototype.maxLength1 = null;
|
|
b2PulleyJointDef.prototype.length2 = null;
|
|
b2PulleyJointDef.prototype.maxLength2 = null;
|
|
b2PulleyJointDef.prototype.ratio = null;
|
|
b2PulleyJointDef.prototype.Initialize = function (b1, b2,
|
|
ga1, ga2,
|
|
anchor1, anchor2,
|
|
r) {
|
|
this.body1 = b1;
|
|
this.body2 = b2;
|
|
this.groundAnchor1.SetV( ga1 );
|
|
this.groundAnchor2.SetV( ga2 );
|
|
this.localAnchor1 = this.body1.GetLocalPoint(anchor1);
|
|
this.localAnchor2 = this.body2.GetLocalPoint(anchor2);
|
|
|
|
var d1X = anchor1.x - ga1.x;
|
|
var d1Y = anchor1.y - ga1.y;
|
|
|
|
this.length1 = Math.sqrt(d1X*d1X + d1Y*d1Y);
|
|
|
|
|
|
var d2X = anchor2.x - ga2.x;
|
|
var d2Y = anchor2.y - ga2.y;
|
|
|
|
this.length2 = Math.sqrt(d2X*d2X + d2Y*d2Y);
|
|
|
|
this.ratio = r;
|
|
|
|
var C = this.length1 + this.ratio * this.length2;
|
|
this.maxLength1 = C - this.ratio * b2PulleyJoint.b2_minPulleyLength;
|
|
this.maxLength2 = (C - b2PulleyJoint.b2_minPulleyLength) / this.ratio;
|
|
}
|
|
exports.b2PulleyJointDef = b2PulleyJointDef;
|
|
|
|
|
|
var b2Jacobian = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Jacobian.prototype.__constructor = function(){}
|
|
b2Jacobian.prototype.__varz = function(){
|
|
this.linear1 = new b2Vec2();
|
|
this.linear2 = new b2Vec2();
|
|
}
|
|
b2Jacobian.prototype.linear1 = new b2Vec2();
|
|
b2Jacobian.prototype.angular1 = null;
|
|
b2Jacobian.prototype.linear2 = new b2Vec2();
|
|
b2Jacobian.prototype.angular2 = null;
|
|
b2Jacobian.prototype.SetZero = function () {
|
|
this.linear1.SetZero(); this.angular1 = 0.0;
|
|
this.linear2.SetZero(); this.angular2 = 0.0;
|
|
}
|
|
b2Jacobian.prototype.Set = function (x1, a1, x2, a2) {
|
|
this.linear1.SetV(x1); this.angular1 = a1;
|
|
this.linear2.SetV(x2); this.angular2 = a2;
|
|
}
|
|
b2Jacobian.prototype.Compute = function (x1, a1, x2, a2) {
|
|
|
|
|
|
return (this.linear1.x*x1.x + this.linear1.y*x1.y) + this.angular1 * a1 + (this.linear2.x*x2.x + this.linear2.y*x2.y) + this.angular2 * a2;
|
|
}
|
|
exports.b2Jacobian = b2Jacobian;
|
|
|
|
|
|
var b2DistanceJointDef = function() {
|
|
b2JointDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2DistanceJointDef.prototype, b2JointDef.prototype)
|
|
b2DistanceJointDef.prototype._super = function(){ b2JointDef.prototype.__constructor.apply(this, arguments) }
|
|
b2DistanceJointDef.prototype.__constructor = function () {
|
|
this.type = b2Joint.e_distanceJoint;
|
|
|
|
|
|
this.length = 1.0;
|
|
this.frequencyHz = 0.0;
|
|
this.dampingRatio = 0.0;
|
|
}
|
|
b2DistanceJointDef.prototype.__varz = function(){
|
|
this.localAnchor1 = new b2Vec2();
|
|
this.localAnchor2 = new b2Vec2();
|
|
}
|
|
b2DistanceJointDef.prototype.localAnchor1 = new b2Vec2();
|
|
b2DistanceJointDef.prototype.localAnchor2 = new b2Vec2();
|
|
b2DistanceJointDef.prototype.length = null;
|
|
b2DistanceJointDef.prototype.frequencyHz = null;
|
|
b2DistanceJointDef.prototype.dampingRatio = null;
|
|
b2DistanceJointDef.prototype.Initialize = function (b1, b2,
|
|
anchor1, anchor2) {
|
|
this.body1 = b1;
|
|
this.body2 = b2;
|
|
this.localAnchor1.SetV( this.body1.GetLocalPoint(anchor1));
|
|
this.localAnchor2.SetV( this.body2.GetLocalPoint(anchor2));
|
|
var dX = anchor2.x - anchor1.x;
|
|
var dY = anchor2.y - anchor1.y;
|
|
this.length = Math.sqrt(dX*dX + dY*dY);
|
|
this.frequencyHz = 0.0;
|
|
this.dampingRatio = 0.0;
|
|
}
|
|
exports.b2DistanceJointDef = b2DistanceJointDef;
|
|
|
|
|
|
var b2PrismaticJointDef = function() {
|
|
b2JointDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PrismaticJointDef.prototype, b2JointDef.prototype)
|
|
b2PrismaticJointDef.prototype._super = function(){ b2JointDef.prototype.__constructor.apply(this, arguments) }
|
|
b2PrismaticJointDef.prototype.__constructor = function () {
|
|
this.type = b2Joint.e_prismaticJoint;
|
|
|
|
|
|
this.localAxis1.Set(1.0, 0.0);
|
|
this.referenceAngle = 0.0;
|
|
this.enableLimit = false;
|
|
this.lowerTranslation = 0.0;
|
|
this.upperTranslation = 0.0;
|
|
this.enableMotor = false;
|
|
this.maxMotorForce = 0.0;
|
|
this.motorSpeed = 0.0;
|
|
}
|
|
b2PrismaticJointDef.prototype.__varz = function(){
|
|
this.localAnchor1 = new b2Vec2();
|
|
this.localAnchor2 = new b2Vec2();
|
|
this.localAxis1 = new b2Vec2();
|
|
}
|
|
b2PrismaticJointDef.prototype.localAnchor1 = new b2Vec2();
|
|
b2PrismaticJointDef.prototype.localAnchor2 = new b2Vec2();
|
|
b2PrismaticJointDef.prototype.localAxis1 = new b2Vec2();
|
|
b2PrismaticJointDef.prototype.referenceAngle = null;
|
|
b2PrismaticJointDef.prototype.enableLimit = null;
|
|
b2PrismaticJointDef.prototype.lowerTranslation = null;
|
|
b2PrismaticJointDef.prototype.upperTranslation = null;
|
|
b2PrismaticJointDef.prototype.enableMotor = null;
|
|
b2PrismaticJointDef.prototype.maxMotorForce = null;
|
|
b2PrismaticJointDef.prototype.motorSpeed = null;
|
|
b2PrismaticJointDef.prototype.Initialize = function (b1, b2, anchor, axis) {
|
|
this.body1 = b1;
|
|
this.body2 = b2;
|
|
this.localAnchor1 = this.body1.GetLocalPoint(anchor);
|
|
this.localAnchor2 = this.body2.GetLocalPoint(anchor);
|
|
this.localAxis1 = this.body1.GetLocalVector(axis);
|
|
this.referenceAngle = this.body2.GetAngle() - this.body1.GetAngle();
|
|
}
|
|
exports.b2PrismaticJointDef = b2PrismaticJointDef;
|
|
|
|
|
|
var b2RevoluteJointDef = function() {
|
|
b2JointDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2RevoluteJointDef.prototype, b2JointDef.prototype)
|
|
b2RevoluteJointDef.prototype._super = function(){ b2JointDef.prototype.__constructor.apply(this, arguments) }
|
|
b2RevoluteJointDef.prototype.__constructor = function () {
|
|
this.type = b2Joint.e_revoluteJoint;
|
|
this.localAnchor1.Set(0.0, 0.0);
|
|
this.localAnchor2.Set(0.0, 0.0);
|
|
this.referenceAngle = 0.0;
|
|
this.lowerAngle = 0.0;
|
|
this.upperAngle = 0.0;
|
|
this.maxMotorTorque = 0.0;
|
|
this.motorSpeed = 0.0;
|
|
this.enableLimit = false;
|
|
this.enableMotor = false;
|
|
}
|
|
b2RevoluteJointDef.prototype.__varz = function(){
|
|
this.localAnchor1 = new b2Vec2();
|
|
this.localAnchor2 = new b2Vec2();
|
|
}
|
|
b2RevoluteJointDef.prototype.localAnchor1 = new b2Vec2();
|
|
b2RevoluteJointDef.prototype.localAnchor2 = new b2Vec2();
|
|
b2RevoluteJointDef.prototype.referenceAngle = null;
|
|
b2RevoluteJointDef.prototype.enableLimit = null;
|
|
b2RevoluteJointDef.prototype.lowerAngle = null;
|
|
b2RevoluteJointDef.prototype.upperAngle = null;
|
|
b2RevoluteJointDef.prototype.enableMotor = null;
|
|
b2RevoluteJointDef.prototype.motorSpeed = null;
|
|
b2RevoluteJointDef.prototype.maxMotorTorque = null;
|
|
b2RevoluteJointDef.prototype.Initialize = function (b1, b2, anchor) {
|
|
this.body1 = b1;
|
|
this.body2 = b2;
|
|
this.localAnchor1 = this.body1.GetLocalPoint(anchor);
|
|
this.localAnchor2 = this.body2.GetLocalPoint(anchor);
|
|
this.referenceAngle = this.body2.GetAngle() - this.body1.GetAngle();
|
|
}
|
|
exports.b2RevoluteJointDef = b2RevoluteJointDef;
|
|
|
|
|
|
var b2Joint = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2Joint.prototype.__constructor = function (def) {
|
|
this.m_type = def.type;
|
|
this.m_prev = null;
|
|
this.m_next = null;
|
|
this.m_body1 = def.body1;
|
|
this.m_body2 = def.body2;
|
|
this.m_collideConnected = def.collideConnected;
|
|
this.m_islandFlag = false;
|
|
this.m_userData = def.userData;
|
|
}
|
|
b2Joint.prototype.__varz = function(){
|
|
this.m_node1 = new b2JointEdge();
|
|
this.m_node2 = new b2JointEdge();
|
|
}
|
|
b2Joint.e_unknownJoint = 0;
|
|
b2Joint.e_revoluteJoint = 1;
|
|
b2Joint.e_prismaticJoint = 2;
|
|
b2Joint.e_distanceJoint = 3;
|
|
b2Joint.e_pulleyJoint = 4;
|
|
b2Joint.e_mouseJoint = 5;
|
|
b2Joint.e_gearJoint = 6;
|
|
b2Joint.e_inactiveLimit = 0;
|
|
b2Joint.e_atLowerLimit = 1;
|
|
b2Joint.e_atUpperLimit = 2;
|
|
b2Joint.e_equalLimits = 3;
|
|
b2Joint.Create = function (def, allocator) {
|
|
var joint = null;
|
|
|
|
switch (def.type)
|
|
{
|
|
case b2Joint.e_distanceJoint:
|
|
{
|
|
|
|
joint = new b2DistanceJoint(def);
|
|
}
|
|
break;
|
|
|
|
case b2Joint.e_mouseJoint:
|
|
{
|
|
|
|
joint = new b2MouseJoint(def);
|
|
}
|
|
break;
|
|
|
|
case b2Joint.e_prismaticJoint:
|
|
{
|
|
|
|
joint = new b2PrismaticJoint(def);
|
|
}
|
|
break;
|
|
|
|
case b2Joint.e_revoluteJoint:
|
|
{
|
|
|
|
joint = new b2RevoluteJoint(def);
|
|
}
|
|
break;
|
|
|
|
case b2Joint.e_pulleyJoint:
|
|
{
|
|
|
|
joint = new b2PulleyJoint(def);
|
|
}
|
|
break;
|
|
|
|
case b2Joint.e_gearJoint:
|
|
{
|
|
|
|
joint = new b2GearJoint(def);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
return joint;
|
|
}
|
|
b2Joint.Destroy = function (joint, allocator) {
|
|
|
|
}
|
|
b2Joint.prototype.m_type = 0;
|
|
b2Joint.prototype.m_prev = null;
|
|
b2Joint.prototype.m_next = null;
|
|
b2Joint.prototype.m_node1 = new b2JointEdge();
|
|
b2Joint.prototype.m_node2 = new b2JointEdge();
|
|
b2Joint.prototype.m_body1 = null;
|
|
b2Joint.prototype.m_body2 = null;
|
|
b2Joint.prototype.m_inv_dt = null;
|
|
b2Joint.prototype.m_islandFlag = null;
|
|
b2Joint.prototype.m_collideConnected = null;
|
|
b2Joint.prototype.m_userData = null;
|
|
b2Joint.prototype.GetType = function () {
|
|
return this.m_type;
|
|
}
|
|
b2Joint.prototype.GetAnchor1 = function () {return null}
|
|
b2Joint.prototype.GetAnchor2 = function () {return null}
|
|
b2Joint.prototype.GetReactionForce = function () {return null}
|
|
b2Joint.prototype.GetReactionTorque = function () {return 0.0}
|
|
b2Joint.prototype.GetBody1 = function () {
|
|
return this.m_body1;
|
|
}
|
|
b2Joint.prototype.GetBody2 = function () {
|
|
return this.m_body2;
|
|
}
|
|
b2Joint.prototype.GetNext = function () {
|
|
return this.m_next;
|
|
}
|
|
b2Joint.prototype.GetUserData = function () {
|
|
return this.m_userData;
|
|
}
|
|
b2Joint.prototype.SetUserData = function (data) {
|
|
this.m_userData = data;
|
|
}
|
|
b2Joint.prototype.InitVelocityConstraints = function (step) {}
|
|
b2Joint.prototype.SolveVelocityConstraints = function (step) {}
|
|
b2Joint.prototype.InitPositionConstraints = function () {}
|
|
b2Joint.prototype.SolvePositionConstraints = function () {return false}
|
|
exports.b2Joint = b2Joint;
|
|
|
|
|
|
var b2GearJoint = function() {
|
|
b2Joint.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2GearJoint.prototype, b2Joint.prototype)
|
|
b2GearJoint.prototype._super = function(){ b2Joint.prototype.__constructor.apply(this, arguments) }
|
|
b2GearJoint.prototype.__constructor = function (def) {
|
|
|
|
this._super(def);
|
|
|
|
var type1 = def.joint1.m_type;
|
|
var type2 = def.joint2.m_type;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.m_revolute1 = null;
|
|
this.m_prismatic1 = null;
|
|
this.m_revolute2 = null;
|
|
this.m_prismatic2 = null;
|
|
|
|
var coordinate1;
|
|
var coordinate2;
|
|
|
|
this.m_ground1 = def.joint1.m_body1;
|
|
this.m_body1 = def.joint1.m_body2;
|
|
if (type1 == b2Joint.e_revoluteJoint)
|
|
{
|
|
this.m_revolute1 = def.joint1;
|
|
this.m_groundAnchor1.SetV( this.m_revolute1.m_localAnchor1 );
|
|
this.m_localAnchor1.SetV( this.m_revolute1.m_localAnchor2 );
|
|
coordinate1 = this.m_revolute1.GetJointAngle();
|
|
}
|
|
else
|
|
{
|
|
this.m_prismatic1 = def.joint1;
|
|
this.m_groundAnchor1.SetV( this.m_prismatic1.m_localAnchor1 );
|
|
this.m_localAnchor1.SetV( this.m_prismatic1.m_localAnchor2 );
|
|
coordinate1 = this.m_prismatic1.GetJointTranslation();
|
|
}
|
|
|
|
this.m_ground2 = def.joint2.m_body1;
|
|
this.m_body2 = def.joint2.m_body2;
|
|
if (type2 == b2Joint.e_revoluteJoint)
|
|
{
|
|
this.m_revolute2 = def.joint2;
|
|
this.m_groundAnchor2.SetV( this.m_revolute2.m_localAnchor1 );
|
|
this.m_localAnchor2.SetV( this.m_revolute2.m_localAnchor2 );
|
|
coordinate2 = this.m_revolute2.GetJointAngle();
|
|
}
|
|
else
|
|
{
|
|
this.m_prismatic2 = def.joint2;
|
|
this.m_groundAnchor2.SetV( this.m_prismatic2.m_localAnchor1 );
|
|
this.m_localAnchor2.SetV( this.m_prismatic2.m_localAnchor2 );
|
|
coordinate2 = this.m_prismatic2.GetJointTranslation();
|
|
}
|
|
|
|
this.m_ratio = def.ratio;
|
|
|
|
this.m_constant = coordinate1 + this.m_ratio * coordinate2;
|
|
|
|
this.m_force = 0.0;
|
|
|
|
}
|
|
b2GearJoint.prototype.__varz = function(){
|
|
this.m_groundAnchor1 = new b2Vec2();
|
|
this.m_groundAnchor2 = new b2Vec2();
|
|
this.m_localAnchor1 = new b2Vec2();
|
|
this.m_localAnchor2 = new b2Vec2();
|
|
this.m_J = new b2Jacobian();
|
|
}
|
|
b2GearJoint.prototype.m_ground1 = null;
|
|
b2GearJoint.prototype.m_ground2 = null;
|
|
b2GearJoint.prototype.m_revolute1 = null;
|
|
b2GearJoint.prototype.m_prismatic1 = null;
|
|
b2GearJoint.prototype.m_revolute2 = null;
|
|
b2GearJoint.prototype.m_prismatic2 = null;
|
|
b2GearJoint.prototype.m_groundAnchor1 = new b2Vec2();
|
|
b2GearJoint.prototype.m_groundAnchor2 = new b2Vec2();
|
|
b2GearJoint.prototype.m_localAnchor1 = new b2Vec2();
|
|
b2GearJoint.prototype.m_localAnchor2 = new b2Vec2();
|
|
b2GearJoint.prototype.m_J = new b2Jacobian();
|
|
b2GearJoint.prototype.m_constant = null;
|
|
b2GearJoint.prototype.m_ratio = null;
|
|
b2GearJoint.prototype.m_mass = null;
|
|
b2GearJoint.prototype.m_force = null;
|
|
b2GearJoint.prototype.GetAnchor1 = function () {
|
|
|
|
return this.m_body1.GetWorldPoint(this.m_localAnchor1);
|
|
}
|
|
b2GearJoint.prototype.GetAnchor2 = function () {
|
|
|
|
return this.m_body2.GetWorldPoint(this.m_localAnchor2);
|
|
}
|
|
b2GearJoint.prototype.GetReactionForce = function () {
|
|
|
|
var F = new b2Vec2(this.m_force * this.m_J.linear2.x, this.m_force * this.m_J.linear2.y);
|
|
return F;
|
|
}
|
|
b2GearJoint.prototype.GetReactionTorque = function () {
|
|
|
|
|
|
var tMat = this.m_body2.m_xf.R;
|
|
var rX = this.m_localAnchor1.x - this.m_body2.m_sweep.localCenter.x;
|
|
var rY = this.m_localAnchor1.y - this.m_body2.m_sweep.localCenter.y;
|
|
var tX = tMat.col1.x * rX + tMat.col2.x * rY;
|
|
rY = tMat.col1.y * rX + tMat.col2.y * rY;
|
|
rX = tX;
|
|
|
|
|
|
tX = this.m_force * this.m_J.angular2 - (rX * (this.m_force * this.m_J.linear2.y) - rY * (this.m_force * this.m_J.linear2.x));
|
|
return tX;
|
|
}
|
|
b2GearJoint.prototype.GetRatio = function () {
|
|
return this.m_ratio;
|
|
}
|
|
b2GearJoint.prototype.InitVelocityConstraints = function (step) {
|
|
var g1 = this.m_ground1;
|
|
var g2 = this.m_ground2;
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
|
|
var ugX;
|
|
var ugY;
|
|
var rX;
|
|
var rY;
|
|
var tMat;
|
|
var tVec;
|
|
var crug;
|
|
var tX;
|
|
|
|
var K = 0.0;
|
|
this.m_J.SetZero();
|
|
|
|
if (this.m_revolute1)
|
|
{
|
|
this.m_J.angular1 = -1.0;
|
|
K += b1.m_invI;
|
|
}
|
|
else
|
|
{
|
|
|
|
tMat = g1.m_xf.R;
|
|
tVec = this.m_prismatic1.m_localXAxis1;
|
|
ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
|
|
ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
|
|
|
|
tMat = b1.m_xf.R;
|
|
rX = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
rY = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = tMat.col1.x * rX + tMat.col2.x * rY;
|
|
rY = tMat.col1.y * rX + tMat.col2.y * rY;
|
|
rX = tX;
|
|
|
|
|
|
crug = rX * ugY - rY * ugX;
|
|
|
|
this.m_J.linear1.Set(-ugX, -ugY);
|
|
this.m_J.angular1 = -crug;
|
|
K += b1.m_invMass + b1.m_invI * crug * crug;
|
|
}
|
|
|
|
if (this.m_revolute2)
|
|
{
|
|
this.m_J.angular2 = -this.m_ratio;
|
|
K += this.m_ratio * this.m_ratio * b2.m_invI;
|
|
}
|
|
else
|
|
{
|
|
|
|
tMat = g2.m_xf.R;
|
|
tVec = this.m_prismatic2.m_localXAxis1;
|
|
ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
|
|
ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
|
|
|
|
tMat = b2.m_xf.R;
|
|
rX = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
rY = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = tMat.col1.x * rX + tMat.col2.x * rY;
|
|
rY = tMat.col1.y * rX + tMat.col2.y * rY;
|
|
rX = tX;
|
|
|
|
|
|
crug = rX * ugY - rY * ugX;
|
|
|
|
this.m_J.linear2.Set(-this.m_ratio*ugX, -this.m_ratio*ugY);
|
|
this.m_J.angular2 = -this.m_ratio * crug;
|
|
K += this.m_ratio * this.m_ratio * (b2.m_invMass + b2.m_invI * crug * crug);
|
|
}
|
|
|
|
|
|
|
|
this.m_mass = 1.0 / K;
|
|
|
|
if (step.warmStarting)
|
|
{
|
|
|
|
var P = step.dt * this.m_force;
|
|
|
|
b1.m_linearVelocity.x += b1.m_invMass * P * this.m_J.linear1.x;
|
|
b1.m_linearVelocity.y += b1.m_invMass * P * this.m_J.linear1.y;
|
|
b1.m_angularVelocity += b1.m_invI * P * this.m_J.angular1;
|
|
|
|
b2.m_linearVelocity.x += b2.m_invMass * P * this.m_J.linear2.x;
|
|
b2.m_linearVelocity.y += b2.m_invMass * P * this.m_J.linear2.y;
|
|
b2.m_angularVelocity += b2.m_invI * P * this.m_J.angular2;
|
|
}
|
|
else
|
|
{
|
|
this.m_force = 0.0;
|
|
}
|
|
}
|
|
b2GearJoint.prototype.SolveVelocityConstraints = function (step) {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var Cdot = this.m_J.Compute( b1.m_linearVelocity, b1.m_angularVelocity,
|
|
b2.m_linearVelocity, b2.m_angularVelocity);
|
|
|
|
var force = -step.inv_dt * this.m_mass * Cdot;
|
|
this.m_force += force;
|
|
|
|
var P = step.dt * force;
|
|
b1.m_linearVelocity.x += b1.m_invMass * P * this.m_J.linear1.x;
|
|
b1.m_linearVelocity.y += b1.m_invMass * P * this.m_J.linear1.y;
|
|
b1.m_angularVelocity += b1.m_invI * P * this.m_J.angular1;
|
|
b2.m_linearVelocity.x += b2.m_invMass * P * this.m_J.linear2.x;
|
|
b2.m_linearVelocity.y += b2.m_invMass * P * this.m_J.linear2.y;
|
|
b2.m_angularVelocity += b2.m_invI * P * this.m_J.angular2;
|
|
}
|
|
b2GearJoint.prototype.SolvePositionConstraints = function () {
|
|
var linearError = 0.0;
|
|
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var coordinate1;
|
|
var coordinate2;
|
|
if (this.m_revolute1)
|
|
{
|
|
coordinate1 = this.m_revolute1.GetJointAngle();
|
|
}
|
|
else
|
|
{
|
|
coordinate1 = this.m_prismatic1.GetJointTranslation();
|
|
}
|
|
|
|
if (this.m_revolute2)
|
|
{
|
|
coordinate2 = this.m_revolute2.GetJointAngle();
|
|
}
|
|
else
|
|
{
|
|
coordinate2 = this.m_prismatic2.GetJointTranslation();
|
|
}
|
|
|
|
var C = this.m_constant - (coordinate1 + this.m_ratio * coordinate2);
|
|
|
|
var impulse = -this.m_mass * C;
|
|
|
|
b1.m_sweep.c.x += b1.m_invMass * impulse * this.m_J.linear1.x;
|
|
b1.m_sweep.c.y += b1.m_invMass * impulse * this.m_J.linear1.y;
|
|
b1.m_sweep.a += b1.m_invI * impulse * this.m_J.angular1;
|
|
b2.m_sweep.c.x += b2.m_invMass * impulse * this.m_J.linear2.x;
|
|
b2.m_sweep.c.y += b2.m_invMass * impulse * this.m_J.linear2.y;
|
|
b2.m_sweep.a += b2.m_invI * impulse * this.m_J.angular2;
|
|
|
|
b1.SynchronizeTransform();
|
|
b2.SynchronizeTransform();
|
|
|
|
return linearError < b2Settings.b2_linearSlop;
|
|
}
|
|
exports.b2GearJoint = b2GearJoint;
|
|
|
|
|
|
var b2GearJointDef = function() {
|
|
b2JointDef.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2GearJointDef.prototype, b2JointDef.prototype)
|
|
b2GearJointDef.prototype._super = function(){ b2JointDef.prototype.__constructor.apply(this, arguments) }
|
|
b2GearJointDef.prototype.__constructor = function () {
|
|
this.type = b2Joint.e_gearJoint;
|
|
this.joint1 = null;
|
|
this.joint2 = null;
|
|
this.ratio = 1.0;
|
|
}
|
|
b2GearJointDef.prototype.__varz = function(){
|
|
}
|
|
b2GearJointDef.prototype.joint1 = null;
|
|
b2GearJointDef.prototype.joint2 = null;
|
|
b2GearJointDef.prototype.ratio = null;
|
|
exports.b2GearJointDef = b2GearJointDef;
|
|
|
|
|
|
var b2DistanceJoint = function() {
|
|
b2Joint.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2DistanceJoint.prototype, b2Joint.prototype)
|
|
b2DistanceJoint.prototype._super = function(){ b2Joint.prototype.__constructor.apply(this, arguments) }
|
|
b2DistanceJoint.prototype.__constructor = function (def) {
|
|
this._super(def);
|
|
|
|
var tMat;
|
|
var tX;
|
|
var tY;
|
|
|
|
this.m_localAnchor1.SetV(def.localAnchor1);
|
|
|
|
this.m_localAnchor2.SetV(def.localAnchor2);
|
|
|
|
this.m_length = def.length;
|
|
this.m_frequencyHz = def.frequencyHz;
|
|
this.m_dampingRatio = def.dampingRatio;
|
|
this.m_impulse = 0.0;
|
|
this.m_gamma = 0.0;
|
|
this.m_bias = 0.0;
|
|
this.m_inv_dt = 0.0;
|
|
}
|
|
b2DistanceJoint.prototype.__varz = function(){
|
|
this.m_localAnchor1 = new b2Vec2();
|
|
this.m_localAnchor2 = new b2Vec2();
|
|
this.m_u = new b2Vec2();
|
|
}
|
|
b2DistanceJoint.prototype.m_localAnchor1 = new b2Vec2();
|
|
b2DistanceJoint.prototype.m_localAnchor2 = new b2Vec2();
|
|
b2DistanceJoint.prototype.m_u = new b2Vec2();
|
|
b2DistanceJoint.prototype.m_frequencyHz = null;
|
|
b2DistanceJoint.prototype.m_dampingRatio = null;
|
|
b2DistanceJoint.prototype.m_gamma = null;
|
|
b2DistanceJoint.prototype.m_bias = null;
|
|
b2DistanceJoint.prototype.m_impulse = null;
|
|
b2DistanceJoint.prototype.m_mass = null;
|
|
b2DistanceJoint.prototype.m_length = null;
|
|
b2DistanceJoint.prototype.InitVelocityConstraints = function (step) {
|
|
|
|
var tMat;
|
|
var tX;
|
|
|
|
this.m_inv_dt = step.inv_dt;
|
|
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
this.m_u.x = b2.m_sweep.c.x + r2X - b1.m_sweep.c.x - r1X;
|
|
this.m_u.y = b2.m_sweep.c.y + r2Y - b1.m_sweep.c.y - r1Y;
|
|
|
|
|
|
|
|
var length = Math.sqrt(this.m_u.x*this.m_u.x + this.m_u.y*this.m_u.y);
|
|
if (length > b2Settings.b2_linearSlop)
|
|
{
|
|
|
|
this.m_u.Multiply( 1.0 / length );
|
|
}
|
|
else
|
|
{
|
|
this.m_u.SetZero();
|
|
}
|
|
|
|
|
|
var cr1u = (r1X * this.m_u.y - r1Y * this.m_u.x);
|
|
|
|
var cr2u = (r2X * this.m_u.y - r2Y * this.m_u.x);
|
|
|
|
var invMass = b1.m_invMass + b1.m_invI * cr1u * cr1u + b2.m_invMass + b2.m_invI * cr2u * cr2u;
|
|
|
|
this.m_mass = 1.0 / invMass;
|
|
|
|
if (this.m_frequencyHz > 0.0)
|
|
{
|
|
var C = length - this.m_length;
|
|
|
|
|
|
var omega = 2.0 * Math.PI * this.m_frequencyHz;
|
|
|
|
|
|
var d = 2.0 * this.m_mass * this.m_dampingRatio * omega;
|
|
|
|
|
|
var k = this.m_mass * omega * omega;
|
|
|
|
|
|
this.m_gamma = 1.0 / (step.dt * (d + step.dt * k));
|
|
this.m_bias = C * step.dt * k * this.m_gamma;
|
|
|
|
this.m_mass = 1.0 / (invMass + this.m_gamma);
|
|
}
|
|
|
|
if (step.warmStarting)
|
|
{
|
|
this.m_impulse *= step.dtRatio;
|
|
|
|
var PX = this.m_impulse * this.m_u.x;
|
|
var PY = this.m_impulse * this.m_u.y;
|
|
|
|
b1.m_linearVelocity.x -= b1.m_invMass * PX;
|
|
b1.m_linearVelocity.y -= b1.m_invMass * PY;
|
|
|
|
b1.m_angularVelocity -= b1.m_invI * (r1X * PY - r1Y * PX);
|
|
|
|
b2.m_linearVelocity.x += b2.m_invMass * PX;
|
|
b2.m_linearVelocity.y += b2.m_invMass * PY;
|
|
|
|
b2.m_angularVelocity += b2.m_invI * (r2X * PY - r2Y * PX);
|
|
}
|
|
else
|
|
{
|
|
this.m_impulse = 0.0;
|
|
}
|
|
}
|
|
b2DistanceJoint.prototype.SolveVelocityConstraints = function (step) {
|
|
|
|
var tMat;
|
|
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
|
|
var v1X = b1.m_linearVelocity.x + (-b1.m_angularVelocity * r1Y);
|
|
var v1Y = b1.m_linearVelocity.y + (b1.m_angularVelocity * r1X);
|
|
|
|
var v2X = b2.m_linearVelocity.x + (-b2.m_angularVelocity * r2Y);
|
|
var v2Y = b2.m_linearVelocity.y + (b2.m_angularVelocity * r2X);
|
|
|
|
var Cdot = (this.m_u.x * (v2X - v1X) + this.m_u.y * (v2Y - v1Y));
|
|
|
|
var impulse = -this.m_mass * (Cdot + this.m_bias + this.m_gamma * this.m_impulse);
|
|
this.m_impulse += impulse;
|
|
|
|
|
|
var PX = impulse * this.m_u.x;
|
|
var PY = impulse * this.m_u.y;
|
|
|
|
b1.m_linearVelocity.x -= b1.m_invMass * PX;
|
|
b1.m_linearVelocity.y -= b1.m_invMass * PY;
|
|
|
|
b1.m_angularVelocity -= b1.m_invI * (r1X * PY - r1Y * PX);
|
|
|
|
b2.m_linearVelocity.x += b2.m_invMass * PX;
|
|
b2.m_linearVelocity.y += b2.m_invMass * PY;
|
|
|
|
b2.m_angularVelocity += b2.m_invI * (r2X * PY - r2Y * PX);
|
|
}
|
|
b2DistanceJoint.prototype.SolvePositionConstraints = function () {
|
|
|
|
var tMat;
|
|
|
|
if (this.m_frequencyHz > 0.0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var dX = b2.m_sweep.c.x + r2X - b1.m_sweep.c.x - r1X;
|
|
var dY = b2.m_sweep.c.y + r2Y - b1.m_sweep.c.y - r1Y;
|
|
|
|
|
|
var length = Math.sqrt(dX*dX + dY*dY);
|
|
dX /= length;
|
|
dY /= length;
|
|
|
|
var C = length - this.m_length;
|
|
C = b2Math.b2Clamp(C, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
|
|
|
|
var impulse = -this.m_mass * C;
|
|
|
|
this.m_u.Set(dX, dY);
|
|
|
|
var PX = impulse * this.m_u.x;
|
|
var PY = impulse * this.m_u.y;
|
|
|
|
|
|
b1.m_sweep.c.x -= b1.m_invMass * PX;
|
|
b1.m_sweep.c.y -= b1.m_invMass * PY;
|
|
|
|
b1.m_sweep.a -= b1.m_invI * (r1X * PY - r1Y * PX);
|
|
|
|
b2.m_sweep.c.x += b2.m_invMass * PX;
|
|
b2.m_sweep.c.y += b2.m_invMass * PY;
|
|
|
|
b2.m_sweep.a += b2.m_invI * (r2X * PY - r2Y * PX);
|
|
|
|
b1.SynchronizeTransform();
|
|
b2.SynchronizeTransform();
|
|
|
|
return b2Math.b2Abs(C) < b2Settings.b2_linearSlop;
|
|
|
|
}
|
|
b2DistanceJoint.prototype.GetAnchor1 = function () {
|
|
return this.m_body1.GetWorldPoint(this.m_localAnchor1);
|
|
}
|
|
b2DistanceJoint.prototype.GetAnchor2 = function () {
|
|
return this.m_body2.GetWorldPoint(this.m_localAnchor2);
|
|
}
|
|
b2DistanceJoint.prototype.GetReactionForce = function () {
|
|
|
|
var F = new b2Vec2();
|
|
F.SetV(this.m_u);
|
|
F.Multiply(this.m_inv_dt * this.m_impulse);
|
|
return F;
|
|
}
|
|
b2DistanceJoint.prototype.GetReactionTorque = function () {
|
|
|
|
return 0.0;
|
|
}
|
|
exports.b2DistanceJoint = b2DistanceJoint;
|
|
|
|
|
|
var b2MouseJoint = function() {
|
|
b2Joint.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2MouseJoint.prototype, b2Joint.prototype)
|
|
b2MouseJoint.prototype._super = function(){ b2Joint.prototype.__constructor.apply(this, arguments) }
|
|
b2MouseJoint.prototype.__constructor = function (def) {
|
|
this._super(def);
|
|
|
|
this.m_target.SetV(def.target);
|
|
|
|
var tX = this.m_target.x - this.m_body2.m_xf.position.x;
|
|
var tY = this.m_target.y - this.m_body2.m_xf.position.y;
|
|
var tMat = this.m_body2.m_xf.R;
|
|
this.m_localAnchor.x = (tX * tMat.col1.x + tY * tMat.col1.y);
|
|
this.m_localAnchor.y = (tX * tMat.col2.x + tY * tMat.col2.y);
|
|
|
|
this.m_maxForce = def.maxForce;
|
|
this.m_impulse.SetZero();
|
|
|
|
var mass = this.m_body2.m_mass;
|
|
|
|
|
|
var omega = 2.0 * b2Settings.b2_pi * def.frequencyHz;
|
|
|
|
|
|
var d = 2.0 * mass * def.dampingRatio * omega;
|
|
|
|
|
|
var k = (def.timeStep * mass) * (omega * omega);
|
|
|
|
|
|
|
|
this.m_gamma = 1.0 / (d + k);
|
|
this.m_beta = k / (d + k);
|
|
}
|
|
b2MouseJoint.prototype.__varz = function(){
|
|
this.K = new b2Mat22();
|
|
this.K1 = new b2Mat22();
|
|
this.K2 = new b2Mat22();
|
|
this.m_localAnchor = new b2Vec2();
|
|
this.m_target = new b2Vec2();
|
|
this.m_impulse = new b2Vec2();
|
|
this.m_mass = new b2Mat22();
|
|
this.m_C = new b2Vec2();
|
|
}
|
|
b2MouseJoint.prototype.K = new b2Mat22();
|
|
b2MouseJoint.prototype.K1 = new b2Mat22();
|
|
b2MouseJoint.prototype.K2 = new b2Mat22();
|
|
b2MouseJoint.prototype.m_localAnchor = new b2Vec2();
|
|
b2MouseJoint.prototype.m_target = new b2Vec2();
|
|
b2MouseJoint.prototype.m_impulse = new b2Vec2();
|
|
b2MouseJoint.prototype.m_mass = new b2Mat22();
|
|
b2MouseJoint.prototype.m_C = new b2Vec2();
|
|
b2MouseJoint.prototype.m_maxForce = null;
|
|
b2MouseJoint.prototype.m_beta = null;
|
|
b2MouseJoint.prototype.m_gamma = null;
|
|
b2MouseJoint.prototype.GetAnchor1 = function () {
|
|
return this.m_target;
|
|
}
|
|
b2MouseJoint.prototype.GetAnchor2 = function () {
|
|
return this.m_body2.GetWorldPoint(this.m_localAnchor);
|
|
}
|
|
b2MouseJoint.prototype.GetReactionForce = function () {
|
|
return this.m_impulse;
|
|
}
|
|
b2MouseJoint.prototype.GetReactionTorque = function () {
|
|
return 0.0;
|
|
}
|
|
b2MouseJoint.prototype.SetTarget = function (target) {
|
|
if (this.m_body2.IsSleeping()){
|
|
this.m_body2.WakeUp();
|
|
}
|
|
this.m_target = target;
|
|
}
|
|
b2MouseJoint.prototype.InitVelocityConstraints = function (step) {
|
|
var b = this.m_body2;
|
|
|
|
var tMat;
|
|
|
|
|
|
|
|
tMat = b.m_xf.R;
|
|
var rX = this.m_localAnchor.x - b.m_sweep.localCenter.x;
|
|
var rY = this.m_localAnchor.y - b.m_sweep.localCenter.y;
|
|
var tX = (tMat.col1.x * rX + tMat.col2.x * rY);
|
|
rY = (tMat.col1.y * rX + tMat.col2.y * rY);
|
|
rX = tX;
|
|
|
|
|
|
|
|
|
|
var invMass = b.m_invMass;
|
|
var invI = b.m_invI;
|
|
|
|
|
|
this.K1.col1.x = invMass; this.K1.col2.x = 0.0;
|
|
this.K1.col1.y = 0.0; this.K1.col2.y = invMass;
|
|
|
|
|
|
this.K2.col1.x = invI * rY * rY; this.K2.col2.x = -invI * rX * rY;
|
|
this.K2.col1.y = -invI * rX * rY; this.K2.col2.y = invI * rX * rX;
|
|
|
|
|
|
this.K.SetM(this.K1);
|
|
this.K.AddM(this.K2);
|
|
this.K.col1.x += this.m_gamma;
|
|
this.K.col2.y += this.m_gamma;
|
|
|
|
|
|
this.K.Invert(this.m_mass);
|
|
|
|
|
|
this.m_C.x = b.m_sweep.c.x + rX - this.m_target.x;
|
|
this.m_C.y = b.m_sweep.c.y + rY - this.m_target.y;
|
|
|
|
|
|
b.m_angularVelocity *= 0.98;
|
|
|
|
|
|
|
|
var PX = step.dt * this.m_impulse.x;
|
|
var PY = step.dt * this.m_impulse.y;
|
|
|
|
b.m_linearVelocity.x += invMass * PX;
|
|
b.m_linearVelocity.y += invMass * PY;
|
|
|
|
b.m_angularVelocity += invI * (rX * PY - rY * PX);
|
|
}
|
|
b2MouseJoint.prototype.SolveVelocityConstraints = function (step) {
|
|
var b = this.m_body2;
|
|
|
|
var tMat;
|
|
var tX;
|
|
var tY;
|
|
|
|
|
|
|
|
tMat = b.m_xf.R;
|
|
var rX = this.m_localAnchor.x - b.m_sweep.localCenter.x;
|
|
var rY = this.m_localAnchor.y - b.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * rX + tMat.col2.x * rY);
|
|
rY = (tMat.col1.y * rX + tMat.col2.y * rY);
|
|
rX = tX;
|
|
|
|
|
|
|
|
var CdotX = b.m_linearVelocity.x + (-b.m_angularVelocity * rY);
|
|
var CdotY = b.m_linearVelocity.y + (b.m_angularVelocity * rX);
|
|
|
|
tMat = this.m_mass;
|
|
tX = CdotX + (this.m_beta * step.inv_dt) * this.m_C.x + this.m_gamma * step.dt * this.m_impulse.x;
|
|
tY = CdotY + (this.m_beta * step.inv_dt) * this.m_C.y + this.m_gamma * step.dt * this.m_impulse.y;
|
|
var forceX = -step.inv_dt * (tMat.col1.x * tX + tMat.col2.x * tY);
|
|
var forceY = -step.inv_dt * (tMat.col1.y * tX + tMat.col2.y * tY);
|
|
|
|
var oldForceX = this.m_impulse.x;
|
|
var oldForceY = this.m_impulse.y;
|
|
|
|
this.m_impulse.x += forceX;
|
|
this.m_impulse.y += forceY;
|
|
var forceMagnitude = this.m_impulse.Length();
|
|
if (forceMagnitude > this.m_maxForce)
|
|
{
|
|
|
|
this.m_impulse.Multiply(this.m_maxForce / forceMagnitude);
|
|
}
|
|
|
|
forceX = this.m_impulse.x - oldForceX;
|
|
forceY = this.m_impulse.y - oldForceY;
|
|
|
|
|
|
var PX = step.dt * forceX;
|
|
var PY = step.dt * forceY;
|
|
|
|
b.m_linearVelocity.x += b.m_invMass * PX;
|
|
b.m_linearVelocity.y += b.m_invMass * PY;
|
|
|
|
b.m_angularVelocity += b.m_invI * (rX * PY - rY * PX);
|
|
}
|
|
b2MouseJoint.prototype.SolvePositionConstraints = function () {
|
|
return true;
|
|
}
|
|
exports.b2MouseJoint = b2MouseJoint;
|
|
|
|
|
|
var b2PulleyJoint = function() {
|
|
b2Joint.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PulleyJoint.prototype, b2Joint.prototype)
|
|
b2PulleyJoint.prototype._super = function(){ b2Joint.prototype.__constructor.apply(this, arguments) }
|
|
b2PulleyJoint.prototype.__constructor = function (def) {
|
|
|
|
|
|
this._super(def);
|
|
|
|
var tMat;
|
|
var tX;
|
|
var tY;
|
|
|
|
this.m_ground = this.m_body1.m_world.m_groundBody;
|
|
|
|
this.m_groundAnchor1.x = def.groundAnchor1.x - this.m_ground.m_xf.position.x;
|
|
this.m_groundAnchor1.y = def.groundAnchor1.y - this.m_ground.m_xf.position.y;
|
|
|
|
this.m_groundAnchor2.x = def.groundAnchor2.x - this.m_ground.m_xf.position.x;
|
|
this.m_groundAnchor2.y = def.groundAnchor2.y - this.m_ground.m_xf.position.y;
|
|
|
|
this.m_localAnchor1.SetV(def.localAnchor1);
|
|
|
|
this.m_localAnchor2.SetV(def.localAnchor2);
|
|
|
|
|
|
this.m_ratio = def.ratio;
|
|
|
|
this.m_constant = def.length1 + this.m_ratio * def.length2;
|
|
|
|
this.m_maxLength1 = b2Math.b2Min(def.maxLength1, this.m_constant - this.m_ratio * b2PulleyJoint.b2_minPulleyLength);
|
|
this.m_maxLength2 = b2Math.b2Min(def.maxLength2, (this.m_constant - b2PulleyJoint.b2_minPulleyLength) / this.m_ratio);
|
|
|
|
this.m_force = 0.0;
|
|
this.m_limitForce1 = 0.0;
|
|
this.m_limitForce2 = 0.0;
|
|
|
|
}
|
|
b2PulleyJoint.prototype.__varz = function(){
|
|
this.m_groundAnchor1 = new b2Vec2();
|
|
this.m_groundAnchor2 = new b2Vec2();
|
|
this.m_localAnchor1 = new b2Vec2();
|
|
this.m_localAnchor2 = new b2Vec2();
|
|
this.m_u1 = new b2Vec2();
|
|
this.m_u2 = new b2Vec2();
|
|
}
|
|
b2PulleyJoint.b2_minPulleyLength = 2.0;
|
|
b2PulleyJoint.prototype.m_ground = null;
|
|
b2PulleyJoint.prototype.m_groundAnchor1 = new b2Vec2();
|
|
b2PulleyJoint.prototype.m_groundAnchor2 = new b2Vec2();
|
|
b2PulleyJoint.prototype.m_localAnchor1 = new b2Vec2();
|
|
b2PulleyJoint.prototype.m_localAnchor2 = new b2Vec2();
|
|
b2PulleyJoint.prototype.m_u1 = new b2Vec2();
|
|
b2PulleyJoint.prototype.m_u2 = new b2Vec2();
|
|
b2PulleyJoint.prototype.m_constant = null;
|
|
b2PulleyJoint.prototype.m_ratio = null;
|
|
b2PulleyJoint.prototype.m_maxLength1 = null;
|
|
b2PulleyJoint.prototype.m_maxLength2 = null;
|
|
b2PulleyJoint.prototype.m_pulleyMass = null;
|
|
b2PulleyJoint.prototype.m_limitMass1 = null;
|
|
b2PulleyJoint.prototype.m_limitMass2 = null;
|
|
b2PulleyJoint.prototype.m_force = null;
|
|
b2PulleyJoint.prototype.m_limitForce1 = null;
|
|
b2PulleyJoint.prototype.m_limitForce2 = null;
|
|
b2PulleyJoint.prototype.m_positionImpulse = null;
|
|
b2PulleyJoint.prototype.m_limitPositionImpulse1 = null;
|
|
b2PulleyJoint.prototype.m_limitPositionImpulse2 = null;
|
|
b2PulleyJoint.prototype.m_state = 0;
|
|
b2PulleyJoint.prototype.m_limitState1 = 0;
|
|
b2PulleyJoint.prototype.m_limitState2 = 0;
|
|
b2PulleyJoint.prototype.GetAnchor1 = function () {
|
|
return this.m_body1.GetWorldPoint(this.m_localAnchor1);
|
|
}
|
|
b2PulleyJoint.prototype.GetAnchor2 = function () {
|
|
return this.m_body2.GetWorldPoint(this.m_localAnchor2);
|
|
}
|
|
b2PulleyJoint.prototype.GetReactionForce = function () {
|
|
|
|
var F = this.m_u2.Copy();
|
|
F.Multiply(this.m_force);
|
|
return F;
|
|
}
|
|
b2PulleyJoint.prototype.GetReactionTorque = function () {
|
|
return 0.0;
|
|
}
|
|
b2PulleyJoint.prototype.GetGroundAnchor1 = function () {
|
|
|
|
var a = this.m_ground.m_xf.position.Copy();
|
|
a.Add(this.m_groundAnchor1);
|
|
return a;
|
|
}
|
|
b2PulleyJoint.prototype.GetGroundAnchor2 = function () {
|
|
|
|
var a = this.m_ground.m_xf.position.Copy();
|
|
a.Add(this.m_groundAnchor2);
|
|
return a;
|
|
}
|
|
b2PulleyJoint.prototype.GetLength1 = function () {
|
|
var p = this.m_body1.GetWorldPoint(this.m_localAnchor1);
|
|
|
|
var sX = this.m_ground.m_xf.position.x + this.m_groundAnchor1.x;
|
|
var sY = this.m_ground.m_xf.position.y + this.m_groundAnchor1.y;
|
|
|
|
var dX = p.x - sX;
|
|
var dY = p.y - sY;
|
|
|
|
return Math.sqrt(dX*dX + dY*dY);
|
|
}
|
|
b2PulleyJoint.prototype.GetLength2 = function () {
|
|
var p = this.m_body2.GetWorldPoint(this.m_localAnchor2);
|
|
|
|
var sX = this.m_ground.m_xf.position.x + this.m_groundAnchor2.x;
|
|
var sY = this.m_ground.m_xf.position.y + this.m_groundAnchor2.y;
|
|
|
|
var dX = p.x - sX;
|
|
var dY = p.y - sY;
|
|
|
|
return Math.sqrt(dX*dX + dY*dY);
|
|
}
|
|
b2PulleyJoint.prototype.GetRatio = function () {
|
|
return this.m_ratio;
|
|
}
|
|
b2PulleyJoint.prototype.InitVelocityConstraints = function (step) {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var p1X = b1.m_sweep.c.x + r1X;
|
|
var p1Y = b1.m_sweep.c.y + r1Y;
|
|
|
|
var p2X = b2.m_sweep.c.x + r2X;
|
|
var p2Y = b2.m_sweep.c.y + r2Y;
|
|
|
|
|
|
var s1X = this.m_ground.m_xf.position.x + this.m_groundAnchor1.x;
|
|
var s1Y = this.m_ground.m_xf.position.y + this.m_groundAnchor1.y;
|
|
|
|
var s2X = this.m_ground.m_xf.position.x + this.m_groundAnchor2.x;
|
|
var s2Y = this.m_ground.m_xf.position.y + this.m_groundAnchor2.y;
|
|
|
|
|
|
|
|
this.m_u1.Set(p1X - s1X, p1Y - s1Y);
|
|
|
|
this.m_u2.Set(p2X - s2X, p2Y - s2Y);
|
|
|
|
var length1 = this.m_u1.Length();
|
|
var length2 = this.m_u2.Length();
|
|
|
|
if (length1 > b2Settings.b2_linearSlop)
|
|
{
|
|
|
|
this.m_u1.Multiply(1.0 / length1);
|
|
}
|
|
else
|
|
{
|
|
this.m_u1.SetZero();
|
|
}
|
|
|
|
if (length2 > b2Settings.b2_linearSlop)
|
|
{
|
|
|
|
this.m_u2.Multiply(1.0 / length2);
|
|
}
|
|
else
|
|
{
|
|
this.m_u2.SetZero();
|
|
}
|
|
|
|
var C = this.m_constant - length1 - this.m_ratio * length2;
|
|
if (C > 0.0)
|
|
{
|
|
this.m_state = b2Joint.e_inactiveLimit;
|
|
this.m_force = 0.0;
|
|
}
|
|
else
|
|
{
|
|
this.m_state = b2Joint.e_atUpperLimit;
|
|
this.m_positionImpulse = 0.0;
|
|
}
|
|
|
|
if (length1 < this.m_maxLength1)
|
|
{
|
|
this.m_limitState1 = b2Joint.e_inactiveLimit;
|
|
this.m_limitForce1 = 0.0;
|
|
}
|
|
else
|
|
{
|
|
this.m_limitState1 = b2Joint.e_atUpperLimit;
|
|
this.m_limitPositionImpulse1 = 0.0;
|
|
}
|
|
|
|
if (length2 < this.m_maxLength2)
|
|
{
|
|
this.m_limitState2 = b2Joint.e_inactiveLimit;
|
|
this.m_limitForce2 = 0.0;
|
|
}
|
|
else
|
|
{
|
|
this.m_limitState2 = b2Joint.e_atUpperLimit;
|
|
this.m_limitPositionImpulse2 = 0.0;
|
|
}
|
|
|
|
|
|
|
|
var cr1u1 = r1X * this.m_u1.y - r1Y * this.m_u1.x;
|
|
|
|
var cr2u2 = r2X * this.m_u2.y - r2Y * this.m_u2.x;
|
|
|
|
this.m_limitMass1 = b1.m_invMass + b1.m_invI * cr1u1 * cr1u1;
|
|
this.m_limitMass2 = b2.m_invMass + b2.m_invI * cr2u2 * cr2u2;
|
|
this.m_pulleyMass = this.m_limitMass1 + this.m_ratio * this.m_ratio * this.m_limitMass2;
|
|
|
|
|
|
|
|
this.m_limitMass1 = 1.0 / this.m_limitMass1;
|
|
this.m_limitMass2 = 1.0 / this.m_limitMass2;
|
|
this.m_pulleyMass = 1.0 / this.m_pulleyMass;
|
|
|
|
if (step.warmStarting)
|
|
{
|
|
|
|
|
|
|
|
var P1X = step.dt * (-this.m_force - this.m_limitForce1) * this.m_u1.x;
|
|
var P1Y = step.dt * (-this.m_force - this.m_limitForce1) * this.m_u1.y;
|
|
|
|
|
|
var P2X = step.dt * (-this.m_ratio * this.m_force - this.m_limitForce2) * this.m_u2.x;
|
|
var P2Y = step.dt * (-this.m_ratio * this.m_force - this.m_limitForce2) * this.m_u2.y;
|
|
|
|
b1.m_linearVelocity.x += b1.m_invMass * P1X;
|
|
b1.m_linearVelocity.y += b1.m_invMass * P1Y;
|
|
|
|
b1.m_angularVelocity += b1.m_invI * (r1X * P1Y - r1Y * P1X);
|
|
|
|
b2.m_linearVelocity.x += b2.m_invMass * P2X;
|
|
b2.m_linearVelocity.y += b2.m_invMass * P2Y;
|
|
|
|
b2.m_angularVelocity += b2.m_invI * (r2X * P2Y - r2Y * P2X);
|
|
}
|
|
else
|
|
{
|
|
this.m_force = 0.0;
|
|
this.m_limitForce1 = 0.0;
|
|
this.m_limitForce2 = 0.0;
|
|
}
|
|
}
|
|
b2PulleyJoint.prototype.SolveVelocityConstraints = function (step) {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var v1X;
|
|
var v1Y;
|
|
var v2X;
|
|
var v2Y;
|
|
var P1X;
|
|
var P1Y;
|
|
var P2X;
|
|
var P2Y;
|
|
var Cdot;
|
|
var force;
|
|
var oldForce;
|
|
|
|
if (this.m_state == b2Joint.e_atUpperLimit)
|
|
{
|
|
|
|
v1X = b1.m_linearVelocity.x + (-b1.m_angularVelocity * r1Y);
|
|
v1Y = b1.m_linearVelocity.y + (b1.m_angularVelocity * r1X);
|
|
|
|
v2X = b2.m_linearVelocity.x + (-b2.m_angularVelocity * r2Y);
|
|
v2Y = b2.m_linearVelocity.y + (b2.m_angularVelocity * r2X);
|
|
|
|
|
|
Cdot = -(this.m_u1.x * v1X + this.m_u1.y * v1Y) - this.m_ratio * (this.m_u2.x * v2X + this.m_u2.y * v2Y);
|
|
force = -step.inv_dt * this.m_pulleyMass * Cdot;
|
|
oldForce = this.m_force;
|
|
this.m_force = b2Math.b2Max(0.0, this.m_force + force);
|
|
force = this.m_force - oldForce;
|
|
|
|
|
|
P1X = -step.dt * force * this.m_u1.x;
|
|
P1Y = -step.dt * force * this.m_u1.y;
|
|
|
|
P2X = -step.dt * this.m_ratio * force * this.m_u2.x;
|
|
P2Y = -step.dt * this.m_ratio * force * this.m_u2.y;
|
|
|
|
b1.m_linearVelocity.x += b1.m_invMass * P1X;
|
|
b1.m_linearVelocity.y += b1.m_invMass * P1Y;
|
|
|
|
b1.m_angularVelocity += b1.m_invI * (r1X * P1Y - r1Y * P1X);
|
|
|
|
b2.m_linearVelocity.x += b2.m_invMass * P2X;
|
|
b2.m_linearVelocity.y += b2.m_invMass * P2Y;
|
|
|
|
b2.m_angularVelocity += b2.m_invI * (r2X * P2Y - r2Y * P2X);
|
|
}
|
|
|
|
if (this.m_limitState1 == b2Joint.e_atUpperLimit)
|
|
{
|
|
|
|
v1X = b1.m_linearVelocity.x + (-b1.m_angularVelocity * r1Y);
|
|
v1Y = b1.m_linearVelocity.y + (b1.m_angularVelocity * r1X);
|
|
|
|
|
|
Cdot = -(this.m_u1.x * v1X + this.m_u1.y * v1Y);
|
|
force = -step.inv_dt * this.m_limitMass1 * Cdot;
|
|
oldForce = this.m_limitForce1;
|
|
this.m_limitForce1 = b2Math.b2Max(0.0, this.m_limitForce1 + force);
|
|
force = this.m_limitForce1 - oldForce;
|
|
|
|
|
|
P1X = -step.dt * force * this.m_u1.x;
|
|
P1Y = -step.dt * force * this.m_u1.y;
|
|
|
|
b1.m_linearVelocity.x += b1.m_invMass * P1X;
|
|
b1.m_linearVelocity.y += b1.m_invMass * P1Y;
|
|
|
|
b1.m_angularVelocity += b1.m_invI * (r1X * P1Y - r1Y * P1X);
|
|
}
|
|
|
|
if (this.m_limitState2 == b2Joint.e_atUpperLimit)
|
|
{
|
|
|
|
v2X = b2.m_linearVelocity.x + (-b2.m_angularVelocity * r2Y);
|
|
v2Y = b2.m_linearVelocity.y + (b2.m_angularVelocity * r2X);
|
|
|
|
|
|
Cdot = -(this.m_u2.x * v2X + this.m_u2.y * v2Y);
|
|
force = -step.inv_dt * this.m_limitMass2 * Cdot;
|
|
oldForce = this.m_limitForce2;
|
|
this.m_limitForce2 = b2Math.b2Max(0.0, this.m_limitForce2 + force);
|
|
force = this.m_limitForce2 - oldForce;
|
|
|
|
|
|
P2X = -step.dt * force * this.m_u2.x;
|
|
P2Y = -step.dt * force * this.m_u2.y;
|
|
|
|
b2.m_linearVelocity.x += b2.m_invMass * P2X;
|
|
b2.m_linearVelocity.y += b2.m_invMass * P2Y;
|
|
|
|
b2.m_angularVelocity += b2.m_invI * (r2X * P2Y - r2Y * P2X);
|
|
}
|
|
}
|
|
b2PulleyJoint.prototype.SolvePositionConstraints = function () {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
|
|
|
|
var s1X = this.m_ground.m_xf.position.x + this.m_groundAnchor1.x;
|
|
var s1Y = this.m_ground.m_xf.position.y + this.m_groundAnchor1.y;
|
|
|
|
var s2X = this.m_ground.m_xf.position.x + this.m_groundAnchor2.x;
|
|
var s2Y = this.m_ground.m_xf.position.y + this.m_groundAnchor2.y;
|
|
|
|
|
|
var r1X;
|
|
var r1Y;
|
|
var r2X;
|
|
var r2Y;
|
|
var p1X;
|
|
var p1Y;
|
|
var p2X;
|
|
var p2Y;
|
|
var length1;
|
|
var length2;
|
|
var C;
|
|
var impulse;
|
|
var oldImpulse;
|
|
var oldLimitPositionImpulse;
|
|
|
|
var tX;
|
|
|
|
var linearError = 0.0;
|
|
|
|
if (this.m_state == b2Joint.e_atUpperLimit)
|
|
{
|
|
|
|
tMat = b1.m_xf.R;
|
|
r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
p1X = b1.m_sweep.c.x + r1X;
|
|
p1Y = b1.m_sweep.c.y + r1Y;
|
|
|
|
p2X = b2.m_sweep.c.x + r2X;
|
|
p2Y = b2.m_sweep.c.y + r2Y;
|
|
|
|
|
|
|
|
this.m_u1.Set(p1X - s1X, p1Y - s1Y);
|
|
|
|
this.m_u2.Set(p2X - s2X, p2Y - s2Y);
|
|
|
|
length1 = this.m_u1.Length();
|
|
length2 = this.m_u2.Length();
|
|
|
|
if (length1 > b2Settings.b2_linearSlop)
|
|
{
|
|
|
|
this.m_u1.Multiply( 1.0 / length1 );
|
|
}
|
|
else
|
|
{
|
|
this.m_u1.SetZero();
|
|
}
|
|
|
|
if (length2 > b2Settings.b2_linearSlop)
|
|
{
|
|
|
|
this.m_u2.Multiply( 1.0 / length2 );
|
|
}
|
|
else
|
|
{
|
|
this.m_u2.SetZero();
|
|
}
|
|
|
|
C = this.m_constant - length1 - this.m_ratio * length2;
|
|
linearError = b2Math.b2Max(linearError, -C);
|
|
C = b2Math.b2Clamp(C + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
|
impulse = -this.m_pulleyMass * C;
|
|
|
|
oldImpulse = this.m_positionImpulse;
|
|
this.m_positionImpulse = b2Math.b2Max(0.0, this.m_positionImpulse + impulse);
|
|
impulse = this.m_positionImpulse - oldImpulse;
|
|
|
|
p1X = -impulse * this.m_u1.x;
|
|
p1Y = -impulse * this.m_u1.y;
|
|
p2X = -this.m_ratio * impulse * this.m_u2.x;
|
|
p2Y = -this.m_ratio * impulse * this.m_u2.y;
|
|
|
|
b1.m_sweep.c.x += b1.m_invMass * p1X;
|
|
b1.m_sweep.c.y += b1.m_invMass * p1Y;
|
|
b1.m_sweep.a += b1.m_invI * (r1X * p1Y - r1Y * p1X);
|
|
b2.m_sweep.c.x += b2.m_invMass * p2X;
|
|
b2.m_sweep.c.y += b2.m_invMass * p2Y;
|
|
b2.m_sweep.a += b2.m_invI * (r2X * p2Y - r2Y * p2X);
|
|
|
|
b1.SynchronizeTransform();
|
|
b2.SynchronizeTransform();
|
|
}
|
|
|
|
if (this.m_limitState1 == b2Joint.e_atUpperLimit)
|
|
{
|
|
|
|
tMat = b1.m_xf.R;
|
|
r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
p1X = b1.m_sweep.c.x + r1X;
|
|
p1Y = b1.m_sweep.c.y + r1Y;
|
|
|
|
|
|
this.m_u1.Set(p1X - s1X, p1Y - s1Y);
|
|
|
|
length1 = this.m_u1.Length();
|
|
|
|
if (length1 > b2Settings.b2_linearSlop)
|
|
{
|
|
|
|
this.m_u1.x *= 1.0 / length1;
|
|
this.m_u1.y *= 1.0 / length1;
|
|
}
|
|
else
|
|
{
|
|
this.m_u1.SetZero();
|
|
}
|
|
|
|
C = this.m_maxLength1 - length1;
|
|
linearError = b2Math.b2Max(linearError, -C);
|
|
C = b2Math.b2Clamp(C + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
|
impulse = -this.m_limitMass1 * C;
|
|
oldLimitPositionImpulse = this.m_limitPositionImpulse1;
|
|
this.m_limitPositionImpulse1 = b2Math.b2Max(0.0, this.m_limitPositionImpulse1 + impulse);
|
|
impulse = this.m_limitPositionImpulse1 - oldLimitPositionImpulse;
|
|
|
|
|
|
p1X = -impulse * this.m_u1.x;
|
|
p1Y = -impulse * this.m_u1.y;
|
|
|
|
b1.m_sweep.c.x += b1.m_invMass * p1X;
|
|
b1.m_sweep.c.y += b1.m_invMass * p1Y;
|
|
|
|
b1.m_sweep.a += b1.m_invI * (r1X * p1Y - r1Y * p1X);
|
|
|
|
b1.SynchronizeTransform();
|
|
}
|
|
|
|
if (this.m_limitState2 == b2Joint.e_atUpperLimit)
|
|
{
|
|
|
|
tMat = b2.m_xf.R;
|
|
r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
p2X = b2.m_sweep.c.x + r2X;
|
|
p2Y = b2.m_sweep.c.y + r2Y;
|
|
|
|
|
|
this.m_u2.Set(p2X - s2X, p2Y - s2Y);
|
|
|
|
length2 = this.m_u2.Length();
|
|
|
|
if (length2 > b2Settings.b2_linearSlop)
|
|
{
|
|
|
|
this.m_u2.x *= 1.0 / length2;
|
|
this.m_u2.y *= 1.0 / length2;
|
|
}
|
|
else
|
|
{
|
|
this.m_u2.SetZero();
|
|
}
|
|
|
|
C = this.m_maxLength2 - length2;
|
|
linearError = b2Math.b2Max(linearError, -C);
|
|
C = b2Math.b2Clamp(C + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
|
impulse = -this.m_limitMass2 * C;
|
|
oldLimitPositionImpulse = this.m_limitPositionImpulse2;
|
|
this.m_limitPositionImpulse2 = b2Math.b2Max(0.0, this.m_limitPositionImpulse2 + impulse);
|
|
impulse = this.m_limitPositionImpulse2 - oldLimitPositionImpulse;
|
|
|
|
|
|
p2X = -impulse * this.m_u2.x;
|
|
p2Y = -impulse * this.m_u2.y;
|
|
|
|
|
|
b2.m_sweep.c.x += b2.m_invMass * p2X;
|
|
b2.m_sweep.c.y += b2.m_invMass * p2Y;
|
|
|
|
b2.m_sweep.a += b2.m_invI * (r2X * p2Y - r2Y * p2X);
|
|
|
|
b2.SynchronizeTransform();
|
|
}
|
|
|
|
return linearError < b2Settings.b2_linearSlop;
|
|
}
|
|
exports.b2PulleyJoint = b2PulleyJoint;
|
|
|
|
|
|
var b2RevoluteJoint = function() {
|
|
b2Joint.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2RevoluteJoint.prototype, b2Joint.prototype)
|
|
b2RevoluteJoint.prototype._super = function(){ b2Joint.prototype.__constructor.apply(this, arguments) }
|
|
b2RevoluteJoint.prototype.__constructor = function (def) {
|
|
this._super(def);
|
|
|
|
|
|
this.m_localAnchor1.SetV(def.localAnchor1);
|
|
|
|
this.m_localAnchor2.SetV(def.localAnchor2);
|
|
|
|
this.m_referenceAngle = def.referenceAngle;
|
|
|
|
this.m_pivotForce.Set(0.0, 0.0);
|
|
this.m_motorForce = 0.0;
|
|
this.m_limitForce = 0.0;
|
|
this.m_limitPositionImpulse = 0.0;
|
|
|
|
this.m_lowerAngle = def.lowerAngle;
|
|
this.m_upperAngle = def.upperAngle;
|
|
this.m_maxMotorTorque = def.maxMotorTorque;
|
|
this.m_motorSpeed = def.motorSpeed;
|
|
this.m_enableLimit = def.enableLimit;
|
|
this.m_enableMotor = def.enableMotor;
|
|
}
|
|
b2RevoluteJoint.prototype.__varz = function(){
|
|
this.K = new b2Mat22();
|
|
this.K1 = new b2Mat22();
|
|
this.K2 = new b2Mat22();
|
|
this.K3 = new b2Mat22();
|
|
this.m_localAnchor1 = new b2Vec2();
|
|
this.m_localAnchor2 = new b2Vec2();
|
|
this.m_pivotForce = new b2Vec2();
|
|
this.m_pivotMass = new b2Mat22();
|
|
}
|
|
b2RevoluteJoint.tImpulse = new b2Vec2();
|
|
b2RevoluteJoint.prototype.K = new b2Mat22();
|
|
b2RevoluteJoint.prototype.K1 = new b2Mat22();
|
|
b2RevoluteJoint.prototype.K2 = new b2Mat22();
|
|
b2RevoluteJoint.prototype.K3 = new b2Mat22();
|
|
b2RevoluteJoint.prototype.m_localAnchor1 = new b2Vec2();
|
|
b2RevoluteJoint.prototype.m_localAnchor2 = new b2Vec2();
|
|
b2RevoluteJoint.prototype.m_pivotForce = new b2Vec2();
|
|
b2RevoluteJoint.prototype.m_motorForce = null;
|
|
b2RevoluteJoint.prototype.m_limitForce = null;
|
|
b2RevoluteJoint.prototype.m_limitPositionImpulse = null;
|
|
b2RevoluteJoint.prototype.m_pivotMass = new b2Mat22();
|
|
b2RevoluteJoint.prototype.m_motorMass = null;
|
|
b2RevoluteJoint.prototype.m_enableMotor = null;
|
|
b2RevoluteJoint.prototype.m_maxMotorTorque = null;
|
|
b2RevoluteJoint.prototype.m_motorSpeed = null;
|
|
b2RevoluteJoint.prototype.m_enableLimit = null;
|
|
b2RevoluteJoint.prototype.m_referenceAngle = null;
|
|
b2RevoluteJoint.prototype.m_lowerAngle = null;
|
|
b2RevoluteJoint.prototype.m_upperAngle = null;
|
|
b2RevoluteJoint.prototype.m_limitState = 0;
|
|
b2RevoluteJoint.prototype.GetAnchor1 = function () {
|
|
return this.m_body1.GetWorldPoint(this.m_localAnchor1);
|
|
}
|
|
b2RevoluteJoint.prototype.GetAnchor2 = function () {
|
|
return this.m_body2.GetWorldPoint(this.m_localAnchor2);
|
|
}
|
|
b2RevoluteJoint.prototype.GetReactionForce = function () {
|
|
return this.m_pivotForce;
|
|
}
|
|
b2RevoluteJoint.prototype.GetReactionTorque = function () {
|
|
return this.m_limitForce;
|
|
}
|
|
b2RevoluteJoint.prototype.GetJointAngle = function () {
|
|
|
|
|
|
return this.m_body2.m_sweep.a - this.m_body1.m_sweep.a - this.m_referenceAngle;
|
|
}
|
|
b2RevoluteJoint.prototype.GetJointSpeed = function () {
|
|
|
|
|
|
return this.m_body2.m_angularVelocity - this.m_body1.m_angularVelocity;
|
|
}
|
|
b2RevoluteJoint.prototype.IsLimitEnabled = function () {
|
|
return this.m_enableLimit;
|
|
}
|
|
b2RevoluteJoint.prototype.EnableLimit = function (flag) {
|
|
this.m_enableLimit = flag;
|
|
}
|
|
b2RevoluteJoint.prototype.GetLowerLimit = function () {
|
|
return this.m_lowerAngle;
|
|
}
|
|
b2RevoluteJoint.prototype.GetUpperLimit = function () {
|
|
return this.m_upperAngle;
|
|
}
|
|
b2RevoluteJoint.prototype.SetLimits = function (lower, upper) {
|
|
|
|
this.m_lowerAngle = lower;
|
|
this.m_upperAngle = upper;
|
|
}
|
|
b2RevoluteJoint.prototype.IsMotorEnabled = function () {
|
|
return this.m_enableMotor;
|
|
}
|
|
b2RevoluteJoint.prototype.EnableMotor = function (flag) {
|
|
this.m_enableMotor = flag;
|
|
}
|
|
b2RevoluteJoint.prototype.SetMotorSpeed = function (speed) {
|
|
this.m_motorSpeed = speed;
|
|
}
|
|
b2RevoluteJoint.prototype.GetMotorSpeed = function () {
|
|
return this.m_motorSpeed;
|
|
}
|
|
b2RevoluteJoint.prototype.SetMaxMotorTorque = function (torque) {
|
|
this.m_maxMotorTorque = torque;
|
|
}
|
|
b2RevoluteJoint.prototype.GetMotorTorque = function () {
|
|
return this.m_motorForce;
|
|
}
|
|
b2RevoluteJoint.prototype.InitVelocityConstraints = function (step) {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
var tX;
|
|
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
|
|
|
|
var invMass1 = b1.m_invMass;
|
|
var invMass2 = b2.m_invMass;
|
|
var invI1 = b1.m_invI;
|
|
var invI2 = b2.m_invI;
|
|
|
|
|
|
this.K1.col1.x = invMass1 + invMass2; this.K1.col2.x = 0.0;
|
|
this.K1.col1.y = 0.0; this.K1.col2.y = invMass1 + invMass2;
|
|
|
|
|
|
this.K2.col1.x = invI1 * r1Y * r1Y; this.K2.col2.x = -invI1 * r1X * r1Y;
|
|
this.K2.col1.y = -invI1 * r1X * r1Y; this.K2.col2.y = invI1 * r1X * r1X;
|
|
|
|
|
|
this.K3.col1.x = invI2 * r2Y * r2Y; this.K3.col2.x = -invI2 * r2X * r2Y;
|
|
this.K3.col1.y = -invI2 * r2X * r2Y; this.K3.col2.y = invI2 * r2X * r2X;
|
|
|
|
|
|
this.K.SetM(this.K1);
|
|
this.K.AddM(this.K2);
|
|
this.K.AddM(this.K3);
|
|
|
|
|
|
this.K.Invert(this.m_pivotMass);
|
|
|
|
this.m_motorMass = 1.0 / (invI1 + invI2);
|
|
|
|
if (this.m_enableMotor == false)
|
|
{
|
|
this.m_motorForce = 0.0;
|
|
}
|
|
|
|
if (this.m_enableLimit)
|
|
{
|
|
|
|
var jointAngle = b2.m_sweep.a - b1.m_sweep.a - this.m_referenceAngle;
|
|
if (b2Math.b2Abs(this.m_upperAngle - this.m_lowerAngle) < 2.0 * b2Settings.b2_angularSlop)
|
|
{
|
|
this.m_limitState = b2Joint.e_equalLimits;
|
|
}
|
|
else if (jointAngle <= this.m_lowerAngle)
|
|
{
|
|
if (this.m_limitState != b2Joint.e_atLowerLimit)
|
|
{
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
this.m_limitState = b2Joint.e_atLowerLimit;
|
|
}
|
|
else if (jointAngle >= this.m_upperAngle)
|
|
{
|
|
if (this.m_limitState != b2Joint.e_atUpperLimit)
|
|
{
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
this.m_limitState = b2Joint.e_atUpperLimit;
|
|
}
|
|
else
|
|
{
|
|
this.m_limitState = b2Joint.e_inactiveLimit;
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
|
|
|
|
if (step.warmStarting)
|
|
{
|
|
|
|
b1.m_linearVelocity.x -= step.dt * invMass1 * this.m_pivotForce.x;
|
|
b1.m_linearVelocity.y -= step.dt * invMass1 * this.m_pivotForce.y;
|
|
|
|
b1.m_angularVelocity -= step.dt * invI1 * ((r1X * this.m_pivotForce.y - r1Y * this.m_pivotForce.x) + this.m_motorForce + this.m_limitForce);
|
|
|
|
|
|
b2.m_linearVelocity.x += step.dt * invMass2 * this.m_pivotForce.x;
|
|
b2.m_linearVelocity.y += step.dt * invMass2 * this.m_pivotForce.y;
|
|
|
|
b2.m_angularVelocity += step.dt * invI2 * ((r2X * this.m_pivotForce.y - r2Y * this.m_pivotForce.x) + this.m_motorForce + this.m_limitForce);
|
|
}
|
|
else{
|
|
this.m_pivotForce.SetZero();
|
|
this.m_motorForce = 0.0;
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
|
|
this.m_limitPositionImpulse = 0.0;
|
|
}
|
|
b2RevoluteJoint.prototype.SolveVelocityConstraints = function (step) {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
var tX;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
var oldLimitForce;
|
|
|
|
|
|
|
|
var pivotCdotX = b2.m_linearVelocity.x + (-b2.m_angularVelocity * r2Y) - b1.m_linearVelocity.x - (-b1.m_angularVelocity * r1Y);
|
|
var pivotCdotY = b2.m_linearVelocity.y + (b2.m_angularVelocity * r2X) - b1.m_linearVelocity.y - (b1.m_angularVelocity * r1X);
|
|
|
|
|
|
var pivotForceX = -step.inv_dt * (this.m_pivotMass.col1.x * pivotCdotX + this.m_pivotMass.col2.x * pivotCdotY);
|
|
var pivotForceY = -step.inv_dt * (this.m_pivotMass.col1.y * pivotCdotX + this.m_pivotMass.col2.y * pivotCdotY);
|
|
this.m_pivotForce.x += pivotForceX;
|
|
this.m_pivotForce.y += pivotForceY;
|
|
|
|
|
|
var PX = step.dt * pivotForceX;
|
|
var PY = step.dt * pivotForceY;
|
|
|
|
|
|
b1.m_linearVelocity.x -= b1.m_invMass * PX;
|
|
b1.m_linearVelocity.y -= b1.m_invMass * PY;
|
|
|
|
b1.m_angularVelocity -= b1.m_invI * (r1X * PY - r1Y * PX);
|
|
|
|
|
|
b2.m_linearVelocity.x += b2.m_invMass * PX;
|
|
b2.m_linearVelocity.y += b2.m_invMass * PY;
|
|
|
|
b2.m_angularVelocity += b2.m_invI * (r2X * PY - r2Y * PX);
|
|
|
|
if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits)
|
|
{
|
|
var motorCdot = b2.m_angularVelocity - b1.m_angularVelocity - this.m_motorSpeed;
|
|
var motorForce = -step.inv_dt * this.m_motorMass * motorCdot;
|
|
var oldMotorForce = this.m_motorForce;
|
|
this.m_motorForce = b2Math.b2Clamp(this.m_motorForce + motorForce, -this.m_maxMotorTorque, this.m_maxMotorTorque);
|
|
motorForce = this.m_motorForce - oldMotorForce;
|
|
|
|
b1.m_angularVelocity -= b1.m_invI * step.dt * motorForce;
|
|
b2.m_angularVelocity += b2.m_invI * step.dt * motorForce;
|
|
}
|
|
|
|
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
|
{
|
|
var limitCdot = b2.m_angularVelocity - b1.m_angularVelocity;
|
|
var limitForce = -step.inv_dt * this.m_motorMass * limitCdot;
|
|
|
|
if (this.m_limitState == b2Joint.e_equalLimits)
|
|
{
|
|
this.m_limitForce += limitForce;
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
|
{
|
|
oldLimitForce = this.m_limitForce;
|
|
this.m_limitForce = b2Math.b2Max(this.m_limitForce + limitForce, 0.0);
|
|
limitForce = this.m_limitForce - oldLimitForce;
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
|
{
|
|
oldLimitForce = this.m_limitForce;
|
|
this.m_limitForce = b2Math.b2Min(this.m_limitForce + limitForce, 0.0);
|
|
limitForce = this.m_limitForce - oldLimitForce;
|
|
}
|
|
|
|
b1.m_angularVelocity -= b1.m_invI * step.dt * limitForce;
|
|
b2.m_angularVelocity += b2.m_invI * step.dt * limitForce;
|
|
}
|
|
}
|
|
b2RevoluteJoint.prototype.SolvePositionConstraints = function () {
|
|
|
|
var oldLimitImpulse;
|
|
var limitC;
|
|
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var positionError = 0.0;
|
|
|
|
var tMat;
|
|
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var p1X = b1.m_sweep.c.x + r1X;
|
|
var p1Y = b1.m_sweep.c.y + r1Y;
|
|
|
|
var p2X = b2.m_sweep.c.x + r2X;
|
|
var p2Y = b2.m_sweep.c.y + r2Y;
|
|
|
|
|
|
var ptpCX = p2X - p1X;
|
|
var ptpCY = p2Y - p1Y;
|
|
|
|
|
|
positionError = Math.sqrt(ptpCX*ptpCX + ptpCY*ptpCY);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var invMass1 = b1.m_invMass;
|
|
var invMass2 = b2.m_invMass;
|
|
|
|
var invI1 = b1.m_invI;
|
|
var invI2 = b2.m_invI;
|
|
|
|
|
|
this.K1.col1.x = invMass1 + invMass2; this.K1.col2.x = 0.0;
|
|
this.K1.col1.y = 0.0; this.K1.col2.y = invMass1 + invMass2;
|
|
|
|
|
|
this.K2.col1.x = invI1 * r1Y * r1Y; this.K2.col2.x = -invI1 * r1X * r1Y;
|
|
this.K2.col1.y = -invI1 * r1X * r1Y; this.K2.col2.y = invI1 * r1X * r1X;
|
|
|
|
|
|
this.K3.col1.x = invI2 * r2Y * r2Y; this.K3.col2.x = -invI2 * r2X * r2Y;
|
|
this.K3.col1.y = -invI2 * r2X * r2Y; this.K3.col2.y = invI2 * r2X * r2X;
|
|
|
|
|
|
this.K.SetM(this.K1);
|
|
this.K.AddM(this.K2);
|
|
this.K.AddM(this.K3);
|
|
|
|
this.K.Solve(b2RevoluteJoint.tImpulse, -ptpCX, -ptpCY);
|
|
var impulseX = b2RevoluteJoint.tImpulse.x;
|
|
var impulseY = b2RevoluteJoint.tImpulse.y;
|
|
|
|
|
|
b1.m_sweep.c.x -= b1.m_invMass * impulseX;
|
|
b1.m_sweep.c.y -= b1.m_invMass * impulseY;
|
|
|
|
b1.m_sweep.a -= b1.m_invI * (r1X * impulseY - r1Y * impulseX);
|
|
|
|
|
|
b2.m_sweep.c.x += b2.m_invMass * impulseX;
|
|
b2.m_sweep.c.y += b2.m_invMass * impulseY;
|
|
|
|
b2.m_sweep.a += b2.m_invI * (r2X * impulseY - r2Y * impulseX);
|
|
|
|
b1.SynchronizeTransform();
|
|
b2.SynchronizeTransform();
|
|
|
|
|
|
|
|
var angularError = 0.0;
|
|
|
|
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
|
{
|
|
var angle = b2.m_sweep.a - b1.m_sweep.a - this.m_referenceAngle;
|
|
var limitImpulse = 0.0;
|
|
|
|
if (this.m_limitState == b2Joint.e_equalLimits)
|
|
{
|
|
|
|
limitC = b2Math.b2Clamp(angle, -b2Settings.b2_maxAngularCorrection, b2Settings.b2_maxAngularCorrection);
|
|
limitImpulse = -this.m_motorMass * limitC;
|
|
angularError = b2Math.b2Abs(limitC);
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
|
{
|
|
limitC = angle - this.m_lowerAngle;
|
|
angularError = b2Math.b2Max(0.0, -limitC);
|
|
|
|
|
|
limitC = b2Math.b2Clamp(limitC + b2Settings.b2_angularSlop, -b2Settings.b2_maxAngularCorrection, 0.0);
|
|
limitImpulse = -this.m_motorMass * limitC;
|
|
oldLimitImpulse = this.m_limitPositionImpulse;
|
|
this.m_limitPositionImpulse = b2Math.b2Max(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
|
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
|
{
|
|
limitC = angle - this.m_upperAngle;
|
|
angularError = b2Math.b2Max(0.0, limitC);
|
|
|
|
|
|
limitC = b2Math.b2Clamp(limitC - b2Settings.b2_angularSlop, 0.0, b2Settings.b2_maxAngularCorrection);
|
|
limitImpulse = -this.m_motorMass * limitC;
|
|
oldLimitImpulse = this.m_limitPositionImpulse;
|
|
this.m_limitPositionImpulse = b2Math.b2Min(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
|
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
|
}
|
|
|
|
b1.m_sweep.a -= b1.m_invI * limitImpulse;
|
|
b2.m_sweep.a += b2.m_invI * limitImpulse;
|
|
|
|
b1.SynchronizeTransform();
|
|
b2.SynchronizeTransform();
|
|
}
|
|
|
|
return positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
|
|
}
|
|
exports.b2RevoluteJoint = b2RevoluteJoint;
|
|
|
|
|
|
var b2PrismaticJoint = function() {
|
|
b2Joint.prototype.__varz.call(this)
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
extend(b2PrismaticJoint.prototype, b2Joint.prototype)
|
|
b2PrismaticJoint.prototype._super = function(){ b2Joint.prototype.__constructor.apply(this, arguments) }
|
|
b2PrismaticJoint.prototype.__constructor = function (def) {
|
|
this._super(def);
|
|
|
|
var tMat;
|
|
var tX;
|
|
var tY;
|
|
|
|
this.m_localAnchor1.SetV(def.localAnchor1);
|
|
this.m_localAnchor2.SetV(def.localAnchor2);
|
|
this.m_localXAxis1.SetV(def.localAxis1);
|
|
|
|
|
|
this.m_localYAxis1.x = -this.m_localXAxis1.y;
|
|
this.m_localYAxis1.y = this.m_localXAxis1.x;
|
|
|
|
this.m_refAngle = def.referenceAngle;
|
|
|
|
this.m_linearJacobian.SetZero();
|
|
this.m_linearMass = 0.0;
|
|
this.m_force = 0.0;
|
|
|
|
this.m_angularMass = 0.0;
|
|
this.m_torque = 0.0;
|
|
|
|
this.m_motorJacobian.SetZero();
|
|
this.m_motorMass = 0.0;
|
|
this.m_motorForce = 0.0;
|
|
this.m_limitForce = 0.0;
|
|
this.m_limitPositionImpulse = 0.0;
|
|
|
|
this.m_lowerTranslation = def.lowerTranslation;
|
|
this.m_upperTranslation = def.upperTranslation;
|
|
this.m_maxMotorForce = def.maxMotorForce;
|
|
this.m_motorSpeed = def.motorSpeed;
|
|
this.m_enableLimit = def.enableLimit;
|
|
this.m_enableMotor = def.enableMotor;
|
|
}
|
|
b2PrismaticJoint.prototype.__varz = function(){
|
|
this.m_localAnchor1 = new b2Vec2();
|
|
this.m_localAnchor2 = new b2Vec2();
|
|
this.m_localXAxis1 = new b2Vec2();
|
|
this.m_localYAxis1 = new b2Vec2();
|
|
this.m_linearJacobian = new b2Jacobian();
|
|
this.m_motorJacobian = new b2Jacobian();
|
|
}
|
|
b2PrismaticJoint.prototype.m_localAnchor1 = new b2Vec2();
|
|
b2PrismaticJoint.prototype.m_localAnchor2 = new b2Vec2();
|
|
b2PrismaticJoint.prototype.m_localXAxis1 = new b2Vec2();
|
|
b2PrismaticJoint.prototype.m_localYAxis1 = new b2Vec2();
|
|
b2PrismaticJoint.prototype.m_refAngle = null;
|
|
b2PrismaticJoint.prototype.m_linearJacobian = new b2Jacobian();
|
|
b2PrismaticJoint.prototype.m_linearMass = null;
|
|
b2PrismaticJoint.prototype.m_force = null;
|
|
b2PrismaticJoint.prototype.m_angularMass = null;
|
|
b2PrismaticJoint.prototype.m_torque = null;
|
|
b2PrismaticJoint.prototype.m_motorJacobian = new b2Jacobian();
|
|
b2PrismaticJoint.prototype.m_motorMass = null;
|
|
b2PrismaticJoint.prototype.m_motorForce = null;
|
|
b2PrismaticJoint.prototype.m_limitForce = null;
|
|
b2PrismaticJoint.prototype.m_limitPositionImpulse = null;
|
|
b2PrismaticJoint.prototype.m_lowerTranslation = null;
|
|
b2PrismaticJoint.prototype.m_upperTranslation = null;
|
|
b2PrismaticJoint.prototype.m_maxMotorForce = null;
|
|
b2PrismaticJoint.prototype.m_motorSpeed = null;
|
|
b2PrismaticJoint.prototype.m_enableLimit = null;
|
|
b2PrismaticJoint.prototype.m_enableMotor = null;
|
|
b2PrismaticJoint.prototype.m_limitState = 0;
|
|
b2PrismaticJoint.prototype.GetAnchor1 = function () {
|
|
return this.m_body1.GetWorldPoint(this.m_localAnchor1);
|
|
}
|
|
b2PrismaticJoint.prototype.GetAnchor2 = function () {
|
|
return this.m_body2.GetWorldPoint(this.m_localAnchor2);
|
|
}
|
|
b2PrismaticJoint.prototype.GetReactionForce = function () {
|
|
var tMat = this.m_body1.m_xf.R;
|
|
|
|
var ax1X = this.m_limitForce* (tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y);
|
|
var ax1Y = this.m_limitForce* (tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y);
|
|
|
|
var ay1X = this.m_force* (tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y);
|
|
var ay1Y = this.m_force* (tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y);
|
|
|
|
|
|
return new b2Vec2( this.m_limitForce*ax1X + this.m_force*ay1X, this.m_limitForce*ax1Y + this.m_force*ay1Y);
|
|
}
|
|
b2PrismaticJoint.prototype.GetReactionTorque = function () {
|
|
return this.m_torque;
|
|
}
|
|
b2PrismaticJoint.prototype.GetJointTranslation = function () {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
|
|
var p1 = b1.GetWorldPoint(this.m_localAnchor1);
|
|
var p2 = b2.GetWorldPoint(this.m_localAnchor2);
|
|
|
|
var dX = p2.x - p1.x;
|
|
var dY = p2.y - p1.y;
|
|
|
|
var axis = b1.GetWorldVector(this.m_localXAxis1);
|
|
|
|
|
|
var translation = axis.x*dX + axis.y*dY;
|
|
return translation;
|
|
}
|
|
b2PrismaticJoint.prototype.GetJointSpeed = function () {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var p1X = b1.m_sweep.c.x + r1X;
|
|
var p1Y = b1.m_sweep.c.y + r1Y;
|
|
|
|
var p2X = b2.m_sweep.c.x + r2X;
|
|
var p2Y = b2.m_sweep.c.y + r2Y;
|
|
|
|
var dX = p2X - p1X;
|
|
var dY = p2Y - p1Y;
|
|
|
|
var axis = b1.GetWorldVector(this.m_localXAxis1);
|
|
|
|
var v1 = b1.m_linearVelocity;
|
|
var v2 = b2.m_linearVelocity;
|
|
var w1 = b1.m_angularVelocity;
|
|
var w2 = b2.m_angularVelocity;
|
|
|
|
|
|
|
|
|
|
var speed = (dX*(-w1 * axis.y) + dY*(w1 * axis.x)) + (axis.x * ((( v2.x + (-w2 * r2Y)) - v1.x) - (-w1 * r1Y)) + axis.y * ((( v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
|
|
|
|
return speed;
|
|
}
|
|
b2PrismaticJoint.prototype.IsLimitEnabled = function () {
|
|
return this.m_enableLimit;
|
|
}
|
|
b2PrismaticJoint.prototype.EnableLimit = function (flag) {
|
|
this.m_enableLimit = flag;
|
|
}
|
|
b2PrismaticJoint.prototype.GetLowerLimit = function () {
|
|
return this.m_lowerTranslation;
|
|
}
|
|
b2PrismaticJoint.prototype.GetUpperLimit = function () {
|
|
return this.m_upperTranslation;
|
|
}
|
|
b2PrismaticJoint.prototype.SetLimits = function (lower, upper) {
|
|
|
|
this.m_lowerTranslation = lower;
|
|
this.m_upperTranslation = upper;
|
|
}
|
|
b2PrismaticJoint.prototype.IsMotorEnabled = function () {
|
|
return this.m_enableMotor;
|
|
}
|
|
b2PrismaticJoint.prototype.EnableMotor = function (flag) {
|
|
this.m_enableMotor = flag;
|
|
}
|
|
b2PrismaticJoint.prototype.SetMotorSpeed = function (speed) {
|
|
this.m_motorSpeed = speed;
|
|
}
|
|
b2PrismaticJoint.prototype.GetMotorSpeed = function () {
|
|
return this.m_motorSpeed;
|
|
}
|
|
b2PrismaticJoint.prototype.SetMaxMotorForce = function (force) {
|
|
this.m_maxMotorForce = force;
|
|
}
|
|
b2PrismaticJoint.prototype.GetMotorForce = function () {
|
|
return this.m_motorForce;
|
|
}
|
|
b2PrismaticJoint.prototype.InitVelocityConstraints = function (step) {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var tMat;
|
|
var tX;
|
|
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var invMass1 = b1.m_invMass;
|
|
var invMass2 = b2.m_invMass;
|
|
|
|
var invI1 = b1.m_invI;
|
|
var invI2 = b2.m_invI;
|
|
|
|
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var ay1X = tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y;
|
|
var ay1Y = tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y;
|
|
|
|
var eX = b2.m_sweep.c.x + r2X - b1.m_sweep.c.x;
|
|
var eY = b2.m_sweep.c.y + r2Y - b1.m_sweep.c.y;
|
|
|
|
|
|
this.m_linearJacobian.linear1.x = -ay1X;
|
|
this.m_linearJacobian.linear1.y = -ay1Y;
|
|
this.m_linearJacobian.linear2.x = ay1X;
|
|
this.m_linearJacobian.linear2.y = ay1Y;
|
|
this.m_linearJacobian.angular1 = -(eX * ay1Y - eY * ay1X);
|
|
this.m_linearJacobian.angular2 = r2X * ay1Y - r2Y * ay1X;
|
|
|
|
this.m_linearMass = invMass1 + invI1 * this.m_linearJacobian.angular1 * this.m_linearJacobian.angular1 +
|
|
invMass2 + invI2 * this.m_linearJacobian.angular2 * this.m_linearJacobian.angular2;
|
|
|
|
this.m_linearMass = 1.0 / this.m_linearMass;
|
|
|
|
|
|
this.m_angularMass = invI1 + invI2;
|
|
if (this.m_angularMass > Number.MIN_VALUE)
|
|
{
|
|
this.m_angularMass = 1.0 / this.m_angularMass;
|
|
}
|
|
|
|
|
|
if (this.m_enableLimit || this.m_enableMotor)
|
|
{
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
|
|
var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
|
|
|
|
this.m_motorJacobian.linear1.x = -ax1X; this.m_motorJacobian.linear1.y = -ax1Y;
|
|
this.m_motorJacobian.linear2.x = ax1X; this.m_motorJacobian.linear2.y = ax1Y;
|
|
this.m_motorJacobian.angular1 = -(eX * ax1Y - eY * ax1X);
|
|
this.m_motorJacobian.angular2 = r2X * ax1Y - r2Y * ax1X;
|
|
|
|
this.m_motorMass = invMass1 + invI1 * this.m_motorJacobian.angular1 * this.m_motorJacobian.angular1 +
|
|
invMass2 + invI2 * this.m_motorJacobian.angular2 * this.m_motorJacobian.angular2;
|
|
|
|
this.m_motorMass = 1.0 / this.m_motorMass;
|
|
|
|
if (this.m_enableLimit)
|
|
{
|
|
|
|
var dX = eX - r1X;
|
|
var dY = eY - r1Y;
|
|
|
|
var jointTranslation = ax1X * dX + ax1Y * dY;
|
|
if (b2Math.b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * b2Settings.b2_linearSlop)
|
|
{
|
|
this.m_limitState = b2Joint.e_equalLimits;
|
|
}
|
|
else if (jointTranslation <= this.m_lowerTranslation)
|
|
{
|
|
if (this.m_limitState != b2Joint.e_atLowerLimit)
|
|
{
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
this.m_limitState = b2Joint.e_atLowerLimit;
|
|
}
|
|
else if (jointTranslation >= this.m_upperTranslation)
|
|
{
|
|
if (this.m_limitState != b2Joint.e_atUpperLimit)
|
|
{
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
this.m_limitState = b2Joint.e_atUpperLimit;
|
|
}
|
|
else
|
|
{
|
|
this.m_limitState = b2Joint.e_inactiveLimit;
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.m_enableMotor == false)
|
|
{
|
|
this.m_motorForce = 0.0;
|
|
}
|
|
|
|
if (this.m_enableLimit == false)
|
|
{
|
|
this.m_limitForce = 0.0;
|
|
}
|
|
|
|
if (step.warmStarting)
|
|
{
|
|
|
|
var P1X = step.dt * (this.m_force * this.m_linearJacobian.linear1.x + (this.m_motorForce + this.m_limitForce) * this.m_motorJacobian.linear1.x);
|
|
var P1Y = step.dt * (this.m_force * this.m_linearJacobian.linear1.y + (this.m_motorForce + this.m_limitForce) * this.m_motorJacobian.linear1.y);
|
|
|
|
var P2X = step.dt * (this.m_force * this.m_linearJacobian.linear2.x + (this.m_motorForce + this.m_limitForce) * this.m_motorJacobian.linear2.x);
|
|
var P2Y = step.dt * (this.m_force * this.m_linearJacobian.linear2.y + (this.m_motorForce + this.m_limitForce) * this.m_motorJacobian.linear2.y);
|
|
|
|
var L1 = step.dt * (this.m_force * this.m_linearJacobian.angular1 - this.m_torque + (this.m_motorForce + this.m_limitForce) * this.m_motorJacobian.angular1);
|
|
|
|
var L2 = step.dt * (this.m_force * this.m_linearJacobian.angular2 + this.m_torque + (this.m_motorForce + this.m_limitForce) * this.m_motorJacobian.angular2);
|
|
|
|
|
|
b1.m_linearVelocity.x += invMass1 * P1X;
|
|
b1.m_linearVelocity.y += invMass1 * P1Y;
|
|
|
|
b1.m_angularVelocity += invI1 * L1;
|
|
|
|
|
|
b2.m_linearVelocity.x += invMass2 * P2X;
|
|
b2.m_linearVelocity.y += invMass2 * P2Y;
|
|
|
|
b2.m_angularVelocity += invI2 * L2;
|
|
}
|
|
else
|
|
{
|
|
this.m_force = 0.0;
|
|
this.m_torque = 0.0;
|
|
this.m_limitForce = 0.0;
|
|
this.m_motorForce = 0.0;
|
|
}
|
|
|
|
this.m_limitPositionImpulse = 0.0;
|
|
|
|
}
|
|
b2PrismaticJoint.prototype.SolveVelocityConstraints = function (step) {
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var invMass1 = b1.m_invMass;
|
|
var invMass2 = b2.m_invMass;
|
|
var invI1 = b1.m_invI;
|
|
var invI2 = b2.m_invI;
|
|
|
|
var oldLimitForce;
|
|
|
|
|
|
var linearCdot = this.m_linearJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity);
|
|
var force = -step.inv_dt * this.m_linearMass * linearCdot;
|
|
this.m_force += force;
|
|
|
|
var P = step.dt * force;
|
|
|
|
b1.m_linearVelocity.x += (invMass1 * P) * this.m_linearJacobian.linear1.x;
|
|
b1.m_linearVelocity.y += (invMass1 * P) * this.m_linearJacobian.linear1.y;
|
|
|
|
b1.m_angularVelocity += invI1 * P * this.m_linearJacobian.angular1;
|
|
|
|
|
|
b2.m_linearVelocity.x += (invMass2 * P) * this.m_linearJacobian.linear2.x;
|
|
b2.m_linearVelocity.y += (invMass2 * P) * this.m_linearJacobian.linear2.y;
|
|
|
|
b2.m_angularVelocity += invI2 * P * this.m_linearJacobian.angular2;
|
|
|
|
|
|
var angularCdot = b2.m_angularVelocity - b1.m_angularVelocity;
|
|
var torque = -step.inv_dt * this.m_angularMass * angularCdot;
|
|
this.m_torque += torque;
|
|
|
|
var L = step.dt * torque;
|
|
b1.m_angularVelocity -= invI1 * L;
|
|
b2.m_angularVelocity += invI2 * L;
|
|
|
|
|
|
if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits)
|
|
{
|
|
var motorCdot = this.m_motorJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity) - this.m_motorSpeed;
|
|
var motorForce = -step.inv_dt * this.m_motorMass * motorCdot;
|
|
var oldMotorForce = this.m_motorForce;
|
|
this.m_motorForce = b2Math.b2Clamp(this.m_motorForce + motorForce, -this.m_maxMotorForce, this.m_maxMotorForce);
|
|
motorForce = this.m_motorForce - oldMotorForce;
|
|
|
|
P = step.dt * motorForce;
|
|
|
|
b1.m_linearVelocity.x += (invMass1 * P) * this.m_motorJacobian.linear1.x;
|
|
b1.m_linearVelocity.y += (invMass1 * P) * this.m_motorJacobian.linear1.y;
|
|
|
|
b1.m_angularVelocity += invI1 * P * this.m_motorJacobian.angular1;
|
|
|
|
|
|
b2.m_linearVelocity.x += (invMass2 * P) * this.m_motorJacobian.linear2.x;
|
|
b2.m_linearVelocity.y += (invMass2 * P) * this.m_motorJacobian.linear2.y;
|
|
|
|
b2.m_angularVelocity += invI2 * P * this.m_motorJacobian.angular2;
|
|
}
|
|
|
|
|
|
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
|
{
|
|
var limitCdot = this.m_motorJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity);
|
|
var limitForce = -step.inv_dt * this.m_motorMass * limitCdot;
|
|
|
|
if (this.m_limitState == b2Joint.e_equalLimits)
|
|
{
|
|
this.m_limitForce += limitForce;
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
|
{
|
|
oldLimitForce = this.m_limitForce;
|
|
this.m_limitForce = b2Math.b2Max(this.m_limitForce + limitForce, 0.0);
|
|
limitForce = this.m_limitForce - oldLimitForce;
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
|
{
|
|
oldLimitForce = this.m_limitForce;
|
|
this.m_limitForce = b2Math.b2Min(this.m_limitForce + limitForce, 0.0);
|
|
limitForce = this.m_limitForce - oldLimitForce;
|
|
}
|
|
|
|
P = step.dt * limitForce;
|
|
|
|
b1.m_linearVelocity.x += (invMass1 * P) * this.m_motorJacobian.linear1.x;
|
|
b1.m_linearVelocity.y += (invMass1 * P) * this.m_motorJacobian.linear1.y;
|
|
|
|
b1.m_angularVelocity += invI1 * P * this.m_motorJacobian.angular1;
|
|
|
|
|
|
b2.m_linearVelocity.x += (invMass2 * P) * this.m_motorJacobian.linear2.x;
|
|
b2.m_linearVelocity.y += (invMass2 * P) * this.m_motorJacobian.linear2.y;
|
|
|
|
b2.m_angularVelocity += invI2 * P * this.m_motorJacobian.angular2;
|
|
}
|
|
}
|
|
b2PrismaticJoint.prototype.SolvePositionConstraints = function () {
|
|
|
|
var limitC;
|
|
var oldLimitImpulse;
|
|
|
|
var b1 = this.m_body1;
|
|
var b2 = this.m_body2;
|
|
|
|
var invMass1 = b1.m_invMass;
|
|
var invMass2 = b2.m_invMass;
|
|
var invI1 = b1.m_invI;
|
|
var invI2 = b2.m_invI;
|
|
|
|
var tMat;
|
|
var tX;
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
var r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
var r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
var r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
var r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
var p1X = b1.m_sweep.c.x + r1X;
|
|
var p1Y = b1.m_sweep.c.y + r1Y;
|
|
|
|
var p2X = b2.m_sweep.c.x + r2X;
|
|
var p2Y = b2.m_sweep.c.y + r2Y;
|
|
|
|
var dX = p2X - p1X;
|
|
var dY = p2Y - p1Y;
|
|
|
|
tMat = b1.m_xf.R;
|
|
var ay1X = tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y;
|
|
var ay1Y = tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y;
|
|
|
|
|
|
|
|
var linearC = ay1X*dX + ay1Y*dY;
|
|
|
|
linearC = b2Math.b2Clamp(linearC, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
|
|
var linearImpulse = -this.m_linearMass * linearC;
|
|
|
|
|
|
b1.m_sweep.c.x += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.x;
|
|
b1.m_sweep.c.y += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.y;
|
|
|
|
b1.m_sweep.a += invI1 * linearImpulse * this.m_linearJacobian.angular1;
|
|
|
|
|
|
|
|
b2.m_sweep.c.x += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.x;
|
|
b2.m_sweep.c.y += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.y;
|
|
|
|
b2.m_sweep.a += invI2 * linearImpulse * this.m_linearJacobian.angular2;
|
|
|
|
|
|
var positionError = b2Math.b2Abs(linearC);
|
|
|
|
|
|
var angularC = b2.m_sweep.a - b1.m_sweep.a - this.m_refAngle;
|
|
|
|
angularC = b2Math.b2Clamp(angularC, -b2Settings.b2_maxAngularCorrection, b2Settings.b2_maxAngularCorrection);
|
|
var angularImpulse = -this.m_angularMass * angularC;
|
|
|
|
b1.m_sweep.a -= b1.m_invI * angularImpulse;
|
|
b2.m_sweep.a += b2.m_invI * angularImpulse;
|
|
b1.SynchronizeTransform();
|
|
b2.SynchronizeTransform();
|
|
|
|
var angularError = b2Math.b2Abs(angularC);
|
|
|
|
|
|
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
|
{
|
|
|
|
|
|
tMat = b1.m_xf.R;
|
|
r1X = this.m_localAnchor1.x - b1.m_sweep.localCenter.x;
|
|
r1Y = this.m_localAnchor1.y - b1.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
|
|
r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
|
|
r1X = tX;
|
|
|
|
tMat = b2.m_xf.R;
|
|
r2X = this.m_localAnchor2.x - b2.m_sweep.localCenter.x;
|
|
r2Y = this.m_localAnchor2.y - b2.m_sweep.localCenter.y;
|
|
tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
|
|
r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
|
|
r2X = tX;
|
|
|
|
|
|
p1X = b1.m_sweep.c.x + r1X;
|
|
p1Y = b1.m_sweep.c.y + r1Y;
|
|
|
|
p2X = b2.m_sweep.c.x + r2X;
|
|
p2Y = b2.m_sweep.c.y + r2Y;
|
|
|
|
dX = p2X - p1X;
|
|
dY = p2Y - p1Y;
|
|
|
|
tMat = b1.m_xf.R;
|
|
var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
|
|
var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
|
|
|
|
|
|
var translation = (ax1X*dX + ax1Y*dY);
|
|
var limitImpulse = 0.0;
|
|
|
|
if (this.m_limitState == b2Joint.e_equalLimits)
|
|
{
|
|
|
|
limitC = b2Math.b2Clamp(translation, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
|
|
limitImpulse = -this.m_motorMass * limitC;
|
|
positionError = b2Math.b2Max(positionError, b2Math.b2Abs(angularC));
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
|
{
|
|
limitC = translation - this.m_lowerTranslation;
|
|
positionError = b2Math.b2Max(positionError, -limitC);
|
|
|
|
|
|
limitC = b2Math.b2Clamp(limitC + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
|
limitImpulse = -this.m_motorMass * limitC;
|
|
oldLimitImpulse = this.m_limitPositionImpulse;
|
|
this.m_limitPositionImpulse = b2Math.b2Max(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
|
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
|
}
|
|
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
|
{
|
|
limitC = translation - this.m_upperTranslation;
|
|
positionError = b2Math.b2Max(positionError, limitC);
|
|
|
|
|
|
limitC = b2Math.b2Clamp(limitC - b2Settings.b2_linearSlop, 0.0, b2Settings.b2_maxLinearCorrection);
|
|
limitImpulse = -this.m_motorMass * limitC;
|
|
oldLimitImpulse = this.m_limitPositionImpulse;
|
|
this.m_limitPositionImpulse = b2Math.b2Min(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
|
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
|
}
|
|
|
|
|
|
b1.m_sweep.c.x += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.x;
|
|
b1.m_sweep.c.y += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.y;
|
|
|
|
b1.m_sweep.a += invI1 * limitImpulse * this.m_motorJacobian.angular1;
|
|
|
|
|
|
b2.m_sweep.c.x += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.x;
|
|
b2.m_sweep.c.y += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.y;
|
|
|
|
b2.m_sweep.a += invI2 * limitImpulse * this.m_motorJacobian.angular2;
|
|
|
|
b1.SynchronizeTransform();
|
|
b2.SynchronizeTransform();
|
|
|
|
}
|
|
|
|
return positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
|
|
|
|
}
|
|
exports.b2PrismaticJoint = b2PrismaticJoint;
|
|
|
|
|
|
var b2World = function() {
|
|
this.__varz();
|
|
this.__constructor.apply(this, arguments);
|
|
}
|
|
b2World.prototype.__constructor = function (worldAABB, gravity, doSleep) {
|
|
|
|
this.m_destructionListener = null;
|
|
this.m_boundaryListener = null;
|
|
this.m_contactFilter = b2ContactFilter.b2_defaultFilter;
|
|
this.m_contactListener = null;
|
|
this.m_debugDraw = null;
|
|
|
|
this.m_bodyList = null;
|
|
this.m_contactList = null;
|
|
this.m_jointList = null;
|
|
|
|
this.m_bodyCount = 0;
|
|
this.m_contactCount = 0;
|
|
this.m_jointCount = 0;
|
|
|
|
b2World.m_positionCorrection = true;
|
|
b2World.m_warmStarting = true;
|
|
b2World.m_continuousPhysics = true;
|
|
|
|
this.m_allowSleep = doSleep;
|
|
this.m_gravity = gravity;
|
|
|
|
this.m_lock = false;
|
|
|
|
this.m_inv_dt0 = 0.0;
|
|
|
|
this.m_contactManager.m_world = this;
|
|
|
|
this.m_broadPhase = new b2BroadPhase(worldAABB, this.m_contactManager);
|
|
|
|
var bd = new b2BodyDef();
|
|
this.m_groundBody = this.CreateBody(bd);
|
|
}
|
|
b2World.prototype.__varz = function(){
|
|
this.m_contactManager = new b2ContactManager();
|
|
}
|
|
// static attributes
|
|
b2World.m_positionCorrection = null;
|
|
b2World.m_warmStarting = null;
|
|
b2World.m_continuousPhysics = null;
|
|
b2World.s_jointColor = new b2Color(0.5, 0.8, 0.8);
|
|
b2World.s_coreColor = new b2Color(0.9, 0.6, 0.6);
|
|
b2World.s_xf = new b2XForm();
|
|
// static methods
|
|
// attributes
|
|
b2World.prototype.m_blockAllocator = null;
|
|
b2World.prototype.m_stackAllocator = null;
|
|
b2World.prototype.m_lock = null;
|
|
b2World.prototype.m_broadPhase = null;
|
|
b2World.prototype.m_contactManager = new b2ContactManager();
|
|
b2World.prototype.m_bodyList = null;
|
|
b2World.prototype.m_jointList = null;
|
|
b2World.prototype.m_contactList = null;
|
|
b2World.prototype.m_bodyCount = 0;
|
|
b2World.prototype.m_contactCount = 0;
|
|
b2World.prototype.m_jointCount = 0;
|
|
b2World.prototype.m_gravity = null;
|
|
b2World.prototype.m_allowSleep = null;
|
|
b2World.prototype.m_groundBody = null;
|
|
b2World.prototype.m_destructionListener = null;
|
|
b2World.prototype.m_boundaryListener = null;
|
|
b2World.prototype.m_contactFilter = null;
|
|
b2World.prototype.m_contactListener = null;
|
|
b2World.prototype.m_debugDraw = null;
|
|
b2World.prototype.m_inv_dt0 = null;
|
|
b2World.prototype.m_positionIterationCount = 0;
|
|
// methods
|
|
b2World.prototype.SetDestructionListener = function (listener) {
|
|
this.m_destructionListener = listener;
|
|
}
|
|
b2World.prototype.SetBoundaryListener = function (listener) {
|
|
this.m_boundaryListener = listener;
|
|
}
|
|
b2World.prototype.SetContactFilter = function (filter) {
|
|
this.m_contactFilter = filter;
|
|
}
|
|
b2World.prototype.SetContactListener = function (listener) {
|
|
this.m_contactListener = listener;
|
|
}
|
|
b2World.prototype.SetDebugDraw = function (debugDraw) {
|
|
this.m_debugDraw = debugDraw;
|
|
}
|
|
b2World.prototype.Validate = function () {
|
|
this.m_broadPhase.Validate();
|
|
}
|
|
b2World.prototype.GetProxyCount = function () {
|
|
return this.m_broadPhase.m_proxyCount;
|
|
}
|
|
b2World.prototype.GetPairCount = function () {
|
|
return this.m_broadPhase.m_pairManager.m_pairCount;
|
|
}
|
|
b2World.prototype.CreateBody = function (def) {
|
|
|
|
|
|
if (this.m_lock == true)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
|
|
var b = new b2Body(def, this);
|
|
|
|
|
|
b.m_prev = null;
|
|
b.m_next = this.m_bodyList;
|
|
if (this.m_bodyList)
|
|
{
|
|
this.m_bodyList.m_prev = b;
|
|
}
|
|
this.m_bodyList = b;
|
|
++this.m_bodyCount;
|
|
|
|
return b;
|
|
|
|
}
|
|
b2World.prototype.DestroyBody = function (b) {
|
|
|
|
|
|
|
|
if (this.m_lock == true)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
var jn = b.m_jointList;
|
|
while (jn)
|
|
{
|
|
var jn0 = jn;
|
|
jn = jn.next;
|
|
|
|
if (this.m_destructionListener)
|
|
{
|
|
this.m_destructionListener.SayGoodbyeJoint(jn0.joint);
|
|
}
|
|
|
|
this.DestroyJoint(jn0.joint);
|
|
}
|
|
|
|
|
|
|
|
var s = b.m_shapeList;
|
|
while (s)
|
|
{
|
|
var s0 = s;
|
|
s = s.m_next;
|
|
|
|
if (this.m_destructionListener)
|
|
{
|
|
this.m_destructionListener.SayGoodbyeShape(s0);
|
|
}
|
|
|
|
s0.DestroyProxy(this.m_broadPhase);
|
|
b2Shape.Destroy(s0, this.m_blockAllocator);
|
|
}
|
|
|
|
|
|
if (b.m_prev)
|
|
{
|
|
b.m_prev.m_next = b.m_next;
|
|
}
|
|
|
|
if (b.m_next)
|
|
{
|
|
b.m_next.m_prev = b.m_prev;
|
|
}
|
|
|
|
if (b == this.m_bodyList)
|
|
{
|
|
this.m_bodyList = b.m_next;
|
|
}
|
|
|
|
--this.m_bodyCount;
|
|
|
|
|
|
|
|
}
|
|
b2World.prototype.CreateJoint = function (def) {
|
|
|
|
|
|
|
|
var j = b2Joint.Create(def, this.m_blockAllocator);
|
|
|
|
|
|
j.m_prev = null;
|
|
j.m_next = this.m_jointList;
|
|
if (this.m_jointList)
|
|
{
|
|
this.m_jointList.m_prev = j;
|
|
}
|
|
this.m_jointList = j;
|
|
++this.m_jointCount;
|
|
|
|
|
|
j.m_node1.joint = j;
|
|
j.m_node1.other = j.m_body2;
|
|
j.m_node1.prev = null;
|
|
j.m_node1.next = j.m_body1.m_jointList;
|
|
if (j.m_body1.m_jointList) j.m_body1.m_jointList.prev = j.m_node1;
|
|
j.m_body1.m_jointList = j.m_node1;
|
|
|
|
j.m_node2.joint = j;
|
|
j.m_node2.other = j.m_body1;
|
|
j.m_node2.prev = null;
|
|
j.m_node2.next = j.m_body2.m_jointList;
|
|
if (j.m_body2.m_jointList) j.m_body2.m_jointList.prev = j.m_node2;
|
|
j.m_body2.m_jointList = j.m_node2;
|
|
|
|
|
|
if (def.collideConnected == false)
|
|
{
|
|
|
|
var b = def.body1.m_shapeCount < def.body2.m_shapeCount ? def.body1 : def.body2;
|
|
for (var s = b.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.RefilterProxy(this.m_broadPhase, b.m_xf);
|
|
}
|
|
}
|
|
|
|
return j;
|
|
|
|
}
|
|
b2World.prototype.DestroyJoint = function (j) {
|
|
|
|
|
|
|
|
var collideConnected = j.m_collideConnected;
|
|
|
|
|
|
if (j.m_prev)
|
|
{
|
|
j.m_prev.m_next = j.m_next;
|
|
}
|
|
|
|
if (j.m_next)
|
|
{
|
|
j.m_next.m_prev = j.m_prev;
|
|
}
|
|
|
|
if (j == this.m_jointList)
|
|
{
|
|
this.m_jointList = j.m_next;
|
|
}
|
|
|
|
|
|
var body1 = j.m_body1;
|
|
var body2 = j.m_body2;
|
|
|
|
|
|
body1.WakeUp();
|
|
body2.WakeUp();
|
|
|
|
|
|
if (j.m_node1.prev)
|
|
{
|
|
j.m_node1.prev.next = j.m_node1.next;
|
|
}
|
|
|
|
if (j.m_node1.next)
|
|
{
|
|
j.m_node1.next.prev = j.m_node1.prev;
|
|
}
|
|
|
|
if (j.m_node1 == body1.m_jointList)
|
|
{
|
|
body1.m_jointList = j.m_node1.next;
|
|
}
|
|
|
|
j.m_node1.prev = null;
|
|
j.m_node1.next = null;
|
|
|
|
|
|
if (j.m_node2.prev)
|
|
{
|
|
j.m_node2.prev.next = j.m_node2.next;
|
|
}
|
|
|
|
if (j.m_node2.next)
|
|
{
|
|
j.m_node2.next.prev = j.m_node2.prev;
|
|
}
|
|
|
|
if (j.m_node2 == body2.m_jointList)
|
|
{
|
|
body2.m_jointList = j.m_node2.next;
|
|
}
|
|
|
|
j.m_node2.prev = null;
|
|
j.m_node2.next = null;
|
|
|
|
b2Joint.Destroy(j, this.m_blockAllocator);
|
|
|
|
|
|
--this.m_jointCount;
|
|
|
|
|
|
if (collideConnected == false)
|
|
{
|
|
|
|
var b = body1.m_shapeCount < body2.m_shapeCount ? body1 : body2;
|
|
for (var s = b.m_shapeList; s; s = s.m_next)
|
|
{
|
|
s.RefilterProxy(this.m_broadPhase, b.m_xf);
|
|
}
|
|
}
|
|
|
|
}
|
|
b2World.prototype.Refilter = function (shape) {
|
|
shape.RefilterProxy(this.m_broadPhase, shape.m_body.m_xf);
|
|
}
|
|
b2World.prototype.SetWarmStarting = function (flag) { b2World.m_warmStarting = flag; }
|
|
b2World.prototype.SetPositionCorrection = function (flag) { b2World.m_positionCorrection = flag; }
|
|
b2World.prototype.SetContinuousPhysics = function (flag) { b2World.m_continuousPhysics = flag; }
|
|
b2World.prototype.GetBodyCount = function () {
|
|
return this.m_bodyCount;
|
|
}
|
|
b2World.prototype.GetJointCount = function () {
|
|
return this.m_jointCount;
|
|
}
|
|
b2World.prototype.GetContactCount = function () {
|
|
return this.m_contactCount;
|
|
}
|
|
b2World.prototype.SetGravity = function (gravity) {
|
|
this.m_gravity = gravity;
|
|
}
|
|
b2World.prototype.GetGroundBody = function () {
|
|
return this.m_groundBody;
|
|
}
|
|
b2World.prototype.Step = function (dt, iterations) {
|
|
|
|
this.m_lock = true;
|
|
|
|
var step = new b2TimeStep();
|
|
step.dt = dt;
|
|
step.maxIterations = iterations;
|
|
if (dt > 0.0)
|
|
{
|
|
step.inv_dt = 1.0 / dt;
|
|
}
|
|
else
|
|
{
|
|
step.inv_dt = 0.0;
|
|
}
|
|
|
|
step.dtRatio = this.m_inv_dt0 * dt;
|
|
|
|
step.positionCorrection = b2World.m_positionCorrection;
|
|
step.warmStarting = b2World.m_warmStarting;
|
|
|
|
|
|
this.m_contactManager.Collide();
|
|
|
|
|
|
if (step.dt > 0.0)
|
|
{
|
|
this.Solve(step);
|
|
}
|
|
|
|
|
|
if (b2World.m_continuousPhysics && step.dt > 0.0)
|
|
{
|
|
this.SolveTOI(step);
|
|
}
|
|
|
|
|
|
this.DrawDebugData();
|
|
|
|
this.m_inv_dt0 = step.inv_dt;
|
|
this.m_lock = false;
|
|
}
|
|
b2World.prototype.Query = function (aabb, shapes, maxCount) {
|
|
|
|
|
|
var results = new Array(maxCount);
|
|
|
|
var count = this.m_broadPhase.QueryAABB(aabb, results, maxCount);
|
|
|
|
for (var i = 0; i < count; ++i)
|
|
{
|
|
shapes[i] = results[i];
|
|
}
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
b2World.prototype.GetBodyList = function () {
|
|
return this.m_bodyList;
|
|
}
|
|
b2World.prototype.GetJointList = function () {
|
|
return this.m_jointList;
|
|
}
|
|
b2World.prototype.Solve = function (step) {
|
|
|
|
var b;
|
|
|
|
this.m_positionIterationCount = 0;
|
|
|
|
|
|
var island = new b2Island(this.m_bodyCount, this.m_contactCount, this.m_jointCount, this.m_stackAllocator, this.m_contactListener);
|
|
|
|
|
|
for (b = this.m_bodyList; b; b = b.m_next)
|
|
{
|
|
b.m_flags &= ~b2Body.e_islandFlag;
|
|
}
|
|
for (var c = this.m_contactList; c; c = c.m_next)
|
|
{
|
|
c.m_flags &= ~b2Contact.e_islandFlag;
|
|
}
|
|
for (var j = this.m_jointList; j; j = j.m_next)
|
|
{
|
|
j.m_islandFlag = false;
|
|
}
|
|
|
|
|
|
var stackSize = this.m_bodyCount;
|
|
|
|
var stack = new Array(stackSize);
|
|
for (var seed = this.m_bodyList; seed; seed = seed.m_next)
|
|
{
|
|
if (seed.m_flags & (b2Body.e_islandFlag | b2Body.e_sleepFlag | b2Body.e_frozenFlag))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (seed.IsStatic())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
island.Clear();
|
|
var stackCount = 0;
|
|
stack[stackCount++] = seed;
|
|
seed.m_flags |= b2Body.e_islandFlag;
|
|
|
|
|
|
while (stackCount > 0)
|
|
{
|
|
|
|
b = stack[--stackCount];
|
|
island.AddBody(b);
|
|
|
|
|
|
b.m_flags &= ~b2Body.e_sleepFlag;
|
|
|
|
|
|
|
|
if (b.IsStatic())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var other;
|
|
|
|
for (var cn = b.m_contactList; cn; cn = cn.next)
|
|
{
|
|
|
|
if (cn.contact.m_flags & (b2Contact.e_islandFlag | b2Contact.e_nonSolidFlag))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
if (cn.contact.m_manifoldCount == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
island.AddContact(cn.contact);
|
|
cn.contact.m_flags |= b2Contact.e_islandFlag;
|
|
|
|
|
|
other = cn.other;
|
|
|
|
|
|
if (other.m_flags & b2Body.e_islandFlag)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
stack[stackCount++] = other;
|
|
other.m_flags |= b2Body.e_islandFlag;
|
|
}
|
|
|
|
|
|
for (var jn = b.m_jointList; jn; jn = jn.next)
|
|
{
|
|
if (jn.joint.m_islandFlag == true)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
island.AddJoint(jn.joint);
|
|
jn.joint.m_islandFlag = true;
|
|
|
|
|
|
other = jn.other;
|
|
if (other.m_flags & b2Body.e_islandFlag)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
stack[stackCount++] = other;
|
|
other.m_flags |= b2Body.e_islandFlag;
|
|
}
|
|
}
|
|
|
|
island.Solve(step, this.m_gravity, b2World.m_positionCorrection, this.m_allowSleep);
|
|
|
|
if (island.m_positionIterationCount > this.m_positionIterationCount) {
|
|
this.m_positionIterationCount = island.m_positionIterationCount;
|
|
}
|
|
|
|
|
|
for (var i = 0; i < island.m_bodyCount; ++i)
|
|
{
|
|
|
|
b = island.m_bodies[i];
|
|
if (b.IsStatic())
|
|
{
|
|
b.m_flags &= ~b2Body.e_islandFlag;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
for (b = this.m_bodyList; b; b = b.m_next)
|
|
{
|
|
if (b.m_flags & (b2Body.e_sleepFlag | b2Body.e_frozenFlag))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (b.IsStatic())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
|
|
var inRange = b.SynchronizeShapes();
|
|
|
|
|
|
if (inRange == false && this.m_boundaryListener != null)
|
|
{
|
|
this.m_boundaryListener.Violation(b);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.m_broadPhase.Commit();
|
|
|
|
}
|
|
b2World.prototype.SolveTOI = function (step) {
|
|
|
|
var b;
|
|
var s1;
|
|
var s2;
|
|
var b1;
|
|
var b2;
|
|
var cn;
|
|
|
|
|
|
var island = new b2Island(this.m_bodyCount, b2Settings.b2_maxTOIContactsPerIsland, 0, this.m_stackAllocator, this.m_contactListener);
|
|
var stackSize = this.m_bodyCount;
|
|
|
|
|
|
var stack = new Array(stackSize);
|
|
|
|
for (b = this.m_bodyList; b; b = b.m_next)
|
|
{
|
|
b.m_flags &= ~b2Body.e_islandFlag;
|
|
b.m_sweep.t0 = 0.0;
|
|
}
|
|
|
|
var c;
|
|
for (c = this.m_contactList; c; c = c.m_next)
|
|
{
|
|
|
|
c.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag);
|
|
}
|
|
|
|
|
|
for (;;)
|
|
{
|
|
|
|
var minContact = null;
|
|
var minTOI = 1.0;
|
|
|
|
for (c = this.m_contactList; c; c = c.m_next)
|
|
{
|
|
if (c.m_flags & (b2Contact.e_slowFlag | b2Contact.e_nonSolidFlag))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
var toi = 1.0;
|
|
if (c.m_flags & b2Contact.e_toiFlag)
|
|
{
|
|
|
|
toi = c.m_toi;
|
|
}
|
|
else
|
|
{
|
|
|
|
s1 = c.m_shape1;
|
|
s2 = c.m_shape2;
|
|
b1 = s1.m_body;
|
|
b2 = s2.m_body;
|
|
|
|
if ((b1.IsStatic() || b1.IsSleeping()) && (b2.IsStatic() || b2.IsSleeping()))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
var t0 = b1.m_sweep.t0;
|
|
|
|
if (b1.m_sweep.t0 < b2.m_sweep.t0)
|
|
{
|
|
t0 = b2.m_sweep.t0;
|
|
b1.m_sweep.Advance(t0);
|
|
}
|
|
else if (b2.m_sweep.t0 < b1.m_sweep.t0)
|
|
{
|
|
t0 = b1.m_sweep.t0;
|
|
b2.m_sweep.Advance(t0);
|
|
}
|
|
|
|
|
|
|
|
|
|
toi = b2TimeOfImpact.TimeOfImpact(c.m_shape1, b1.m_sweep, c.m_shape2, b2.m_sweep);
|
|
|
|
|
|
if (toi > 0.0 && toi < 1.0)
|
|
{
|
|
|
|
toi = (1.0 - toi) * t0 + toi;
|
|
if (toi > 1) toi = 1;
|
|
}
|
|
|
|
|
|
c.m_toi = toi;
|
|
c.m_flags |= b2Contact.e_toiFlag;
|
|
}
|
|
|
|
if (Number.MIN_VALUE < toi && toi < minTOI)
|
|
{
|
|
|
|
minContact = c;
|
|
minTOI = toi;
|
|
}
|
|
}
|
|
|
|
if (minContact == null || 1.0 - 100.0 * Number.MIN_VALUE < minTOI)
|
|
{
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
s1 = minContact.m_shape1;
|
|
s2 = minContact.m_shape2;
|
|
b1 = s1.m_body;
|
|
b2 = s2.m_body;
|
|
b1.Advance(minTOI);
|
|
b2.Advance(minTOI);
|
|
|
|
|
|
minContact.Update(this.m_contactListener);
|
|
minContact.m_flags &= ~b2Contact.e_toiFlag;
|
|
|
|
if (minContact.m_manifoldCount == 0)
|
|
{
|
|
|
|
|
|
continue;
|
|
}
|
|
|
|
|
|
var seed = b1;
|
|
if (seed.IsStatic())
|
|
{
|
|
seed = b2;
|
|
}
|
|
|
|
|
|
island.Clear();
|
|
var stackCount = 0;
|
|
stack[stackCount++] = seed;
|
|
seed.m_flags |= b2Body.e_islandFlag;
|
|
|
|
|
|
while (stackCount > 0)
|
|
{
|
|
|
|
b = stack[--stackCount];
|
|
island.AddBody(b);
|
|
|
|
|
|
b.m_flags &= ~b2Body.e_sleepFlag;
|
|
|
|
|
|
|
|
if (b.IsStatic())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
for (cn = b.m_contactList; cn; cn = cn.next)
|
|
{
|
|
|
|
if (island.m_contactCount == island.m_contactCapacity)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
if (cn.contact.m_flags & (b2Contact.e_islandFlag | b2Contact.e_slowFlag | b2Contact.e_nonSolidFlag))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
if (cn.contact.m_manifoldCount == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
island.AddContact(cn.contact);
|
|
cn.contact.m_flags |= b2Contact.e_islandFlag;
|
|
|
|
|
|
var other = cn.other;
|
|
|
|
|
|
if (other.m_flags & b2Body.e_islandFlag)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
if (other.IsStatic() == false)
|
|
{
|
|
other.Advance(minTOI);
|
|
other.WakeUp();
|
|
}
|
|
|
|
|
|
stack[stackCount++] = other;
|
|
other.m_flags |= b2Body.e_islandFlag;
|
|
}
|
|
}
|
|
|
|
var subStep = new b2TimeStep();
|
|
subStep.dt = (1.0 - minTOI) * step.dt;
|
|
|
|
subStep.inv_dt = 1.0 / subStep.dt;
|
|
subStep.maxIterations = step.maxIterations;
|
|
|
|
island.SolveTOI(subStep);
|
|
|
|
var i = 0;
|
|
|
|
for (i = 0; i < island.m_bodyCount; ++i)
|
|
{
|
|
|
|
b = island.m_bodies[i];
|
|
b.m_flags &= ~b2Body.e_islandFlag;
|
|
|
|
if (b.m_flags & (b2Body.e_sleepFlag | b2Body.e_frozenFlag))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (b.IsStatic())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
|
|
var inRange = b.SynchronizeShapes();
|
|
|
|
|
|
if (inRange == false && this.m_boundaryListener != null)
|
|
{
|
|
this.m_boundaryListener.Violation(b);
|
|
}
|
|
|
|
|
|
|
|
for (cn = b.m_contactList; cn; cn = cn.next)
|
|
{
|
|
cn.contact.m_flags &= ~b2Contact.e_toiFlag;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < island.m_contactCount; ++i)
|
|
{
|
|
|
|
c = island.m_contacts[i];
|
|
c.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag);
|
|
}
|
|
|
|
|
|
|
|
this.m_broadPhase.Commit();
|
|
}
|
|
|
|
|
|
|
|
}
|
|
b2World.prototype.DrawJoint = function (joint) {
|
|
|
|
var b1 = joint.m_body1;
|
|
var b2 = joint.m_body2;
|
|
var xf1 = b1.m_xf;
|
|
var xf2 = b2.m_xf;
|
|
var x1 = xf1.position;
|
|
var x2 = xf2.position;
|
|
var p1 = joint.GetAnchor1();
|
|
var p2 = joint.GetAnchor2();
|
|
|
|
|
|
var color = b2World.s_jointColor;
|
|
|
|
switch (joint.m_type)
|
|
{
|
|
case b2Joint.e_distanceJoint:
|
|
this.m_debugDraw.DrawSegment(p1, p2, color);
|
|
break;
|
|
|
|
case b2Joint.e_pulleyJoint:
|
|
{
|
|
var pulley = (joint);
|
|
var s1 = pulley.GetGroundAnchor1();
|
|
var s2 = pulley.GetGroundAnchor2();
|
|
this.m_debugDraw.DrawSegment(s1, p1, color);
|
|
this.m_debugDraw.DrawSegment(s2, p2, color);
|
|
this.m_debugDraw.DrawSegment(s1, s2, color);
|
|
}
|
|
break;
|
|
|
|
case b2Joint.e_mouseJoint:
|
|
this.m_debugDraw.DrawSegment(p1, p2, color);
|
|
break;
|
|
|
|
default:
|
|
if (b1 != this.m_groundBody)
|
|
this.m_debugDraw.DrawSegment(x1, p1, color);
|
|
this.m_debugDraw.DrawSegment(p1, p2, color);
|
|
if (b2 != this.m_groundBody)
|
|
this.m_debugDraw.DrawSegment(x2, p2, color);
|
|
}
|
|
}
|
|
b2World.prototype.DrawShape = function (shape, xf, color, core) {
|
|
|
|
var coreColor = b2World.s_coreColor;
|
|
|
|
switch (shape.m_type)
|
|
{
|
|
case b2Shape.e_circleShape:
|
|
{
|
|
var circle = (shape);
|
|
|
|
var center = b2Math.b2MulX(xf, circle.m_localPosition);
|
|
var radius = circle.m_radius;
|
|
var axis = xf.R.col1;
|
|
|
|
this.m_debugDraw.DrawSolidCircle(center, radius, axis, color);
|
|
|
|
if (core)
|
|
{
|
|
this.m_debugDraw.DrawCircle(center, radius - b2Settings.b2_toiSlop, coreColor);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case b2Shape.e_polygonShape:
|
|
{
|
|
var i = 0;
|
|
var poly = (shape);
|
|
var vertexCount = poly.GetVertexCount();
|
|
var localVertices = poly.GetVertices();
|
|
|
|
|
|
var vertices = new Array(b2Settings.b2_maxPolygonVertices);
|
|
|
|
for (i = 0; i < vertexCount; ++i)
|
|
{
|
|
vertices[i] = b2Math.b2MulX(xf, localVertices[i]);
|
|
}
|
|
|
|
this.m_debugDraw.DrawSolidPolygon(vertices, vertexCount, color);
|
|
|
|
if (core)
|
|
{
|
|
var localCoreVertices = poly.GetCoreVertices();
|
|
for (i = 0; i < vertexCount; ++i)
|
|
{
|
|
vertices[i] = b2Math.b2MulX(xf, localCoreVertices[i]);
|
|
}
|
|
this.m_debugDraw.DrawPolygon(vertices, vertexCount, coreColor);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
b2World.prototype.DrawDebugData = function () {
|
|
|
|
if (this.m_debugDraw == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this.m_debugDraw.m_sprite.graphics.clear();
|
|
|
|
var flags = this.m_debugDraw.GetFlags();
|
|
|
|
var i = 0;
|
|
var b;
|
|
var s;
|
|
var j;
|
|
var bp;
|
|
var invQ = new b2Vec2;
|
|
var x1 = new b2Vec2;
|
|
var x2 = new b2Vec2;
|
|
var color = new b2Color(0,0,0);
|
|
var xf;
|
|
var b1 = new b2AABB();
|
|
var b2 = new b2AABB();
|
|
var vs = [new b2Vec2(), new b2Vec2(), new b2Vec2(), new b2Vec2()];
|
|
|
|
if (flags & b2DebugDraw.e_shapeBit)
|
|
{
|
|
var core = (flags & b2DebugDraw.e_coreShapeBit) == b2DebugDraw.e_coreShapeBit;
|
|
|
|
for (b = this.m_bodyList; b; b = b.m_next)
|
|
{
|
|
xf = b.m_xf;
|
|
for (s = b.GetShapeList(); s; s = s.m_next)
|
|
{
|
|
if (b.IsStatic())
|
|
{
|
|
this.DrawShape(s, xf, new b2Color(0.5, 0.9, 0.5), core);
|
|
}
|
|
else if (b.IsSleeping())
|
|
{
|
|
this.DrawShape(s, xf, new b2Color(0.5, 0.5, 0.9), core);
|
|
}
|
|
else
|
|
{
|
|
this.DrawShape(s, xf, new b2Color(0.9, 0.9, 0.9), core);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flags & b2DebugDraw.e_jointBit)
|
|
{
|
|
for (j = this.m_jointList; j; j = j.m_next)
|
|
{
|
|
|
|
|
|
this.DrawJoint(j);
|
|
|
|
}
|
|
}
|
|
|
|
if (flags & b2DebugDraw.e_pairBit)
|
|
{
|
|
bp = this.m_broadPhase;
|
|
|
|
invQ.Set(1.0 / bp.m_quantizationFactor.x, 1.0 / bp.m_quantizationFactor.y);
|
|
|
|
color.Set(0.9, 0.9, 0.3);
|
|
|
|
for (i = 0; i < b2Pair.b2_tableCapacity; ++i)
|
|
{
|
|
var index = bp.m_pairManager.m_hashTable[i];
|
|
while (index != b2Pair.b2_nullPair)
|
|
{
|
|
var pair = bp.m_pairManager.m_pairs[ index ];
|
|
var p1 = bp.m_proxyPool[ pair.proxyId1 ];
|
|
var p2 = bp.m_proxyPool[ pair.proxyId2 ];
|
|
|
|
|
|
b1.lowerBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p1.lowerBounds[0]].value;
|
|
b1.lowerBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p1.lowerBounds[1]].value;
|
|
b1.upperBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p1.upperBounds[0]].value;
|
|
b1.upperBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p1.upperBounds[1]].value;
|
|
b2.lowerBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p2.lowerBounds[0]].value;
|
|
b2.lowerBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p2.lowerBounds[1]].value;
|
|
b2.upperBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p2.upperBounds[0]].value;
|
|
b2.upperBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p2.upperBounds[1]].value;
|
|
|
|
|
|
x1.x = 0.5 * (b1.lowerBound.x + b1.upperBound.x);
|
|
x1.y = 0.5 * (b1.lowerBound.y + b1.upperBound.y);
|
|
|
|
x2.x = 0.5 * (b2.lowerBound.x + b2.upperBound.x);
|
|
x2.y = 0.5 * (b2.lowerBound.y + b2.upperBound.y);
|
|
|
|
this.m_debugDraw.DrawSegment(x1, x2, color);
|
|
|
|
index = pair.next;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flags & b2DebugDraw.e_aabbBit)
|
|
{
|
|
bp = this.m_broadPhase;
|
|
var worldLower = bp.m_worldAABB.lowerBound;
|
|
var worldUpper = bp.m_worldAABB.upperBound;
|
|
|
|
|
|
invQ.Set(1.0 / bp.m_quantizationFactor.x, 1.0 / bp.m_quantizationFactor.y);
|
|
|
|
color.Set(0.9, 0.3, 0.9);
|
|
for (i = 0; i < b2Settings.b2_maxProxies; ++i)
|
|
{
|
|
var p = bp.m_proxyPool[ i];
|
|
if (p.IsValid() == false)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
b1.lowerBound.x = worldLower.x + invQ.x * bp.m_bounds[0][p.lowerBounds[0]].value;
|
|
b1.lowerBound.y = worldLower.y + invQ.y * bp.m_bounds[1][p.lowerBounds[1]].value;
|
|
b1.upperBound.x = worldLower.x + invQ.x * bp.m_bounds[0][p.upperBounds[0]].value;
|
|
b1.upperBound.y = worldLower.y + invQ.y * bp.m_bounds[1][p.upperBounds[1]].value;
|
|
|
|
|
|
vs[0].Set(b1.lowerBound.x, b1.lowerBound.y);
|
|
vs[1].Set(b1.upperBound.x, b1.lowerBound.y);
|
|
vs[2].Set(b1.upperBound.x, b1.upperBound.y);
|
|
vs[3].Set(b1.lowerBound.x, b1.upperBound.y);
|
|
|
|
this.m_debugDraw.DrawPolygon(vs, 4, color);
|
|
}
|
|
|
|
|
|
vs[0].Set(worldLower.x, worldLower.y);
|
|
vs[1].Set(worldUpper.x, worldLower.y);
|
|
vs[2].Set(worldUpper.x, worldUpper.y);
|
|
vs[3].Set(worldLower.x, worldUpper.y);
|
|
this.m_debugDraw.DrawPolygon(vs, 4, new b2Color(0.3, 0.9, 0.9));
|
|
}
|
|
|
|
if (flags & b2DebugDraw.e_obbBit)
|
|
{
|
|
|
|
color.Set(0.5, 0.3, 0.5);
|
|
|
|
for (b = this.m_bodyList; b; b = b.m_next)
|
|
{
|
|
xf = b.m_xf;
|
|
for (s = b.GetShapeList(); s; s = s.m_next)
|
|
{
|
|
if (s.m_type != b2Shape.e_polygonShape)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var poly = (s);
|
|
var obb = poly.GetOBB();
|
|
var h = obb.extents;
|
|
|
|
vs[0].Set(-h.x, -h.y);
|
|
vs[1].Set( h.x, -h.y);
|
|
vs[2].Set( h.x, h.y);
|
|
vs[3].Set(-h.x, h.y);
|
|
|
|
for (i = 0; i < 4; ++i)
|
|
{
|
|
|
|
var tMat = obb.R;
|
|
var tVec = vs[i];
|
|
var tX;
|
|
tX = obb.center.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
vs[i].y = obb.center.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
vs[i].x = tX;
|
|
|
|
tMat = xf.R;
|
|
tX = xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
|
|
vs[i].y = xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
|
|
vs[i].x = tX;
|
|
}
|
|
|
|
this.m_debugDraw.DrawPolygon(vs, 4, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flags & b2DebugDraw.e_centerOfMassBit)
|
|
{
|
|
for (b = this.m_bodyList; b; b = b.m_next)
|
|
{
|
|
xf = b2World.s_xf;
|
|
xf.R = b.m_xf.R;
|
|
xf.position = b.GetWorldCenter();
|
|
this.m_debugDraw.DrawXForm(xf);
|
|
}
|
|
}
|
|
}
|
|
exports.b2World = b2World;
|