From d910497e909528fbf6f006bb53406bc1a72217c4 Mon Sep 17 00:00:00 2001 From: wassname Date: Sat, 1 Dec 2018 16:16:46 +0800 Subject: [PATCH] tidy --- js/walker.js | 4 - vendor/jsbox2d.js | 11582 ++++++++++++++++++++++++++++++++++++++++- vendor/neurojs-v2.js | 4908 ----------------- 3 files changed, 11581 insertions(+), 4913 deletions(-) delete mode 100644 vendor/neurojs-v2.js diff --git a/js/walker.js b/js/walker.js index 8386ae9..48864b4 100644 --- a/js/walker.js +++ b/js/walker.js @@ -677,7 +677,3 @@ var agent = new DDPGAgent(env, { }); agent.train(true); -// setInterval(() => { -// walker.step() -// console.log(walker.getState()) -// }, 100) diff --git a/vendor/jsbox2d.js b/vendor/jsbox2d.js index 54061f8..e6aa5ad 100644 --- a/vendor/jsbox2d.js +++ b/vendor/jsbox2d.js @@ -1,2 +1,11582 @@ /** https://github.com/kripken/box2d.js v2.3.1 */ -(function(){Function.prototype._extend=function(parent){this.prototype.parent=parent;for(var x in parent.prototype){if(!this.prototype[x]){this.prototype[x]=parent.prototype[x]}}};Function.prototype._implement=function(parent){return this._extend(parent)};var b2Profiler=(function(){if(typeof(performance)==="undefined"){window.performance={now:function(){return +new Date()}}}function profileStruct(name,parent){this.name=name;this.parent=parent;this.children={};this.startTime=0;this.elapsedTime=0;this.totalTime=0;this.running=false;this.childrenCount=0}profileStruct.prototype={start:function(){this.startTime=performance.now();this.running=true},stop:function(reset){if(!this.running){return}this.running=false;this.elapsedTime+=performance.now()-this.startTime;if(reset){this.start()}for(var x in this.children){this.children[x].stop()}},reset:function(dontRun){if(!dontRun){this.running=true;this.totalTime+=this.elapsedTime;this.start()}this.elapsedTime=0;for(var x in this.children){this.children[x].reset(true)}}};var profiles=[];var root=new profileStruct("root");function create(name,parent){if(!profiles){throw new Error("late profile creation not allowed")}var s=new profileStruct(name,parent||"root");profiles.push(s);return s}function destroy(profile){profile.childrenCount--;delete profile.children[profile.name]}function recursiveParentCheck(node,profile){if(node.name===profile.parent){return node}for(var x in node.children){var n;if(n=recursiveParentCheck(node.children[x],profile)){return n}}return null}function init(){while(profiles.length){var p=profiles.pop();if(!(p.parentNode=recursiveParentCheck(root,p))){profiles.unshift(p)}else{p.parentNode.children[p.name]=p;p.parentNode.childrenCount++}}profiles=null}function resetAll(){root.reset(true)}return{create:create,destroy:destroy,init:init,reset:resetAll,profileRoot:root}}());"use strict";var b2_maxFloat=Number.MAX_VALUE;var b2_epsilon=2.220446049250313e-16;var b2_pi=Math.PI;var b2_maxManifoldPoints=2;var b2_maxPolygonVertices=8;var b2_aabbExtension=0.1;var b2_aabbMultiplier=2;var b2_linearSlop=0.005;var b2_angularSlop=(2/180*b2_pi);var b2_polygonRadius=(2*b2_linearSlop);var b2_maxSubSteps=8;var b2_maxTOIContacts=32;var b2_velocityThreshold=1;var b2_maxLinearCorrection=0.2;var b2_maxAngularCorrection=(8/180*b2_pi);var b2_maxTranslation=2;var b2_maxTranslationSquared=(b2_maxTranslation*b2_maxTranslation);var b2_maxRotation=(0.5*b2_pi);var b2_maxRotationSquared=(b2_maxRotation*b2_maxRotation);var b2_baumgarte=0.2;var b2_toiBaugarte=0.75;var b2_timeToSleep=0.5;var b2_linearSleepTolerance=0.01;var b2_angularSleepTolerance=(2/180*b2_pi);function b2Version(ma,mi,re){this.major=ma;this.minor=mi;this.revision=re}b2Version.prototype={toString:function(){return this.major+"."+this.minor+"."+this.revision}};var b2_version=new b2Version(2,3,1);"use strict";function b2IsValid(x){return isFinite(x)&&!isNaN(x)}var sqrtf=Math.sqrt;var atan2f=Math.atan2;var sinf=Math.sin;var cosf=Math.cos;var floorf=Math.floor;var ceilf=Math.ceil;var b2Sqrt=sqrtf;var b2Atan2=atan2f;function b2InvSqrt(x){return 1/sqrtf(x)}function b2Vec2(x,y){if(typeof(x)!=="undefined"){this.x=x;this.y=y}else{this.x=this.y=0}}b2Vec2.prototype={Clone:function(){return new b2Vec2(this.x,this.y)},SetZero:function(){this.x=0;this.y=0;return this},Set:function(x_,y_){this.x=x_;this.y=y_;return this},Assign:function(l){this.x=l.x;this.y=l.y;return this},Negate:function(){var v=new b2Vec2();v.Set(-this.x,-this.y);return v},get_i:function(i){switch(i){case 0:return this.x;case 1:return this.y}},set_i:function(i,v){switch(i){case 0:return this.x=v;case 1:return this.y=v}},Add:function(v){this.x+=v.x;this.y+=v.y;return this},Subtract:function(v){this.x-=v.x;this.y-=v.y;return this},Multiply:function(a){this.x*=a;this.y*=a;return this},Length:function(){return b2Sqrt(this.x*this.x+this.y*this.y)},LengthSquared:function(){return this.x*this.x+this.y*this.y},Normalize:function(){var length=this.Length();if(length>1);x|=(x>>2);x|=(x>>4);x|=(x>>8);x|=(x>>16);return x+1}function b2IsPowerOfTwo(x){var result=x>0&&(x&(x-1))==0;return result}var RAND_LIMIT=32767;function b2RandomFloat(lo,hi){var r=Math.random();if(typeof(lo)!=="undefined"){r=(hi-lo)*r+lo}else{r=2*r-1}return r}"use strict";function b2Color(r,g,b){this.r=r||0;this.g=g||0;this.b=b||0}b2Color.prototype={Set:function(r,g,b){this.r=r;this.g=g;this.b=b}};function b2Draw(){}b2Draw.prototype={SetFlags:function(flags){this.m_drawFlags=flags},GetFlags:function(){return this.m_drawFlags},AppendFlags:function(flags){this.m_drawFlags|=flags},ClearFlags:function(flags){this.m_drawFlags&=~flags},ToggleFlags:function(flags){this.m_drawFlags^=flags},DrawPolygon:function(vertices,vertexCount,color){},DrawSolidPolygon:function(vertices,vertexCount,color){},DrawCircle:function(center,radius,color){},DrawSolidCircle:function(center,radius,axis,color){},DrawSegment:function(p1,p2,color){},DrawTransform:function(xf){},m_drawFlags:0};b2Draw.e_shapeBit=1;b2Draw.e_jointBit=2;b2Draw.e_aabbBit=4;b2Draw.e_centerOfMassBit=8;b2Draw.e_contactPoints=16;b2Draw.e_contactNormals=32;b2Draw.e_contactImpulses=64;b2Draw.e_frictionImpulses=128;b2Draw.e_statistics=256;b2Draw.e_profile=512;b2Draw.e_pairBit=1024;"use strict";if(typeof(performance)==="undefined"){window.performance={now:function(){return +new Date()}}}function b2Timer(){this.Reset()}b2Timer.prototype={Reset:function(){this.m_start=performance.now()},GetMilliseconds:function(){return performance.now()-this.m_start}};"use strict";function b2MassData(){this.mass=0;this.center=new b2Vec2();this.I=0}function b2Shape(){this.m_type=0;this.m_radius=0}b2Shape.prototype={Clone:function(){},GetType:function(){return this.m_type},GetChildCount:function(){},TestPoint:function(xf,p){},RayCast:function(output,input,transform,childIndex){},ComputeAABB:function(aabb,xf,childIndex){},ComputeMass:function(massData,density){},_serialize:function(out){var obj=out||{};obj.m_type=this.m_type;obj.m_radius=this.m_radius;return obj},_deserialize:function(data){this.m_radius=data.m_radius}};b2Shape.e_circle=0;b2Shape.e_edge=1;b2Shape.e_polygon=2;b2Shape.e_chain=3;b2Shape.e_typeCount=4;"use strict";function b2CircleShape(){this.parent.call(this);this.m_type=b2Shape.e_circle;this.m_radius=0;this.m_p=new b2Vec2();Object.seal(this)}b2CircleShape.prototype={Clone:function(){var shape=new b2CircleShape();shape.m_radius=this.m_radius;shape.m_p=this.m_p.Clone();return shape},GetChildCount:function(){return 1},TestPoint:function(transform,p){var center=b2Vec2.Add(transform.p,b2Mul_r_v2(transform.q,this.m_p));var d=b2Vec2.Subtract(p,center);return b2Dot_v2_v2(d,d)<=this.m_radius*this.m_radius},RayCast:function(output,input,transform,childIndex){var position=b2Vec2.Add(transform.p,b2Mul_r_v2(transform.q,this.m_p));var s=b2Vec2.Subtract(input.p1,position);var b=b2Dot_v2_v2(s,s)-this.m_radius*this.m_radius;var r=b2Vec2.Subtract(input.p2,input.p1);var c=b2Dot_v2_v2(s,r);var rr=b2Dot_v2_v2(r,r);var sigma=c*c-rr*b;if(sigma<0||rr0){output.normal=b2Mul_r_v2(xf.q,normal).Negate()}else{output.normal=b2Mul_r_v2(xf.q,normal)}return true},ComputeAABB:function(aabb,xf,childIndex){var v1x=(xf.q.c*this.m_vertex1.x-xf.q.s*this.m_vertex1.y)+xf.p.x;var v1y=(xf.q.s*this.m_vertex1.x+xf.q.c*this.m_vertex1.y)+xf.p.y;var v2x=(xf.q.c*this.m_vertex2.x-xf.q.s*this.m_vertex2.y)+xf.p.x;var v2y=(xf.q.s*this.m_vertex2.x+xf.q.c*this.m_vertex2.y)+xf.p.y;var lowerx=b2Min(v1x,v2x);var lowery=b2Min(v1y,v2y);var upperx=b2Max(v1x,v2x);var uppery=b2Max(v1y,v2y);aabb.lowerBound.x=lowerx-this.m_radius;aabb.lowerBound.y=lowery-this.m_radius;aabb.upperBound.x=upperx+this.m_radius;aabb.upperBound.y=uppery+this.m_radius},ComputeMass:function(massData,density){massData.mass=0;massData.center=b2Vec2.Multiply(0.5,b2Vec2.Add(this.m_vertex1,this.m_vertex2));massData.I=0},_serialize:function(out){var obj=out||{};this.parent.prototype._serialize.call(this,obj);obj.m_vertex1=this.m_vertex1._serialize();obj.m_vertex2=this.m_vertex2._serialize();obj.m_hasVertex0=this.m_hasVertex0;if(this.m_hasVertex0){obj.m_vertex0=this.m_vertex0._serialize()}obj.m_hasVertex3=this.m_hasVertex3;if(this.m_hasVertex3){obj.m_vertex3=this.m_vertex3._serialize()}return obj},_deserialize:function(data){this.parent.prototype._deserialize.call(this,data);this.m_vertex1._deserialize(data.m_vertex1);this.m_vertex2._deserialize(data.m_vertex2);this.m_hasVertex0=data.m_hasVertex0;if(this.m_hasVertex0){this.m_vertex0._deserialize(data.m_vertex0)}this.m_hasVertex3=data.m_hasVertex3;if(this.m_hasVertex3){this.m_vertex3._deserialize(data.m_vertex3)}}};b2EdgeShape._extend(b2Shape);"use strict";function b2ChainShape(){this.parent.call(this);this.m_type=b2Shape.e_chain;this.m_radius=b2_polygonRadius;this.m_vertices=null;this.m_count=0;this.m_prevVertex=new b2Vec2();this.m_nextVertex=new b2Vec2();this.m_hasPrevVertex=false;this.m_hasNextVertex=false;Object.seal(this)}b2ChainShape.prototype={CreateLoop:function(vertices,count){for(var i=1;i0){edge.m_vertex0=this.m_vertices[index-1];edge.m_hasVertex0=true}else{edge.m_vertex0=this.m_prevVertex;edge.m_hasVertex0=this.m_hasPrevVertex}if(indexx0||(x==x0&&ps[i].yr.LengthSquared()){ie=j}}++m;ih=ie;if(ie==i0){break}}this.m_count=m;for(i=0;i0){return false}}return true},RayCast:function(output,input,xf,childIndex){var p1=b2MulT_r_v2(xf.q,b2Vec2.Subtract(input.p1,xf.p));var p2=b2MulT_r_v2(xf.q,b2Vec2.Subtract(input.p2,xf.p));var d=b2Vec2.Subtract(p2,p1);var lower=0,upper=input.maxFraction;var index=-1;for(var i=0;i0&&numerator=0){output.fraction=lower;output.normal=b2Mul_r_v2(xf.q,this.m_normals[index]);return true}return false},ComputeAABB:function(aabb,xf,childIndex){var lowerx=(xf.q.c*this.m_vertices[0].x-xf.q.s*this.m_vertices[0].y)+xf.p.x;var lowery=(xf.q.s*this.m_vertices[0].x+xf.q.c*this.m_vertices[0].y)+xf.p.y;var upperx=lowerx;var uppery=lowery;for(var i=1;ibestValue){bestIndex=i;bestValue=value}}return bestIndex},GetSupportVertex:function(dx,dy){return this.m_vertices[this.GetSupport(dx,dy)]},GetVertexCount:function(){return this.m_count},GetVertex:function(index){return this.m_vertices[index]}};function b2SimplexCache(){this.metric=0;this.count=0;this.indexA=[0,0,0];this.indexB=[0,0,0]}function b2DistanceInput(){this.proxyA=new b2DistanceProxy();this.proxyB=new b2DistanceProxy();this.transformA=new b2Transform();this.transformB=new b2Transform();this.useRadii=false}function b2DistanceOutput(){this.pointA=new b2Vec2();this.pointB=new b2Vec2();this.distance=0;this.iterations=0}function b2SimplexVertex(){this.wA=new b2Vec2();this.wB=new b2Vec2();this.w=new b2Vec2();this.a=0;this.indexA=0;this.indexB=0}b2SimplexVertex.prototype={Assign:function(l){this.wA.x=l.wA.x;this.wA.y=l.wA.y;this.wB.x=l.wB.x;this.wB.y=l.wB.y;this.w.x=l.w.x;this.w.y=l.w.y;this.a=l.a;this.indexA=l.indexA;this.indexB=l.indexB}};function b2Simplex(){this.m_v=[new b2SimplexVertex(),new b2SimplexVertex(),new b2SimplexVertex()];this.m_count=0}b2Simplex.prototype={ReadCache:function(cache,proxyA,transformA,proxyB,transformB){this.m_count=cache.count;var vertices=this.m_v;for(var i=0;i1){var metric1=cache.metric;var metric2=this.GetMetric();if(metric2<0.5*metric1||2*metric10){p.x=-1*e12y;p.y=1*e12x}else{p.x=1*e12y;p.y=-1*e12x}break}},GetClosestPoint:function(p){switch(this.m_count){case 1:p.x=this.m_v[0].w.x;p.y=this.m_v[0].w.y;break;case 2:p.x=(this.m_v[0].a*this.m_v[0].w.x)+(this.m_v[1].a*this.m_v[1].w.x);p.y=(this.m_v[0].a*this.m_v[0].w.y)+(this.m_v[1].a*this.m_v[1].w.y);break;case 3:p.x=p.y=0;break}},GetWitnessPoints:function(pA,pB){switch(this.m_count){case 1:pA.x=this.m_v[0].wA.x;pA.y=this.m_v[0].wA.y;pB.x=this.m_v[0].wB.x;pB.y=this.m_v[0].wB.y;break;case 2:pA.x=(this.m_v[0].a*this.m_v[0].wA.x)+(this.m_v[1].a*this.m_v[1].wA.x);pA.y=(this.m_v[0].a*this.m_v[0].wA.y)+(this.m_v[1].a*this.m_v[1].wA.y);pB.x=(this.m_v[0].a*this.m_v[0].wB.x)+(this.m_v[1].a*this.m_v[1].wB.x);pB.y=(this.m_v[0].a*this.m_v[0].wB.y)+(this.m_v[1].a*this.m_v[1].wB.y);break;case 3:pA.x=(this.m_v[0].a,this.m_v[0].wA.x)+(this.m_v[1].a,this.m_v[1].wA.x)+(this.m_v[2].a,this.m_v[2].wA.x);pA.y=(this.m_v[0].a,this.m_v[0].wA.y)+(this.m_v[1].a,this.m_v[1].wA.y)+(this.m_v[2].a,this.m_v[2].wA.y);pB.x=pA.x;pB.y=pA.y;break}},GetMetric:function(){switch(this.m_count){case 1:return 0;case 2:return b2Distance(this.m_v[0].w,this.m_v[1].w);case 3:return(this.m_v[1].w.x-this.m_v[0].w.x)*(this.m_v[2].w.y-this.m_v[0].w.y)-(this.m_v[1].w.y-this.m_v[0].w.y)*(this.m_v[2].w.x-this.m_v[0].w.x)}},Solve2:function(){var w1=this.m_v[0].w;var w2=this.m_v[1].w;var e12x=w2.x-w1.x;var e12y=w2.y-w1.y;var d12_2=-(w1.x*e12x+w1.y*e12y);if(d12_2<=0){this.m_v[0].a=1;this.m_count=1;return}var d12_1=w2.x*e12x+w2.y*e12y;if(d12_1<=0){this.m_v[1].a=1;this.m_count=1;this.m_v[0].Assign(this.m_v[1]);return}var inv_d12=1/(d12_1+d12_2);this.m_v[0].a=d12_1*inv_d12;this.m_v[1].a=d12_2*inv_d12;this.m_count=2},Solve3:function(){var w1=this.m_v[0].w;var w2=this.m_v[1].w;var w3=this.m_v[2].w;var e12x=w2.x-w1.x;var e12y=w2.y-w1.y;var w1e12=w1.x*e12x+w1.y*e12y;var w2e12=w2.x*e12x+w2.y*e12y;var d12_1=w2e12;var d12_2=-w1e12;var e13x=w3.x-w1.x;var e13y=w3.y-w1.y;var w1e13=w1.x*e13x+w1.y*e13y;var w3e13=w3.x*e13x+w3.y*e13y;var d13_1=w3e13;var d13_2=-w1e13;var e23x=w3.x-w2.x;var e23y=w3.y-w2.y;var w2e23=w2.x*e23x+w2.y*e23y;var w3e23=w3.x*e23x+w3.y*e23y;var d23_1=w3e23;var d23_2=-w2e23;var n123=e12x*e13y-e12y*e13x;var d123_1=n123*(w2.x*w3.y-w2.y*w3.x);var d123_2=n123*(w3.x*w1.y-w3.y*w1.x);var d123_3=n123*(w1.x*w2.y-w1.y*w2.x);if(d12_2<=0&&d13_2<=0){this.m_v[0].a=1;this.m_count=1;return}if(d12_1>0&&d12_2>0&&d123_3<=0){var inv_d12=1/(d12_1+d12_2);this.m_v[0].a=d12_1*inv_d12;this.m_v[1].a=d12_2*inv_d12;this.m_count=2;return}if(d13_1>0&&d13_2>0&&d123_2<=0){var inv_d13=1/(d13_1+d13_2);this.m_v[0].a=d13_1*inv_d13;this.m_v[2].a=d13_2*inv_d13;this.m_count=2;this.m_v[1].Assign(this.m_v[2]);return}if(d12_1<=0&&d23_2<=0){this.m_v[1].a=1;this.m_count=1;this.m_v[0].Assign(this.m_v[1]);return}if(d13_1<=0&&d23_1<=0){this.m_v[2].a=1;this.m_count=1;this.m_v[0].Assign(this.m_v[2]);return}if(d23_1>0&&d23_2>0&&d123_1<=0){var inv_d23=1/(d23_1+d23_2);this.m_v[1].a=d23_1*inv_d23;this.m_v[2].a=d23_2*inv_d23;this.m_count=2;this.m_v[0].Assign(this.m_v[2]);return}var inv_d123=1/(d123_1+d123_2+d123_3);this.m_v[0].a=d123_1*inv_d123;this.m_v[1].a=d123_2*inv_d123;this.m_v[2].a=d123_3*inv_d123;this.m_count=3}};var _b2Distance_simplex=new b2Simplex();var _b2Distance_normal=new b2Vec2();var _b2Distance_p=new b2Vec2();function b2DistanceFunc(output,cache,input){++b2DistanceFunc.b2_gjkCalls;var proxyA=input.proxyA;var proxyB=input.proxyB;var transformA=input.transformA;var transformB=input.transformB;_b2Distance_simplex.ReadCache(cache,proxyA,transformA,proxyB,transformB);var vertices=_b2Distance_simplex.m_v;var k_maxIters=20;var saveA=[0,0,0],saveB=[0,0,0];var saveCount=0;var distanceSqr1=b2_maxFloat;var distanceSqr2=distanceSqr1;var iter=0;while(iter=distanceSqr1){}distanceSqr1=distanceSqr2;_b2Distance_simplex.GetSearchDirection(_b2Distance_p);if(_b2Distance_p.LengthSquared()rA+rB&&output.distance>b2_epsilon){output.distance-=rA+rB;_b2Distance_normal.x=output.pointB.x-output.pointA.x;_b2Distance_normal.y=output.pointB.y-output.pointA.y;_b2Distance_normal.Normalize();output.pointA.x+=(rA*_b2Distance_normal.x);output.pointA.y+=(rA*_b2Distance_normal.y);output.pointB.x-=(rB*_b2Distance_normal.x);output.pointB.y-=(rB*_b2Distance_normal.y)}else{var px=(0.5*(output.pointA.x+output.pointB.x));var py=(0.5*(output.pointA.y+output.pointB.y));output.pointA.x=px;output.pointA.y=py;output.pointB.x=px;output.pointB.y=py;output.distance=0}}}b2DistanceFunc.b2_gjkCalls=0;b2DistanceFunc.b2_gjkIters=0;b2DistanceFunc.b2_gjkMaxIters=0;"use strict";var b2_nullFeature=255;function b2ContactID(){}b2ContactID.prototype={indexA:0,indexB:0,typeA:0,typeB:0,Reset:function(){this.indexA=this.indexB=this.typeA=this.typeB=0},Get:function(){return this.indexA|(this.indexB<<8)|(this.typeA<<16)|(this.typeB<<24)},Assign:function(k){this.indexA=k.indexA;this.indexB=k.indexB;this.typeA=k.typeA;this.typeB=k.typeB}};b2ContactID.e_vertex=0;b2ContactID.e_face=1;function b2ManifoldPoint(){this.localPoint=new b2Vec2();this.normalImpulse=0;this.tangentImpulse=0;this.id=new b2ContactID()}b2ManifoldPoint.prototype={Clone:function(){var point=new b2ManifoldPoint();point.localPoint.x=this.localPoint.x;point.localPoint.y=this.localPoint.y;point.normalImpulse=this.normalImpulse;point.tangentImpulse=this.tangentImpulse;point.id.Assign(this.id);return point}};function b2Manifold(){this.points=new Array(b2_maxManifoldPoints);this.localNormal=new b2Vec2();this.localPoint=new b2Vec2();this.type=0;this.pointCount=0}b2Manifold.prototype={Clone:function(){var manifold=new b2Manifold();manifold.pointCount=this.pointCount;manifold.type=this.type;manifold.localPoint.x=this.localPoint.x;manifold.localPoint.y=this.localPoint.y;manifold.localNormal.x=this.localNormal.x;manifold.localNormal.y=this.localNormal.y;for(var i=0;ib2_epsilon*b2_epsilon){this.normal.x=pointBx-pointAx;this.normal.y=pointBy-pointAy;this.normal.Normalize()}var cAx=pointAx+(radiusA*this.normal.x);var cAy=pointAy+(radiusA*this.normal.y);var cBx=pointBx-(radiusB*this.normal.x);var cBy=pointBy-(radiusB*this.normal.y);this.points[0]=new b2Vec2(0.5*(cAx+cBx),0.5*(cAy+cBy));this.separations[0]=(cBx-cAx)*this.normal.x+(cBy-cAy)*this.normal.y;break;case b2Manifold.e_faceA:this.normal.x=xfA.q.c*manifold.localNormal.x-xfA.q.s*manifold.localNormal.y;this.normal.y=xfA.q.s*manifold.localNormal.x+xfA.q.c*manifold.localNormal.y;var planePointx=(xfA.q.c*manifold.localPoint.x-xfA.q.s*manifold.localPoint.y)+xfA.p.x;var planePointy=(xfA.q.s*manifold.localPoint.x+xfA.q.c*manifold.localPoint.y)+xfA.p.y;for(var i=0;i=0&&(this.upperBound.y-this.lowerBound.y)>=0&&this.lowerBound.IsValid()&&this.upperBound.IsValid()},GetCenter:function(){return new b2Vec2(0.5*(this.lowerBound.x+this.upperBound.x),0.5*(this.lowerBound.y+this.upperBound.y))},GetExtents:function(){return new b2Vec2(0.5*(this.upperBound.x-this.lowerBound.x),0.5*(this.upperBound.y-this.lowerBound.y))},GetPerimeter:function(){return 2*((this.upperBound.x-this.lowerBound.x)+(this.upperBound.y-this.lowerBound.y))},Combine:function(aabb1,aabb2){if(aabb2){this.lowerBound.x=b2Min(aabb1.lowerBound.x,aabb2.lowerBound.x);this.lowerBound.y=b2Min(aabb1.lowerBound.y,aabb2.lowerBound.y);this.upperBound.x=b2Max(aabb1.upperBound.x,aabb2.upperBound.x);this.upperBound.y=b2Max(aabb1.upperBound.y,aabb2.upperBound.y)}else{this.lowerBound.x=b2Min(this.lowerBound.x,aabb1.lowerBound.x);this.lowerBound.y=b2Min(this.lowerBound.y,aabb1.lowerBound.y);this.upperBound.x=b2Max(this.upperBound.x,aabb1.upperBound.x);this.upperBound.y=b2Max(this.upperBound.y,aabb1.upperBound.y)}},Contains:function(aabb){return this.lowerBound.x<=aabb.lowerBound.x&&this.lowerBound.y<=aabb.lowerBound.y&&aabb.upperBound.x<=this.upperBound.x&&aabb.upperBound.y<=this.upperBound.y},RayCast:function(output,input){var tmin=-b2_maxFloat;var tmax=b2_maxFloat;var p=input.p1;var d=b2Vec2.Subtract(input.p2,input.p1);var absD=b2Abs_v2(d);var normal=new b2Vec2();for(var i=0;i<2;++i){if(absD.get_i(i)t2){var temp=t2;t2=t1;t1=temp;s=1}if(t1>tmin){normal.x=normal.y=0;normal.set_i(i,s);tmin=t1}tmax=b2Min(tmax,t2);if(tmin>tmax){return false}}}if(tmin<0||input.maxFractionradius*radius){return}manifold.type=b2Manifold.e_circles;manifold.localPoint.x=circleA.m_p.x;manifold.localPoint.y=circleA.m_p.y;manifold.localNormal.x=manifold.localNormal.y=0;manifold.pointCount=1;manifold.points[0]=new b2ManifoldPoint();manifold.points[0].localPoint.x=circleB.m_p.x;manifold.points[0].localPoint.y=circleB.m_p.y;manifold.points[0].id.Reset()}function b2CollidePolygonAndCircle(manifold,polygonA,xfA,circleB,xfB){manifold.pointCount=0;var c=b2Mul_t_v2(xfB,circleB.m_p);var cLocal=b2MulT_t_v2(xfA,c);var normalIndex=0;var separation=-b2_maxFloat;var radius=polygonA.m_radius+circleB.m_radius;var vertexCount=polygonA.m_count;var vertices=polygonA.m_vertices;var normals=polygonA.m_normals;for(var i=0;iradius){return}if(s>separation){separation=s;normalIndex=i}}var vertIndex1=normalIndex;var vertIndex2=vertIndex1+1radius*radius){return}manifold.pointCount=1;manifold.type=b2Manifold.e_faceA;manifold.localNormal.x=cLocal.x-v1.x;manifold.localNormal.y=cLocal.y-v1.y;manifold.localNormal.Normalize();manifold.localPoint.x=v1.x;manifold.localPoint.y=v1.y;manifold.points[0]=new b2ManifoldPoint();manifold.points[0].localPoint.x=circleB.m_p.x;manifold.points[0].localPoint.y=circleB.m_p.y;manifold.points[0].id.Reset()}else{if(u2<=0){if(b2DistanceSquared(cLocal,v2)>radius*radius){return}manifold.pointCount=1;manifold.type=b2Manifold.e_faceA;manifold.localNormal.x=cLocal.x-v2.x;manifold.localNormal.y=cLocal.y-v2.y;manifold.localNormal.Normalize();manifold.localPoint.x=v2.x;manifold.localPoint.y=v2.y;manifold.points[0]=new b2ManifoldPoint();manifold.points[0].localPoint.x=circleB.m_p.x;manifold.points[0].localPoint.y=circleB.m_p.y;manifold.points[0].id.Reset()}else{var faceCenterx=0.5*(v1.x+v2.x);var faceCentery=0.5*(v1.y+v2.y);var separation=(cLocal.x-faceCenterx)*normals[vertIndex1].x+(cLocal.y-faceCentery)*normals[vertIndex1].y;if(separation>radius){return}manifold.pointCount=1;manifold.type=b2Manifold.e_faceA;manifold.localNormal.x=normals[vertIndex1].x;manifold.localNormal.y=normals[vertIndex1].y;manifold.localPoint.x=faceCenterx;manifold.localPoint.y=faceCentery;manifold.points[0]=new b2ManifoldPoint();manifold.points[0].localPoint.x=circleB.m_p.x;manifold.points[0].localPoint.y=circleB.m_p.y;manifold.points[0].id.Reset()}}}function b2FindMaxSeparation(edgeIndex,poly1,xf1,poly2,xf2){var count1=poly1.m_count;var count2=poly2.m_count;var n1s=poly1.m_normals;var v1s=poly1.m_vertices;var v2s=poly2.m_vertices;var xf=b2MulT_t_t(xf2,xf1);var bestIndex=0;var maxSeparation=-b2_maxFloat;for(var i=0;imaxSeparation){maxSeparation=si;bestIndex=i}}edgeIndex[0]=bestIndex;return maxSeparation}function b2FindIncidentEdge(c,poly1,xf1,edge1,poly2,xf2){var normals1=poly1.m_normals;var count2=poly2.m_count;var vertices2=poly2.m_vertices;var normals2=poly2.m_normals;var t1x=xf1.q.c*normals1[edge1].x-xf1.q.s*normals1[edge1].y;var t1y=xf1.q.s*normals1[edge1].x+xf1.q.c*normals1[edge1].y;var normal1x=xf2.q.c*t1x+xf2.q.s*t1y;var normal1y=-xf2.q.s*t1x+xf2.q.c*t1y;var index=0;var minDot=b2_maxFloat;for(var i=0;itotalRadius){return}var edgeB=[0];var separationB=b2FindMaxSeparation(edgeB,polyB,xfB,polyA,xfA);if(separationB>totalRadius){return}var poly1;var poly2;var xf1,xf2;var edge1=0;var flip=0;var k_tol=0.1*b2_linearSlop;if(separationB>separationA+k_tol){poly1=polyB;poly2=polyA;xf1=xfB;xf2=xfA;edge1=edgeB[0];manifold.type=b2Manifold.e_faceB;flip=1}else{poly1=polyA;poly2=polyB;xf1=xfA;xf2=xfB;edge1=edgeA[0];manifold.type=b2Manifold.e_faceA;flip=0}b2FindIncidentEdge(b2CollidePolygons._local_incidentEdges,poly1,xf1,edge1,poly2,xf2);var count1=poly1.m_count;var vertices1=poly1.m_vertices;var iv1=edge1;var iv2=edge1+1radius*radius){return}if(edgeA.m_hasVertex0){var A1=edgeA.m_vertex0;var B1=A;var e1x=B1.x-A1.x;var e1y=B1.y-A1.y;var u1=e1x*(B1.x-Q.x)+e1y*(B1.y-Q.y);if(u1>0){return}}cf.indexA=0;cf.typeA=b2ContactID.e_vertex;manifold.pointCount=1;manifold.type=b2Manifold.e_circles;manifold.localNormal.x=manifold.localNormal.y=0;manifold.localPoint.x=P.x;manifold.localPoint.y=P.y;manifold.points[0]=new b2ManifoldPoint();manifold.points[0].id.Assign(cf);manifold.points[0].localPoint.x=circleB.m_p.x;manifold.points[0].localPoint.y=circleB.m_p.y;return}if(u<=0){var P=B;var dx=Q.x-P.x;var dy=Q.y-P.y;var dd=dx*dx+dy*dy;if(dd>radius*radius){return}if(edgeA.m_hasVertex3){var B2=edgeA.m_vertex3;var A2=B;var e2x=B2.x-A2.x;var e2y=B2.y-A2.y;var v2=e2x*(Q.x-A2.x)+e2y*(Q.y-A2.y);if(v2>0){return}}cf.indexA=1;cf.typeA=b2ContactID.e_vertex;manifold.pointCount=1;manifold.type=b2Manifold.e_circles;manifold.localNormal.x=manifold.localNormal.y=0;manifold.localPoint.x=P.x;manifold.localPoint.y=P.y;manifold.points[0]=new b2ManifoldPoint();manifold.points[0].id.Assign(cf);manifold.points[0].localPoint.x=circleB.m_p.x;manifold.points[0].localPoint.y=circleB.m_p.y;return}var den=ex*ex+ey*ey;var Px=(1/den)*((u*A.x)+(v*B.x));var Py=(1/den)*((u*A.y)+(v*B.y));var dx=Q.x-Px;var dy=Q.y-Py;var dd=dx*dx+dy*dy;if(dd>radius*radius){return}var nx=-ey;var ny=ex;if(nx*(Q.x-A.x)+ny*(Q.y-A.y)<0){nx=-nx;ny=-ny}cf.indexA=0;cf.typeA=b2ContactID.e_face;manifold.pointCount=1;manifold.type=b2Manifold.e_faceA;manifold.localNormal.x=nx;manifold.localNormal.y=ny;manifold.localNormal.Normalize();manifold.localPoint.x=A.x;manifold.localPoint.y=A.y;manifold.points[0]=new b2ManifoldPoint();manifold.points[0].id.Assign(cf);manifold.points[0].localPoint.x=circleB.m_p.x;manifold.points[0].localPoint.y=circleB.m_p.y}function b2EPAxis(){this.type=0;this.index=0;this.separation=0}b2EPAxis.e_unknown=0;b2EPAxis.e_edgeA=1;b2EPAxis.e_edgeB=2;function b2TempPolygon(){this.vertices=new Array(b2_maxPolygonVertices);this.normals=new Array(b2_maxPolygonVertices);this.count=0}function b2ReferenceFace(){this.i1=0,this.i2=0;this.v1=new b2Vec2(),this.v2=new b2Vec2();this.normal=new b2Vec2();this.sideNormal1=new b2Vec2();this.sideOffset1=0;this.sideNormal2=new b2Vec2();this.sideOffset2=0}function b2EPCollider(){this.m_polygonB=new b2TempPolygon();this.m_xf=new b2Transform();this.m_centroidB=new b2Vec2();this.m_v0=new b2Vec2(),this.m_v1=new b2Vec2(),this.m_v2=new b2Vec2(),this.m_v3=new b2Vec2();this.m_normal0=new b2Vec2(),this.m_normal1=new b2Vec2(),this.m_normal2=new b2Vec2();this.m_normal=new b2Vec2();this.m_type1=0,this.m_type2=0;this.m_lowerLimit=new b2Vec2(),this.m_upperLimit=new b2Vec2();this.m_radius=0;this.m_front=false}b2EPCollider._temp_edge=new b2Vec2();b2EPCollider._temp_edge0=new b2Vec2();b2EPCollider._temp_edge2=new b2Vec2();b2EPCollider.prototype={Collide:function(manifold,edgeA,xfA,polygonB,xfB){this.m_xf.Assign(b2MulT_t_t(xfA,xfB));this.m_centroidB.x=(this.m_xf.q.c*polygonB.m_centroid.x-this.m_xf.q.s*polygonB.m_centroid.y)+this.m_xf.p.x;this.m_centroidB.y=(this.m_xf.q.s*polygonB.m_centroid.x+this.m_xf.q.c*polygonB.m_centroid.y)+this.m_xf.p.y;this.m_v0.x=edgeA.m_vertex0.x;this.m_v0.y=edgeA.m_vertex0.y;this.m_v1.x=edgeA.m_vertex1.x;this.m_v1.y=edgeA.m_vertex1.y;this.m_v2.x=edgeA.m_vertex2.x;this.m_v2.y=edgeA.m_vertex2.y;this.m_v3.x=edgeA.m_vertex3.x;this.m_v3.y=edgeA.m_vertex3.y;var hasVertex0=edgeA.m_hasVertex0;var hasVertex3=edgeA.m_hasVertex3;b2EPCollider._temp_edge.x=this.m_v2.x-this.m_v1.x;b2EPCollider._temp_edge.y=this.m_v2.y-this.m_v1.y;b2EPCollider._temp_edge.Normalize();this.m_normal1.x=b2EPCollider._temp_edge.y;this.m_normal1.y=-b2EPCollider._temp_edge.x;var offset1=this.m_normal1.x*(this.m_centroidB.x-this.m_v1.x)+this.m_normal1.y*(this.m_centroidB.y-this.m_v1.y);var offset0=0,offset2=0;var convex1=false,convex2=false;if(hasVertex0){b2EPCollider._temp_edge0.x=this.m_v1.x-this.m_v0.x;b2EPCollider._temp_edge0.y=this.m_v1.y-this.m_v0.y;b2EPCollider._temp_edge0.Normalize();this.m_normal0.x=b2EPCollider._temp_edge0.y;this.m_normal0.y=-b2EPCollider._temp_edge0.x;convex1=(b2EPCollider._temp_edge0.x*b2EPCollider._temp_edge.y-b2EPCollider._temp_edge0.y*b2EPCollider._temp_edge.x)>=0;offset0=this.m_normal0.x*(this.m_centroidB.x-this.m_v0.x)+this.m_normal0.y*(this.m_centroidB.y-this.m_v0.y)}if(hasVertex3){b2EPCollider._temp_edge2.x=this.m_v3.x-this.m_v2.x;b2EPCollider._temp_edge2.y=this.m_v3.y-this.m_v2.y;b2EPCollider._temp_edge2.Normalize();this.m_normal2.x=b2EPCollider._temp_edge2.y;this.m_normal2.y=-b2EPCollider._temp_edge2.x;convex2=(b2EPCollider._temp_edge.x*b2EPCollider._temp_edge2.y-b2EPCollider._temp_edge.y*b2EPCollider._temp_edge2.x)>0;offset2=this.m_normal2.x*(this.m_centroidB.x-this.m_v2.x)+this.m_normal2.y*(this.m_centroidB.y-this.m_v2.y)}if(hasVertex0&&hasVertex3){if(convex1&&convex2){this.m_front=offset0>=0||offset1>=0||offset2>=0;if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=this.m_normal0.x;this.m_lowerLimit.y=this.m_normal0.y;this.m_upperLimit.x=this.m_normal2.x;this.m_upperLimit.y=this.m_normal2.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal1.x;this.m_lowerLimit.y=-this.m_normal1.y;this.m_upperLimit.x=-this.m_normal1.x;this.m_upperLimit.y=-this.m_normal1.y}}else{if(convex1){this.m_front=offset0>=0||(offset1>=0&&offset2>=0);if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=this.m_normal0.x;this.m_lowerLimit.y=this.m_normal0.y;this.m_upperLimit.x=this.m_normal1.x;this.m_upperLimit.y=this.m_normal1.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal2.x;this.m_lowerLimit.y=-this.m_normal2.y;this.m_upperLimit.x=-this.m_normal1.x;this.m_upperLimit.y=-this.m_normal1.y}}else{if(convex2){this.m_front=offset2>=0||(offset0>=0&&offset1>=0);if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=this.m_normal1.x;this.m_lowerLimit.y=this.m_normal1.y;this.m_upperLimit.x=this.m_normal2.x;this.m_upperLimit.y=this.m_normal2.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal1.x;this.m_lowerLimit.y=-this.m_normal1.y;this.m_upperLimit.x=-this.m_normal0.x;this.m_upperLimit.y=-this.m_normal0.y}}else{this.m_front=offset0>=0&&offset1>=0&&offset2>=0;if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=this.m_normal1.x;this.m_lowerLimit.y=this.m_normal1.y;this.m_upperLimit.x=this.m_normal1.x;this.m_upperLimit.y=this.m_normal1.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal2.x;this.m_lowerLimit.y=-this.m_normal2.y;this.m_upperLimit.x=-this.m_normal0.x;this.m_upperLimit.y=-this.m_normal0.y}}}}}else{if(hasVertex0){if(convex1){this.m_front=offset0>=0||offset1>=0;if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=this.m_normal0.x;this.m_lowerLimit.y=this.m_normal0.y;this.m_upperLimit.x=-this.m_normal1.x;this.m_upperLimit.y=-this.m_normal1.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=this.m_normal1.x;this.m_lowerLimit.y=this.m_normal1.y;this.m_upperLimit.x=-this.m_normal1.x;this.m_upperLimit.y=-this.m_normal1.y}}else{this.m_front=offset0>=0&&offset1>=0;if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=this.m_normal1.x;this.m_lowerLimit.y=this.m_normal1.y;this.m_upperLimit.x=-this.m_normal1.x;this.m_upperLimit.y=-this.m_normal1.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=this.m_normal1.x;this.m_lowerLimit.y=this.m_normal1.y;this.m_upperLimit.x=-this.m_normal0.x;this.m_upperLimit.y=-this.m_normal0.y}}}else{if(hasVertex3){if(convex2){this.m_front=offset1>=0||offset2>=0;if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal1.x;this.m_lowerLimit.y=-this.m_normal1.y;this.m_upperLimit.x=this.m_normal2.x;this.m_upperLimit.y=this.m_normal2.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal1.x;this.m_lowerLimit.y=-this.m_normal1.y;this.m_upperLimit.x=this.m_normal1.x;this.m_upperLimit.y=this.m_normal1.y}}else{this.m_front=offset1>=0&&offset2>=0;if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal1.x;this.m_lowerLimit.y=-this.m_normal1.y;this.m_upperLimit.x=this.m_normal1.x;this.m_upperLimit.y=this.m_normal1.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal2.x;this.m_lowerLimit.y=-this.m_normal2.y;this.m_upperLimit.x=this.m_normal1.x;this.m_upperLimit.y=this.m_normal1.y}}}else{this.m_front=offset1>=0;if(this.m_front){this.m_normal.x=this.m_normal1.x;this.m_normal.y=this.m_normal1.y;this.m_lowerLimit.x=-this.m_normal1.x;this.m_lowerLimit.y=-this.m_normal1.y;this.m_upperLimit.x=-this.m_normal1.x;this.m_upperLimit.y=-this.m_normal1.y}else{this.m_normal.x=-this.m_normal1.x;this.m_normal.y=-this.m_normal1.y;this.m_lowerLimit.x=this.m_normal1.x;this.m_lowerLimit.y=this.m_normal1.y;this.m_upperLimit.x=this.m_normal1.x;this.m_upperLimit.y=this.m_normal1.y}}}}this.m_polygonB.count=polygonB.m_count;for(var i=0;ithis.m_radius){return}var polygonAxis=this.ComputePolygonSeparation();if(polygonAxis.type!=b2EPAxis.e_unknown&&polygonAxis.separation>this.m_radius){return}var k_relativeTol=0.98;var k_absoluteTol=0.001;var primaryAxis=new b2EPAxis();if(polygonAxis.type==b2EPAxis.e_unknown){primaryAxis=edgeAxis}else{if(polygonAxis.separation>k_relativeTol*edgeAxis.separation+k_absoluteTol){primaryAxis=polygonAxis}else{primaryAxis=edgeAxis}}var ie=new Array(2);var rf=new b2ReferenceFace();if(primaryAxis.type==b2EPAxis.e_edgeA){manifold.type=b2Manifold.e_faceA;var bestIndex=0;var bestValue=this.m_normal.x*this.m_polygonB.normals[0].x+this.m_normal.y*this.m_polygonB.normals[0].y;for(var i=1;ithis.m_radius){axis.type=b2EPAxis.e_edgeB;axis.index=i;axis.separation=s;return axis}if(nx*perpx+ny*perpy>=0){if((nx-this.m_upperLimit.x)*this.m_normal.x+(ny-this.m_upperLimit.y)*this.m_normal.y<-b2_angularSlop){continue}}else{if((nx-this.m_lowerLimit.x)*this.m_normal.x+(ny-this.m_lowerLimit.y)*this.m_normal.y<-b2_angularSlop){continue}}if(s>axis.separation){axis.type=b2EPAxis.e_edgeB;axis.index=i;axis.separation=s}}return axis}};b2EPCollider.e_isolated=0;b2EPCollider.e_concave=1;b2EPCollider.e_convex=2;function b2CollideEdgeAndPolygon(manifold,edgeA,xfA,polygonB,xfB){b2CollideEdgeAndPolygon.collider.Collide(manifold,edgeA,xfA,polygonB,xfB)}b2CollideEdgeAndPolygon.collider=new b2EPCollider();function b2ClipSegmentToLine(vOut,vIn,normalx,normaly,offset,vertexIndexA){var numOut=0;var distance0=(normalx*vIn[0].v.x+normaly*vIn[0].v.y)-offset;var distance1=(normalx*vIn[1].v.x+normaly*vIn[1].v.y)-offset;if(distance0<=0){vOut[numOut++]=vIn[0]}if(distance1<=0){vOut[numOut++]=vIn[1]}if(distance0*distance1<0){var interp=distance0/(distance0-distance1);vOut[numOut]=new b2ClipVertex();vOut[numOut].v.x=vIn[0].v.x+(interp*(vIn[1].v.x-vIn[0].v.x));vOut[numOut].v.y=vIn[0].v.y+(interp*(vIn[1].v.y-vIn[0].v.y));vOut[numOut].id.indexA=vertexIndexA;vOut[numOut].id.indexB=vIn[0].id.indexB;vOut[numOut].id.typeA=b2ContactID.e_vertex;vOut[numOut].id.typeB=b2ContactID.e_face;++numOut}return numOut}function b2TestShapeOverlap(shapeA,indexA,shapeB,indexB,xfA,xfB){b2TestShapeOverlap.input.proxyA.Set(shapeA,indexA);b2TestShapeOverlap.input.proxyB.Set(shapeB,indexB);b2TestShapeOverlap.input.transformA=xfA;b2TestShapeOverlap.input.transformB=xfB;b2TestShapeOverlap.input.useRadii=true;b2TestShapeOverlap.cache.count=0;b2DistanceFunc(b2TestShapeOverlap.output,b2TestShapeOverlap.cache,b2TestShapeOverlap.input);return b2TestShapeOverlap.output.distance<10*b2_epsilon}b2TestShapeOverlap.input=new b2DistanceInput();b2TestShapeOverlap.cache=new b2SimplexCache();b2TestShapeOverlap.output=new b2DistanceOutput();function b2TestOverlap(a,b){return !((b.lowerBound.x-a.upperBound.x)>0||(b.lowerBound.y-a.upperBound.y)>0||(a.lowerBound.x-b.upperBound.x)>0||(a.lowerBound.y-b.upperBound.y)>0)}"use strict";var b2_nullNode=-1;function b2TreeNode(){this.aabb=new b2AABB();this.userData=null;this.parent=0;this.child1=this.child2=this.height=0}b2TreeNode.prototype={IsLeaf:function(){return this.child1==b2_nullNode}};function b2DynamicTree(){this.m_root=b2_nullNode;this.m_nodeCapacity=16;this.m_nodeCount=0;this.m_nodes=new Array(this.m_nodeCapacity);for(var i=0;i0){var nodeId=stack.pop();if(nodeId==b2_nullNode){continue}var node=this.m_nodes[nodeId];if(b2TestOverlap(node.aabb,aabb)){if(node.IsLeaf()){var proceed=callback.QueryCallback(nodeId);if(proceed==false){return}}else{stack.push(node.child1);stack.push(node.child2)}}}},RayCast:function(callback,input){var p1=input.p1;var p2=input.p2;var r=b2Vec2.Subtract(p2,p1);r.Normalize();var v=b2Cross_f_v2(1,r);var abs_v=b2Abs_v2(v);var maxFraction=input.maxFraction;var segmentAABB=new b2AABB();var t=b2Vec2.Add(p1,b2Vec2.Multiply(maxFraction,b2Vec2.Subtract(p2,p1)));segmentAABB.lowerBound.Assign(b2Min_v2(p1,t));segmentAABB.upperBound.Assign(b2Max_v2(p1,t));var stack=[];stack.push(this.m_root);while(stack.length>0){var nodeId=stack.pop();if(nodeId==b2_nullNode){continue}var node=this.m_nodes[nodeId];if(b2TestOverlap(node.aabb,segmentAABB)==false){continue}var c=node.aabb.GetCenter();var h=node.aabb.GetExtents();var separation=b2Abs(b2Dot_v2_v2(v,b2Vec2.Subtract(p1,c)))-b2Dot_v2_v2(abs_v,h);if(separation>0){continue}if(node.IsLeaf()){var subInput=new b2RayCastInput();subInput.p1.Assign(input.p1);subInput.p2.Assign(input.p2);subInput.maxFraction=maxFraction;var value=callback.RayCastCallback(subInput,nodeId);if(value==0){return}if(value>0){maxFraction=value;var t=b2Vec2.Add(p1,b2Vec2.Multiply(maxFraction,b2Vec2.Subtract(p2,p1)));segmentAABB.lowerBound.Assign(b2Min_v2(p1,t));segmentAABB.upperBound.Assign(b2Max_v2(p1,t))}}else{stack.push(node.child1);stack.push(node.child2)}}},Validate:function(){this.ValidateStructure(this.m_root);this.ValidateMetrics(this.m_root);var freeCount=0;var freeIndex=this.m_freeList;while(freeIndex!=b2_nullNode){freeIndex=this.m_nodes[freeIndex].parent;++freeCount}},GetHeight:function(){if(this.m_root==b2_nullNode){return 0}return this.m_nodes[this.m_root].height},GetMaxBalance:function(){var maxBalance=0;for(var i=0;i1){var minCost=b2_maxFloat;var iMin=-1,jMin=-1;for(i=0;i1){var iF=C.child1;var iG=C.child2;var F=this.m_nodes[iF];var G=this.m_nodes[iG];C.child1=iA;C.parent=A.parent;A.parent=iC;if(C.parent!=b2_nullNode){if(this.m_nodes[C.parent].child1==iA){this.m_nodes[C.parent].child1=iC}else{this.m_nodes[C.parent].child2=iC}}else{this.m_root=iC}if(F.height>G.height){C.child2=iF;A.child2=iG;G.parent=iA;A.aabb.Combine(B.aabb,G.aabb);C.aabb.Combine(A.aabb,F.aabb);A.height=1+b2Max(B.height,G.height);C.height=1+b2Max(A.height,F.height)}else{C.child2=iG;A.child2=iF;F.parent=iA;A.aabb.Combine(B.aabb,F.aabb);C.aabb.Combine(A.aabb,G.aabb);A.height=1+b2Max(B.height,F.height);C.height=1+b2Max(A.height,G.height)}return iC}if(balance<-1){var iD=B.child1;var iE=B.child2;var D=this.m_nodes[iD];var E=this.m_nodes[iE];B.child1=iA;B.parent=A.parent;A.parent=iB;if(B.parent!=b2_nullNode){if(this.m_nodes[B.parent].child1==iA){this.m_nodes[B.parent].child1=iB}else{this.m_nodes[B.parent].child2=iB}}else{this.m_root=iB}if(D.height>E.height){B.child2=iD;A.child1=iE;E.parent=iA;A.aabb.Combine(C.aabb,E.aabb);B.aabb.Combine(A.aabb,D.aabb);A.height=1+b2Max(C.height,E.height);B.height=1+b2Max(A.height,D.height)}else{B.child2=iE;A.child1=iD;D.parent=iA;A.aabb.Combine(C.aabb,D.aabb);B.aabb.Combine(A.aabb,E.aabb);A.height=1+b2Max(C.height,D.height);B.height=1+b2Max(A.height,E.height)}return iB}return iA},ComputeHeight:function(nodeId){if(typeof(nodeId)==="undefined"){nodeId=this.m_root}var node=this.m_nodes[nodeId];if(node.IsLeaf()){return 0}var height1=this.ComputeHeight(node.child1);var height2=this.ComputeHeight(node.child2);return 1+b2Max(height1,height2)},ValidateStructure:function(index){if(index==b2_nullNode){return}var node=this.m_nodes[index];var child1=node.child1;var child2=node.child2;if(node.IsLeaf()){return}this.ValidateStructure(child1);this.ValidateStructure(child2)},ValidateMetrics:function(index){if(index==b2_nullNode){return}var node=this.m_nodes[index];var child1=node.child1;var child2=node.child2;if(node.IsLeaf()){return}var height1=this.m_nodes[child1].height;var height2=this.m_nodes[child2].height;var height;height=1+b2Max(height1,height2);var aabb=new b2AABB();aabb.Combine(this.m_nodes[child1].aabb,this.m_nodes[child2].aabb);this.ValidateMetrics(child1);this.ValidateMetrics(child2)}};"use strict";function b2TOIInput(){this.proxyA=new b2DistanceProxy();this.proxyB=new b2DistanceProxy();this.sweepA=new b2Sweep();this.sweepB=new b2Sweep();this.tMax=0}function b2TOIOutput(){this.state=0;this.t=0}b2TOIOutput.e_unknown=0;b2TOIOutput.e_failed=1;b2TOIOutput.e_overlapped=2;b2TOIOutput.e_touching=3;b2TOIOutput.e_separated=4;function b2SeparationFunction(){this.m_proxyA=null;this.m_proxyB=null;this.m_sweepA=null;this.m_sweepB=null;this.m_type=0;this.m_localPoint=new b2Vec2();this.m_axis=new b2Vec2()}var _local_xfA=new b2Transform();var _local_xfB=new b2Transform();b2SeparationFunction.prototype={Initialize:function(cache,proxyA,sweepA,proxyB,sweepB,t1){this.m_proxyA=proxyA;this.m_proxyB=proxyB;var count=cache.count;this.m_sweepA=sweepA;this.m_sweepB=sweepB;this.m_sweepA.GetTransform(_local_xfA,t1);this.m_sweepB.GetTransform(_local_xfB,t1);if(count==1){this.m_type=b2SeparationFunction.e_points;var localPointA=this.m_proxyA.GetVertex(cache.indexA[0]);var localPointB=this.m_proxyB.GetVertex(cache.indexB[0]);var pointAx=(_local_xfA.q.c*localPointA.x-_local_xfA.q.s*localPointA.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*localPointA.x+_local_xfA.q.c*localPointA.y)+_local_xfA.p.y;var pointBx=(_local_xfB.q.c*localPointB.x-_local_xfB.q.s*localPointB.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*localPointB.x+_local_xfB.q.c*localPointB.y)+_local_xfB.p.y;this.m_axis.x=pointBx-pointAx;this.m_axis.y=pointBy-pointAy;var s=this.m_axis.Normalize();return s}else{if(cache.indexA[0]==cache.indexA[1]){this.m_type=b2SeparationFunction.e_faceB;var localPointB1=proxyB.GetVertex(cache.indexB[0]);var localPointB2=proxyB.GetVertex(cache.indexB[1]);this.m_axis.x=1*(localPointB2.y-localPointB1.y);this.m_axis.y=-1*(localPointB2.x-localPointB1.x);this.m_axis.Normalize();var normalx=_local_xfB.q.c*this.m_axis.x-_local_xfB.q.s*this.m_axis.y;var normaly=_local_xfB.q.s*this.m_axis.x+_local_xfB.q.c*this.m_axis.y;this.m_localPoint.x=0.5*(localPointB1.x+localPointB2.x);this.m_localPoint.y=0.5*(localPointB1.y+localPointB2.y);var pointBx=(_local_xfB.q.c*this.m_localPoint.x-_local_xfB.q.s*this.m_localPoint.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*this.m_localPoint.x+_local_xfB.q.c*this.m_localPoint.y)+_local_xfB.p.y;var localPointA=proxyA.GetVertex(cache.indexA[0]);var pointAx=(_local_xfA.q.c*localPointA.x-_local_xfA.q.s*localPointA.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*localPointA.x+_local_xfA.q.c*localPointA.y)+_local_xfA.p.y;var s=(pointAx-pointBx)*normalx+(pointAy-pointBy)*normaly;if(s<0){this.m_axis.x=-this.m_axis.x;this.m_axis.y=-this.m_axis.y;s=-s}return s}else{this.m_type=b2SeparationFunction.e_faceA;var localPointA1=this.m_proxyA.GetVertex(cache.indexA[0]);var localPointA2=this.m_proxyA.GetVertex(cache.indexA[1]);this.m_axis.x=1*(localPointA2.y-localPointA1.y);this.m_axis.y=-1*(localPointA2.x-localPointA1.x);this.m_axis.Normalize();var normalx=_local_xfA.q.c*this.m_axis.x-_local_xfA.q.s*this.m_axis.y;var normaly=_local_xfA.q.s*this.m_axis.x+_local_xfA.q.c*this.m_axis.y;this.m_localPoint.x=0.5*(localPointA1.x+localPointA2.x);this.m_localPoint.y=0.5*(localPointA1.y+localPointA2.y);var pointAx=(_local_xfA.q.c*this.m_localPoint.x-_local_xfA.q.s*this.m_localPoint.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*this.m_localPoint.x+_local_xfA.q.c*this.m_localPoint.y)+_local_xfA.p.y;var localPointB=this.m_proxyB.GetVertex(cache.indexB[0]);var pointBx=(_local_xfB.q.c*localPointB.x-_local_xfB.q.s*localPointB.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*localPointB.x+_local_xfB.q.c*localPointB.y)+_local_xfB.p.y;var s=(pointBx-pointAx)*normalx+(pointBy-pointAy)*normaly;if(s<0){this.m_axis.x=-this.m_axis.x;this.m_axis.y=-this.m_axis.y;s=-s}return s}}},FindMinSeparation:function(indices,t){this.m_sweepA.GetTransform(_local_xfA,t);this.m_sweepB.GetTransform(_local_xfB,t);switch(this.m_type){case b2SeparationFunction.e_points:var axisAx=_local_xfA.q.c*this.m_axis.x+_local_xfA.q.s*this.m_axis.y;var axisAy=-_local_xfA.q.s*this.m_axis.x+_local_xfA.q.c*this.m_axis.y;var axisBx=_local_xfB.q.c*-this.m_axis.x+_local_xfB.q.s*-this.m_axis.y;var axisBy=-_local_xfB.q.s*-this.m_axis.x+_local_xfB.q.c*-this.m_axis.y;indices[0]=this.m_proxyA.GetSupport(axisAx,axisAy);indices[1]=this.m_proxyB.GetSupport(axisBx,axisBy);var localPointA=this.m_proxyA.GetVertex(indices[0]);var localPointB=this.m_proxyB.GetVertex(indices[1]);var pointAx=(_local_xfA.q.c*localPointA.x-_local_xfA.q.s*localPointA.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*localPointA.x+_local_xfA.q.c*localPointA.y)+_local_xfA.p.y;var pointBx=(_local_xfB.q.c*localPointB.x-_local_xfB.q.s*localPointB.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*localPointB.x+_local_xfB.q.c*localPointB.y)+_local_xfB.p.y;return(pointBx-pointAx)*this.m_axis.x+(pointBy-pointAy)*this.m_axis.y;case b2SeparationFunction.e_faceA:var normalx=_local_xfA.q.c*this.m_axis.x-_local_xfA.q.s*this.m_axis.y;var normaly=_local_xfA.q.s*this.m_axis.x+_local_xfA.q.c*this.m_axis.y;var pointAx=(_local_xfA.q.c*this.m_localPoint.x-_local_xfA.q.s*this.m_localPoint.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*this.m_localPoint.x+_local_xfA.q.c*this.m_localPoint.y)+_local_xfA.p.y;var axisBx=_local_xfB.q.c*-normalx+_local_xfB.q.s*-normaly;var axisBy=-_local_xfB.q.s*-normalx+_local_xfB.q.c*-normaly;indices[0]=-1;indices[1]=this.m_proxyB.GetSupport(axisBx,axisBy);var localPointB=this.m_proxyB.GetVertex(indices[1]);var pointBx=(_local_xfB.q.c*localPointB.x-_local_xfB.q.s*localPointB.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*localPointB.x+_local_xfB.q.c*localPointB.y)+_local_xfB.p.y;return(pointBx-pointAx)*normalx+(pointBy-pointAy)*normaly;case b2SeparationFunction.e_faceB:var normalx=_local_xfB.q.c*this.m_axis.x-_local_xfB.q.s*this.m_axis.y;var normaly=_local_xfB.q.s*this.m_axis.x+_local_xfB.q.c*this.m_axis.y;var pointBx=(_local_xfB.q.c*this.m_localPoint.x-_local_xfB.q.s*this.m_localPoint.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*this.m_localPoint.x+_local_xfB.q.c*this.m_localPoint.y)+_local_xfB.p.y;var axisAx=_local_xfA.q.c*-normalx+_local_xfA.q.s*-normaly;var axisBy=-_local_xfA.q.s*-normalx+_local_xfA.q.c*-normaly;indices[1]=-1;indices[0]=this.m_proxyA.GetSupport(axisAx,axisBy);var localPointA=this.m_proxyA.GetVertex(indices[0]);var pointAx=(_local_xfA.q.c*localPointA.x-_local_xfA.q.s*localPointA.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*localPointA.x+_local_xfA.q.c*localPointA.y)+_local_xfA.p.y;return(pointAx-pointBx)*normalx+(pointAy-pointBy)*normaly}},Evaluate:function(indexA,indexB,t){this.m_sweepA.GetTransform(_local_xfA,t);this.m_sweepB.GetTransform(_local_xfB,t);switch(this.m_type){case b2SeparationFunction.e_points:var localPointA=this.m_proxyA.GetVertex(indexA);var localPointB=this.m_proxyB.GetVertex(indexB);var pointAx=(_local_xfA.q.c*localPointA.x-_local_xfA.q.s*localPointA.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*localPointA.x+_local_xfA.q.c*localPointA.y)+_local_xfA.p.y;var pointBx=(_local_xfB.q.c*localPointB.x-_local_xfB.q.s*localPointB.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*localPointB.x+_local_xfB.q.c*localPointB.y)+_local_xfB.p.y;var separation=(pointBx-pointAx)*this.m_axis.x+(pointBy-pointAy)*this.m_axis.y;return separation;case b2SeparationFunction.e_faceA:var normalx=_local_xfA.q.c*this.m_axis.x-_local_xfA.q.s*this.m_axis.y;var normaly=_local_xfA.q.s*this.m_axis.x+_local_xfA.q.c*this.m_axis.y;var pointAx=(_local_xfA.q.c*this.m_localPoint.x-_local_xfA.q.s*this.m_localPoint.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*this.m_localPoint.x+_local_xfA.q.c*this.m_localPoint.y)+_local_xfA.p.y;var localPointB=this.m_proxyB.GetVertex(indexB);var pointBx=(_local_xfB.q.c*localPointB.x-_local_xfB.q.s*localPointB.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*localPointB.x+_local_xfB.q.c*localPointB.y)+_local_xfB.p.y;var separation=(pointBx-pointAx)*normalx+(pointBy-pointAy)*normaly;return separation;case b2SeparationFunction.e_faceB:var normalx=_local_xfB.q.c*this.m_axis.x-_local_xfB.q.s*this.m_axis.y;var normaly=_local_xfB.q.s*this.m_axis.x+_local_xfB.q.c*this.m_axis.y;var pointBx=(_local_xfB.q.c*this.m_localPoint.x-_local_xfB.q.s*this.m_localPoint.y)+_local_xfB.p.x;var pointBy=(_local_xfB.q.s*this.m_localPoint.x+_local_xfB.q.c*this.m_localPoint.y)+_local_xfB.p.y;var localPointA=this.m_proxyA.GetVertex(indexA);var pointAx=(_local_xfA.q.c*localPointA.x-_local_xfA.q.s*localPointA.y)+_local_xfA.p.x;var pointAy=(_local_xfA.q.s*localPointA.x+_local_xfA.q.c*localPointA.y)+_local_xfA.p.y;var separation=(pointAx-pointBx)*normalx+(pointAy-pointBy)*normaly;return separation}}};b2SeparationFunction.e_points=0;b2SeparationFunction.e_faceA=1;b2SeparationFunction.e_faceB=2;var profile_toi=b2Profiler.create("toi","solveTOI");function b2TimeOfImpact(output,input){profile_toi.start();++b2TimeOfImpact.b2_toiCalls;output.state=b2TOIOutput.e_unknown;output.t=input.tMax;var proxyA=input.proxyA;var proxyB=input.proxyB;b2TimeOfImpact._temp_sweepA.Assign(input.sweepA);b2TimeOfImpact._temp_sweepB.Assign(input.sweepB);b2TimeOfImpact._temp_sweepA.Normalize();b2TimeOfImpact._temp_sweepB.Normalize();var tMax=input.tMax;var totalRadius=proxyA.m_radius+proxyB.m_radius;var target=b2Max(b2_linearSlop,totalRadius-3*b2_linearSlop);var tolerance=0.25*b2_linearSlop;var t1=0;var k_maxIterations=20;var iter=0;var cache=new b2SimplexCache();cache.count=0;var distanceInput=new b2DistanceInput();distanceInput.proxyA.Assign(input.proxyA);distanceInput.proxyB.Assign(input.proxyB);distanceInput.useRadii=false;for(;;){b2TimeOfImpact._temp_sweepA.GetTransform(distanceInput.transformA,t1);b2TimeOfImpact._temp_sweepB.GetTransform(distanceInput.transformB,t1);var distanceOutput=new b2DistanceOutput();b2DistanceFunc(distanceOutput,cache,distanceInput);if(distanceOutput.distance<=0){output.state=b2TOIOutput.e_overlapped;output.t=0;break}if(distanceOutput.distancetarget+tolerance){output.state=b2TOIOutput.e_separated;output.t=tMax;done=true;break}if(s2>target-tolerance){t1=t2;break}var s1=fcn.Evaluate(indices[0],indices[1],t1);if(s1target){a1=t;s1=s}else{a2=t;s2=s}if(rootIterCount==50){break}}b2TimeOfImpact.b2_toiMaxRootIters=b2Max(b2TimeOfImpact.b2_toiMaxRootIters,rootIterCount);++pushBackIter;if(pushBackIter==b2_maxPolygonVertices){break}}++iter;++b2TimeOfImpact.b2_toiIters;if(done){break}if(iter==k_maxIterations){output.state=b2TOIOutput.e_failed;output.t=t1;break}}b2TimeOfImpact.b2_toiMaxIters=b2Max(b2TimeOfImpact.b2_toiMaxIters,iter);profile_toi.stop();b2TimeOfImpact.b2_toiMaxTime=b2Max(b2TimeOfImpact.b2_toiMaxTime,profile_toi.elapsedTime);b2TimeOfImpact.b2_toiTime+=profile_toi.elapsedTime}b2TimeOfImpact._temp_sweepA=new b2Sweep();b2TimeOfImpact._temp_sweepB=new b2Sweep();b2TimeOfImpact.b2_toiTime=0;b2TimeOfImpact.b2_toiMaxTime=0;b2TimeOfImpact.b2_toiCalls=0;b2TimeOfImpact.b2_toiIters=0;b2TimeOfImpact.b2_toiMaxIters=0;b2TimeOfImpact.b2_toiRootIters=0;b2TimeOfImpact.b2_toiMaxRootIters=0;"use strict";function b2BodyDef(){this.type=b2Body.b2_staticBody;this.position=new b2Vec2(0,0);this.angle=0;this.linearVelocity=new b2Vec2(0,0);this.angularVelocity=0;this.linearDamping=0;this.angularDamping=0;this.allowSleep=true;this.awake=true;this.fixedRotation=false;this.bullet=false;this.active=true;this.userData=null;this.gravityScale=1;Object.seal(this)}b2BodyDef.prototype={_deserialize:function(data){this.type=data.type;this.position._deserialize(data.position);this.angle=data.angle;this.linearVelocity._deserialize(data.linearVelocity);this.angularVelocity=data.angularVelocity;this.linearDamping=data.linearDamping;this.angularDamping=data.angularDamping;this.allowSleep=data.allowSleep;this.awake=data.awake;this.fixedRotation=data.fixedRotation;this.bullet=data.bullet;this.active=data.active;this.gravityScale=data.gravityScale}};function b2Body(bd,world){this.m_islandIndex=0;this.m_flags=0;if(bd.bullet){this.m_flags|=b2Body.e_bulletFlag}if(bd.fixedRotation){this.m_flags|=b2Body.e_fixedRotationFlag}if(bd.allowSleep){this.m_flags|=b2Body.e_autoSleepFlag}if(bd.awake){this.m_flags|=b2Body.e_awakeFlag}if(bd.active){this.m_flags|=b2Body.e_activeFlag}this.m_world=world;this.m_xf=new b2Transform();this.m_xf.p.Assign(bd.position);this.m_xf.q.Set(bd.angle);this.m_sweep=new b2Sweep();this.m_sweep.localCenter.SetZero();this.m_sweep.c0.Assign(this.m_xf.p);this.m_sweep.c.Assign(this.m_xf.p);this.m_sweep.a0=bd.angle;this.m_sweep.a=bd.angle;this.m_sweep.alpha0=0;this.m_jointList=null;this.m_contactList=null;this.m_prev=null;this.m_next=null;this.m_linearVelocity=bd.linearVelocity.Clone();this.m_angularVelocity=bd.angularVelocity;this.m_linearDamping=bd.linearDamping;this.m_angularDamping=bd.angularDamping;this.m_gravityScale=bd.gravityScale;this.m_force=new b2Vec2();this.m_torque=0;this.m_sleepTime=0;this.m_type=bd.type;if(this.m_type==b2Body.b2_dynamicBody){this.m_mass=1;this.m_invMass=1}else{this.m_mass=0;this.m_invMass=0}this.m_I=0;this.m_invI=0;this.m_userData=bd.userData;this.m_fixtureList=null;this.m_fixtureCount=0}b2Body.b2_staticBody=0;b2Body.b2_kinematicBody=1;b2Body.b2_dynamicBody=2;b2Body.e_islandFlag=1;b2Body.e_awakeFlag=2;b2Body.e_autoSleepFlag=4;b2Body.e_bulletFlag=8;b2Body.e_fixedRotationFlag=16;b2Body.e_activeFlag=32;b2Body.e_toiFlag=64;b2Body.m_local_oldCenter=new b2Vec2();b2Body.m_local_xf1=new b2Transform();b2Body.prototype={CreateFixture:function(def,density){if(typeof(density)!=="undefined"){var ndef=new b2FixtureDef();ndef.shape=def;ndef.density=density;return this.CreateFixture(ndef)}if(this.m_world.IsLocked()==true){return null}var fixture=new b2Fixture();fixture.Create(this,def);if(this.m_flags&b2Body.e_activeFlag){var broadPhase=this.m_world.m_contactManager.m_broadPhase;fixture.CreateProxies(broadPhase,this.m_xf)}fixture.m_next=this.m_fixtureList;this.m_fixtureList=fixture;++this.m_fixtureCount;fixture.m_body=this;if(fixture.m_density>0){this.ResetMassData()}this.m_world.m_flags|=b2World.e_newFixture;return fixture},DestroyFixture:function(fixture){if(this.m_world.IsLocked()==true){return}var node=this.m_fixtureList;var found=false;while(node!=null){if(node==fixture){this.m_fixtureList=node=fixture.m_next;found=true;break}node=node.m_next}var edge=this.m_contactList;while(edge){var c=edge.contact;edge=edge.next;var fixtureA=c.GetFixtureA();var fixtureB=c.GetFixtureB();if(fixture==fixtureA||fixture==fixtureB){this.m_world.m_contactManager.Destroy(c)}}if(this.m_flags&b2Body.e_activeFlag){var broadPhase=this.m_world.m_contactManager.m_broadPhase;fixture.DestroyProxies(broadPhase)}fixture.Destroy();fixture.m_body=null;fixture.m_next=null;--this.m_fixtureCount;this.ResetMassData()},SetTransform:function(position,angle){if(this.m_world.IsLocked()==true){return}this.m_xf.q.Set(angle);this.m_xf.p.Assign(position);this.m_sweep.c.Assign(b2Mul_t_v2(this.m_xf,this.m_sweep.localCenter));this.m_sweep.a=angle;this.m_sweep.c0.Assign(this.m_sweep.c);this.m_sweep.a0=angle;var broadPhase=this.m_world.m_contactManager.m_broadPhase;for(var f=this.m_fixtureList;f;f=f.m_next){f.Synchronize(broadPhase,this.m_xf,this.m_xf)}},GetTransform:function(){return this.m_xf},GetPosition:function(){return this.m_xf.p},GetAngle:function(){return this.m_sweep.a},GetWorldCenter:function(){return this.m_sweep.c},GetLocalCenter:function(){return this.m_sweep.localCenter},SetLinearVelocity:function(v){if(this.m_type==b2Body.b2_staticBody){return}if(b2Dot_v2_v2(v,v)>0){this.SetAwake(true)}this.m_linearVelocity=v},GetLinearVelocity:function(){return this.m_linearVelocity},SetAngularVelocity:function(w){if(this.m_type==b2Body.b2_staticBody){return}if(w*w>0){this.SetAwake(true)}this.m_angularVelocity=w},GetAngularVelocity:function(){return this.m_angularVelocity},ApplyForce:function(force,point,wake){if(this.m_type!=b2Body.b2_dynamicBody){return}if(wake&&(this.m_flags&b2Body.e_awakeFlag)==0){this.SetAwake(true)}if(this.m_flags&b2Body.e_awakeFlag){this.m_force.Add(force);this.m_torque+=b2Cross_v2_v2(b2Vec2.Subtract(point,this.m_sweep.c),force)}},ApplyForceToCenter:function(force,wake){if(this.m_type!=b2Body.b2_dynamicBody){return}if(wake&&(this.m_flags&b2Body.e_awakeFlag)==0){this.SetAwake(true)}if(this.m_flags&b2Body.e_awakeFlag){this.m_force.Add(force)}},ApplyTorque:function(torque,wake){if(this.m_type!=b2Body.b2_dynamicBody){return}if(wake&&(this.m_flags&b2Body.e_awakeFlag)==0){this.SetAwake(true)}if(this.m_flags&b2Body.e_awakeFlag){this.m_torque+=torque}},ApplyLinearImpulse:function(impulse,point,wake){if(this.m_type!=b2Body.b2_dynamicBody){return}if(wake&&(this.m_flags&b2Body.e_awakeFlag)==0){this.SetAwake(true)}if(this.m_flags&b2Body.e_awakeFlag){this.m_linearVelocity.Add(b2Vec2.Multiply(this.m_invMass,impulse));this.m_angularVelocity+=this.m_invI*b2Cross_v2_v2(b2Vec2.Subtract(point,this.m_sweep.c),impulse)}},ApplyAngularImpulse:function(impulse,wake){if(this.m_type!=b2Body.b2_dynamicBody){return}if(wake&&(this.m_flags&b2Body.e_awakeFlag)==0){this.SetAwake(true)}if(this.m_flags&b2Body.e_awakeFlag){this.m_angularVelocity+=this.m_invI*impulse}},GetMass:function(){return this.m_mass},GetInertia:function(){return this.m_I+this.m_mass*b2Dot_v2_v2(this.m_sweep.localCenter,this.m_sweep.localCenter)},GetMassData:function(data){data.mass=this.m_mass;data.I=this.m_I+this.m_mass*b2Dot_v2_v2(this.m_sweep.localCenter,this.m_sweep.localCenter);data.center=this.m_sweep.localCenter},SetMassData:function(massData){if(this.m_world.IsLocked()==true){return}if(this.m_type!=b2Body.b2_dynamicBody){return}this.m_invMass=0;this.m_I=0;this.m_invI=0;this.m_mass=massData.mass;if(this.m_mass<=0){this.m_mass=1}this.m_invMass=1/this.m_mass;if(massData.I>0&&(this.m_flags&b2Body.e_fixedRotationFlag)==0){this.m_I=massData.I-this.m_mass*b2Dot_v2_v2(massData.center,massData.center);this.m_invI=1/this.m_I}b2Body.m_local_oldCenter.Assign(this.m_sweep.c);this.m_sweep.localCenter.Assign(massData.center);this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf,this.m_sweep.localCenter));this.m_sweep.c.Assign(this.m_sweep.c0);this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity,b2Vec2.Subtract(this.m_sweep.c,b2Body.m_local_oldCenter)))},ResetMassData:function(){this.m_mass=0;this.m_invMass=0;this.m_I=0;this.m_invI=0;this.m_sweep.localCenter.SetZero();if(this.m_type==b2Body.b2_staticBody||this.m_type==b2Body.b2_kinematicBody){this.m_sweep.c0.Assign(this.m_xf.p);this.m_sweep.c.Assign(this.m_xf.p);this.m_sweep.a0=this.m_sweep.a;return}var localCenter=new b2Vec2(0,0);for(var f=this.m_fixtureList;f;f=f.m_next){if(f.m_density==0){continue}var massData=new b2MassData();f.GetMassData(massData);this.m_mass+=massData.mass;localCenter.Add(b2Vec2.Multiply(massData.mass,massData.center));this.m_I+=massData.I}if(this.m_mass>0){this.m_invMass=1/this.m_mass;localCenter.Multiply(this.m_invMass)}else{this.m_mass=1;this.m_invMass=1}if(this.m_I>0&&(this.m_flags&b2Body.e_fixedRotationFlag)==0){this.m_I-=this.m_mass*b2Dot_v2_v2(localCenter,localCenter);this.m_invI=1/this.m_I}else{this.m_I=0;this.m_invI=0}b2Body.m_local_oldCenter.Assign(this.m_sweep.c);this.m_sweep.localCenter.Assign(localCenter);this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf,this.m_sweep.localCenter));this.m_sweep.c.Assign(this.m_sweep.c0);this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity,b2Vec2.Subtract(this.m_sweep.c,b2Body.m_local_oldCenter)))},GetWorldPoint:function(localPoint){return b2Mul_t_v2(this.m_xf,localPoint)},GetWorldVector:function(localVector){return b2Mul_r_v2(this.m_xf.q,localVector)},GetLocalPoint:function(worldPoint){return b2MulT_t_v2(this.m_xf,worldPoint)},GetLocalVector:function(worldVector){return b2MulT_r_v2(this.m_xf.q,worldVector)},GetLinearVelocityFromWorldPoint:function(worldPoint){return b2Vec2.Add(this.m_linearVelocity,b2Cross_f_v2(this.m_angularVelocity,b2Vec2.Subtract(worldPoint,this.m_sweep.c)))},GetLinearVelocityFromLocalPoint:function(localPoint){return this.GetLinearVelocityFromWorldPoint(this.GetWorldPoint(localPoint))},GetLinearDamping:function(){return this.m_linearDamping},SetLinearDamping:function(linearDamping){this.m_linearDamping=linearDamping},GetAngularDamping:function(){return this.m_angularDamping},SetAngularDamping:function(angularDamping){this.m_angularDamping=angularDamping},GetGravityScale:function(){return this.m_gravityScale},SetGravityScale:function(scale){this.m_gravityScale=scale},SetType:function(type){if(this.m_world.IsLocked()==true){return}if(this.m_type==type){return}this.m_type=type;this.ResetMassData();if(this.m_type==b2Body.b2_staticBody){this.m_linearVelocity.SetZero();this.m_angularVelocity=0;this.m_sweep.a0=this.m_sweep.a;this.m_sweep.c0.Assign(this.m_sweep.c);this.SynchronizeFixtures()}this.SetAwake(true);this.m_force.SetZero();this.m_torque=0;var ce=this.m_contactList;while(ce){var ce0=ce;ce=ce.next;this.m_world.m_contactManager.Destroy(ce0.contact)}this.m_contactList=null;var broadPhase=this.m_world.m_contactManager.m_broadPhase;for(var f=this.m_fixtureList;f;f=f.m_next){var proxyCount=f.m_proxyCount;for(var i=0;i0}var collide=(filterA.maskBits&filterB.categoryBits)!=0&&(filterA.categoryBits&filterB.maskBits)!=0;return collide}};function b2ContactImpulse(){this.normalImpulses=new Array(b2_maxManifoldPoints);this.tangentImpulses=new Array(b2_maxManifoldPoints);this.count=0}function b2ContactListener(){}b2ContactListener.prototype={BeginContact:function(contact){},EndContact:function(contact){},PreSolve:function(contact,oldManifold){},PostSolve:function(contact,impulse){}};function b2QueryCallback(){}b2QueryCallback.prototype={ReportFixture:function(fixture){}};function b2RayCastCallback(){}b2RayCastCallback.prototype={ReportFixture:function(fixture,point,normal,fraction){}};"use strict";function b2TimeStep(){this.dt=0;this.inv_dt=0;this.dtRatio=0;this.velocityIterations=0;this.positionIterations=0;this.warmStarting=false}function b2Position(){this.c=new b2Vec2();this.a=0}function b2Velocity(){this.v=new b2Vec2();this.w=0}function b2SolverData(){this.step=new b2TimeStep();this.positions=null;this.velocities=null}"use strict";var profile_world_step=b2Profiler.create("step");var profile_world_collide=b2Profiler.create("collide","step");var profile_world_solve=b2Profiler.create("solve","step");var profile_world_solveTOI=b2Profiler.create("solveTOI","step");var profile_world_broadphase=b2Profiler.create("broadphase","step");function b2World(gravity){this.m_contactManager=new b2ContactManager();this.m_destructionListener=null;this.g_debugDraw=null;this.m_bodyList=null;this.m_jointList=null;this.m_bodyCount=0;this.m_jointCount=0;this.m_warmStarting=true;this.m_continuousPhysics=true;this.m_subStepping=false;this.m_stepComplete=true;this.m_allowSleep=true;this.m_gravity=gravity;this.m_flags=b2World.e_clearForces;this.m_inv_dt0=0;this.p_step=new b2TimeStep();this.p_island=new b2Island()}function b2WorldQueryWrapper(){this.broadPhase=null;this.callback=null}b2WorldQueryWrapper.prototype={QueryCallback:function(proxyId){var proxy=this.broadPhase.GetUserData(proxyId);return this.callback.ReportFixture(proxy.fixture)}};function b2WorldRayCastWrapper(){this.broadPhase=null;this.callback=null}b2WorldRayCastWrapper.prototype={RayCastCallback:function(input,proxyId){var userData=this.broadPhase.GetUserData(proxyId);var proxy=userData;var fixture=proxy.fixture;var index=proxy.childIndex;var output=new b2RayCastOutput();var hit=fixture.RayCast(output,input,index);if(hit){var fraction=output.fraction;var point=b2Vec2.Add(b2Vec2.Multiply((1-fraction),input.p1),b2Vec2.Multiply(fraction,input.p2));return this.callback.ReportFixture(fixture,point,output.normal,fraction)}return input.maxFraction}};b2World.m_local_sweep_backupA=new b2Sweep();b2World.m_local_sweep_backupB=new b2Sweep();b2World.m_local_sweep_backupC=new b2Sweep();b2World.prototype={Destroy:function(){var b=this.m_bodyList;while(b){var bNext=b.m_next;var f=b.m_fixtureList;while(f){var fNext=f.m_next;f.m_proxyCount=0;f.Destroy();f=fNext}b=bNext}},SetDestructionListener:function(listener){this.m_destructionListener=listener},SetContactFilter:function(filter){this.m_contactManager.m_contactFilter=filter},SetContactListener:function(listener){this.m_contactManager.m_contactListener=listener},SetDebugDraw:function(debugDraw){this.g_debugDraw=debugDraw},CreateBody:function(def){if(this.IsLocked()){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},DestroyBody:function(b){if(this.IsLocked()){return}var je=b.m_jointList;while(je){var je0=je;je=je.next;if(this.m_destructionListener){this.m_destructionListener.SayGoodbyeJoint(je0.joint)}this.DestroyJoint(je0.joint);b.m_jointList=je}b.m_jointList=null;var ce=b.m_contactList;while(ce){var ce0=ce;ce=ce.next;this.m_contactManager.Destroy(ce0.contact)}b.m_contactList=null;var f=b.m_fixtureList;while(f){var f0=f;f=f.m_next;if(this.m_destructionListener){this.m_destructionListener.SayGoodbyeFixture(f0)}f0.DestroyProxies(this.m_contactManager.m_broadPhase);f0.Destroy();b.m_fixtureList=f;b.m_fixtureCount-=1}b.m_fixtureList=null;b.m_fixtureCount=0;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}b.m_destroyed=true;--this.m_bodyCount},CreateJoint:function(def){if(this.IsLocked()){return null}var j=b2Joint.Create(def);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_edgeA.joint=j;j.m_edgeA.other=j.m_bodyB;j.m_edgeA.prev=null;j.m_edgeA.next=j.m_bodyA.m_jointList;if(j.m_bodyA.m_jointList){j.m_bodyA.m_jointList.prev=j.m_edgeA}j.m_bodyA.m_jointList=j.m_edgeA;j.m_edgeB.joint=j;j.m_edgeB.other=j.m_bodyA;j.m_edgeB.prev=null;j.m_edgeB.next=j.m_bodyB.m_jointList;if(j.m_bodyB.m_jointList){j.m_bodyB.m_jointList.prev=j.m_edgeB}j.m_bodyB.m_jointList=j.m_edgeB;var bodyA=def.bodyA;var bodyB=def.bodyB;if(def.collideConnected==false){var edge=bodyB.GetContactList();while(edge){if(edge.other==bodyA){edge.contact.FlagForFiltering()}edge=edge.next}}return j},DestroyJoint:function(j){if(this.IsLocked()){return}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 bodyA=j.m_bodyA;var bodyB=j.m_bodyB;bodyA.SetAwake(true);bodyB.SetAwake(true);if(j.m_edgeA.prev){j.m_edgeA.prev.next=j.m_edgeA.next}if(j.m_edgeA.next){j.m_edgeA.next.prev=j.m_edgeA.prev}if(j.m_edgeA==bodyA.m_jointList){bodyA.m_jointList=j.m_edgeA.next}j.m_edgeA.prev=null;j.m_edgeA.next=null;if(j.m_edgeB.prev){j.m_edgeB.prev.next=j.m_edgeB.next}if(j.m_edgeB.next){j.m_edgeB.next.prev=j.m_edgeB.prev}if(j.m_edgeB==bodyB.m_jointList){bodyB.m_jointList=j.m_edgeB.next}j.m_edgeB.prev=null;j.m_edgeB.next=null;b2Joint.Destroy(j);--this.m_jointCount;if(collideConnected==false){var edge=bodyB.GetContactList();while(edge){if(edge.other==bodyA){edge.contact.FlagForFiltering()}edge=edge.next}}},Step:function(dt,velocityIterations,positionIterations){profile_world_step.start();if(this.m_flags&b2World.e_newFixture){this.m_contactManager.FindNewContacts();this.m_flags&=~b2World.e_newFixture}this.m_flags|=b2World.e_locked;this.p_step.dt=dt;this.p_step.velocityIterations=velocityIterations;this.p_step.positionIterations=positionIterations;if(dt>0){this.p_step.inv_dt=1/dt}else{this.p_step.inv_dt=0}this.p_step.dtRatio=this.m_inv_dt0*dt;this.p_step.warmStarting=this.m_warmStarting;profile_world_collide.start();this.m_contactManager.Collide();profile_world_collide.stop();if(this.m_stepComplete&&this.p_step.dt>0){profile_world_solve.start();this.Solve(this.p_step);profile_world_solve.stop()}if(this.m_continuousPhysics&&this.p_step.dt>0){profile_world_solveTOI.start();this.SolveTOI(this.p_step);profile_world_solveTOI.stop()}if(this.p_step.dt>0){this.m_inv_dt0=this.p_step.inv_dt}if(this.m_flags&b2World.e_clearForces){this.ClearForces()}this.m_flags&=~b2World.e_locked;profile_world_step.stop()},ClearForces:function(){for(var body=this.m_bodyList;body;body=body.GetNext()){body.m_force.x=body.m_force.y=0;body.m_torque=0}},DrawDebugData:function(){if(this.g_debugDraw==null){return}var flags=this.g_debugDraw.GetFlags();if(flags&b2Draw.e_shapeBit){for(var b=this.m_bodyList;b;b=b.GetNext()){var xf=b.GetTransform();for(var f=b.GetFixtureList();f;f=f.GetNext()){if(b.IsActive()==false){this.DrawShape(f,xf,new b2Color(0.5,0.5,0.3))}else{if(b.GetType()==b2Body.b2_staticBody){this.DrawShape(f,xf,new b2Color(0.5,0.9,0.5))}else{if(b.GetType()==b2Body.b2_kinematicBody){this.DrawShape(f,xf,new b2Color(0.5,0.5,0.9))}else{if(b.IsAwake()==false){this.DrawShape(f,xf,new b2Color(0.6,0.6,0.6))}else{this.DrawShape(f,xf,new b2Color(0.9,0.7,0.7))}}}}}}}if(flags&b2Draw.e_jointBit){for(var j=this.m_jointList;j;j=j.GetNext()){this.DrawJoint(j)}}if(flags&b2Draw.e_pairBit){var color=new b2Color(0.3,0.9,0.9);for(var c=this.m_contactManager.m_contactList;c;c=c.GetNext()){var fixtureA=c.GetFixtureA();var fixtureB=c.GetFixtureB();var cA=fixtureA.GetAABB(c.GetChildIndexA()).GetCenter();var cB=fixtureB.GetAABB(c.GetChildIndexB()).GetCenter();this.g_debugDraw.DrawSegment(cA,cB,color)}}if(flags&b2Draw.e_aabbBit){var color=new b2Color(0.9,0.3,0.9);var bp=this.m_contactManager.m_broadPhase;for(var b=this.m_bodyList;b;b=b.GetNext()){if(b.IsActive()==false){continue}for(var f=b.GetFixtureList();f;f=f.GetNext()){for(var i=0;i0){var b=stack[--stackCount];this.p_island.AddBody(b);b.SetAwake(true);if(b.GetType()==b2Body.b2_staticBody){continue}for(var ce=b.m_contactList;ce;ce=ce.next){var contact=ce.contact;if(contact.m_flags&b2Contact.e_islandFlag){continue}if(contact.IsEnabled()==false||contact.IsTouching()==false){continue}var sensorA=contact.m_fixtureA.m_isSensor;var sensorB=contact.m_fixtureB.m_isSensor;if(sensorA||sensorB){continue}this.p_island.AddContact(contact);contact.m_flags|=b2Contact.e_islandFlag;var other=ce.other;if(other.m_flags&b2Body.e_islandFlag){continue}stack[stackCount++]=other;other.m_flags|=b2Body.e_islandFlag}for(var je=b.m_jointList;je;je=je.next){if(je.joint.m_islandFlag==true){continue}var other=je.other;if(other.IsActive()==false){continue}this.p_island.AddJoint(je.joint);je.joint.m_islandFlag=true;if(other.m_flags&b2Body.e_islandFlag){continue}stack[stackCount++]=other;other.m_flags|=b2Body.e_islandFlag}}this.p_island.Solve(step,this.m_gravity,this.m_allowSleep);for(var i=0;ib2_maxSubSteps){continue}var alpha=1;if(c.m_flags&b2Contact.e_toiFlag){alpha=c.m_toi}else{var fA=c.GetFixtureA();var fB=c.GetFixtureB();if(fA.IsSensor()||fB.IsSensor()){continue}var bA=fA.GetBody();var bB=fB.GetBody();var typeA=bA.m_type;var typeB=bB.m_type;var activeA=bA.IsAwake()&&typeA!=b2Body.b2_staticBody;var activeB=bB.IsAwake()&&typeB!=b2Body.b2_staticBody;if(activeA==false&&activeB==false){continue}var collideA=bA.IsBullet()||typeA!=b2Body.b2_dynamicBody;var collideB=bB.IsBullet()||typeB!=b2Body.b2_dynamicBody;if(collideA==false&&collideB==false){continue}var alpha0=bA.m_sweep.alpha0;if(bA.m_sweep.alpha0restitution2?restitution1:restitution2}function b2ContactRegister(){this.fcn=null;this.primary=false}function b2ContactEdge(){this.other=null;this.contact=null;this.prev=null;this.next=null}function b2Contact(){this.m_nodeA=new b2ContactEdge();this.m_nodeB=new b2ContactEdge();this.m_manifold=new b2Manifold()}b2Contact.m_local_tempManifold=new b2Manifold();b2Contact.prototype={Create:function(fA,indexA,fB,indexB){this.m_toi=0;this.m_flags=b2Contact.e_enabledFlag;this.m_fixtureA=fA||null;this.m_fixtureB=fB||null;this.m_indexA=indexA||0;this.m_indexB=indexB||0;this.m_manifold.pointCount=0;this.m_prev=null;this.m_next=null;this.m_nodeA.contact=null;this.m_nodeA.prev=null;this.m_nodeA.next=null;this.m_nodeA.other=null;this.m_nodeB.contact=null;this.m_nodeB.prev=null;this.m_nodeB.next=null;this.m_nodeB.other=null;this.m_toiCount=0;if(fA){this.m_friction=b2MixFriction(this.m_fixtureA.m_friction,this.m_fixtureB.m_friction);this.m_restitution=b2MixRestitution(this.m_fixtureA.m_restitution,this.m_fixtureB.m_restitution)}else{this.m_friction=0;this.m_restitution=0}this.m_tangentSpeed=0},GetManifold:function(){return this.m_manifold},GetWorldManifold:function(worldManifold){var bodyA=this.m_fixtureA.GetBody();var bodyB=this.m_fixtureB.GetBody();var shapeA=this.m_fixtureA.GetShape();var shapeB=this.m_fixtureB.GetShape();worldManifold.Initialize(this.m_manifold,bodyA.GetTransform(),shapeA.m_radius,bodyB.GetTransform(),shapeB.m_radius)},IsTouching:function(){return(this.m_flags&b2Contact.e_touchingFlag)==b2Contact.e_touchingFlag},SetEnabled:function(flag){if(flag){this.m_flags|=b2Contact.e_enabledFlag}else{this.m_flags&=~b2Contact.e_enabledFlag}},IsEnabled:function(){return(this.m_flags&b2Contact.e_enabledFlag)==b2Contact.e_enabledFlag},GetNext:function(){return this.m_next},GetFixtureA:function(){return this.m_fixtureA},GetChildIndexA:function(){return this.m_indexA},GetFixtureB:function(){return this.m_fixtureB},GetChildIndexB:function(){return this.m_indexB},SetFriction:function(friction){this.m_friction=friction},GetFriction:function(){return this.m_friction},ResetFriction:function(){this.m_friction=b2MixFriction(this.m_fixtureA.m_friction,this.m_fixtureB.m_friction)},SetRestitution:function(restitution){this.m_restitution=restitution},GetRestitution:function(){return this.m_restitution},ResetRestitution:function(){this.m_restitution=b2MixRestitution(this.m_fixtureA.m_restitution,this.m_fixtureB.m_restitution)},SetTangentSpeed:function(speed){this.m_tangentSpeed=speed},GetTangentSpeed:function(){return this.m_tangentSpeed},Evaluate:function(manifold,xfA,xfB){},FlagForFiltering:function(){this.m_flags|=b2Contact.e_filterFlag},m_oldManifold:null,Update:function(listener){b2Contact.m_local_tempManifold.Assign(this.m_manifold);this.m_flags|=b2Contact.e_enabledFlag;var touching=false;var wasTouching=(this.m_flags&b2Contact.e_touchingFlag)==b2Contact.e_touchingFlag;var sensorA=this.m_fixtureA.IsSensor();var sensorB=this.m_fixtureB.IsSensor();var sensor=sensorA||sensorB;var bodyA=this.m_fixtureA.GetBody();var bodyB=this.m_fixtureB.GetBody();var xfA=bodyA.GetTransform();var xfB=bodyB.GetTransform();if(sensor){var shapeA=this.m_fixtureA.GetShape();var shapeB=this.m_fixtureB.GetShape();touching=b2TestShapeOverlap(shapeA,this.m_indexA,shapeB,this.m_indexB,xfA,xfB);this.m_manifold.pointCount=0}else{this.Evaluate(this.m_manifold,xfA,xfB);touching=this.m_manifold.pointCount>0;for(var i=0;i0&&fixtureA.IsSensor()==false&&fixtureB.IsSensor()==false){fixtureA.GetBody().SetAwake(true);fixtureB.GetBody().SetAwake(true)}var typeA=fixtureA.GetType();var typeB=fixtureB.GetType();b2Contact.s_registers[typeA][typeB].fcn.garbage.push(contact)};b2Contact.s_registers=[];b2Contact.s_initialized=false;"use strict";var b2_defaultFilter=new b2ContactFilter();var b2_defaultListener=new b2ContactListener();function b2ContactManager(){this.m_broadPhase=new b2BroadPhase();this.m_contactList=null;this.m_contactCount=0;this.m_contactFilter=b2_defaultFilter;this.m_contactListener=b2_defaultListener}b2ContactManager.prototype={AddPair:function(proxyUserDataA,proxyUserDataB){var proxyA=proxyUserDataA;var proxyB=proxyUserDataB;var fixtureA=proxyA.fixture;var fixtureB=proxyB.fixture;var indexA=proxyA.childIndex;var indexB=proxyB.childIndex;var bodyA=fixtureA.GetBody();var bodyB=fixtureB.GetBody();if(bodyA==bodyB){return}var edge=bodyB.GetContactList();while(edge){if(edge.other==bodyA){var fA=edge.contact.GetFixtureA();var fB=edge.contact.GetFixtureB();var iA=edge.contact.GetChildIndexA();var iB=edge.contact.GetChildIndexB();if(fA==fixtureA&&fB==fixtureB&&iA==indexA&&iB==indexB){return}if(fA==fixtureB&&fB==fixtureA&&iA==indexB&&iB==indexA){return}}edge=edge.next}if(bodyB.ShouldCollide(bodyA)==false){return}if(this.m_contactFilter&&this.m_contactFilter.ShouldCollide(fixtureA,fixtureB)==false){return}var c=b2Contact.Create(fixtureA,indexA,fixtureB,indexB);if(c==null){return}fixtureA=c.GetFixtureA();fixtureB=c.GetFixtureB();indexA=c.GetChildIndexA();indexB=c.GetChildIndexB();bodyA=fixtureA.GetBody();bodyB=fixtureB.GetBody();c.m_prev=null;c.m_next=this.m_contactList;if(this.m_contactList!=null){this.m_contactList.m_prev=c}this.m_contactList=c;c.m_nodeA.contact=c;c.m_nodeA.other=bodyB;c.m_nodeA.prev=null;c.m_nodeA.next=bodyA.m_contactList;if(bodyA.m_contactList!=null){bodyA.m_contactList.prev=c.m_nodeA}bodyA.m_contactList=c.m_nodeA;c.m_nodeB.contact=c;c.m_nodeB.other=bodyA;c.m_nodeB.prev=null;c.m_nodeB.next=bodyB.m_contactList;if(bodyB.m_contactList!=null){bodyB.m_contactList.prev=c.m_nodeB}bodyB.m_contactList=c.m_nodeB;if(fixtureA.IsSensor()==false&&fixtureB.IsSensor()==false){bodyA.SetAwake(true);bodyB.SetAwake(true)}++this.m_contactCount},FindNewContacts:function(){this.m_broadPhase.UpdatePairs(this)},Destroy:function(c){var fixtureA=c.GetFixtureA();var fixtureB=c.GetFixtureB();var bodyA=fixtureA.GetBody();var bodyB=fixtureB.GetBody();if(this.m_contactListener&&c.IsTouching()){this.m_contactListener.EndContact(c)}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_contactList){this.m_contactList=c.m_next}if(c.m_nodeA.prev){c.m_nodeA.prev.next=c.m_nodeA.next}if(c.m_nodeA.next){c.m_nodeA.next.prev=c.m_nodeA.prev}if(c.m_nodeA==bodyA.m_contactList){bodyA.m_contactList=c.m_nodeA.next}if(c.m_nodeB.prev){c.m_nodeB.prev.next=c.m_nodeB.next}if(c.m_nodeB.next){c.m_nodeB.next.prev=c.m_nodeB.prev}if(c.m_nodeB==bodyB.m_contactList){bodyB.m_contactList=c.m_nodeB.next}b2Contact.Destroy(c);--this.m_contactCount},Collide:function(){var c=this.m_contactList;while(c){var fixtureA=c.GetFixtureA();var fixtureB=c.GetFixtureB();var indexA=c.GetChildIndexA();var indexB=c.GetChildIndexB();var bodyA=fixtureA.GetBody();var bodyB=fixtureB.GetBody();if(c.m_flags&b2Contact.e_filterFlag){if(bodyB.ShouldCollide(bodyA)==false){var cNuke=c;c=cNuke.GetNext();this.Destroy(cNuke);continue}if(this.m_contactFilter&&this.m_contactFilter.ShouldCollide(fixtureA,fixtureB)==false){var cNuke=c;c=cNuke.GetNext();this.Destroy(cNuke);continue}c.m_flags&=~b2Contact.e_filterFlag}var activeA=bodyA.IsAwake()&&bodyA.m_type!=b2Body.b2_staticBody;var activeB=bodyB.IsAwake()&&bodyB.m_type!=b2Body.b2_staticBody;if(activeA==false&&activeB==false){c=c.GetNext();continue}var proxyIdA=fixtureA.m_proxies[indexA].proxyId;var proxyIdB=fixtureB.m_proxies[indexB].proxyId;var overlap=this.m_broadPhase.TestOverlap(proxyIdA,proxyIdB);if(overlap==false){var cNuke=c;c=cNuke.GetNext();this.Destroy(cNuke);continue}c.Update(this.m_contactListener);c=c.GetNext()}}};function b2VelocityConstraintPoint(){this.rA=new b2Vec2();this.rB=new b2Vec2();this.normalImpulse=0;this.tangentImpulse=0;this.normalMass=0;this.tangentMass=0;this.velocityBias=0}function b2ContactPositionConstraint(){this.localPoints=new Array(b2_maxManifoldPoints);this.localNormal=new b2Vec2();this.localPoint=new b2Vec2();this.indexA=0;this.indexB=0;this.invMassA=0,this.invMassB=0;this.localCenterA=new b2Vec2(),this.localCenterB=new b2Vec2();this.invIA=0,this.invIB=0;this.type=0;this.radiusA=0,this.radiusB=0;this.pointCount=0}function b2ContactVelocityConstraint(){this.points=new Array(b2_maxManifoldPoints);for(var i=0;i0?1/kNormal:0;var tangentx=1*vc.normal.y;var tangenty=-1*vc.normal.x;var rtA=vcp.rA.x*tangenty-vcp.rA.y*tangentx;var rtB=vcp.rB.x*tangenty-vcp.rB.y*tangentx;var kTangent=mA+mB+iA*rtA*rtA+iB*rtB*rtB;vcp.tangentMass=kTangent>0?1/kTangent:0;vcp.velocityBias=0;var vRel=vc.normal.x*(((vB.x+(-wB*vcp.rB.y))-vA.x)-(-wA*vcp.rA.y))+vc.normal.y*(((vB.y+(wB*vcp.rB.x))-vA.y)-(wA*vcp.rA.x));if(vRel<-b2_velocityThreshold){vcp.velocityBias=-vc.restitution*vRel}}if(vc.pointCount==2){var vcp1=vc.points[0];var vcp2=vc.points[1];var rn1A=vcp1.rA.x*vc.normal.y-vcp1.rA.y*vc.normal.x;var rn1B=vcp1.rB.x*vc.normal.y-vcp1.rB.y*vc.normal.x;var rn2A=vcp2.rA.x*vc.normal.y-vcp2.rA.y*vc.normal.x;var rn2B=vcp2.rB.x*vc.normal.y-vcp2.rB.y*vc.normal.x;var k11=mA+mB+iA*rn1A*rn1A+iB*rn1B*rn1B;var k22=mA+mB+iA*rn2A*rn2A+iB*rn2B*rn2B;var k12=mA+mB+iA*rn1A*rn2A+iB*rn1B*rn2B;var k_maxConditionNumber=1000;if(k11*k11=0&&xy>=0){var dx=xx-ax;var dy=xy-ay;var P1x=dx*normal.x;var P1y=dx*normal.y;var P2x=dy*normal.x;var P2y=dy*normal.y;vA.x-=mA*(P1x+P2x);vA.y-=mA*(P1y+P2y);wA-=iA*((cp1.rA.x*P1y-cp1.rA.y*P1x)+(cp2.rA.x*P2y-cp2.rA.y*P2x));vB.x+=mB*(P1x+P2x);vB.y+=mB*(P1y+P2y);wB+=iB*((cp1.rB.x*P1y-cp1.rB.y*P1x)+(cp2.rB.x*P2y-cp2.rB.y*P2x));cp1.normalImpulse=xx;cp2.normalImpulse=xy;break}xx=-cp1.normalMass*bx;xy=0;vn1=0;vn2=vc.K.ex.y*xx+by;if(xx>=0&&vn2>=0){dx=xx-ax;dy=xy-ay;P1x=dx*normal.x;P1y=dx*normal.y;P2x=dy*normal.x;P2y=dy*normal.y;vA.x-=mA*(P1x+P2x);vA.y-=mA*(P1y+P2y);wA-=iA*((cp1.rA.x*P1y-cp1.rA.y*P1x)+(cp2.rA.x*P2y-cp2.rA.y*P2x));vB.x+=mB*(P1x+P2x);vB.y+=mB*(P1y+P2y);wB+=iB*((cp1.rB.x*P1y-cp1.rB.y*P1x)+(cp2.rB.x*P2y-cp2.rB.y*P2x));cp1.normalImpulse=xx;cp2.normalImpulse=xy;break}xx=0;xy=-cp2.normalMass*by;vn1=vc.K.ey.x*xy+bx;vn2=0;if(xy>=0&&vn1>=0){dx=xx-ax;dy=xy-ay;P1x=dx*normal.x;P1y=dx*normal.y;P2x=dy*normal.x;P2y=dy*normal.y;vA.x-=mA*(P1x+P2x);vA.y-=mA*(P1y+P2y);wA-=iA*((cp1.rA.x*P1y-cp1.rA.y*P1x)+(cp2.rA.x*P2y-cp2.rA.y*P2x));vB.x+=mB*(P1x+P2x);vB.y+=mB*(P1y+P2y);wB+=iB*((cp1.rB.x*P1y-cp1.rB.y*P1x)+(cp2.rB.x*P2y-cp2.rB.y*P2x));cp1.normalImpulse=xx;cp2.normalImpulse=xy;break}xx=0;xy=0;vn1=bx;vn2=by;if(vn1>=0&&vn2>=0){dx=xx-ax;dy=xy-ay;P1x=dx*normal.x;P1y=dx*normal.y;P2x=dy*normal.x;P2y=dy*normal.y;vA.x-=mA*(P1x+P2x);vA.y-=mA*(P1y+P2y);wA-=iA*((cp1.rA.x*P1y-cp1.rA.y*P1x)+(cp2.rA.x*P2y-cp2.rA.y*P2x));vB.x+=mB*(P1x+P2x);vB.y+=mB*(P1y+P2y);wB+=iB*((cp1.rB.x*P1y-cp1.rB.y*P1x)+(cp2.rB.x*P2y-cp2.rB.y*P2x));cp1.normalImpulse=xx;cp2.normalImpulse=xy;break}break}}this.m_velocities[indexA].w=wA;this.m_velocities[indexB].w=wB}},StoreImpulses:function(){for(var i=0;i0?-C/K:0;var Px=impulse*normal.x;var Py=impulse*normal.y;cA.x-=mA*Px;cA.y-=mA*Py;aA-=iA*(rAx*Py-rAy*Px);cB.x+=mB*Px;cB.y+=mB*Py;aB+=iB*(rBx*Py-rBy*Px)}this.m_positions[indexA].a=aA;this.m_positions[indexB].a=aB}return minSeparation>=-3*b2_linearSlop},SolveTOIPositionConstraints:function(toiIndexA,toiIndexB){var minSeparation=0;for(var i=0;i0?-C/K:0;var P=b2Vec2.Multiply(impulse,normal);cA.Subtract(b2Vec2.Multiply(mA,P));aA-=iA*b2Cross_v2_v2(rA,P);cB.Add(b2Vec2.Multiply(mB,P));aB+=iB*b2Cross_v2_v2(rB,P)}this.m_positions[indexA].a=aA;this.m_positions[indexB].a=aB}return minSeparation>=-1.5*b2_linearSlop}};"use strict";function b2Island(){this.m_bodies=[];this.m_contacts=[];this.m_joints=[];this.m_velocities=[];this.m_positions=[]}var profile_solve_init=b2Profiler.create("solve initialization","solve");var profile_solve_init_warmStarting=b2Profiler.create("warm starting","solve initialization");var profile_solve_velocity=b2Profiler.create("solve velocities","solve");var profile_solve_position=b2Profiler.create("solve positions","solve");b2Island._solverData=new b2SolverData();b2Island._solverDef=new b2ContactSolverDef();b2Island._solver=new b2ContactSolver();b2Island.prototype={Clear:function(){this.m_bodyCount=0;this.m_contactCount=0;this.m_jointCount=0},Initialize:function(bodyCapacity,contactCapacity,jointCapacity,listener){this.m_listener=listener;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_bodies.length=bodyCapacity;this.m_contacts.length=contactCapacity;this.m_joints.length=jointCapacity;this.m_velocities.length=bodyCapacity;this.m_positions.length=bodyCapacity},Solve:function(step,gravity,allowSleep){profile_solve_init.start();var h=step.dt;for(var i=0;ib2_maxTranslationSquared){var ratio=b2_maxTranslation/b2Sqrt(translationl);v.x*=ratio;v.y*=ratio}var rotation=h*w;if(rotation*rotation>b2_maxRotationSquared){var ratio=b2_maxRotation/b2Abs(rotation);w*=ratio}c.x+=h*v.x;c.y+=h*v.y;a+=h*w;this.m_positions[i].a=a;this.m_velocities[i].w=w}var positionSolved=false;for(var i=0;iangTolSqr||b2Dot_v2_v2(b.m_linearVelocity,b.m_linearVelocity)>linTolSqr){b.m_sleepTime=0;minSleepTime=0}else{b.m_sleepTime+=h;minSleepTime=b2Min(minSleepTime,b.m_sleepTime)}}if(minSleepTime>=b2_timeToSleep&&positionSolved){for(var i=0;ib2_maxTranslationSquared){var ratio=b2_maxTranslation/translation.Length();v.Multiply(ratio)}var rotation=h*w;if(rotation*rotation>b2_maxRotationSquared){var ratio=b2_maxRotation/b2Abs(rotation);w*=ratio}c.Add(b2Vec2.Multiply(h,v));a+=h*w;this.m_positions[i].a=a;this.m_velocities[i].w=w;var body=this.m_bodies[i];body.m_sweep.c.Assign(c);body.m_sweep.a=a;body.m_linearVelocity.Assign(v);body.m_angularVelocity=w;body.SynchronizeTransform()}this.Report(b2Island._solver.m_velocityConstraints)},AddBody:function(body){body.m_islandIndex=this.m_bodyCount;this.m_bodies[this.m_bodyCount]=body;if(!this.m_positions[this.m_bodyCount]){this.m_positions[this.m_bodyCount]=new b2Position();this.m_velocities[this.m_bodyCount]=new b2Velocity()}++this.m_bodyCount},AddContact:function(contact){this.m_contacts[this.m_contactCount++]=contact},AddJoint:function(joint){this.m_joints[this.m_jointCount++]=joint},Report:function(constraints){if(this.m_listener==null){return}for(var i=0;i0){this.m_motorMass=1/this.m_motorMass}if(this.m_enableMotor==false||fixedRotation){this.m_motorImpulse=0}if(this.m_enableLimit&&fixedRotation==false){var jointAngle=aB-aA-this.m_referenceAngle;if(b2Abs(this.m_upperAngle-this.m_lowerAngle)<2*b2_angularSlop){this.m_limitState=b2Joint.e_equalLimits}else{if(jointAngle<=this.m_lowerAngle){if(this.m_limitState!=b2Joint.e_atLowerLimit){this.m_impulse.z=0}this.m_limitState=b2Joint.e_atLowerLimit}else{if(jointAngle>=this.m_upperAngle){if(this.m_limitState!=b2Joint.e_atUpperLimit){this.m_impulse.z=0}this.m_limitState=b2Joint.e_atUpperLimit}else{this.m_limitState=b2Joint.e_inactiveLimit;this.m_impulse.z=0}}}}else{this.m_limitState=b2Joint.e_inactiveLimit}if(data.step.warmStarting){this.m_impulse.Multiply(data.step.dtRatio);this.m_motorImpulse*=data.step.dtRatio;var P=new b2Vec2(this.m_impulse.x,this.m_impulse.y);vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*(b2Cross_v2_v2(this.m_rA,P)+this.m_motorImpulse+this.m_impulse.z);vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*(b2Cross_v2_v2(this.m_rB,P)+this.m_motorImpulse+this.m_impulse.z)}else{this.m_impulse.SetZero();this.m_motorImpulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var fixedRotation=(iA+iB==0);if(this.m_enableMotor&&this.m_limitState!=b2Joint.e_equalLimits&&fixedRotation==false){var Cdot=wB-wA-this.m_motorSpeed;var impulse=-this.m_motorMass*Cdot;var oldImpulse=this.m_motorImpulse;var maxImpulse=data.step.dt*this.m_maxMotorTorque;this.m_motorImpulse=b2Clamp(this.m_motorImpulse+impulse,-maxImpulse,maxImpulse);impulse=this.m_motorImpulse-oldImpulse;wA-=iA*impulse;wB+=iB*impulse}if(this.m_enableLimit&&this.m_limitState!=b2Joint.e_inactiveLimit&&fixedRotation==false){var Cdot1=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB)),vA),b2Cross_f_v2(wA,this.m_rA));var Cdot2=wB-wA;var Cdot=new b2Vec3(Cdot1.x,Cdot1.y,Cdot2);var impulse=this.m_mass.Solve33(Cdot).Negate();if(this.m_limitState==b2Joint.e_equalLimits){this.m_impulse.Add(impulse)}else{if(this.m_limitState==b2Joint.e_atLowerLimit){var newImpulse=this.m_impulse.z+impulse.z;if(newImpulse<0){var rhs=b2Vec2.Add(Cdot1.Negate(),b2Vec2.Multiply(this.m_impulse.z,new b2Vec2(this.m_mass.ez.x,this.m_mass.ez.y)));var reduced=this.m_mass.Solve22(rhs);impulse.x=reduced.x;impulse.y=reduced.y;impulse.z=-this.m_impulse.z;this.m_impulse.x+=reduced.x;this.m_impulse.y+=reduced.y;this.m_impulse.z=0}else{this.m_impulse.Add(impulse)}}else{if(this.m_limitState==b2Joint.e_atUpperLimit){var newImpulse=this.m_impulse.z+impulse.z;if(newImpulse>0){var rhs=b2Vec2.Add(Cdot1.Negate(),b2Vec2.Multiply(this.m_impulse.z,new b2Vec2(this.m_mass.ez.x,this.m_mass.ez.y)));var reduced=this.m_mass.Solve22(rhs);impulse.x=reduced.x;impulse.y=reduced.y;impulse.z=-this.m_impulse.z;this.m_impulse.x+=reduced.x;this.m_impulse.y+=reduced.y;this.m_impulse.z=0}else{this.m_impulse.Add(impulse)}}}}var P=new b2Vec2(impulse.x,impulse.y);vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*(b2Cross_v2_v2(this.m_rA,P)+impulse.z);vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*(b2Cross_v2_v2(this.m_rB,P)+impulse.z)}else{var Cdot=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB)),vA),b2Cross_f_v2(wA,this.m_rA));var impulse=this.m_mass.Solve22(Cdot.Negate());this.m_impulse.x+=impulse.x;this.m_impulse.y+=impulse.y;vA.Subtract(b2Vec2.Multiply(mA,impulse));wA-=iA*b2Cross_v2_v2(this.m_rA,impulse);vB.Add(b2Vec2.Multiply(mB,impulse));wB+=iB*b2Cross_v2_v2(this.m_rB,impulse)}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var qA=new b2Rot(aA),qB=new b2Rot(aB);var angularError=0;var positionError=0;var fixedRotation=(this.m_invIA+this.m_invIB==0);if(this.m_enableLimit&&this.m_limitState!=b2Joint.e_inactiveLimit&&fixedRotation==false){var angle=aB-aA-this.m_referenceAngle;var limitImpulse=0;if(this.m_limitState==b2Joint.e_equalLimits){var C=b2Clamp(angle-this.m_lowerAngle,-b2_maxAngularCorrection,b2_maxAngularCorrection);limitImpulse=-this.m_motorMass*C;angularError=b2Abs(C)}else{if(this.m_limitState==b2Joint.e_atLowerLimit){var C=angle-this.m_lowerAngle;angularError=-C;C=b2Clamp(C+b2_angularSlop,-b2_maxAngularCorrection,0);limitImpulse=-this.m_motorMass*C}else{if(this.m_limitState==b2Joint.e_atUpperLimit){var C=angle-this.m_upperAngle;angularError=C;C=b2Clamp(C-b2_angularSlop,0,b2_maxAngularCorrection);limitImpulse=-this.m_motorMass*C}}}aA-=this.m_invIA*limitImpulse;aB+=this.m_invIB*limitImpulse}qA.Set(aA);qB.Set(aB);var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var C=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,rB),cA),rA);positionError=C.Length();var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var K=new b2Mat22();K.ex.x=mA+mB+iA*rA.y*rA.y+iB*rB.y*rB.y;K.ex.y=-iA*rA.x*rA.y-iB*rB.x*rB.y;K.ey.x=K.ex.y;K.ey.y=mA+mB+iA*rA.x*rA.x+iB*rB.x*rB.x;var impulse=K.Solve(C).Negate();cA.Subtract(b2Vec2.Multiply(mA,impulse));aA-=iA*b2Cross_v2_v2(rA,impulse);cB.Add(b2Vec2.Multiply(mB,impulse));aB+=iB*b2Cross_v2_v2(rB,impulse);data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;return positionError<=b2_linearSlop&&angularError<=b2_angularSlop},_serialize:function(out){var obj=out||{};this.parent.prototype._serialize.call(this,obj);obj.localAnchorA=this.m_localAnchorA._serialize();obj.localAnchorB=this.m_localAnchorB._serialize();obj.referenceAngle=this.m_referenceAngle;obj.lowerAngle=this.m_lowerAngle;obj.upperAngle=this.m_upperAngle;obj.maxMotorTorque=this.m_maxMotorTorque;obj.motorSpeed=this.m_motorSpeed;obj.enableLimit=this.m_enableLimit;obj.enableMotor=this.m_enableMotor;return obj}};b2RevoluteJoint._extend(b2Joint);function b2MouseJointDef(){this.parent.call(this);this.type=b2Joint.e_mouseJoint;this.target=new b2Vec2(0,0);this.maxForce=0;this.frequencyHz=5;this.dampingRatio=0.7;Object.seal(this)}b2MouseJointDef._extend(b2JointDef);function b2MouseJoint(def){this.parent.call(this,def);this.m_targetA=def.target.Clone();this.m_localAnchorB=b2MulT_t_v2(this.m_bodyB.GetTransform(),this.m_targetA);this.m_maxForce=def.maxForce;this.m_impulse=new b2Vec2();this.m_frequencyHz=def.frequencyHz;this.m_dampingRatio=def.dampingRatio;this.m_beta=0;this.m_gamma=0;this.m_indexA=0;this.m_indexB=0;this.m_rB=new b2Vec2();this.m_localCenterB=new b2Vec2();this.m_invMassB=0;this.m_invIB=0;this.m_mass=new b2Mat22();this.m_C=new b2Vec2()}b2MouseJoint.prototype={GetAnchorA:function(){return this.m_targetA},GetAnchorB:function(){return this.m_bodyB.GetWorldPoint(this.m_localAnchorB)},GetReactionForce:function(inv_dt){return b2Vec2.Multiply(inv_dt,this.m_impulse)},GetReactionTorque:function(inv_dt){return inv_dt*0},SetTarget:function(target){if(this.m_bodyB.IsAwake()==false){this.m_bodyB.SetAwake(true)}this.m_targetA.Assign(target)},GetTarget:function(){return this.m_targetA},SetMaxForce:function(force){this.m_maxForce=force},GetMaxForce:function(){return this.m_maxForce},SetFrequency:function(hz){this.m_frequencyHz=hz},GetFrequency:function(){return this.m_frequencyHz},SetDampingRatio:function(ratio){this.m_dampingRatio=ratio},GetDampingRatio:function(){return this.m_dampingRatio},ShiftOrigin:function(newOrigin){this.m_targetA.Subtract(newOrigin)},InitVelocityConstraints:function(data){this.m_indexB=this.m_bodyB.m_islandIndex;this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter);this.m_invMassB=this.m_bodyB.m_invMass;this.m_invIB=this.m_bodyB.m_invI;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var qB=new b2Rot(aB);var mass=this.m_bodyB.GetMass();var omega=2*b2_pi*this.m_frequencyHz;var d=2*mass*this.m_dampingRatio*omega;var k=mass*(omega*omega);var h=data.step.dt;this.m_gamma=h*(d+h*k);if(this.m_gamma!=0){this.m_gamma=1/this.m_gamma}this.m_beta=h*k*this.m_gamma;this.m_rB.Assign(b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB)));var K=new b2Mat22();K.ex.x=this.m_invMassB+this.m_invIB*this.m_rB.y*this.m_rB.y+this.m_gamma;K.ex.y=-this.m_invIB*this.m_rB.x*this.m_rB.y;K.ey.x=K.ex.y;K.ey.y=this.m_invMassB+this.m_invIB*this.m_rB.x*this.m_rB.x+this.m_gamma;this.m_mass.Assign(K.GetInverse());this.m_C.Assign(b2Vec2.Subtract(b2Vec2.Add(cB,this.m_rB),this.m_targetA));this.m_C.Multiply(this.m_beta);wB*=0.98;if(data.step.warmStarting){this.m_impulse.Multiply(data.step.dtRatio);vB.Add(b2Vec2.Multiply(this.m_invMassB,this.m_impulse));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,this.m_impulse)}else{this.m_impulse.SetZero()}data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var Cdot=b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB));var impulse=b2Mul_m22_v2(this.m_mass,(b2Vec2.Add(b2Vec2.Add(Cdot,this.m_C),b2Vec2.Multiply(this.m_gamma,this.m_impulse))).Negate());var oldImpulse=this.m_impulse.Clone();this.m_impulse.Add(impulse);var maxImpulse=data.step.dt*this.m_maxForce;if(this.m_impulse.LengthSquared()>maxImpulse*maxImpulse){this.m_impulse.Multiply(maxImpulse/this.m_impulse.Length())}impulse.Assign(b2Vec2.Subtract(this.m_impulse,oldImpulse));vB.Add(b2Vec2.Multiply(this.m_invMassB,impulse));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,impulse);data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){return true}};b2MouseJoint._extend(b2Joint);function b2DistanceJointDef(){this.parent.call(this);this.type=b2Joint.e_distanceJoint;this.localAnchorA=new b2Vec2(0,0);this.localAnchorB=new b2Vec2(0,0);this.length=1;this.frequencyHz=0;this.dampingRatio=0;Object.seal(this)}b2DistanceJointDef.prototype={Initialize:function(b1,b2,anchor1,anchor2){this.bodyA=b1;this.bodyB=b2;this.localAnchorA=this.bodyA.GetLocalPoint(anchor1);this.localAnchorB=this.bodyB.GetLocalPoint(anchor2);var d=b2Vec2.Subtract(anchor2,anchor1);this.length=d.Length()},_deserialize:function(data,bodies,joints){this.parent.prototype._deserialize.call(this,data,bodies,joints);this.localAnchorA._deserialize(data.localAnchorA);this.localAnchorB._deserialize(data.localAnchorB);this.length=data.length;this.frequencyHz=data.frequencyHz;this.dampingRatio=data.dampingRatio}};b2DistanceJointDef._extend(b2JointDef);function b2DistanceJoint(def){this.parent.call(this,def);this.m_localAnchorA=def.localAnchorA.Clone();this.m_localAnchorB=def.localAnchorB.Clone();this.m_length=def.length;this.m_frequencyHz=def.frequencyHz;this.m_dampingRatio=def.dampingRatio;this.m_impulse=0;this.m_gamma=0;this.m_bias=0;this.m_indexA=0;this.m_indexB=0;this.m_u=new b2Vec2();this.m_rA=new b2Vec2();this.m_rB=new b2Vec2();this.m_localCenterA=new b2Vec2();this.m_localCenterB=new b2Vec2();this.m_invMassA=0;this.m_invMassB=0;this.m_invIA=0;this.m_invIB=0;this.m_mass=0}b2DistanceJoint.prototype={GetAnchorA:function(){return this.m_bodyA.GetWorldPoint(this.m_localAnchorA)},GetAnchorB:function(){return this.m_bodyB.GetWorldPoint(this.m_localAnchorB)},GetReactionForce:function(inv_dt){var F=b2Vec2.Multiply((inv_dt*this.m_impulse),this.m_u);return F},GetReactionTorque:function(inv_dt){return 0},GetLocalAnchorA:function(){return this.m_localAnchorA},GetLocalAnchorB:function(){return this.m_localAnchorB},SetLength:function(length){this.m_length=length},GetLength:function(){return this.m_length},SetFrequency:function(hz){this.m_frequencyHz=hz},GetFrequency:function(){return this.m_frequencyHz},SetDampingRatio:function(ratio){this.m_dampingRatio=ratio},GetDampingRatio:function(){return this.m_dampingRatio},InitVelocityConstraints:function(data){this.m_indexA=this.m_bodyA.m_islandIndex;this.m_indexB=this.m_bodyB.m_islandIndex;this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter);this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter);this.m_invMassA=this.m_bodyA.m_invMass;this.m_invMassB=this.m_bodyB.m_invMass;this.m_invIA=this.m_bodyA.m_invI;this.m_invIB=this.m_bodyB.m_invI;var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var qA=new b2Rot(aA),qB=new b2Rot(aB);this.m_rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));this.m_rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));this.m_u=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,this.m_rB),cA),this.m_rA);var length=this.m_u.Length();if(length>b2_linearSlop){this.m_u.Multiply(1/length)}else{this.m_u.Set(0,0)}var crAu=b2Cross_v2_v2(this.m_rA,this.m_u);var crBu=b2Cross_v2_v2(this.m_rB,this.m_u);var invMass=this.m_invMassA+this.m_invIA*crAu*crAu+this.m_invMassB+this.m_invIB*crBu*crBu;this.m_mass=invMass!=0?1/invMass:0;if(this.m_frequencyHz>0){var C=length-this.m_length;var omega=2*b2_pi*this.m_frequencyHz;var d=2*this.m_mass*this.m_dampingRatio*omega;var k=this.m_mass*omega*omega;var h=data.step.dt;this.m_gamma=h*(d+h*k);this.m_gamma=this.m_gamma!=0?1/this.m_gamma:0;this.m_bias=C*h*k*this.m_gamma;invMass+=this.m_gamma;this.m_mass=invMass!=0?1/invMass:0}else{this.m_gamma=0;this.m_bias=0}if(data.step.warmStarting){this.m_impulse*=data.step.dtRatio;var P=b2Vec2.Multiply(this.m_impulse,this.m_u);vA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));wA-=this.m_invIA*b2Cross_v2_v2(this.m_rA,P);vB.Add(b2Vec2.Multiply(this.m_invMassB,P));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,P)}else{this.m_impulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var vpA=b2Vec2.Add(vA,b2Cross_f_v2(wA,this.m_rA));var vpB=b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB));var Cdot=b2Dot_v2_v2(this.m_u,b2Vec2.Subtract(vpB,vpA));var impulse=-this.m_mass*(Cdot+this.m_bias+this.m_gamma*this.m_impulse);this.m_impulse+=impulse;var P=b2Vec2.Multiply(impulse,this.m_u);vA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));wA-=this.m_invIA*b2Cross_v2_v2(this.m_rA,P);vB.Add(b2Vec2.Multiply(this.m_invMassB,P));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,P);data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){if(this.m_frequencyHz>0){return true}var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var qA=new b2Rot(aA),qB=new b2Rot(aB);var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var u=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,rB),cA),rA);var length=u.Normalize();var C=length-this.m_length;C=b2Clamp(C,-b2_maxLinearCorrection,b2_maxLinearCorrection);var impulse=-this.m_mass*C;var P=b2Vec2.Multiply(impulse,u);cA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));aA-=this.m_invIA*b2Cross_v2_v2(rA,P);cB.Add(b2Vec2.Multiply(this.m_invMassB,P));aB+=this.m_invIB*b2Cross_v2_v2(rB,P);data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;return b2Abs(C)0){this.m_motorMass=1/this.m_motorMass}this.m_perp=b2Mul_r_v2(qA,this.m_localYAxisA);this.m_s1=b2Cross_v2_v2(b2Vec2.Add(d,rA),this.m_perp);this.m_s2=b2Cross_v2_v2(rB,this.m_perp);var k11=mA+mB+iA*this.m_s1*this.m_s1+iB*this.m_s2*this.m_s2;var k12=iA*this.m_s1+iB*this.m_s2;var k13=iA*this.m_s1*this.m_a1+iB*this.m_s2*this.m_a2;var k22=iA+iB;if(k22==0){k22=1}var k23=iA*this.m_a1+iB*this.m_a2;var k33=mA+mB+iA*this.m_a1*this.m_a1+iB*this.m_a2*this.m_a2;this.m_K.ex.Set(k11,k12,k13);this.m_K.ey.Set(k12,k22,k23);this.m_K.ez.Set(k13,k23,k33);if(this.m_enableLimit){var jointTranslation=b2Dot_v2_v2(this.m_axis,d);if(b2Abs(this.m_upperTranslation-this.m_lowerTranslation)<2*b2_linearSlop){this.m_limitState=b2Joint.e_equalLimits}else{if(jointTranslation<=this.m_lowerTranslation){if(this.m_limitState!=b2Joint.e_atLowerLimit){this.m_limitState=b2Joint.e_atLowerLimit;this.m_impulse.z=0}}else{if(jointTranslation>=this.m_upperTranslation){if(this.m_limitState!=b2Joint.e_atUpperLimit){this.m_limitState=b2Joint.e_atUpperLimit;this.m_impulse.z=0}}else{this.m_limitState=b2Joint.e_inactiveLimit;this.m_impulse.z=0}}}}else{this.m_limitState=b2Joint.e_inactiveLimit;this.m_impulse.z=0}if(this.m_enableMotor==false){this.m_motorImpulse=0}if(data.step.warmStarting){this.m_impulse.Multiply(data.step.dtRatio);this.m_motorImpulse*=data.step.dtRatio;var P=b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x,this.m_perp),b2Vec2.Multiply((this.m_motorImpulse+this.m_impulse.z),this.m_axis));var LA=this.m_impulse.x*this.m_s1+this.m_impulse.y+(this.m_motorImpulse+this.m_impulse.z)*this.m_a1;var LB=this.m_impulse.x*this.m_s2+this.m_impulse.y+(this.m_motorImpulse+this.m_impulse.z)*this.m_a2;vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*LA;vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*LB}else{this.m_impulse.SetZero();this.m_motorImpulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;if(this.m_enableMotor&&this.m_limitState!=b2Joint.e_equalLimits){var Cdot=b2Dot_v2_v2(this.m_axis,b2Vec2.Subtract(vB,vA))+this.m_a2*wB-this.m_a1*wA;var impulse=this.m_motorMass*(this.m_motorSpeed-Cdot);var oldImpulse=this.m_motorImpulse;var maxImpulse=data.step.dt*this.m_maxMotorForce;this.m_motorImpulse=b2Clamp(this.m_motorImpulse+impulse,-maxImpulse,maxImpulse);impulse=this.m_motorImpulse-oldImpulse;var P=b2Vec2.Multiply(impulse,this.m_axis);var LA=impulse*this.m_a1;var LB=impulse*this.m_a2;vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*LA;vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*LB}var Cdot1=new b2Vec2();Cdot1.x=b2Dot_v2_v2(this.m_perp,b2Vec2.Subtract(vB,vA))+this.m_s2*wB-this.m_s1*wA;Cdot1.y=wB-wA;if(this.m_enableLimit&&this.m_limitState!=b2Joint.e_inactiveLimit){var Cdot2;Cdot2=b2Dot_v2_v2(this.m_axis,b2Vec2.Subtract(vB,vA))+this.m_a2*wB-this.m_a1*wA;var Cdot=new b2Vec3(Cdot1.x,Cdot1.y,Cdot2);var f1=this.m_impulse.Clone();var df=this.m_K.Solve33(Cdot.Negate());this.m_impulse.Add(df);if(this.m_limitState==b2Joint.e_atLowerLimit){this.m_impulse.z=b2Max(this.m_impulse.z,0)}else{if(this.m_limitState==b2Joint.e_atUpperLimit){this.m_impulse.z=b2Min(this.m_impulse.z,0)}}var b=b2Vec2.Subtract(Cdot1.Negate(),b2Vec2.Multiply((this.m_impulse.z-f1.z),new b2Vec2(this.m_K.ez.x,this.m_K.ez.y)));var f2r=b2Vec2.Add(this.m_K.Solve22(b),new b2Vec2(f1.x,f1.y));this.m_impulse.x=f2r.x;this.m_impulse.y=f2r.y;df=b2Vec3.Subtract(this.m_impulse,f1);var P=b2Vec2.Add(b2Vec2.Multiply(df.x,this.m_perp),b2Vec2.Multiply(df.z,this.m_axis));var LA=df.x*this.m_s1+df.y+df.z*this.m_a1;var LB=df.x*this.m_s2+df.y+df.z*this.m_a2;vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*LA;vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*LB}else{var df=this.m_K.Solve22(Cdot1.Negate());this.m_impulse.x+=df.x;this.m_impulse.y+=df.y;var P=b2Vec2.Multiply(df.x,this.m_perp);var LA=df.x*this.m_s1+df.y;var LB=df.x*this.m_s2+df.y;vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*LA;vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*LB}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var qA=new b2Rot(aA),qB=new b2Rot(aB);var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var d=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,rB),cA),rA);var axis=b2Mul_r_v2(qA,this.m_localXAxisA);var a1=b2Cross_v2_v2(b2Vec2.Add(d,rA),axis);var a2=b2Cross_v2_v2(rB,axis);var perp=b2Mul_r_v2(qA,this.m_localYAxisA);var s1=b2Cross_v2_v2(b2Vec2.Add(d,rA),perp);var s2=b2Cross_v2_v2(rB,perp);var impulse=new b2Vec3();var C1=new b2Vec2();C1.x=b2Dot_v2_v2(perp,d);C1.y=aB-aA-this.m_referenceAngle;var linearError=b2Abs(C1.x);var angularError=b2Abs(C1.y);var active=false;var C2=0;if(this.m_enableLimit){var translation=b2Dot_v2_v2(axis,d);if(b2Abs(this.m_upperTranslation-this.m_lowerTranslation)<2*b2_linearSlop){C2=b2Clamp(translation,-b2_maxLinearCorrection,b2_maxLinearCorrection);linearError=b2Max(linearError,b2Abs(translation));active=true}else{if(translation<=this.m_lowerTranslation){C2=b2Clamp(translation-this.m_lowerTranslation+b2_linearSlop,-b2_maxLinearCorrection,0);linearError=b2Max(linearError,this.m_lowerTranslation-translation);active=true}else{if(translation>=this.m_upperTranslation){C2=b2Clamp(translation-this.m_upperTranslation-b2_linearSlop,0,b2_maxLinearCorrection);linearError=b2Max(linearError,translation-this.m_upperTranslation);active=true}}}}if(active){var k11=mA+mB+iA*s1*s1+iB*s2*s2;var k12=iA*s1+iB*s2;var k13=iA*s1*a1+iB*s2*a2;var k22=iA+iB;if(k22==0){k22=1}var k23=iA*a1+iB*a2;var k33=mA+mB+iA*a1*a1+iB*a2*a2;var K=new b2Mat33();K.ex.Set(k11,k12,k13);K.ey.Set(k12,k22,k23);K.ez.Set(k13,k23,k33);var C=new b2Vec3();C.x=C1.x;C.y=C1.y;C.z=C2;impulse=K.Solve33(C.Negate())}else{var k11=mA+mB+iA*s1*s1+iB*s2*s2;var k12=iA*s1+iB*s2;var k22=iA+iB;if(k22==0){k22=1}var K=new b2Mat22();K.ex.Set(k11,k12);K.ey.Set(k12,k22);var impulse1=K.Solve(C1.Negate());impulse.x=impulse1.x;impulse.y=impulse1.y;impulse.z=0}var P=b2Vec2.Add(b2Vec2.Multiply(impulse.x,perp),b2Vec2.Multiply(impulse.z,axis));var LA=impulse.x*s1+impulse.y+impulse.z*a1;var LB=impulse.x*s2+impulse.y+impulse.z*a2;cA.Subtract(b2Vec2.Multiply(mA,P));aA-=iA*LA;cB.Add(b2Vec2.Multiply(mB,P));aB+=iB*LB;data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;return linearError<=b2_linearSlop&&angularError<=b2_angularSlop},_serialize:function(out){var obj=out||{};this.parent.prototype._serialize.call(this,obj);obj.localAnchorA=this.m_localAnchorA._serialize();obj.localAnchorB=this.m_localAnchorB._serialize();obj.localAxisA=this.m_localXAxisA._serialize();obj.referenceAngle=this.m_referenceAngle;obj.enableLimit=this.m_enableLimit;obj.lowerTranslation=this.m_lowerTranslation;obj.upperTranslation=this.m_upperTranslation;obj.enableMotor=this.m_enableMotor;obj.maxMotorForce=this.m_maxMotorForce;obj.motorSpeed=this.m_motorSpeed;return obj}};b2PrismaticJoint._extend(b2Joint);function b2FrictionJointDef(){this.parent.call(this);this.type=b2Joint.e_frictionJoint;this.localAnchorA=new b2Vec2();this.localAnchorB=new b2Vec2();this.maxForce=0;this.maxTorque=0;Object.seal(this)}b2FrictionJointDef.prototype={Initialize:function(bA,bB,anchor){this.bodyA=bA;this.bodyB=bB;this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor));this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor))},_deserialize:function(data,bodies,joints){this.parent.prototype._deserialize.call(this,data,bodies,joints);this.localAnchorA._deserialize(data.localAnchorA);this.localAnchorB._deserialize(data.localAnchorB);this.maxForce=data.maxForce;this.maxTorque=data.maxTorque}};b2FrictionJointDef._extend(b2JointDef);function b2FrictionJoint(def){this.parent.call(this,def);this.m_localAnchorA=def.localAnchorA.Clone();this.m_localAnchorB=def.localAnchorB.Clone();this.m_linearImpulse=new b2Vec2();this.m_angularImpulse=0;this.m_maxForce=def.maxForce;this.m_maxTorque=def.maxTorque;this.m_indexA=0;this.m_indexB=0;this.m_rA=new b2Vec2();this.m_rB=new b2Vec2();this.m_localCenterA=new b2Vec2();this.m_localCenterB=new b2Vec2();this.m_invMassA=0;this.m_invMassB=0;this.m_invIA=0;this.m_invIB=0;this.m_linearMass=new b2Mat22();this.m_angularMass=0}b2FrictionJoint.prototype={GetAnchorA:function(){return this.m_bodyA.GetWorldPoint(this.m_localAnchorA)},GetAnchorB:function(){return this.m_bodyB.GetWorldPoint(this.m_localAnchorB)},GetReactionForce:function(inv_dt){return b2Vec2.Multiply(inv_dt,this.m_linearImpulse)},GetReactionTorque:function(inv_dt){return inv_dt*this.m_angularImpulse},GetLocalAnchorA:function(){return this.m_localAnchorA},GetLocalAnchorB:function(){return this.m_localAnchorB},SetMaxForce:function(force){this.m_maxForce=force},GetMaxForce:function(){return this.m_maxForce},SetMaxTorque:function(torque){this.m_maxTorque=torque},GetMaxTorque:function(){return this.m_maxTorque},InitVelocityConstraints:function(data){this.m_indexA=this.m_bodyA.m_islandIndex;this.m_indexB=this.m_bodyB.m_islandIndex;this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter);this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter);this.m_invMassA=this.m_bodyA.m_invMass;this.m_invMassB=this.m_bodyB.m_invMass;this.m_invIA=this.m_bodyA.m_invI;this.m_invIB=this.m_bodyB.m_invI;var aA=data.positions[this.m_indexA].a;var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var aB=data.positions[this.m_indexB].a;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var qA=new b2Rot(aA),qB=new b2Rot(aB);this.m_rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));this.m_rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var K=new b2Mat22();K.ex.x=mA+mB+iA*this.m_rA.y*this.m_rA.y+iB*this.m_rB.y*this.m_rB.y;K.ex.y=-iA*this.m_rA.x*this.m_rA.y-iB*this.m_rB.x*this.m_rB.y;K.ey.x=K.ex.y;K.ey.y=mA+mB+iA*this.m_rA.x*this.m_rA.x+iB*this.m_rB.x*this.m_rB.x;this.m_linearMass=K.GetInverse();this.m_angularMass=iA+iB;if(this.m_angularMass>0){this.m_angularMass=1/this.m_angularMass}if(data.step.warmStarting){this.m_linearImpulse.Multiply(data.step.dtRatio);this.m_angularImpulse*=data.step.dtRatio;var P=new b2Vec2(this.m_linearImpulse.x,this.m_linearImpulse.y);vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*(b2Cross_v2_v2(this.m_rA,P)+this.m_angularImpulse);vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*(b2Cross_v2_v2(this.m_rB,P)+this.m_angularImpulse)}else{this.m_linearImpulse.SetZero();this.m_angularImpulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var h=data.step.dt;var Cdot=wB-wA;var impulse=-this.m_angularMass*Cdot;var oldImpulse=this.m_angularImpulse;var maxImpulse=h*this.m_maxTorque;this.m_angularImpulse=b2Clamp(this.m_angularImpulse+impulse,-maxImpulse,maxImpulse);impulse=this.m_angularImpulse-oldImpulse;wA-=iA*impulse;wB+=iB*impulse;var Cdot=b2Vec2.Add(vB,b2Vec2.Subtract(b2Cross_f_v2(wB,this.m_rB),b2Vec2.Subtract(vA,b2Cross_f_v2(wA,this.m_rA))));var impulse=b2Mul_m22_v2(this.m_linearMass,Cdot).Negate();var oldImpulse=this.m_linearImpulse.Clone();this.m_linearImpulse.Add(impulse);var maxImpulse=h*this.m_maxForce;if(this.m_linearImpulse.LengthSquared()>maxImpulse*maxImpulse){this.m_linearImpulse.Normalize();this.m_linearImpulse.Multiply(maxImpulse)}impulse=b2Vec2.Subtract(this.m_linearImpulse,oldImpulse);vA.Subtract(b2Vec2.Multiply(mA,impulse));wA-=iA*b2Cross_v2_v2(this.m_rA,impulse);vB.Add(b2Vec2.Multiply(mB,impulse));wB+=iB*b2Cross_v2_v2(this.m_rB,impulse);data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){return true},_serialize:function(out){var obj=out||{};this.parent.prototype._serialize.call(this,obj);obj.localAnchorA=this.m_localAnchorA._serialize();obj.localAnchorB=this.m_localAnchorB._serialize();obj.maxForce=this.m_maxForce;obj.maxTorque=this.m_maxTorque;return obj}};b2FrictionJoint._extend(b2Joint);function b2WeldJointDef(){this.parent.call(this);this.type=b2Joint.e_weldJoint;this.localAnchorA=new b2Vec2(0,0);this.localAnchorB=new b2Vec2(0,0);this.referenceAngle=0;this.frequencyHz=0;this.dampingRatio=0;Object.seal(this)}b2WeldJointDef.prototype={Initialize:function(bA,bB,anchor){this.bodyA=bA;this.bodyB=bB;this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor));this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor));this.referenceAngle=this.bodyB.GetAngle()-this.bodyA.GetAngle()},_deserialize:function(data,bodies,joints){this.parent.prototype._deserialize.call(this,data,bodies,joints);this.localAnchorA._deserialize(data.localAnchorA);this.localAnchorB._deserialize(data.localAnchorB);this.referenceAngle=data.referenceAngle;this.frequencyHz=data.frequencyHz;this.dampingRatio=data.dampingRatio}};b2WeldJointDef._extend(b2JointDef);function b2WeldJoint(def){this.parent.call(this,def);this.m_bias=0;this.m_gamma=0;this.m_indexA=0;this.m_indexB=0;this.m_rA=new b2Vec2();this.m_rB=new b2Vec2();this.m_localCenterA=new b2Vec2();this.m_localCenterB=new b2Vec2();this.m_invMassA=0;this.m_invMassB=0;this.m_invIA=0;this.m_invIB=0;this.m_mass=new b2Mat33();this.m_localAnchorA=def.localAnchorA.Clone();this.m_localAnchorB=def.localAnchorB.Clone();this.m_referenceAngle=def.referenceAngle;this.m_frequencyHz=def.frequencyHz;this.m_dampingRatio=def.dampingRatio;this.m_impulse=new b2Vec3()}b2WeldJoint.prototype={GetAnchorA:function(){return this.m_bodyA.GetWorldPoint(this.m_localAnchorA)},GetAnchorB:function(){return this.m_bodyB.GetWorldPoint(this.m_localAnchorB)},GetReactionForce:function(inv_dt){var P=new b2Vec2(this.m_impulse.x,this.m_impulse.y);return b2Vec2.Multiply(inv_dt,P)},GetReactionTorque:function(inv_dt){return inv_dt*this.m_impulse.z},GetLocalAnchorA:function(){return this.m_localAnchorA},GetLocalAnchorB:function(){return this.m_localAnchorB},GetReferenceAngle:function(){return this.m_referenceAngle},SetFrequency:function(hz){this.m_frequencyHz=hz},GetFrequency:function(){return this.m_frequencyHz},SetDampingRatio:function(ratio){this.m_dampingRatio=ratio},GetDampingRatio:function(){return this.m_dampingRatio},InitVelocityConstraints:function(data){this.m_indexA=this.m_bodyA.m_islandIndex;this.m_indexB=this.m_bodyB.m_islandIndex;this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter);this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter);this.m_invMassA=this.m_bodyA.m_invMass;this.m_invMassB=this.m_bodyB.m_invMass;this.m_invIA=this.m_bodyA.m_invI;this.m_invIB=this.m_bodyB.m_invI;var aA=data.positions[this.m_indexA].a;var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var aB=data.positions[this.m_indexB].a;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var qA=new b2Rot(aA),qB=new b2Rot(aB);this.m_rA.Assign(b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA)));this.m_rB.Assign(b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB)));var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var K=new b2Mat33();K.ex.x=mA+mB+this.m_rA.y*this.m_rA.y*iA+this.m_rB.y*this.m_rB.y*iB;K.ey.x=-this.m_rA.y*this.m_rA.x*iA-this.m_rB.y*this.m_rB.x*iB;K.ez.x=-this.m_rA.y*iA-this.m_rB.y*iB;K.ex.y=K.ey.x;K.ey.y=mA+mB+this.m_rA.x*this.m_rA.x*iA+this.m_rB.x*this.m_rB.x*iB;K.ez.y=this.m_rA.x*iA+this.m_rB.x*iB;K.ex.z=K.ez.x;K.ey.z=K.ez.y;K.ez.z=iA+iB;if(this.m_frequencyHz>0){K.GetInverse22(this.m_mass);var invM=iA+iB;var m=invM>0?1/invM:0;var C=aB-aA-this.m_referenceAngle;var omega=2*b2_pi*this.m_frequencyHz;var d=2*m*this.m_dampingRatio*omega;var k=m*omega*omega;var h=data.step.dt;this.m_gamma=h*(d+h*k);this.m_gamma=this.m_gamma!=0?1/this.m_gamma:0;this.m_bias=C*h*k*this.m_gamma;invM+=this.m_gamma;this.m_mass.ez.z=invM!=0?1/invM:0}else{K.GetSymInverse33(this.m_mass);this.m_gamma=0;this.m_bias=0}if(data.step.warmStarting){this.m_impulse.Multiply(data.step.dtRatio);var P=new b2Vec2(this.m_impulse.x,this.m_impulse.y);vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*(b2Cross_v2_v2(this.m_rA,P)+this.m_impulse.z);vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*(b2Cross_v2_v2(this.m_rB,P)+this.m_impulse.z)}else{this.m_impulse.SetZero()}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;if(this.m_frequencyHz>0){var Cdot2=wB-wA;var impulse2=-this.m_mass.ez.z*(Cdot2+this.m_bias+this.m_gamma*this.m_impulse.z);this.m_impulse.z+=impulse2;wA-=iA*impulse2;wB+=iB*impulse2;var Cdot1=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB)),vA),b2Cross_f_v2(wA,this.m_rA));var impulse1=b2Mul22_m33_v2(this.m_mass,Cdot1).Negate();this.m_impulse.x+=impulse1.x;this.m_impulse.y+=impulse1.y;var P=impulse1.Clone();vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*b2Cross_v2_v2(this.m_rA,P);vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*b2Cross_v2_v2(this.m_rB,P)}else{var Cdot1=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB)),vA),b2Cross_f_v2(wA,this.m_rA));var Cdot2=wB-wA;var Cdot=new b2Vec3(Cdot1.x,Cdot1.y,Cdot2);var impulse=b2Mul_m33_v3(this.m_mass,Cdot).Negate();this.m_impulse.Add(impulse);var P=new b2Vec2(impulse.x,impulse.y);vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*(b2Cross_v2_v2(this.m_rA,P)+impulse.z);vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*(b2Cross_v2_v2(this.m_rB,P)+impulse.z)}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var qA=new b2Rot(aA),qB=new b2Rot(aB);var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var positionError,angularError;var K=new b2Mat33();K.ex.x=mA+mB+rA.y*rA.y*iA+rB.y*rB.y*iB;K.ey.x=-rA.y*rA.x*iA-rB.y*rB.x*iB;K.ez.x=-rA.y*iA-rB.y*iB;K.ex.y=K.ey.x;K.ey.y=mA+mB+rA.x*rA.x*iA+rB.x*rB.x*iB;K.ez.y=rA.x*iA+rB.x*iB;K.ex.z=K.ez.x;K.ey.z=K.ez.y;K.ez.z=iA+iB;if(this.m_frequencyHz>0){var C1=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,rB),cA),rA);positionError=C1.Length();angularError=0;var P=K.Solve22(C1).Negate();cA.Subtract(b2Vec2.Multiply(mA,P));aA-=iA*b2Cross_v2_v2(rA,P);cB.Add(b2Vec2.Multiply(mB,P));aB+=iB*b2Cross_v2_v2(rB,P)}else{var C1=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,rB),cA),rA);var C2=aB-aA-this.m_referenceAngle;positionError=C1.Length();angularError=b2Abs(C2);var C=new b2Vec3(C1.x,C1.y,C2);var impulse=K.Solve33(C).Negate();var P=new b2Vec2(impulse.x,impulse.y);cA.Subtract(b2Vec2.Multiply(mA,P));aA-=iA*(b2Cross_v2_v2(rA,P)+impulse.z);cB.Add(b2Vec2.Multiply(mB,P));aB+=iB*(b2Cross_v2_v2(rB,P)+impulse.z)}data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;return positionError<=b2_linearSlop&&angularError<=b2_angularSlop},_serialize:function(out){var obj=out||{};this.parent.prototype._serialize.call(this,obj);obj.localAnchorA=this.m_localAnchorA._serialize();obj.localAnchorB=this.m_localAnchorB._serialize();obj.referenceAngle=this.m_referenceAngle;obj.frequencyHz=this.m_frequencyHz;obj.dampingRatio=this.m_dampingRatio;return obj}};b2WeldJoint._extend(b2Joint);function b2WheelJointDef(){this.parent.call(this);this.type=b2Joint.e_wheelJoint;this.localAnchorA=new b2Vec2();this.localAnchorB=new b2Vec2();this.localAxisA=new b2Vec2(1,0);this.enableMotor=false;this.maxMotorTorque=0;this.motorSpeed=0;this.frequencyHz=2;this.dampingRatio=0.7;Object.seal(this)}b2WheelJointDef.prototype={Initialize:function(bA,bB,anchor,axis){this.bodyA=bA;this.bodyB=bB;this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor));this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor));this.localAxisA.Assign(this.bodyA.GetLocalVector(axis))},_deserialize:function(data,bodies,joints){this.parent.prototype._deserialize.call(this,data,bodies,joints);this.localAnchorA._deserialize(data.localAnchorA);this.localAnchorB._deserialize(data.localAnchorB);this.localAxisA._deserialize(data.localAxisA);this.enableMotor=data.enableMotor;this.maxMotorTorque=data.maxMotorTorque;this.motorSpeed=data.motorSpeed;this.frequencyHz=data.frequencyHz;this.dampingRatio=data.dampingRatio}};b2WheelJointDef._extend(b2JointDef);function b2WheelJoint(def){this.parent.call(this,def);this.m_indexA=0;this.m_indexB=0;this.m_localCenterA=new b2Vec2();this.m_localCenterB=new b2Vec2();this.m_invMassA=0;this.m_invMassB=0;this.m_invIA=0;this.m_invIB=0;this.m_localAnchorA=def.localAnchorA.Clone();this.m_localAnchorB=def.localAnchorB.Clone();this.m_localXAxisA=def.localAxisA.Clone();this.m_localYAxisA=b2Cross_f_v2(1,this.m_localXAxisA);this.m_mass=0;this.m_impulse=0;this.m_motorMass=0;this.m_motorImpulse=0;this.m_springMass=0;this.m_springImpulse=0;this.m_maxMotorTorque=def.maxMotorTorque;this.m_motorSpeed=def.motorSpeed;this.m_enableMotor=def.enableMotor;this.m_frequencyHz=def.frequencyHz;this.m_dampingRatio=def.dampingRatio;this.m_bias=0;this.m_gamma=0;this.m_ax=new b2Vec2();this.m_ay=new b2Vec2();this.m_sAx=this.m_sBx=0;this.m_sAy=this.m_sBy=0}b2WheelJoint.prototype={GetAnchorA:function(){return this.m_bodyA.GetWorldPoint(this.m_localAnchorA)},GetAnchorB:function(){return this.m_bodyB.GetWorldPoint(this.m_localAnchorB)},GetReactionForce:function(inv_dt){return b2Vec2.Multiply(inv_dt,b2Vec2.Add(b2Vec2.Multiply(this.m_impulse,this.m_ay),b2Vec2.Multiply(this.m_springImpulse,this.m_ax)))},GetReactionTorque:function(inv_dt){return inv_dt*this.m_motorImpulse},GetLocalAnchorA:function(){return this.m_localAnchorA},GetLocalAnchorB:function(){return this.m_localAnchorB},GetLocalAxisA:function(){return this.m_localXAxisA},GetJointTranslation:function(){var bA=this.m_bodyA;var bB=this.m_bodyB;var pA=bA.GetWorldPoint(this.m_localAnchorA);var pB=bB.GetWorldPoint(this.m_localAnchorB);var d=b2Vec2.Subtract(pB,pA);var axis=bA.GetWorldVector(this.m_localXAxisA);var translation=b2Dot_v2_v2(d,axis);return translation},GetJointSpeed:function(){var wA=this.m_bodyA.m_angularVelocity;var wB=this.m_bodyB.m_angularVelocity;return wB-wA},IsMotorEnabled:function(){return this.m_enableMotor},EnableMotor:function(flag){this.m_bodyA.SetAwake(true);this.m_bodyB.SetAwake(true);this.m_enableMotor=flag},SetMotorSpeed:function(speed){this.m_bodyA.SetAwake(true);this.m_bodyB.SetAwake(true);this.m_motorSpeed=speed},GetMotorSpeed:function(){return this.m_motorSpeed},SetMaxMotorTorque:function(torque){this.m_bodyA.SetAwake(true);this.m_bodyB.SetAwake(true);this.m_maxMotorTorque=torque},GetMaxMotorTorque:function(){return this.m_maxMotorTorque},GetMotorTorque:function(inv_dt){return inv_dt*this.m_motorImpulse},SetSpringFrequencyHz:function(hz){this.m_frequencyHz=hz},GetSpringFrequencyHz:function(){return this.m_frequencyHz},SetSpringDampingRatio:function(ratio){this.m_dampingRatio=ratio},GetSpringDampingRatio:function(){return this.m_dampingRatio},InitVelocityConstraints:function(data){this.m_indexA=this.m_bodyA.m_islandIndex;this.m_indexB=this.m_bodyB.m_islandIndex;this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter);this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter);this.m_invMassA=this.m_bodyA.m_invMass;this.m_invMassB=this.m_bodyB.m_invMass;this.m_invIA=this.m_bodyA.m_invI;this.m_invIB=this.m_bodyB.m_invI;var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var qA=new b2Rot(aA),qB=new b2Rot(aB);var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var d=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,rB),cA),rA);this.m_ay.Assign(b2Mul_r_v2(qA,this.m_localYAxisA));this.m_sAy=b2Cross_v2_v2(b2Vec2.Add(d,rA),this.m_ay);this.m_sBy=b2Cross_v2_v2(rB,this.m_ay);this.m_mass=mA+mB+iA*this.m_sAy*this.m_sAy+iB*this.m_sBy*this.m_sBy;if(this.m_mass>0){this.m_mass=1/this.m_mass}this.m_springMass=0;this.m_bias=0;this.m_gamma=0;if(this.m_frequencyHz>0){this.m_ax.Assign(b2Mul_r_v2(qA,this.m_localXAxisA));this.m_sAx=b2Cross_v2_v2(b2Vec2.Add(d,rA),this.m_ax);this.m_sBx=b2Cross_v2_v2(rB,this.m_ax);var invMass=mA+mB+iA*this.m_sAx*this.m_sAx+iB*this.m_sBx*this.m_sBx;if(invMass>0){this.m_springMass=1/invMass;var C=b2Dot_v2_v2(d,this.m_ax);var omega=2*b2_pi*this.m_frequencyHz;var d=2*this.m_springMass*this.m_dampingRatio*omega;var k=this.m_springMass*omega*omega;var h=data.step.dt;this.m_gamma=h*(d+h*k);if(this.m_gamma>0){this.m_gamma=1/this.m_gamma}this.m_bias=C*h*k*this.m_gamma;this.m_springMass=invMass+this.m_gamma;if(this.m_springMass>0){this.m_springMass=1/this.m_springMass}}}else{this.m_springImpulse=0}if(this.m_enableMotor){this.m_motorMass=iA+iB;if(this.m_motorMass>0){this.m_motorMass=1/this.m_motorMass}}else{this.m_motorMass=0;this.m_motorImpulse=0}if(data.step.warmStarting){this.m_impulse*=data.step.dtRatio;this.m_springImpulse*=data.step.dtRatio;this.m_motorImpulse*=data.step.dtRatio;var P=b2Vec2.Add(b2Vec2.Multiply(this.m_impulse,this.m_ay),b2Vec2.Multiply(this.m_springImpulse,this.m_ax));var LA=this.m_impulse*this.m_sAy+this.m_springImpulse*this.m_sAx+this.m_motorImpulse;var LB=this.m_impulse*this.m_sBy+this.m_springImpulse*this.m_sBx+this.m_motorImpulse;vA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));wA-=this.m_invIA*LA;vB.Add(b2Vec2.Multiply(this.m_invMassB,P));wB+=this.m_invIB*LB}else{this.m_impulse=0;this.m_springImpulse=0;this.m_motorImpulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var Cdot=b2Dot_v2_v2(this.m_ax,b2Vec2.Subtract(vB,vA))+this.m_sBx*wB-this.m_sAx*wA;var impulse=-this.m_springMass*(Cdot+this.m_bias+this.m_gamma*this.m_springImpulse);this.m_springImpulse+=impulse;var P=b2Vec2.Multiply(impulse,this.m_ax);var LA=impulse*this.m_sAx;var LB=impulse*this.m_sBx;vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*LA;vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*LB;var Cdot=wB-wA-this.m_motorSpeed;var impulse=-this.m_motorMass*Cdot;var oldImpulse=this.m_motorImpulse;var maxImpulse=data.step.dt*this.m_maxMotorTorque;this.m_motorImpulse=b2Clamp(this.m_motorImpulse+impulse,-maxImpulse,maxImpulse);impulse=this.m_motorImpulse-oldImpulse;wA-=iA*impulse;wB+=iB*impulse;var Cdot=b2Dot_v2_v2(this.m_ay,b2Vec2.Subtract(vB,vA))+this.m_sBy*wB-this.m_sAy*wA;var impulse=-this.m_mass*Cdot;this.m_impulse+=impulse;var P=b2Vec2.Multiply(impulse,this.m_ay);var LA=impulse*this.m_sAy;var LB=impulse*this.m_sBy;vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*LA;vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*LB;data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var qA=new b2Rot(aA),qB=new b2Rot(aB);var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var d=b2Vec2.Add(b2Vec2.Subtract(cB,cA),b2Vec2.Subtract(rB,rA));var ay=b2Mul_r_v2(qA,this.m_localYAxisA);var sAy=b2Cross_v2_v2(b2Vec2.Add(d,rA),ay);var sBy=b2Cross_v2_v2(rB,ay);var C=b2Dot_v2_v2(d,ay);var k=this.m_invMassA+this.m_invMassB+this.m_invIA*this.m_sAy*this.m_sAy+this.m_invIB*this.m_sBy*this.m_sBy;var impulse;if(k!=0){impulse=-C/k}else{impulse=0}var P=b2Vec2.Multiply(impulse,ay);var LA=impulse*sAy;var LB=impulse*sBy;cA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));aA-=this.m_invIA*LA;cB.Add(b2Vec2.Multiply(this.m_invMassB,P));aB+=this.m_invIB*LB;data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;return b2Abs(C)<=b2_linearSlop},_serialize:function(out){var obj=out||{};this.parent.prototype._serialize.call(this,obj);obj.localAnchorA=this.m_localAnchorA._serialize();obj.localAnchorB=this.m_localAnchorB._serialize();obj.localAxisA=this.m_localAxisA._serialize();obj.enableMotor=this.m_enableMotor;obj.maxMotorTorque=this.m_maxMotorTorque;obj.motorSpeed=this.m_motorSpeed;obj.frequencyHz=this.m_frequencyHz;obj.dampingRatio=this.m_dampingRatio;return obj}};b2WheelJoint._extend(b2Joint);function b2GearJointDef(){this.parent.call(this);this.type=b2Joint.e_gearJoint;this.joint1=null;this.joint2=null;this.ratio=1;Object.seal(this)}b2GearJointDef.prototype={_deserialize:function(data,bodies,joints){this.parent.prototype._deserialize.call(this,data,bodies,joints);this.joint1=data.joint1;this.joint2=data.joint2;this.ratio=data.ratio}};b2GearJointDef._extend(b2JointDef);function b2GearJoint(def){this.parent.call(this,def);this.m_joint1=def.joint1;this.m_joint2=def.joint2;this.m_typeA=this.m_joint1.GetType();this.m_typeB=this.m_joint2.GetType();var coordinateA,coordinateB;this.m_bodyC=this.m_joint1.GetBodyA();this.m_bodyA=this.m_joint1.GetBodyB();var xfA=this.m_bodyA.m_xf;var aA=this.m_bodyA.m_sweep.a;var xfC=this.m_bodyC.m_xf;var aC=this.m_bodyC.m_sweep.a;this.m_localAnchorA=new b2Vec2();this.m_localAnchorB=new b2Vec2();this.m_localAnchorC=new b2Vec2();this.m_localAnchorD=new b2Vec2();this.m_localAxisC=new b2Vec2();this.m_localAxisD=new b2Vec2();if(this.m_typeA==b2Joint.e_revoluteJoint){var revolute=def.joint1;this.m_localAnchorC.Assign(revolute.m_localAnchorA);this.m_localAnchorA.Assign(revolute.m_localAnchorB);this.m_referenceAngleA=revolute.m_referenceAngle;this.m_localAxisC.SetZero();coordinateA=aA-aC-this.m_referenceAngleA}else{var prismatic=def.joint1;this.m_localAnchorC.Assign(prismatic.m_localAnchorA);this.m_localAnchorA.Assign(prismatic.m_localAnchorB);this.m_referenceAngleA=prismatic.m_referenceAngle;this.m_localAxisC.Assign(prismatic.m_localXAxisA);var pC=this.m_localAnchorC;var pA=b2MulT_r_v2(xfC.q,b2Vec2.Add(b2Mul_r_v2(xfA.q,this.m_localAnchorA),b2Vec2.Subtract(xfA.p,xfC.p)));coordinateA=b2Dot_v2_v2(b2Vec2.Subtract(pA,pC),this.m_localAxisC)}this.m_bodyD=this.m_joint2.GetBodyA();this.m_bodyB=this.m_joint2.GetBodyB();var xfB=this.m_bodyB.m_xf;var aB=this.m_bodyB.m_sweep.a;var xfD=this.m_bodyD.m_xf;var aD=this.m_bodyD.m_sweep.a;if(this.m_typeB==b2Joint.e_revoluteJoint){var revolute=def.joint2;this.m_localAnchorD.Assign(revolute.m_localAnchorA);this.m_localAnchorB.Assign(revolute.m_localAnchorB);this.m_referenceAngleB=revolute.m_referenceAngle;this.m_localAxisD.SetZero();coordinateB=aB-aD-this.m_referenceAngleB}else{var prismatic=def.joint2;this.m_localAnchorD.Assign(prismatic.m_localAnchorA);this.m_localAnchorB.Assign(prismatic.m_localAnchorB);this.m_referenceAngleB=prismatic.m_referenceAngle;this.m_localAxisD.Assign(prismatic.m_localXAxisA);var pD=this.m_localAnchorD;var pB=b2MulT_r_v2(xfD.q,b2Vec2.Add(b2Mul_r_v2(xfB.q,this.m_localAnchorB),b2Vec2.Subtract(xfB.p,xfD.p)));coordinateB=b2Dot_v2_v2(b2Vec2.Subtract(pB,pD),this.m_localAxisD)}this.m_ratio=def.ratio;this.m_constant=coordinateA+this.m_ratio*coordinateB;this.m_impulse=0;this.m_indexA=this.m_indexB=this.m_indexC=this.m_indexD=0;this.m_lcA=new b2Vec2();this.m_lcB=new b2Vec2();this.m_lcC=new b2Vec2();this.m_lcD=new b2Vec2();this.m_mA=this.m_mB=this.m_mC=this.m_mD=0;this.m_iA=this.m_iB=this.m_iC=this.m_iD=0;this.m_JvAC=new b2Vec2(),this.m_JvBD=new b2Vec2();this.m_JwA=this.m_JwB=this.m_JwC=this.m_JwD=0;this.m_mass=0}b2GearJoint.prototype={GetAnchorA:function(){return this.m_bodyA.GetWorldPoint(this.m_localAnchorA)},GetAnchorB:function(){return this.m_bodyB.GetWorldPoint(this.m_localAnchorB)},GetReactionForce:function(inv_dt){var P=b2Vec2.Multiply(this.m_impulse,this.m_JvAC);return b2Vec2.Multiply(inv_dt,P)},GetReactionTorque:function(inv_dt){var L=this.m_impulse*this.m_JwA;return inv_dt*L},GetJoint1:function(){return this.m_joint1},GetJoint2:function(){return this.m_joint2},SetRatio:function(ratio){this.m_ratio=ratio},GetRatio:function(){return this.m_ratio},InitVelocityConstraints:function(data){this.m_indexA=this.m_bodyA.m_islandIndex;this.m_indexB=this.m_bodyB.m_islandIndex;this.m_indexC=this.m_bodyC.m_islandIndex;this.m_indexD=this.m_bodyD.m_islandIndex;this.m_lcA.Assign(this.m_bodyA.m_sweep.localCenter);this.m_lcB.Assign(this.m_bodyB.m_sweep.localCenter);this.m_lcC.Assign(this.m_bodyC.m_sweep.localCenter);this.m_lcD.Assign(this.m_bodyD.m_sweep.localCenter);this.m_mA=this.m_bodyA.m_invMass;this.m_mB=this.m_bodyB.m_invMass;this.m_mC=this.m_bodyC.m_invMass;this.m_mD=this.m_bodyD.m_invMass;this.m_iA=this.m_bodyA.m_invI;this.m_iB=this.m_bodyB.m_invI;this.m_iC=this.m_bodyC.m_invI;this.m_iD=this.m_bodyD.m_invI;var aA=data.positions[this.m_indexA].a;var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var aB=data.positions[this.m_indexB].a;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var aC=data.positions[this.m_indexC].a;var vC=data.velocities[this.m_indexC].v.Clone();var wC=data.velocities[this.m_indexC].w;var aD=data.positions[this.m_indexD].a;var vD=data.velocities[this.m_indexD].v.Clone();var wD=data.velocities[this.m_indexD].w;var qA=new b2Rot(aA),qB=new b2Rot(aB),qC=new b2Rot(aC),qD=new b2Rot(aD);this.m_mass=0;if(this.m_typeA==b2Joint.e_revoluteJoint){this.m_JvAC.SetZero();this.m_JwA=1;this.m_JwC=1;this.m_mass+=this.m_iA+this.m_iC}else{var u=b2Mul_r_v2(qC,this.m_localAxisC);var rC=b2Mul_r_v2(qC,b2Vec2.Subtract(this.m_localAnchorC,this.m_lcC));var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_lcA));this.m_JvAC.Assign(u);this.m_JwC=b2Cross_v2_v2(rC,u);this.m_JwA=b2Cross_v2_v2(rA,u);this.m_mass+=this.m_mC+this.m_mA+this.m_iC*this.m_JwC*this.m_JwC+this.m_iA*this.m_JwA*this.m_JwA}if(this.m_typeB==b2Joint.e_revoluteJoint){this.m_JvBD.SetZero();this.m_JwB=this.m_ratio;this.m_JwD=this.m_ratio;this.m_mass+=this.m_ratio*this.m_ratio*(this.m_iB+this.m_iD)}else{var u=b2Mul_r_v2(qD,this.m_localAxisD);var rD=b2Mul_r_v2(qD,b2Vec2.Subtract(this.m_localAnchorD,this.m_lcD));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_lcB));this.m_JvBD.Assign(b2Vec2.Multiply(this.m_ratio,u));this.m_JwD=this.m_ratio*b2Cross_v2_v2(rD,u);this.m_JwB=this.m_ratio*b2Cross_v2_v2(rB,u);this.m_mass+=this.m_ratio*this.m_ratio*(this.m_mD+this.m_mB)+this.m_iD*this.m_JwD*this.m_JwD+this.m_iB*this.m_JwB*this.m_JwB}this.m_mass=this.m_mass>0?1/this.m_mass:0;if(data.step.warmStarting){vA.Add(b2Vec2.Multiply((this.m_mA*this.m_impulse),this.m_JvAC));wA+=this.m_iA*this.m_impulse*this.m_JwA;vB.Add(b2Vec2.Multiply((this.m_mB*this.m_impulse),this.m_JvBD));wB+=this.m_iB*this.m_impulse*this.m_JwB;vC.Subtract(b2Vec2.Multiply((this.m_mC*this.m_impulse),this.m_JvAC));wC-=this.m_iC*this.m_impulse*this.m_JwC;vD.Subtract(b2Vec2.Multiply((this.m_mD*this.m_impulse),this.m_JvBD));wD-=this.m_iD*this.m_impulse*this.m_JwD}else{this.m_impulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB;data.velocities[this.m_indexC].v.Assign(vC);data.velocities[this.m_indexC].w=wC;data.velocities[this.m_indexD].v.Assign(vD);data.velocities[this.m_indexD].w=wD},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var vC=data.velocities[this.m_indexC].v.Clone();var wC=data.velocities[this.m_indexC].w;var vD=data.velocities[this.m_indexD].v.Clone();var wD=data.velocities[this.m_indexD].w;var Cdot=b2Dot_v2_v2(this.m_JvAC,b2Vec2.Subtract(vA,vC))+b2Dot_v2_v2(this.m_JvBD,b2Vec2.Subtract(vB,vD));Cdot+=(this.m_JwA*wA-this.m_JwC*wC)+(this.m_JwB*wB-this.m_JwD*wD);var impulse=-this.m_mass*Cdot;this.m_impulse+=impulse;vA.Add(b2Vec2.Multiply((this.m_mA*impulse),this.m_JvAC));wA+=this.m_iA*impulse*this.m_JwA;vB.Add(b2Vec2.Multiply((this.m_mB*impulse),this.m_JvBD));wB+=this.m_iB*impulse*this.m_JwB;vC.Subtract(b2Vec2.Multiply((this.m_mC*impulse),this.m_JvAC));wC-=this.m_iC*impulse*this.m_JwC;vD.Subtract(b2Vec2.Multiply((this.m_mD*impulse),this.m_JvBD));wD-=this.m_iD*impulse*this.m_JwD;data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB;data.velocities[this.m_indexC].v.Assign(vC);data.velocities[this.m_indexC].w=wC;data.velocities[this.m_indexD].v.Assign(vD);data.velocities[this.m_indexD].w=wD},SolvePositionConstraints:function(data){var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var cC=data.positions[this.m_indexC].c.Clone();var aC=data.positions[this.m_indexC].a;var cD=data.positions[this.m_indexD].c.Clone();var aD=data.positions[this.m_indexD].a;var qA=new b2Rot(aA),qB=new b2Rot(aB),qC=new b2Rot(aC),qD=new b2Rot(aD);var linearError=0;var coordinateA,coordinateB;var JvAC=new b2Vec2(),JvBD=new b2Vec2();var JwA,JwB,JwC,JwD;var mass=0;if(this.m_typeA==b2Joint.e_revoluteJoint){JvAC.SetZero();JwA=1;JwC=1;mass+=this.m_iA+this.m_iC;coordinateA=aA-aC-this.m_referenceAngleA}else{var u=b2Mul_r_v2(qC,this.m_localAxisC);var rC=b2Mul_r_v2(qC,b2Vec2.Subtract(this.m_localAnchorC,this.m_lcC));var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_lcA));JvAC.Assign(u);JwC=b2Cross_v2_v2(rC,u);JwA=b2Cross_v2_v2(rA,u);mass+=this.m_mC+this.m_mA+this.m_iC*JwC*JwC+this.m_iA*JwA*JwA;var pC=b2Vec2.Subtract(this.m_localAnchorC,this.m_lcC);var pA=b2MulT_r_v2(qC,b2Vec2.Add(rA,b2Vec2.Subtract(cA,cC)));coordinateA=b2Dot_v2_v2(b2Vec2.Subtract(pA,pC),this.m_localAxisC)}if(this.m_typeB==b2Joint.e_revoluteJoint){JvBD.SetZero();JwB=this.m_ratio;JwD=this.m_ratio;mass+=this.m_ratio*this.m_ratio*(this.m_iB+this.m_iD);coordinateB=aB-aD-this.m_referenceAngleB}else{var u=b2Mul_r_v2(qD,this.m_localAxisD);var rD=b2Mul_r_v2(qD,b2Vec2.Subtract(this.m_localAnchorD,this.m_lcD));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_lcB));JvBD.Assign(b2Vec2.Multiply(this.m_ratio,u));JwD=this.m_ratio*b2Cross_v2_v2(rD,u);JwB=this.m_ratio*b2Cross_v2_v2(rB,u);mass+=this.m_ratio*this.m_ratio*(this.m_mD+this.m_mB)+this.m_iD*JwD*JwD+this.m_iB*JwB*JwB;var pD=b2Vec2.Subtract(this.m_localAnchorD,this.m_lcD);var pB=b2MulT_r_v2(qD,b2Vec2.Add(rB,b2Vec2.Subtract(cB,cD)));coordinateB=b2Dot_v2_v2(b2Vec2.Subtract(pB,pD),this.m_localAxisD)}var C=(coordinateA+this.m_ratio*coordinateB)-this.m_constant;var impulse=0;if(mass>0){impulse=-C/mass}cA.Add(b2Vec2.Multiply(this.m_mA,b2Vec2.Multiply(impulse,JvAC)));aA+=this.m_iA*impulse*JwA;cB.Add(b2Vec2.Multiply(this.m_mB,b2Vec2.Multiply(impulse,JvBD)));aB+=this.m_iB*impulse*JwB;cC.Subtract(b2Vec2.Multiply(this.m_mC,b2Vec2.Multiply(impulse,JvAC)));aC-=this.m_iC*impulse*JwC;cD.Subtract(b2Vec2.Multiply(this.m_mD,b2Vec2.Multiply(impulse,JvBD)));aD-=this.m_iD*impulse*JwD;data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;data.positions[this.m_indexC].c.Assign(cC);data.positions[this.m_indexC].a=aC;data.positions[this.m_indexD].c.Assign(cD);data.positions[this.m_indexD].a=aD;return linearError0){this.m_angularMass=1/this.m_angularMass}this.m_linearError.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,this.m_rB),cA),this.m_rA),b2Mul_r_v2(qA,this.m_linearOffset)));this.m_angularError=aB-aA-this.m_angularOffset;if(data.step.warmStarting){this.m_linearImpulse.Multiply(data.step.dtRatio);this.m_angularImpulse*=data.step.dtRatio;var P=new b2Vec2(this.m_linearImpulse.x,this.m_linearImpulse.y);vA.Subtract(b2Vec2.Multiply(mA,P));wA-=iA*(b2Cross_v2_v2(this.m_rA,P)+this.m_angularImpulse);vB.Add(b2Vec2.Multiply(mB,P));wB+=iB*(b2Cross_v2_v2(this.m_rB,P)+this.m_angularImpulse)}else{this.m_linearImpulse.SetZero();this.m_angularImpulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var mA=this.m_invMassA,mB=this.m_invMassB;var iA=this.m_invIA,iB=this.m_invIB;var h=data.step.dt;var inv_h=data.step.inv_dt;var Cdot=wB-wA+inv_h*this.m_correctionFactor*this.m_angularError;var impulse=-this.m_angularMass*Cdot;var oldImpulse=this.m_angularImpulse;var maxImpulse=h*this.m_maxTorque;this.m_angularImpulse=b2Clamp(this.m_angularImpulse+impulse,-maxImpulse,maxImpulse);impulse=this.m_angularImpulse-oldImpulse;wA-=iA*impulse;wB+=iB*impulse;var Cdot=b2Vec2.Add(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB)),vA),b2Cross_f_v2(wA,this.m_rA)),b2Vec2.Multiply(inv_h,b2Vec2.Multiply(this.m_correctionFactor,this.m_linearError)));var impulse=b2Mul_m22_v2(this.m_linearMass,Cdot).Negate();var oldImpulse=this.m_linearImpulse;this.m_linearImpulse.Add(impulse);var maxImpulse=h*this.m_maxForce;if(this.m_linearImpulse.LengthSquared()>maxImpulse*maxImpulse){this.m_linearImpulse.Normalize();this.m_linearImpulse.Multiply(maxImpulse)}impulse.Assign(b2Vec2.Subtract(this.m_linearImpulse,oldImpulse));vA.Subtract(b2Vec2.Multiply(mA,impulse));wA-=iA*b2Cross_v2_v2(this.m_rA,impulse);vB.Add(b2Vec2.Multiply(mB,impulse));wB+=iB*b2Cross_v2_v2(this.m_rB,impulse);data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){return true},_serialize:function(out){var obj=out||{};this.parent.prototype._serialize.call(this,obj);obj.linearOffset=this.m_linearOffset._serialize();obj.angularOffset=this.m_angularOffset;obj.maxForce=this.m_maxForce;obj.maxTorque=this.m_maxTorque;obj.correctionFactor=this.m_correctionFactor;return obj}};b2MotorJoint._extend(b2Joint);var b2_minPulleyLength=2;function b2PulleyJointDef(){this.parent.call(this);this.type=b2Joint.e_pulleyJoint;this.groundAnchorA=new b2Vec2(-1,1);this.groundAnchorB=new b2Vec2(1,1);this.localAnchorA=new b2Vec2(-1,0);this.localAnchorB=new b2Vec2(1,0);this.lengthA=0;this.lengthB=0;this.ratio=1;this.collideConnected=true;Object.seal(this)}b2PulleyJointDef.prototype={Initialize:function(bA,bB,groundA,groundB,anchorA,anchorB,r){this.bodyA=bA;this.bodyB=bB;this.groundAnchorA.Assign(groundA);this.groundAnchorB.Assign(groundB);this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchorA));this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchorB));var dA=b2Vec2.Subtract(anchorA,groundA);this.lengthA=dA.Length();var dB=b2Vec2.Subtract(anchorB,groundB);this.lengthB=dB.Length();this.ratio=r},_deserialize:function(data,bodies,joints){this.parent.prototype._deserialize.call(this,data,bodies,joints);this.groundAnchorA._deserialize(data.groundAnchorA);this.groundAnchorB._deserialize(data.groundAnchorB);this.localAnchorA._deserialize(data.localAnchorA);this.localAnchorB._deserialize(data.localAnchorB);this.lengthA=data.lengthA;this.lengthB=data.lengthB;this.ratio=data.ratio}};b2PulleyJointDef._extend(b2JointDef);function b2PulleyJoint(def){this.parent.call(this,def);this.m_indexA=0;this.m_indexB=0;this.m_uA=new b2Vec2();this.m_uB=new b2Vec2();this.m_rA=new b2Vec2();this.m_rB=new b2Vec2();this.m_localCenterA=new b2Vec2();this.m_localCenterB=new b2Vec2();this.m_invMassA=0;this.m_invMassB=0;this.m_invIA=0;this.m_invIB=0;this.m_mass=0;this.m_groundAnchorA=def.groundAnchorA.Clone();this.m_groundAnchorB=def.groundAnchorB.Clone();this.m_localAnchorA=def.localAnchorA.Clone();this.m_localAnchorB=def.localAnchorB.Clone();this.m_lengthA=def.lengthA;this.m_lengthB=def.lengthB;this.m_ratio=def.ratio;this.m_constant=def.lengthA+this.m_ratio*def.lengthB;this.m_impulse=0}b2PulleyJoint.prototype={GetAnchorA:function(){return this.m_bodyA.GetWorldPoint(this.m_localAnchorA)},GetAnchorB:function(){return this.m_bodyB.GetWorldPoint(this.m_localAnchorB)},GetReactionForce:function(inv_dt){var P=b2Vec2.Multiply(this.m_impulse,this.m_uB);return b2Vec2.Multiply(inv_dt,P)},GetReactionTorque:function(inv_dt){return 0},GetGroundAnchorA:function(){return this.m_groundAnchorA},GetGroundAnchorB:function(){return this.m_groundAnchorB},GetLengthA:function(){return this.m_lengthA},GetLengthB:function(){return this.m_lengthB},GetRatio:function(){return this.m_ratio},GetCurrentLengthA:function(){var p=this.m_bodyA.GetWorldPoint(this.m_localAnchorA);var s=this.m_groundAnchorA;var d=b2Vec2.Subtract(p,s);return d.Length()},GetCurrentLengthB:function(){var p=this.m_bodyB.GetWorldPoint(this.m_localAnchorB);var s=this.m_groundAnchorB;var d=b2Vec2.Subtract(p,s);return d.Length()},ShiftOrigin:function(newOrigin){this.m_groundAnchorA.Subtract(newOrigin);this.m_groundAnchorB.Subtract(newOrigin)},InitVelocityConstraints:function(data){this.m_indexA=this.m_bodyA.m_islandIndex;this.m_indexB=this.m_bodyB.m_islandIndex;this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter);this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter);this.m_invMassA=this.m_bodyA.m_invMass;this.m_invMassB=this.m_bodyB.m_invMass;this.m_invIA=this.m_bodyA.m_invI;this.m_invIB=this.m_bodyB.m_invI;var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var qA=new b2Rot(aA),qB=new b2Rot(aB);this.m_rA.Assign(b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA)));this.m_rB.Assign(b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB)));this.m_uA.Assign(b2Vec2.Add(cA,b2Vec2.Subtract(this.m_rA,this.m_groundAnchorA)));this.m_uB.Assign(b2Vec2.Add(cB,b2Vec2.Subtract(this.m_rB,this.m_groundAnchorB)));var lengthA=this.m_uA.Length();var lengthB=this.m_uB.Length();if(lengthA>10*b2_linearSlop){this.m_uA.Multiply(1/lengthA)}else{this.m_uA.SetZero()}if(lengthB>10*b2_linearSlop){this.m_uB.Multiply(1/lengthB)}else{this.m_uB.SetZero()}var ruA=b2Cross_v2_v2(this.m_rA,this.m_uA);var ruB=b2Cross_v2_v2(this.m_rB,this.m_uB);var mA=this.m_invMassA+this.m_invIA*ruA*ruA;var mB=this.m_invMassB+this.m_invIB*ruB*ruB;this.m_mass=mA+this.m_ratio*this.m_ratio*mB;if(this.m_mass>0){this.m_mass=1/this.m_mass}if(data.step.warmStarting){this.m_impulse*=data.step.dtRatio;var PA=b2Vec2.Multiply(-(this.m_impulse),this.m_uA);var PB=b2Vec2.Multiply((-this.m_ratio*this.m_impulse),this.m_uB);vA.Add(b2Vec2.Multiply(this.m_invMassA,PA));wA+=this.m_invIA*b2Cross_v2_v2(this.m_rA,PA);vB.Add(b2Vec2.Multiply(this.m_invMassB,PB));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,PB)}else{this.m_impulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var vpA=b2Vec2.Add(vA,b2Cross_f_v2(wA,this.m_rA));var vpB=b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB));var Cdot=-b2Dot_v2_v2(this.m_uA,vpA)-this.m_ratio*b2Dot_v2_v2(this.m_uB,vpB);var impulse=-this.m_mass*Cdot;this.m_impulse+=impulse;var PA=b2Vec2.Multiply(-impulse,this.m_uA);var PB=b2Vec2.Multiply(-this.m_ratio,b2Vec2.Multiply(impulse,this.m_uB));vA.Add(b2Vec2.Multiply(this.m_invMassA,PA));wA+=this.m_invIA*b2Cross_v2_v2(this.m_rA,PA);vB.Add(b2Vec2.Multiply(this.m_invMassB,PB));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,PB);data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var qA=new b2Rot(aA),qB=new b2Rot(aB);var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var uA=b2Vec2.Add(cA,b2Vec2.Subtract(rA,this.m_groundAnchorA));var uB=b2Vec2.Add(cB,b2Vec2.Subtract(rB,this.m_groundAnchorB));var lengthA=uA.Length();var lengthB=uB.Length();if(lengthA>10*b2_linearSlop){uA.Multiply(1/lengthA)}else{uA.SetZero()}if(lengthB>10*b2_linearSlop){uB.Multiply(1/lengthB)}else{uB.SetZero()}var ruA=b2Cross_v2_v2(rA,uA);var ruB=b2Cross_v2_v2(rB,uB);var mA=this.m_invMassA+this.m_invIA*ruA*ruA;var mB=this.m_invMassB+this.m_invIB*ruB*ruB;var mass=mA+this.m_ratio*this.m_ratio*mB;if(mass>0){mass=1/mass}var C=this.m_constant-lengthA-this.m_ratio*lengthB;var linearError=b2Abs(C);var impulse=-mass*C;var PA=b2Vec2.Multiply(-impulse,uA);var PB=b2Vec2.Multiply(-this.m_ratio,b2Vec2.Multiply(impulse,uB));cA.Add(b2Vec2.Multiply(this.m_invMassA,PA));aA+=this.m_invIA*b2Cross_v2_v2(rA,PA);cB.Add(b2Vec2.Multiply(this.m_invMassB,PB));aB+=this.m_invIB*b2Cross_v2_v2(rB,PB);data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;return linearError0){this.m_state=b2Joint.e_atUpperLimit}else{this.m_state=b2Joint.e_inactiveLimit}if(this.m_length>b2_linearSlop){this.m_u.Multiply(1/this.m_length)}else{this.m_u.SetZero();this.m_mass=0;this.m_impulse=0;return}var crA=b2Cross_v2_v2(this.m_rA,this.m_u);var crB=b2Cross_v2_v2(this.m_rB,this.m_u);var invMass=this.m_invMassA+this.m_invIA*crA*crA+this.m_invMassB+this.m_invIB*crB*crB;this.m_mass=invMass!=0?1/invMass:0;if(data.step.warmStarting){this.m_impulse*=data.step.dtRatio;var P=b2Vec2.Multiply(this.m_impulse,this.m_u);vA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));wA-=this.m_invIA*b2Cross_v2_v2(this.m_rA,P);vB.Add(b2Vec2.Multiply(this.m_invMassB,P));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,P)}else{this.m_impulse=0}data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolveVelocityConstraints:function(data){var vA=data.velocities[this.m_indexA].v.Clone();var wA=data.velocities[this.m_indexA].w;var vB=data.velocities[this.m_indexB].v.Clone();var wB=data.velocities[this.m_indexB].w;var vpA=b2Vec2.Add(vA,b2Cross_f_v2(wA,this.m_rA));var vpB=b2Vec2.Add(vB,b2Cross_f_v2(wB,this.m_rB));var C=this.m_length-this.m_maxLength;var Cdot=b2Dot_v2_v2(this.m_u,b2Vec2.Subtract(vpB,vpA));if(C<0){Cdot+=data.step.inv_dt*C}var impulse=-this.m_mass*Cdot;var oldImpulse=this.m_impulse;this.m_impulse=b2Min(0,this.m_impulse+impulse);impulse=this.m_impulse-oldImpulse;var P=b2Vec2.Multiply(impulse,this.m_u);vA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));wA-=this.m_invIA*b2Cross_v2_v2(this.m_rA,P);vB.Add(b2Vec2.Multiply(this.m_invMassB,P));wB+=this.m_invIB*b2Cross_v2_v2(this.m_rB,P);data.velocities[this.m_indexA].v.Assign(vA);data.velocities[this.m_indexA].w=wA;data.velocities[this.m_indexB].v.Assign(vB);data.velocities[this.m_indexB].w=wB},SolvePositionConstraints:function(data){var cA=data.positions[this.m_indexA].c.Clone();var aA=data.positions[this.m_indexA].a;var cB=data.positions[this.m_indexB].c.Clone();var aB=data.positions[this.m_indexB].a;var qA=new b2Rot(aA),qB=new b2Rot(aB);var rA=b2Mul_r_v2(qA,b2Vec2.Subtract(this.m_localAnchorA,this.m_localCenterA));var rB=b2Mul_r_v2(qB,b2Vec2.Subtract(this.m_localAnchorB,this.m_localCenterB));var u=b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB,rB),cA),rA);var length=u.Normalize();var C=length-this.m_maxLength;C=b2Clamp(C,0,b2_maxLinearCorrection);var impulse=-this.m_mass*C;var P=b2Vec2.Multiply(impulse,u);cA.Subtract(b2Vec2.Multiply(this.m_invMassA,P));aA-=this.m_invIA*b2Cross_v2_v2(rA,P);cB.Add(b2Vec2.Multiply(this.m_invMassB,P));aB+=this.m_invIB*b2Cross_v2_v2(rB,P);data.positions[this.m_indexA].c.Assign(cA);data.positions[this.m_indexA].a=aA;data.positions[this.m_indexB].c.Assign(cB);data.positions[this.m_indexB].a=aB;return length-this.m_maxLength0){this.m_ims[i]=1/m}else{this.m_ims[i]=0}}var count2=this.m_count-1;var count3=this.m_count-2;this.m_Ls=new Array(count2);this.m_as=new Array(count3);for(var i=0;i0){this.m_vs[i].Add(b2Vec2.Multiply(h,this.m_gravity))}this.m_vs[i].Multiply(d);this.m_ps[i].Add(b2Vec2.Multiply(h,this.m_vs[i]))}for(var i=0;ib2_pi){angle-=2*b2_pi;C=angle-this.m_as[i]}while(C<-b2_pi){angle+=2*b2_pi;C=angle-this.m_as[i]}var impulse=-this.m_k3*mass*C;p1.Add(b2Vec2.Multiply((m1*impulse),J1));p2.Add(b2Vec2.Multiply((m2*impulse),J2));p3.Add(b2Vec2.Multiply((m3*impulse),J3))}}};var b2JsonSerializer={serialize:function(world){var shapes=[];var i;var serialized;var b;var f;var shape;for(b=world.GetBodyList();b;b=b.GetNext()){for(f=b.GetFixtureList();f;f=f.GetNext()){shape=f.GetShape();f.__temp_shape_id=shapes.length;shapes.push(shape._serialize())}}var fixtures=[];for(b=world.GetBodyList();b;b=b.GetNext()){b.__temp_fixture_ids=[];for(f=b.GetFixtureList();f;f=f.GetNext()){serialized=f._serialize();serialized.shape=f.__temp_shape_id;delete f.__temp_shape_id;b.__temp_fixture_ids.push(fixtures.length);fixtures.push(serialized)}}var bodies=[];for(b=world.GetBodyList();b;b=b.GetNext()){serialized=b._serialize();serialized.fixtures=[];for(i=0;i> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x + 1 + } + + function b2IsPowerOfTwo(x) { + var result = x > 0 && (x & (x - 1)) == 0; + return result + } + var RAND_LIMIT = 32767; + + function b2RandomFloat(lo, hi) { + var r = Math.random(); + if (typeof (lo) !== "undefined") { + r = (hi - lo) * r + lo + } else { + r = 2 * r - 1 + } + return r + } + "use strict"; + + function b2Color(r, g, b) { + this.r = r || 0; + this.g = g || 0; + this.b = b || 0 + } + b2Color.prototype = { + Set: function (r, g, b) { + this.r = r; + this.g = g; + this.b = b + } + }; + + function b2Draw() {} + b2Draw.prototype = { + SetFlags: function (flags) { + this.m_drawFlags = flags + }, + GetFlags: function () { + return this.m_drawFlags + }, + AppendFlags: function (flags) { + this.m_drawFlags |= flags + }, + ClearFlags: function (flags) { + this.m_drawFlags &= ~flags + }, + ToggleFlags: function (flags) { + this.m_drawFlags ^= flags + }, + DrawPolygon: function (vertices, vertexCount, color) {}, + DrawSolidPolygon: function (vertices, vertexCount, color) {}, + DrawCircle: function (center, radius, color) {}, + DrawSolidCircle: function (center, radius, axis, color) {}, + DrawSegment: function (p1, p2, color) {}, + DrawTransform: function (xf) {}, + m_drawFlags: 0 + }; + b2Draw.e_shapeBit = 1; + b2Draw.e_jointBit = 2; + b2Draw.e_aabbBit = 4; + b2Draw.e_centerOfMassBit = 8; + b2Draw.e_contactPoints = 16; + b2Draw.e_contactNormals = 32; + b2Draw.e_contactImpulses = 64; + b2Draw.e_frictionImpulses = 128; + b2Draw.e_statistics = 256; + b2Draw.e_profile = 512; + b2Draw.e_pairBit = 1024; + + "use strict"; + function b2Timer() { + this.Reset() + } + b2Timer.prototype = { + Reset: function () { + this.m_start = performance.now() + }, + GetMilliseconds: function () { + return performance.now() - this.m_start + } + }; + "use strict"; + + function b2MassData() { + this.mass = 0; + this.center = new b2Vec2(); + this.I = 0 + } + + function b2Shape() { + this.m_type = 0; + this.m_radius = 0 + } + b2Shape.prototype = { + Clone: function () {}, + GetType: function () { + return this.m_type + }, + GetChildCount: function () {}, + TestPoint: function (xf, p) {}, + RayCast: function (output, input, transform, childIndex) {}, + ComputeAABB: function (aabb, xf, childIndex) {}, + ComputeMass: function (massData, density) {}, + _serialize: function (out) { + var obj = out || {}; + obj.m_type = this.m_type; + obj.m_radius = this.m_radius; + return obj + }, + _deserialize: function (data) { + this.m_radius = data.m_radius + } + }; + b2Shape.e_circle = 0; + b2Shape.e_edge = 1; + b2Shape.e_polygon = 2; + b2Shape.e_chain = 3; + b2Shape.e_typeCount = 4; + "use strict"; + + function b2CircleShape() { + this.parent.call(this); + this.m_type = b2Shape.e_circle; + this.m_radius = 0; + this.m_p = new b2Vec2(); + Object.seal(this) + } + b2CircleShape.prototype = { + Clone: function () { + var shape = new b2CircleShape(); + shape.m_radius = this.m_radius; + shape.m_p = this.m_p.Clone(); + return shape + }, + GetChildCount: function () { + return 1 + }, + TestPoint: function (transform, p) { + var center = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); + var d = b2Vec2.Subtract(p, center); + return b2Dot_v2_v2(d, d) <= this.m_radius * this.m_radius + }, + RayCast: function (output, input, transform, childIndex) { + var position = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); + var s = b2Vec2.Subtract(input.p1, position); + var b = b2Dot_v2_v2(s, s) - this.m_radius * this.m_radius; + var r = b2Vec2.Subtract(input.p2, input.p1); + var c = b2Dot_v2_v2(s, r); + var rr = b2Dot_v2_v2(r, r); + var sigma = c * c - rr * b; + if (sigma < 0 || rr < b2_epsilon) { + return false + } + var a = -(c + b2Sqrt(sigma)); + if (0 <= a && a <= input.maxFraction * rr) { + a /= rr; + output.fraction = a; + output.normal = b2Vec2.Add(s, b2Vec2.Multiply(a, r)); + output.normal.Normalize(); + return true + } + return false + }, + ComputeAABB: function (aabb, transform, childIndex) { + var px = transform.p.x + (transform.q.c * this.m_p.x - transform.q.s * this.m_p.y); + var py = transform.p.y + (transform.q.s * this.m_p.x + transform.q.c * this.m_p.y); + aabb.lowerBound.x = px - this.m_radius; + aabb.lowerBound.y = py - this.m_radius; + aabb.upperBound.x = px + this.m_radius; + aabb.upperBound.y = py + this.m_radius + }, + ComputeMass: function (massData, density) { + massData.mass = density * b2_pi * this.m_radius * this.m_radius; + massData.center = this.m_p; + massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + b2Dot_v2_v2(this.m_p, this.m_p)) + }, + GetSupport: function (d) { + return 0 + }, + GetSupportVertex: function (d) { + return this.m_p + }, + GetVertexCount: function () { + return 1 + }, + GetVertex: function (index) { + return this.m_p + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_p = this.m_p._serialize(); + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_p._deserialize(data.m_p) + } + }; + b2CircleShape._extend(b2Shape); + "use strict"; + + function b2EdgeShape() { + this.parent.call(this); + this.m_type = b2Shape.e_edge; + this.m_radius = b2_polygonRadius; + this.m_vertex0 = new b2Vec2(); + this.m_vertex1 = new b2Vec2(); + this.m_vertex2 = new b2Vec2(); + this.m_vertex3 = new b2Vec2(); + this.m_hasVertex0 = false; + this.m_hasVertex3 = false; + Object.seal(this) + } + b2EdgeShape.prototype = { + Set: function (v1, v2) { + this.m_vertex1.Assign(v1); + this.m_vertex2.Assign(v2); + this.m_hasVertex0 = false; + this.m_hasVertex3 = false + }, + Clone: function () { + var shape = new b2EdgeShape(); + shape.m_vertex0 = this.m_vertex0.Clone(); + shape.m_vertex1 = this.m_vertex1.Clone(); + shape.m_vertex2 = this.m_vertex2.Clone(); + shape.m_vertex3 = this.m_vertex3.Clone(); + shape.m_hasVertex0 = this.m_hasVertex0; + shape.m_hasVertex3 = this.m_hasVertex3; + return shape + }, + GetChildCount: function () { + return 1 + }, + TestPoint: function (transform, p) { + return false + }, + RayCast: function (output, input, xf, childIndex) { + var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); + var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); + var d = b2Vec2.Subtract(p2, p1); + var v1 = this.m_vertex1; + var v2 = this.m_vertex2; + var e = b2Vec2.Subtract(v2, v1); + var normal = new b2Vec2(e.y, -e.x); + normal.Normalize(); + var numerator = b2Dot_v2_v2(normal, b2Vec2.Subtract(v1, p1)); + var denominator = b2Dot_v2_v2(normal, d); + if (denominator == 0) { + return false + } + var t = numerator / denominator; + if (t < 0 || input.maxFraction < t) { + return false + } + var q = b2Vec2.Add(p1, b2Vec2.Multiply(t, d)); + var r = b2Vec2.Subtract(v2, v1); + var rr = b2Dot_v2_v2(r, r); + if (rr == 0) { + return false + } + var s = b2Dot_v2_v2(b2Vec2.Subtract(q, v1), r) / rr; + if (s < 0 || 1 < s) { + return false + } + output.fraction = t; + if (numerator > 0) { + output.normal = b2Mul_r_v2(xf.q, normal).Negate() + } else { + output.normal = b2Mul_r_v2(xf.q, normal) + } + return true + }, + ComputeAABB: function (aabb, xf, childIndex) { + var v1x = (xf.q.c * this.m_vertex1.x - xf.q.s * this.m_vertex1.y) + xf.p.x; + var v1y = (xf.q.s * this.m_vertex1.x + xf.q.c * this.m_vertex1.y) + xf.p.y; + var v2x = (xf.q.c * this.m_vertex2.x - xf.q.s * this.m_vertex2.y) + xf.p.x; + var v2y = (xf.q.s * this.m_vertex2.x + xf.q.c * this.m_vertex2.y) + xf.p.y; + var lowerx = b2Min(v1x, v2x); + var lowery = b2Min(v1y, v2y); + var upperx = b2Max(v1x, v2x); + var uppery = b2Max(v1y, v2y); + aabb.lowerBound.x = lowerx - this.m_radius; + aabb.lowerBound.y = lowery - this.m_radius; + aabb.upperBound.x = upperx + this.m_radius; + aabb.upperBound.y = uppery + this.m_radius + }, + ComputeMass: function (massData, density) { + massData.mass = 0; + massData.center = b2Vec2.Multiply(0.5, b2Vec2.Add(this.m_vertex1, this.m_vertex2)); + massData.I = 0 + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_vertex1 = this.m_vertex1._serialize(); + obj.m_vertex2 = this.m_vertex2._serialize(); + obj.m_hasVertex0 = this.m_hasVertex0; + if (this.m_hasVertex0) { + obj.m_vertex0 = this.m_vertex0._serialize() + } + obj.m_hasVertex3 = this.m_hasVertex3; + if (this.m_hasVertex3) { + obj.m_vertex3 = this.m_vertex3._serialize() + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_vertex1._deserialize(data.m_vertex1); + this.m_vertex2._deserialize(data.m_vertex2); + this.m_hasVertex0 = data.m_hasVertex0; + if (this.m_hasVertex0) { + this.m_vertex0._deserialize(data.m_vertex0) + } + this.m_hasVertex3 = data.m_hasVertex3; + if (this.m_hasVertex3) { + this.m_vertex3._deserialize(data.m_vertex3) + } + } + }; + b2EdgeShape._extend(b2Shape); + "use strict"; + + function b2ChainShape() { + this.parent.call(this); + this.m_type = b2Shape.e_chain; + this.m_radius = b2_polygonRadius; + this.m_vertices = null; + this.m_count = 0; + this.m_prevVertex = new b2Vec2(); + this.m_nextVertex = new b2Vec2(); + this.m_hasPrevVertex = false; + this.m_hasNextVertex = false; + Object.seal(this) + } + b2ChainShape.prototype = { + CreateLoop: function (vertices, count) { + for (var i = 1; i < count; ++i) { + var v1 = vertices[i - 1]; + var v2 = vertices[i] + } + this.m_count = count + 1; + this.m_vertices = new Array(this.m_count); + for (var i = 0; i < count; ++i) { + this.m_vertices[i] = vertices[i].Clone() + } + this.m_vertices[count] = this.m_vertices[0].Clone(); + this.m_prevVertex.Assign(this.m_vertices[this.m_count - 2]); + this.m_nextVertex.Assign(this.m_vertices[1]); + this.m_hasPrevVertex = true; + this.m_hasNextVertex = true + }, + CreateChain: function (vertices, count) { + for (var i = 1; i < count; ++i) { + var v1 = vertices[i - 1]; + var v2 = vertices[i] + } + this.m_count = count; + this.m_vertices = new Array(count); + for (var i = 0; i < count; ++i) { + this.m_vertices[i] = vertices[i].Clone() + } + this.m_hasPrevVertex = false; + this.m_hasNextVertex = false; + this.m_prevVertex.SetZero(); + this.m_nextVertex.SetZero() + }, + SetPrevVertex: function (prevVertex) { + this.m_prevVertex.Assign(prevVertex); + this.m_hasPrevVertex = true + }, + SetNextVertex: function (nextVertex) { + this.m_nextVertex.Assign(nextVertex); + this.m_hasNextVertex = true + }, + Clone: function () { + var shape = new b2ChainShape(); + shape.m_count = this.m_count; + shape.m_vertices = new Array(this.m_count); + for (var i = 0; i < this.m_count; ++i) { + shape.m_vertices[i] = this.m_vertices[i].Clone() + } + shape.m_prevVertex = this.m_prevVertex.Clone(); + shape.m_nextVertex = this.m_nextVertex.Clone(); + shape.m_hasPrevVertex = this.m_hasPrevVertex; + shape.m_hasNextVertex = this.m_hasNextVertex; + return shape + }, + GetChildCount: function () { + return this.m_count - 1 + }, + GetChildEdge: function (edge, index) { + edge.m_type = b2Shape.e_edge; + edge.m_radius = this.m_radius; + edge.m_vertex1 = this.m_vertices[index + 0]; + edge.m_vertex2 = this.m_vertices[index + 1]; + if (index > 0) { + edge.m_vertex0 = this.m_vertices[index - 1]; + edge.m_hasVertex0 = true + } else { + edge.m_vertex0 = this.m_prevVertex; + edge.m_hasVertex0 = this.m_hasPrevVertex + } + if (index < this.m_count - 2) { + edge.m_vertex3 = this.m_vertices[index + 2]; + edge.m_hasVertex3 = true + } else { + edge.m_vertex3 = this.m_nextVertex; + edge.m_hasVertex3 = this.m_hasNextVertex + } + }, + TestPoint: function (transform, p) { + return false + }, + RayCast: function (output, input, xf, childIndex) { + var edgeShape = new b2EdgeShape(); + var i1 = childIndex; + var i2 = childIndex + 1; + if (i2 == this.m_count) { + i2 = 0 + } + edgeShape.m_vertex1 = this.m_vertices[i1].Clone(); + edgeShape.m_vertex2 = this.m_vertices[i2].Clone(); + return edgeShape.RayCast(output, input, xf, 0) + }, + ComputeAABB: function (aabb, xf, childIndex) { + var i1 = childIndex; + var i2 = childIndex + 1; + if (i2 == this.m_count) { + i2 = 0 + } + var v1x = (xf.q.c * this.m_vertices[i1].x - xf.q.s * this.m_vertices[i1].y) + xf.p.x; + var v1y = (xf.q.s * this.m_vertices[i1].x + xf.q.c * this.m_vertices[i1].y) + xf.p.y; + var v2x = (xf.q.c * this.m_vertices[i2].x - xf.q.s * this.m_vertices[i2].y) + xf.p.x; + var v2y = (xf.q.s * this.m_vertices[i2].x + xf.q.c * this.m_vertices[i2].y) + xf.p.y; + aabb.lowerBound.x = b2Min(v1x, v2x); + aabb.lowerBound.y = b2Min(v1y, v2y); + aabb.upperBound.x = b2Max(v1x, v2x); + aabb.upperBound.y = b2Max(v1y, v2y) + }, + ComputeMass: function (massData, density) { + massData.mass = 0; + massData.center.SetZero(); + massData.I = 0 + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_count = this.m_count; + obj.m_vertices = []; + for (var i = 0; i < this.m_count; ++i) { + obj.m_vertices.push(this.m_vertices[i]._serialize()) + } + obj.m_hasPrevVertex = this.m_hasPrevVertex; + if (this.m_hasPrevVertex) { + obj.m_prevVertex = this.m_prevVertex._serialize() + } + obj.m_hasNextVertex = this.m_hasNextVertex; + if (this.m_hasNextVertex) { + obj.m_nextVertex = this.m_nextVertex._serialize() + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_count = data.m_count; + this.m_vertices = []; + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i] = new b2Vec2(); + this.m_vertices[i]._deserialize(data.m_vertices[i]) + } + this.m_hasPrevVertex = data.m_hasPrevVertex; + if (this.m_hasPrevVertex) { + this.m_prevVertex._deserialize(data.m_prevVertex) + } + this.m_hasNextVertex = data.m_hasNextVertex; + if (this.m_hasNextVertex) { + this.m_nextVertex._deserialize(data.m_nextVertex) + } + } + }; + b2ChainShape._extend(b2Shape); + "use strict"; + + function b2PolygonShape() { + this.parent.call(this); + this.m_type = b2Shape.e_polygon; + this.m_radius = b2_polygonRadius; + this.m_count = 0; + this.m_centroid = new b2Vec2(); + this.m_vertices = new Array(b2_maxPolygonVertices); + this.m_normals = new Array(b2_maxPolygonVertices); + Object.seal(this) + } + b2PolygonShape.prototype = { + Clone: function () { + var shape = new b2PolygonShape(); + shape.m_count = this.m_count; + shape.m_centroid = this.m_centroid.Clone(); + for (var i = 0; i < this.m_count; ++i) { + shape.m_vertices[i] = this.m_vertices[i].Clone(); + shape.m_normals[i] = this.m_normals[i].Clone() + } + return shape + }, + GetChildCount: function () { + return 1 + }, + Set: function (vertices, count) { + if (count < 3) { + this.SetAsBox(1, 1); + return + } + var n = b2Min(count, b2_maxPolygonVertices); + var ps = new Array(b2_maxPolygonVertices); + var tempCount = 0; + for (var i = 0; i < n; ++i) { + var v = vertices[i]; + var unique = true; + for (var j = 0; j < tempCount; ++j) { + if (b2DistanceSquared(v, ps[j]) < 0.5 * b2_linearSlop) { + unique = false; + break + } + } + if (unique) { + ps[tempCount++] = v.Clone() + } + } + n = tempCount; + if (n < 3) { + this.SetAsBox(1, 1); + return + } + var i0 = 0; + var x0 = ps[0].x; + for (i = 1; i < n; ++i) { + var x = ps[i].x; + if (x > x0 || (x == x0 && ps[i].y < ps[i0].y)) { + i0 = i; + x0 = x + } + } + var hull = new Array(b2_maxPolygonVertices); + var m = 0; + var ih = i0; + for (;;) { + hull[m] = ih; + var ie = 0; + for (j = 1; j < n; ++j) { + if (ie == ih) { + ie = j; + continue + } + var r = b2Vec2.Subtract(ps[ie], ps[hull[m]]); + var v = b2Vec2.Subtract(ps[j], ps[hull[m]]); + var c = b2Cross_v2_v2(r, v); + if (c < 0) { + ie = j + } + if (c == 0 && v.LengthSquared() > r.LengthSquared()) { + ie = j + } + }++m; + ih = ie; + if (ie == i0) { + break + } + } + this.m_count = m; + for (i = 0; i < m; ++i) { + this.m_vertices[i] = ps[hull[i]].Clone() + } + for (i = 0; i < m; ++i) { + var i1 = i; + var i2 = i + 1 < m ? i + 1 : 0; + var edge = b2Vec2.Subtract(this.m_vertices[i2], this.m_vertices[i1]); + this.m_normals[i] = b2Cross_v2_f(edge, 1).Clone(); + this.m_normals[i].Normalize() + } + this.m_centroid = b2PolygonShape.ComputeCentroid(this.m_vertices, m) + }, + SetAsBox: function (hx, hy, center, angle) { + this.m_count = 4; + this.m_vertices[0] = new b2Vec2(-hx, -hy); + this.m_vertices[1] = new b2Vec2(hx, -hy); + this.m_vertices[2] = new b2Vec2(hx, hy); + this.m_vertices[3] = new b2Vec2(-hx, hy); + this.m_normals[0] = new b2Vec2(0, -1); + this.m_normals[1] = new b2Vec2(1, 0); + this.m_normals[2] = new b2Vec2(0, 1); + this.m_normals[3] = new b2Vec2(-1, 0); + if (!center) { + return + } + this.m_centroid.Assign(center); + var xf = new b2Transform(); + xf.p = center; + xf.q.Set(angle); + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i].Assign(b2Mul_t_v2(xf, this.m_vertices[i])); + this.m_normals[i].Assign(b2Mul_r_v2(xf.q, this.m_normals[i])) + } + }, + TestPoint: function (xf, p) { + var pLocal = b2MulT_r_v2(xf.q, b2Vec2.Subtract(p, xf.p)); + for (var i = 0; i < this.m_count; ++i) { + var dot = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(pLocal, this.m_vertices[i])); + if (dot > 0) { + return false + } + } + return true + }, + RayCast: function (output, input, xf, childIndex) { + var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); + var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); + var d = b2Vec2.Subtract(p2, p1); + var lower = 0, + upper = input.maxFraction; + var index = -1; + for (var i = 0; i < this.m_count; ++i) { + var numerator = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(this.m_vertices[i], p1)); + var denominator = b2Dot_v2_v2(this.m_normals[i], d); + if (denominator == 0) { + if (numerator < 0) { + return false + } + } else { + if (denominator < 0 && numerator < lower * denominator) { + lower = numerator / denominator; + index = i + } else { + if (denominator > 0 && numerator < upper * denominator) { + upper = numerator / denominator + } + } + } + if (upper < lower) { + return false + } + } + if (index >= 0) { + output.fraction = lower; + output.normal = b2Mul_r_v2(xf.q, this.m_normals[index]); + return true + } + return false + }, + ComputeAABB: function (aabb, xf, childIndex) { + var lowerx = (xf.q.c * this.m_vertices[0].x - xf.q.s * this.m_vertices[0].y) + xf.p.x; + var lowery = (xf.q.s * this.m_vertices[0].x + xf.q.c * this.m_vertices[0].y) + xf.p.y; + var upperx = lowerx; + var uppery = lowery; + for (var i = 1; i < this.m_count; ++i) { + var vx = (xf.q.c * this.m_vertices[i].x - xf.q.s * this.m_vertices[i].y) + xf.p.x; + var vy = (xf.q.s * this.m_vertices[i].x + xf.q.c * this.m_vertices[i].y) + xf.p.y; + lowerx = b2Min(lowerx, vx); + lowery = b2Min(lowery, vy); + upperx = b2Max(upperx, vx); + uppery = b2Max(uppery, vy) + } + aabb.lowerBound.x = lowerx - this.m_radius; + aabb.lowerBound.y = lowery - this.m_radius; + aabb.upperBound.x = upperx + this.m_radius; + aabb.upperBound.y = uppery + this.m_radius + }, + ComputeMass: function (massData, density) { + var center = new b2Vec2(0, 0); + var area = 0; + var I = 0; + var s = new b2Vec2(0, 0); + for (var i = 0; i < this.m_count; ++i) { + s.Add(this.m_vertices[i]) + } + s.Multiply(1 / this.m_count); + var k_inv3 = 1 / 3; + for (var i = 0; i < this.m_count; ++i) { + var e1 = b2Vec2.Subtract(this.m_vertices[i], s); + var e2 = i + 1 < this.m_count ? b2Vec2.Subtract(this.m_vertices[i + 1], s) : b2Vec2.Subtract(this.m_vertices[0], s); + var D = b2Cross_v2_v2(e1, e2); + var triangleArea = 0.5 * D; + area += triangleArea; + center.Add(b2Vec2.Multiply(triangleArea * k_inv3, b2Vec2.Add(e1, e2))); + var ex1 = e1.x, + ey1 = e1.y; + var ex2 = e2.x, + ey2 = e2.y; + var intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2; + var inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2; + I += (0.25 * k_inv3 * D) * (intx2 + inty2) + } + massData.mass = density * area; + center.Multiply(1 / area); + massData.center = b2Vec2.Add(center, s); + massData.I = density * I; + massData.I += massData.mass * (b2Dot_v2_v2(massData.center, massData.center) - b2Dot_v2_v2(center, center)) + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertex: function (index) { + return this.m_vertices[index] + }, + Validate: function () { + for (var i = 0; i < this.m_count; ++i) { + var i1 = i; + var i2 = i < this.m_count - 1 ? i1 + 1 : 0; + var p = this.m_vertices[i1]; + var e = b2Vec2.Subtract(this.m_vertices[i2], p); + for (var j = 0; j < this.m_count; ++j) { + if (j == i1 || j == i2) { + continue + } + var v = b2Vec2.Subtract(this.m_vertices[j], p); + var c = b2Cross_v2_v2(e, v); + if (c < 0) { + return false + } + } + } + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_count = this.m_count; + obj.m_centroid = this.m_centroid._serialize(); + obj.m_vertices = []; + obj.m_normals = []; + for (var i = 0; i < this.m_count; ++i) { + obj.m_vertices.push(this.m_vertices[i]._serialize()); + obj.m_normals.push(this.m_normals[i]._serialize()) + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_count = data.m_count; + this.m_centroid._deserialize(data.m_centroid); + this.m_vertices = []; + this.m_normals = []; + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i] = new b2Vec2(); + this.m_vertices[i]._deserialize(data.m_vertices[i]); + this.m_normals[i] = new b2Vec2(); + this.m_normals[i]._deserialize(data.m_normals[i]) + } + } + }; + b2PolygonShape.ComputeCentroid = function (vs, count) { + var c = new b2Vec2(); + var area = 0; + var pRef = new b2Vec2(0, 0); + var inv3 = 1 / 3; + for (var i = 0; i < count; ++i) { + var p1 = pRef; + var p2 = vs[i]; + var p3 = i + 1 < count ? vs[i + 1] : vs[0]; + var e1 = b2Vec2.Subtract(p2, p1); + var e2 = b2Vec2.Subtract(p3, p1); + var D = b2Cross_v2_v2(e1, e2); + var triangleArea = 0.5 * D; + area += triangleArea; + c.Add(b2Vec2.Multiply(triangleArea, b2Vec2.Multiply(inv3, b2Vec2.Add(b2Vec2.Add(p1, p2), p3)))) + } + c.Multiply(1 / area); + return c + }; + b2PolygonShape._extend(b2Shape); + "use strict"; + + function b2Pair() { + this.proxyIdA = 0; + this.proxyIdB = 0 + } + + function b2PairLessThan(pair1, pair2) { + if (pair1.proxyIdA == pair2.proxyIdA) { + return pair1.proxyIdB - pair2.proxyIdB + } + return pair1.proxyIdA - pair2.proxyIdA + } + + function b2BroadPhase() { + this.m_tree = new b2DynamicTree(); + this.m_queryProxyId = 0; + this.m_proxyCount = 0; + this.m_pairCount = 0; + this.m_pairBuffer = []; + this.m_moveCount = 0; + this.m_moveBuffer = [] + } + b2BroadPhase.prototype = { + CreateProxy: function (aabb, userData) { + var proxyId = this.m_tree.CreateProxy(aabb, userData); + ++this.m_proxyCount; + this.BufferMove(proxyId); + return proxyId + }, + DestroyProxy: function (proxyId) { + this.UnBufferMove(proxyId); + --this.m_proxyCount; + this.m_tree.DestroyProxy(proxyId) + }, + MoveProxy: function (proxyId, aabb, displacement) { + var buffer = this.m_tree.MoveProxy(proxyId, aabb, displacement); + if (buffer) { + this.BufferMove(proxyId) + } + }, + TouchProxy: function (proxyId) { + this.BufferMove(proxyId) + }, + GetFatAABB: function (proxyId) { + return this.m_tree.GetFatAABB(proxyId) + }, + GetUserData: function (proxyId) { + return this.m_tree.GetUserData(proxyId) + }, + TestOverlap: function (proxyIdA, proxyIdB) { + var aabbA = this.m_tree.GetFatAABB(proxyIdA); + var aabbB = this.m_tree.GetFatAABB(proxyIdB); + return b2TestOverlap(aabbA, aabbB) + }, + GetProxyCount: function () { + return this.m_proxyCount + }, + UpdatePairs: function (callback) { + this.m_pairCount = 0; + this.m_pairBuffer.length = 0; + for (var i = 0; i < this.m_moveCount; ++i) { + this.m_queryProxyId = this.m_moveBuffer[i]; + if (this.m_queryProxyId == b2BroadPhase.e_nullProxy) { + continue + } + var fatAABB = this.m_tree.GetFatAABB(this.m_queryProxyId); + this.m_tree.Query(this, fatAABB) + } + this.m_moveCount = 0; + this.m_pairBuffer.sort(b2PairLessThan); + var i = 0; + while (i < this.m_pairCount) { + var primaryPair = this.m_pairBuffer[i]; + var userDataA = this.m_tree.GetUserData(primaryPair.proxyIdA); + var userDataB = this.m_tree.GetUserData(primaryPair.proxyIdB); + callback.AddPair(userDataA, userDataB); + ++i; + while (i < this.m_pairCount) { + var pair = this.m_pairBuffer[i]; + if (pair.proxyIdA != primaryPair.proxyIdA || pair.proxyIdB != primaryPair.proxyIdB) { + break + }++i + } + } + }, + Query: function (callback, aabb) { + this.m_tree.Query(callback, aabb) + }, + RayCast: function (callback, input) { + this.m_tree.RayCast(callback, input) + }, + GetTreeHeight: function () { + return this.m_tree.GetHeight() + }, + GetTreeBalance: function () { + return this.m_tree.GetMaxBalance() + }, + GetTreeQuality: function () { + return this.m_tree.GetAreaRatio() + }, + ShiftOrigin: function (newOrigin) { + this.m_tree.ShiftOrigin(newOrigin) + }, + BufferMove: function (proxyId) { + this.m_moveBuffer[this.m_moveCount] = proxyId; + ++this.m_moveCount + }, + UnBufferMove: function (proxyId) { + for (var i = 0; i < this.m_moveCount; ++i) { + if (this.m_moveBuffer[i] == proxyId) { + this.m_moveBuffer[i] = b2BroadPhase.e_nullProxy + } + } + }, + QueryCallback: function (proxyId) { + if (proxyId == this.m_queryProxyId) { + return true + } + this.m_pairBuffer[this.m_pairCount] = new b2Pair(); + this.m_pairBuffer[this.m_pairCount].proxyIdA = b2Min(proxyId, this.m_queryProxyId); + this.m_pairBuffer[this.m_pairCount].proxyIdB = b2Max(proxyId, this.m_queryProxyId); + ++this.m_pairCount; + return true + } + }; + b2BroadPhase.e_nullProxy = -1; + "use strict"; + + function b2DistanceProxy() { + this.m_vertices = null; + this.m_count = 0; + this.m_radius = 0 + } + b2DistanceProxy.prototype = { + Assign: function (l) { + this.m_vertices = l.m_vertices; + this.m_count = l.m_count; + this.m_radius = l.m_radius + }, + Set: function (shape, index) { + switch (shape.GetType()) { + case b2Shape.e_circle: + var circle = shape; + this.m_vertices = [circle.m_p]; + this.m_count = 1; + this.m_radius = circle.m_radius; + break; + case b2Shape.e_polygon: + var polygon = shape; + this.m_vertices = polygon.m_vertices; + this.m_count = polygon.m_count; + this.m_radius = polygon.m_radius; + break; + case b2Shape.e_chain: + var chain = shape; + this.m_vertices = [chain.m_vertices[index]]; + if (index + 1 < chain.m_count) { + this.m_vertices[1] = chain.m_vertices[index + 1] + } else { + this.m_vertices[1] = chain.m_vertices[0] + } + this.m_count = 2; + this.m_radius = chain.m_radius; + break; + case b2Shape.e_edge: + var edge = shape; + this.m_vertices = [edge.m_vertex1, edge.m_vertex2]; + this.m_count = 2; + this.m_radius = edge.m_radius; + break + } + }, + GetSupport: function (dx, dy) { + var bestIndex = 0; + var bestValue = this.m_vertices[0].x * dx + this.m_vertices[0].y * dy; + for (var i = 1; i < this.m_count; ++i) { + var value = this.m_vertices[i].x * dx + this.m_vertices[i].y * dy; + if (value > bestValue) { + bestIndex = i; + bestValue = value + } + } + return bestIndex + }, + GetSupportVertex: function (dx, dy) { + return this.m_vertices[this.GetSupport(dx, dy)] + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertex: function (index) { + return this.m_vertices[index] + } + }; + + function b2SimplexCache() { + this.metric = 0; + this.count = 0; + this.indexA = [0, 0, 0]; + this.indexB = [0, 0, 0] + } + + function b2DistanceInput() { + this.proxyA = new b2DistanceProxy(); + this.proxyB = new b2DistanceProxy(); + this.transformA = new b2Transform(); + this.transformB = new b2Transform(); + this.useRadii = false + } + + function b2DistanceOutput() { + this.pointA = new b2Vec2(); + this.pointB = new b2Vec2(); + this.distance = 0; + this.iterations = 0 + } + + function b2SimplexVertex() { + this.wA = new b2Vec2(); + this.wB = new b2Vec2(); + this.w = new b2Vec2(); + this.a = 0; + this.indexA = 0; + this.indexB = 0 + } + b2SimplexVertex.prototype = { + Assign: function (l) { + this.wA.x = l.wA.x; + this.wA.y = l.wA.y; + this.wB.x = l.wB.x; + this.wB.y = l.wB.y; + this.w.x = l.w.x; + this.w.y = l.w.y; + this.a = l.a; + this.indexA = l.indexA; + this.indexB = l.indexB + } + }; + + function b2Simplex() { + this.m_v = [new b2SimplexVertex(), new b2SimplexVertex(), new b2SimplexVertex()]; + this.m_count = 0 + } + b2Simplex.prototype = { + ReadCache: function (cache, proxyA, transformA, proxyB, transformB) { + this.m_count = cache.count; + var vertices = this.m_v; + for (var i = 0; i < this.m_count; ++i) { + var v = vertices[i]; + v.indexA = cache.indexA[i]; + v.indexB = cache.indexB[i]; + var wALocal = proxyA.GetVertex(v.indexA); + var wBLocal = proxyB.GetVertex(v.indexB); + v.wA.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; + v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; + v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; + v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; + v.w.x = v.wB.x - v.wA.x; + v.w.y = v.wB.y - v.wA.y; + v.a = 0 + } + if (this.m_count > 1) { + var metric1 = cache.metric; + var metric2 = this.GetMetric(); + if (metric2 < 0.5 * metric1 || 2 * metric1 < metric2 || metric2 < b2_epsilon) { + this.m_count = 0 + } + } + if (this.m_count == 0) { + var v = vertices[0]; + v.indexA = 0; + v.indexB = 0; + var wALocal = proxyA.GetVertex(0); + var wBLocal = proxyB.GetVertex(0); + v.wA.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; + v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; + v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; + v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; + v.w.x = v.wB.x - v.wA.x; + v.w.y = v.wB.y - v.wA.y; + v.a = 1; + this.m_count = 1 + } + }, + WriteCache: function (cache) { + cache.metric = this.GetMetric(); + cache.count = this.m_count; + var vertices = this.m_v; + for (var i = 0; i < this.m_count; ++i) { + cache.indexA[i] = vertices[i].indexA; + cache.indexB[i] = vertices[i].indexB + } + }, + GetSearchDirection: function (p) { + switch (this.m_count) { + case 1: + p.x = -this.m_v[0].w.x; + p.y = -this.m_v[0].w.y; + break; + case 2: + var e12x = this.m_v[1].w.x - this.m_v[0].w.x; + var e12y = this.m_v[1].w.y - this.m_v[0].w.y; + var sgn = e12x * -this.m_v[0].w.y - e12y * -this.m_v[0].w.x; + if (sgn > 0) { + p.x = -1 * e12y; + p.y = 1 * e12x + } else { + p.x = 1 * e12y; + p.y = -1 * e12x + } + break + } + }, + GetClosestPoint: function (p) { + switch (this.m_count) { + case 1: + p.x = this.m_v[0].w.x; + p.y = this.m_v[0].w.y; + break; + case 2: + p.x = (this.m_v[0].a * this.m_v[0].w.x) + (this.m_v[1].a * this.m_v[1].w.x); + p.y = (this.m_v[0].a * this.m_v[0].w.y) + (this.m_v[1].a * this.m_v[1].w.y); + break; + case 3: + p.x = p.y = 0; + break + } + }, + GetWitnessPoints: function (pA, pB) { + switch (this.m_count) { + case 1: + pA.x = this.m_v[0].wA.x; + pA.y = this.m_v[0].wA.y; + pB.x = this.m_v[0].wB.x; + pB.y = this.m_v[0].wB.y; + break; + case 2: + pA.x = (this.m_v[0].a * this.m_v[0].wA.x) + (this.m_v[1].a * this.m_v[1].wA.x); + pA.y = (this.m_v[0].a * this.m_v[0].wA.y) + (this.m_v[1].a * this.m_v[1].wA.y); + pB.x = (this.m_v[0].a * this.m_v[0].wB.x) + (this.m_v[1].a * this.m_v[1].wB.x); + pB.y = (this.m_v[0].a * this.m_v[0].wB.y) + (this.m_v[1].a * this.m_v[1].wB.y); + break; + case 3: + pA.x = (this.m_v[0].a, this.m_v[0].wA.x) + (this.m_v[1].a, this.m_v[1].wA.x) + (this.m_v[2].a, this.m_v[2].wA.x); + pA.y = (this.m_v[0].a, this.m_v[0].wA.y) + (this.m_v[1].a, this.m_v[1].wA.y) + (this.m_v[2].a, this.m_v[2].wA.y); + pB.x = pA.x; + pB.y = pA.y; + break + } + }, + GetMetric: function () { + switch (this.m_count) { + case 1: + return 0; + case 2: + return b2Distance(this.m_v[0].w, this.m_v[1].w); + case 3: + return (this.m_v[1].w.x - this.m_v[0].w.x) * (this.m_v[2].w.y - this.m_v[0].w.y) - (this.m_v[1].w.y - this.m_v[0].w.y) * (this.m_v[2].w.x - this.m_v[0].w.x) + } + }, + Solve2: function () { + var w1 = this.m_v[0].w; + var w2 = this.m_v[1].w; + var e12x = w2.x - w1.x; + var e12y = w2.y - w1.y; + var d12_2 = -(w1.x * e12x + w1.y * e12y); + if (d12_2 <= 0) { + this.m_v[0].a = 1; + this.m_count = 1; + return + } + var d12_1 = w2.x * e12x + w2.y * e12y; + if (d12_1 <= 0) { + this.m_v[1].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[1]); + return + } + var inv_d12 = 1 / (d12_1 + d12_2); + this.m_v[0].a = d12_1 * inv_d12; + this.m_v[1].a = d12_2 * inv_d12; + this.m_count = 2 + }, + Solve3: function () { + var w1 = this.m_v[0].w; + var w2 = this.m_v[1].w; + var w3 = this.m_v[2].w; + var e12x = w2.x - w1.x; + var e12y = w2.y - w1.y; + var w1e12 = w1.x * e12x + w1.y * e12y; + var w2e12 = w2.x * e12x + w2.y * e12y; + var d12_1 = w2e12; + var d12_2 = -w1e12; + var e13x = w3.x - w1.x; + var e13y = w3.y - w1.y; + var w1e13 = w1.x * e13x + w1.y * e13y; + var w3e13 = w3.x * e13x + w3.y * e13y; + var d13_1 = w3e13; + var d13_2 = -w1e13; + var e23x = w3.x - w2.x; + var e23y = w3.y - w2.y; + var w2e23 = w2.x * e23x + w2.y * e23y; + var w3e23 = w3.x * e23x + w3.y * e23y; + var d23_1 = w3e23; + var d23_2 = -w2e23; + var n123 = e12x * e13y - e12y * e13x; + var d123_1 = n123 * (w2.x * w3.y - w2.y * w3.x); + var d123_2 = n123 * (w3.x * w1.y - w3.y * w1.x); + var d123_3 = n123 * (w1.x * w2.y - w1.y * w2.x); + if (d12_2 <= 0 && d13_2 <= 0) { + this.m_v[0].a = 1; + this.m_count = 1; + return + } + if (d12_1 > 0 && d12_2 > 0 && d123_3 <= 0) { + var inv_d12 = 1 / (d12_1 + d12_2); + this.m_v[0].a = d12_1 * inv_d12; + this.m_v[1].a = d12_2 * inv_d12; + this.m_count = 2; + return + } + if (d13_1 > 0 && d13_2 > 0 && d123_2 <= 0) { + var inv_d13 = 1 / (d13_1 + d13_2); + this.m_v[0].a = d13_1 * inv_d13; + this.m_v[2].a = d13_2 * inv_d13; + this.m_count = 2; + this.m_v[1].Assign(this.m_v[2]); + return + } + if (d12_1 <= 0 && d23_2 <= 0) { + this.m_v[1].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[1]); + return + } + if (d13_1 <= 0 && d23_1 <= 0) { + this.m_v[2].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[2]); + return + } + if (d23_1 > 0 && d23_2 > 0 && d123_1 <= 0) { + var inv_d23 = 1 / (d23_1 + d23_2); + this.m_v[1].a = d23_1 * inv_d23; + this.m_v[2].a = d23_2 * inv_d23; + this.m_count = 2; + this.m_v[0].Assign(this.m_v[2]); + return + } + var inv_d123 = 1 / (d123_1 + d123_2 + d123_3); + this.m_v[0].a = d123_1 * inv_d123; + this.m_v[1].a = d123_2 * inv_d123; + this.m_v[2].a = d123_3 * inv_d123; + this.m_count = 3 + } + }; + var _b2Distance_simplex = new b2Simplex(); + var _b2Distance_normal = new b2Vec2(); + var _b2Distance_p = new b2Vec2(); + + function b2DistanceFunc(output, cache, input) { + ++b2DistanceFunc.b2_gjkCalls; + var proxyA = input.proxyA; + var proxyB = input.proxyB; + var transformA = input.transformA; + var transformB = input.transformB; + _b2Distance_simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB); + var vertices = _b2Distance_simplex.m_v; + var k_maxIters = 20; + var saveA = [0, 0, 0], + saveB = [0, 0, 0]; + var saveCount = 0; + var distanceSqr1 = b2_maxFloat; + var distanceSqr2 = distanceSqr1; + var iter = 0; + while (iter < k_maxIters) { + saveCount = _b2Distance_simplex.m_count; + for (var i = 0; i < saveCount; ++i) { + saveA[i] = vertices[i].indexA; + saveB[i] = vertices[i].indexB + } + switch (_b2Distance_simplex.m_count) { + case 1: + break; + case 2: + _b2Distance_simplex.Solve2(); + break; + case 3: + _b2Distance_simplex.Solve3(); + break + } + if (_b2Distance_simplex.m_count == 3) { + break + } + _b2Distance_simplex.GetClosestPoint(_b2Distance_p); + distanceSqr2 = _b2Distance_p.LengthSquared(); + if (distanceSqr2 >= distanceSqr1) {} + distanceSqr1 = distanceSqr2; + _b2Distance_simplex.GetSearchDirection(_b2Distance_p); + if (_b2Distance_p.LengthSquared() < b2_epsilon * b2_epsilon) { + break + } + var vertex = vertices[_b2Distance_simplex.m_count]; + vertex.indexA = proxyA.GetSupport(transformA.q.c * -_b2Distance_p.x + transformA.q.s * -_b2Distance_p.y, -transformA.q.s * -_b2Distance_p.x + transformA.q.c * -_b2Distance_p.y); + var pva = proxyA.GetVertex(vertex.indexA); + vertex.wA.x = (transformA.q.c * pva.x - transformA.q.s * pva.y) + transformA.p.x; + vertex.wA.y = (transformA.q.s * pva.x + transformA.q.c * pva.y) + transformA.p.y; + vertex.indexB = proxyB.GetSupport(transformB.q.c * _b2Distance_p.x + transformB.q.s * _b2Distance_p.y, -transformB.q.s * _b2Distance_p.x + transformB.q.c * _b2Distance_p.y); + var pvb = proxyB.GetVertex(vertex.indexB); + vertex.wB.x = (transformB.q.c * pvb.x - transformB.q.s * pvb.y) + transformB.p.x; + vertex.wB.y = (transformB.q.s * pvb.x + transformB.q.c * pvb.y) + transformB.p.y; + vertex.w.x = vertex.wB.x - vertex.wA.x; + vertex.w.y = vertex.wB.y - vertex.wA.y; + ++iter; + ++b2DistanceFunc.b2_gjkIters; + var duplicate = false; + for (var i = 0; i < saveCount; ++i) { + if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) { + duplicate = true; + break + } + } + if (duplicate) { + break + }++_b2Distance_simplex.m_count + } + b2DistanceFunc.b2_gjkMaxIters = b2Max(b2DistanceFunc.b2_gjkMaxIters, iter); + _b2Distance_simplex.GetWitnessPoints(output.pointA, output.pointB); + output.distance = b2Distance(output.pointA, output.pointB); + output.iterations = iter; + _b2Distance_simplex.WriteCache(cache); + if (input.useRadii) { + var rA = proxyA.m_radius; + var rB = proxyB.m_radius; + if (output.distance > rA + rB && output.distance > b2_epsilon) { + output.distance -= rA + rB; + _b2Distance_normal.x = output.pointB.x - output.pointA.x; + _b2Distance_normal.y = output.pointB.y - output.pointA.y; + _b2Distance_normal.Normalize(); + output.pointA.x += (rA * _b2Distance_normal.x); + output.pointA.y += (rA * _b2Distance_normal.y); + output.pointB.x -= (rB * _b2Distance_normal.x); + output.pointB.y -= (rB * _b2Distance_normal.y) + } else { + var px = (0.5 * (output.pointA.x + output.pointB.x)); + var py = (0.5 * (output.pointA.y + output.pointB.y)); + output.pointA.x = px; + output.pointA.y = py; + output.pointB.x = px; + output.pointB.y = py; + output.distance = 0 + } + } + } + b2DistanceFunc.b2_gjkCalls = 0; + b2DistanceFunc.b2_gjkIters = 0; + b2DistanceFunc.b2_gjkMaxIters = 0; + "use strict"; + var b2_nullFeature = 255; + + function b2ContactID() {} + b2ContactID.prototype = { + indexA: 0, + indexB: 0, + typeA: 0, + typeB: 0, + Reset: function () { + this.indexA = this.indexB = this.typeA = this.typeB = 0 + }, + Get: function () { + return this.indexA | (this.indexB << 8) | (this.typeA << 16) | (this.typeB << 24) + }, + Assign: function (k) { + this.indexA = k.indexA; + this.indexB = k.indexB; + this.typeA = k.typeA; + this.typeB = k.typeB + } + }; + b2ContactID.e_vertex = 0; + b2ContactID.e_face = 1; + + function b2ManifoldPoint() { + this.localPoint = new b2Vec2(); + this.normalImpulse = 0; + this.tangentImpulse = 0; + this.id = new b2ContactID() + } + b2ManifoldPoint.prototype = { + Clone: function () { + var point = new b2ManifoldPoint(); + point.localPoint.x = this.localPoint.x; + point.localPoint.y = this.localPoint.y; + point.normalImpulse = this.normalImpulse; + point.tangentImpulse = this.tangentImpulse; + point.id.Assign(this.id); + return point + } + }; + + function b2Manifold() { + this.points = new Array(b2_maxManifoldPoints); + this.localNormal = new b2Vec2(); + this.localPoint = new b2Vec2(); + this.type = 0; + this.pointCount = 0 + } + b2Manifold.prototype = { + Clone: function () { + var manifold = new b2Manifold(); + manifold.pointCount = this.pointCount; + manifold.type = this.type; + manifold.localPoint.x = this.localPoint.x; + manifold.localPoint.y = this.localPoint.y; + manifold.localNormal.x = this.localNormal.x; + manifold.localNormal.y = this.localNormal.y; + for (var i = 0; i < this.pointCount; ++i) { + manifold.points[i] = this.points[i].Clone() + } + return manifold + }, + Assign: function (manifold) { + this.pointCount = manifold.pointCount; + this.type = manifold.type; + this.localPoint.x = manifold.localPoint.x; + this.localPoint.y = manifold.localPoint.y; + this.localNormal.x = manifold.localNormal.x; + this.localNormal.y = manifold.localNormal.y; + for (var i = 0; i < this.pointCount; ++i) { + this.points[i] = manifold.points[i].Clone() + } + } + }; + b2Manifold.e_circles = 0; + b2Manifold.e_faceA = 1; + b2Manifold.e_faceB = 2; + b2Manifold.b2_nullState = 0; + b2Manifold.b2_addState = 1; + b2Manifold.b2_persistState = 2; + b2Manifold.b2_removeState = 3; + + function b2WorldManifold() { + this.normal = new b2Vec2(); + this.points = new Array(b2_maxManifoldPoints); + this.separations = new Array(b2_maxManifoldPoints) + } + b2WorldManifold.prototype = { + Initialize: function (manifold, xfA, radiusA, xfB, radiusB) { + if (manifold.pointCount == 0) { + return + } + switch (manifold.type) { + case b2Manifold.e_circles: + this.normal.x = 1; + this.normal.y = 0; + var pointAx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; + var pointAy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; + var pointBx = (xfB.q.c * manifold.points[0].localPoint.x - xfB.q.s * manifold.points[0].localPoint.y) + xfB.p.x; + var pointBy = (xfB.q.s * manifold.points[0].localPoint.x + xfB.q.c * manifold.points[0].localPoint.y) + xfB.p.y; + var cx = pointAx - pointBx; + var cy = pointAy - pointBy; + if ((cx * cx + cy * cy) > b2_epsilon * b2_epsilon) { + this.normal.x = pointBx - pointAx; + this.normal.y = pointBy - pointAy; + this.normal.Normalize() + } + var cAx = pointAx + (radiusA * this.normal.x); + var cAy = pointAy + (radiusA * this.normal.y); + var cBx = pointBx - (radiusB * this.normal.x); + var cBy = pointBy - (radiusB * this.normal.y); + this.points[0] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[0] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y; + break; + case b2Manifold.e_faceA: + this.normal.x = xfA.q.c * manifold.localNormal.x - xfA.q.s * manifold.localNormal.y; + this.normal.y = xfA.q.s * manifold.localNormal.x + xfA.q.c * manifold.localNormal.y; + var planePointx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; + var planePointy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; + for (var i = 0; i < manifold.pointCount; ++i) { + var clipPointx = (xfB.q.c * manifold.points[i].localPoint.x - xfB.q.s * manifold.points[i].localPoint.y) + xfB.p.x; + var clipPointy = (xfB.q.s * manifold.points[i].localPoint.x + xfB.q.c * manifold.points[i].localPoint.y) + xfB.p.y; + var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; + var cAx = clipPointx + ((radiusA - d) * this.normal.x); + var cAy = clipPointy + ((radiusA - d) * this.normal.y); + var cBx = (clipPointx - (radiusB * this.normal.x)); + var cBy = (clipPointy - (radiusB * this.normal.y)); + this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[i] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y + } + break; + case b2Manifold.e_faceB: + this.normal.x = xfB.q.c * manifold.localNormal.x - xfB.q.s * manifold.localNormal.y; + this.normal.y = xfB.q.s * manifold.localNormal.x + xfB.q.c * manifold.localNormal.y; + var planePointx = (xfB.q.c * manifold.localPoint.x - xfB.q.s * manifold.localPoint.y) + xfB.p.x; + var planePointy = (xfB.q.s * manifold.localPoint.x + xfB.q.c * manifold.localPoint.y) + xfB.p.y; + for (var i = 0; i < manifold.pointCount; ++i) { + var clipPointx = (xfA.q.c * manifold.points[i].localPoint.x - xfA.q.s * manifold.points[i].localPoint.y) + xfA.p.x; + var clipPointy = (xfA.q.s * manifold.points[i].localPoint.x + xfA.q.c * manifold.points[i].localPoint.y) + xfA.p.y; + var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; + var cBx = clipPointx + ((radiusB - d) * this.normal.x); + var cBy = clipPointy + ((radiusB - d) * this.normal.y); + var cAx = (clipPointx - (radiusA * this.normal.x)); + var cAy = (clipPointy - (radiusA * this.normal.y)); + this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[i] = (cAx - cBx) * this.normal.x + (cAy - cBy) * this.normal.y + } + this.normal.x = -this.normal.x; + this.normal.y = -this.normal.y; + break + } + } + }; + + function b2GetPointStates(state1, state2, manifold1, manifold2) { + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + state1[i] = b2Manifold.b2_nullState; + state2[i] = b2Manifold.b2_nullState + } + for (var i = 0; i < manifold1.pointCount; ++i) { + var id = manifold1.points[i].id; + state1[i] = b2Manifold.b2_removeState; + for (var j = 0; j < manifold2.pointCount; ++j) { + if (manifold2.points[j].id.Get() == id.Get()) { + state1[i] = b2Manifold.b2_persistState; + break + } + } + } + for (var i = 0; i < manifold2.pointCount; ++i) { + var id = manifold2.points[i].id; + state2[i] = b2Manifold.b2_addState; + for (var j = 0; j < manifold1.pointCount; ++j) { + if (manifold1.points[j].id.Get() == id.Get()) { + state2[i] = b2Manifold.b2_persistState; + break + } + } + } + } + + function b2ClipVertex() { + this.v = new b2Vec2(); + this.id = new b2ContactID() + } + + function b2RayCastInput() { + this.p1 = new b2Vec2(), this.p2 = new b2Vec2(); + this.maxFraction = 0 + } + + function b2RayCastOutput() { + this.normal = new b2Vec2(); + this.fraction = 0 + } + + function b2AABB() { + this.lowerBound = new b2Vec2(); + this.upperBound = new b2Vec2() + } + b2AABB.prototype = { + Assign: function (other) { + this.lowerBound.x = other.lowerBound.x; + this.lowerBound.y = other.lowerBound.y; + this.upperBound.x = other.upperBound.x; + this.upperBound.y = other.upperBound.y + }, + Clone: function () { + var clone = new b2AABB(); + clone.lowerBound.x = this.lowerBound.x; + clone.lowerBound.y = this.lowerBound.y; + clone.lowerBound.x = this.lowerBound.x; + clone.lowerBound.y = this.lowerBound.y; + return clone + }, + IsValid: function () { + return (this.upperBound.x - this.lowerBound.x) >= 0 && (this.upperBound.y - this.lowerBound.y) >= 0 && this.lowerBound.IsValid() && this.upperBound.IsValid() + }, + GetCenter: function () { + return new b2Vec2(0.5 * (this.lowerBound.x + this.upperBound.x), 0.5 * (this.lowerBound.y + this.upperBound.y)) + }, + GetExtents: function () { + return new b2Vec2(0.5 * (this.upperBound.x - this.lowerBound.x), 0.5 * (this.upperBound.y - this.lowerBound.y)) + }, + GetPerimeter: function () { + return 2 * ((this.upperBound.x - this.lowerBound.x) + (this.upperBound.y - this.lowerBound.y)) + }, + Combine: function (aabb1, aabb2) { + if (aabb2) { + this.lowerBound.x = b2Min(aabb1.lowerBound.x, aabb2.lowerBound.x); + this.lowerBound.y = b2Min(aabb1.lowerBound.y, aabb2.lowerBound.y); + this.upperBound.x = b2Max(aabb1.upperBound.x, aabb2.upperBound.x); + this.upperBound.y = b2Max(aabb1.upperBound.y, aabb2.upperBound.y) + } else { + this.lowerBound.x = b2Min(this.lowerBound.x, aabb1.lowerBound.x); + this.lowerBound.y = b2Min(this.lowerBound.y, aabb1.lowerBound.y); + this.upperBound.x = b2Max(this.upperBound.x, aabb1.upperBound.x); + this.upperBound.y = b2Max(this.upperBound.y, aabb1.upperBound.y) + } + }, + Contains: function (aabb) { + return this.lowerBound.x <= aabb.lowerBound.x && this.lowerBound.y <= aabb.lowerBound.y && aabb.upperBound.x <= this.upperBound.x && aabb.upperBound.y <= this.upperBound.y + }, + RayCast: function (output, input) { + var tmin = -b2_maxFloat; + var tmax = b2_maxFloat; + var p = input.p1; + var d = b2Vec2.Subtract(input.p2, input.p1); + var absD = b2Abs_v2(d); + var normal = new b2Vec2(); + for (var i = 0; i < 2; ++i) { + if (absD.get_i(i) < b2_epsilon) { + if (p.get_i(i) < this.lowerBound.get_i(i) || this.upperBound.get_i(i) < p.get_i(i)) { + return false + } + } else { + var inv_d = 1 / d.get_i(i); + var t1 = (this.lowerBound.get_i(i) - p.get_i(i)) * inv_d; + var t2 = (this.upperBound.get_i(i) - p.get_i(i)) * inv_d; + var s = -1; + if (t1 > t2) { + var temp = t2; + t2 = t1; + t1 = temp; + s = 1 + } + if (t1 > tmin) { + normal.x = normal.y = 0; + normal.set_i(i, s); + tmin = t1 + } + tmax = b2Min(tmax, t2); + if (tmin > tmax) { + return false + } + } + } + if (tmin < 0 || input.maxFraction < tmin) { + return false + } + output.fraction = tmin; + output.normal.x = normal.x; + output.normal.y = normal.y; + return true + } + }; + + function b2CollideCircles(manifold, circleA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var pA = b2Mul_t_v2(xfA, circleA.m_p); + var pB = b2Mul_t_v2(xfB, circleB.m_p); + var dx = pB.x - pA.x; + var dy = pB.y - pA.y; + var distSqr = dx * dx + dy * dy; + var rA = circleA.m_radius, + rB = circleB.m_radius; + var radius = rA + rB; + if (distSqr > radius * radius) { + return + } + manifold.type = b2Manifold.e_circles; + manifold.localPoint.x = circleA.m_p.x; + manifold.localPoint.y = circleA.m_p.y; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.pointCount = 1; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() + } + + function b2CollidePolygonAndCircle(manifold, polygonA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var c = b2Mul_t_v2(xfB, circleB.m_p); + var cLocal = b2MulT_t_v2(xfA, c); + var normalIndex = 0; + var separation = -b2_maxFloat; + var radius = polygonA.m_radius + circleB.m_radius; + var vertexCount = polygonA.m_count; + var vertices = polygonA.m_vertices; + var normals = polygonA.m_normals; + for (var i = 0; i < vertexCount; ++i) { + var s = normals[i].x * (cLocal.x - vertices[i].x) + normals[i].y * (cLocal.y - vertices[i].y); + if (s > radius) { + return + } + if (s > separation) { + separation = s; + normalIndex = i + } + } + var vertIndex1 = normalIndex; + var vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; + var v1 = vertices[vertIndex1]; + var v2 = vertices[vertIndex2]; + if (separation < b2_epsilon) { + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = normals[normalIndex].x; + manifold.localNormal.y = normals[normalIndex].y; + manifold.localPoint.x = 0.5 * (v1.x + v2.x); + manifold.localPoint.y = 0.5 * (v1.y + v2.y); + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset(); + return + } + var u1 = (cLocal.x - v1.x) * (v2.x - v1.x) + (cLocal.y - v1.y) * (v2.y - v1.y); + var u2 = (cLocal.x - v2.x) * (v1.x - v2.x) + (cLocal.y - v2.y) * (v1.y - v2.y); + if (u1 <= 0) { + if (b2DistanceSquared(cLocal, v1) > radius * radius) { + return + } + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = cLocal.x - v1.x; + manifold.localNormal.y = cLocal.y - v1.y; + manifold.localNormal.Normalize(); + manifold.localPoint.x = v1.x; + manifold.localPoint.y = v1.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() + } else { + if (u2 <= 0) { + if (b2DistanceSquared(cLocal, v2) > radius * radius) { + return + } + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = cLocal.x - v2.x; + manifold.localNormal.y = cLocal.y - v2.y; + manifold.localNormal.Normalize(); + manifold.localPoint.x = v2.x; + manifold.localPoint.y = v2.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() + } else { + var faceCenterx = 0.5 * (v1.x + v2.x); + var faceCentery = 0.5 * (v1.y + v2.y); + var separation = (cLocal.x - faceCenterx) * normals[vertIndex1].x + (cLocal.y - faceCentery) * normals[vertIndex1].y; + if (separation > radius) { + return + } + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = normals[vertIndex1].x; + manifold.localNormal.y = normals[vertIndex1].y; + manifold.localPoint.x = faceCenterx; + manifold.localPoint.y = faceCentery; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() + } + } + } + + function b2FindMaxSeparation(edgeIndex, poly1, xf1, poly2, xf2) { + var count1 = poly1.m_count; + var count2 = poly2.m_count; + var n1s = poly1.m_normals; + var v1s = poly1.m_vertices; + var v2s = poly2.m_vertices; + var xf = b2MulT_t_t(xf2, xf1); + var bestIndex = 0; + var maxSeparation = -b2_maxFloat; + for (var i = 0; i < count1; ++i) { + var nx = xf.q.c * n1s[i].x - xf.q.s * n1s[i].y; + var ny = xf.q.s * n1s[i].x + xf.q.c * n1s[i].y; + var v1x = (xf.q.c * v1s[i].x - xf.q.s * v1s[i].y) + xf.p.x; + var v1y = (xf.q.s * v1s[i].x + xf.q.c * v1s[i].y) + xf.p.y; + var si = b2_maxFloat; + for (var j = 0; j < count2; ++j) { + var sij = nx * (v2s[j].x - v1x) + ny * (v2s[j].y - v1y); + if (sij < si) { + si = sij + } + } + if (si > maxSeparation) { + maxSeparation = si; + bestIndex = i + } + } + edgeIndex[0] = bestIndex; + return maxSeparation + } + + function b2FindIncidentEdge(c, poly1, xf1, edge1, poly2, xf2) { + var normals1 = poly1.m_normals; + var count2 = poly2.m_count; + var vertices2 = poly2.m_vertices; + var normals2 = poly2.m_normals; + var t1x = xf1.q.c * normals1[edge1].x - xf1.q.s * normals1[edge1].y; + var t1y = xf1.q.s * normals1[edge1].x + xf1.q.c * normals1[edge1].y; + var normal1x = xf2.q.c * t1x + xf2.q.s * t1y; + var normal1y = -xf2.q.s * t1x + xf2.q.c * t1y; + var index = 0; + var minDot = b2_maxFloat; + for (var i = 0; i < count2; ++i) { + var dot = normal1x * normals2[i].x + normal1y * normals2[i].y; + if (dot < minDot) { + minDot = dot; + index = i + } + } + var i1 = index; + var i2 = i1 + 1 < count2 ? i1 + 1 : 0; + c[0].v.x = (xf2.q.c * vertices2[i1].x - xf2.q.s * vertices2[i1].y) + xf2.p.x; + c[0].v.y = (xf2.q.s * vertices2[i1].x + xf2.q.c * vertices2[i1].y) + xf2.p.y; + c[0].id.indexA = edge1; + c[0].id.indexB = i1; + c[0].id.typeA = b2ContactID.e_face; + c[0].id.typeB = b2ContactID.e_vertex; + c[1].v.x = (xf2.q.c * vertices2[i2].x - xf2.q.s * vertices2[i2].y) + xf2.p.x; + c[1].v.y = (xf2.q.s * vertices2[i2].x + xf2.q.c * vertices2[i2].y) + xf2.p.y; + c[1].id.indexA = edge1; + c[1].id.indexB = i2; + c[1].id.typeA = b2ContactID.e_face; + c[1].id.typeB = b2ContactID.e_vertex + } + + function b2CollidePolygons(manifold, polyA, xfA, polyB, xfB) { + manifold.pointCount = 0; + var totalRadius = polyA.m_radius + polyB.m_radius; + var edgeA = [0]; + var separationA = b2FindMaxSeparation(edgeA, polyA, xfA, polyB, xfB); + if (separationA > totalRadius) { + return + } + var edgeB = [0]; + var separationB = b2FindMaxSeparation(edgeB, polyB, xfB, polyA, xfA); + if (separationB > totalRadius) { + return + } + var poly1; + var poly2; + var xf1, xf2; + var edge1 = 0; + var flip = 0; + var k_tol = 0.1 * b2_linearSlop; + if (separationB > separationA + k_tol) { + poly1 = polyB; + poly2 = polyA; + xf1 = xfB; + xf2 = xfA; + edge1 = edgeB[0]; + manifold.type = b2Manifold.e_faceB; + flip = 1 + } else { + poly1 = polyA; + poly2 = polyB; + xf1 = xfA; + xf2 = xfB; + edge1 = edgeA[0]; + manifold.type = b2Manifold.e_faceA; + flip = 0 + } + b2FindIncidentEdge(b2CollidePolygons._local_incidentEdges, poly1, xf1, edge1, poly2, xf2); + var count1 = poly1.m_count; + var vertices1 = poly1.m_vertices; + var iv1 = edge1; + var iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0; + var v11 = vertices1[iv1]; + var v12 = vertices1[iv2]; + b2CollidePolygons._localTangent.x = v12.x - v11.x; + b2CollidePolygons._localTangent.y = v12.y - v11.y; + b2CollidePolygons._localTangent.Normalize(); + var localNormalx = 1 * b2CollidePolygons._localTangent.y; + var localNormaly = -1 * b2CollidePolygons._localTangent.x; + var planePointx = 0.5 * (v11.x + v12.x); + var planePointy = 0.5 * (v11.y + v12.y); + var tangentx = xf1.q.c * b2CollidePolygons._localTangent.x - xf1.q.s * b2CollidePolygons._localTangent.y; + var tangenty = xf1.q.s * b2CollidePolygons._localTangent.x + xf1.q.c * b2CollidePolygons._localTangent.y; + var normalx = 1 * tangenty; + var normaly = -1 * tangentx; + v11 = b2Mul_t_v2(xf1, v11); + v12 = b2Mul_t_v2(xf1, v12); + var frontOffset = normalx * v11.x + normaly * v11.y; + var sideOffset1 = -(tangentx * v11.x + tangenty * v11.y) + totalRadius; + var sideOffset2 = (tangentx * v12.x + tangenty * v12.y) + totalRadius; + var clipPoints1 = new Array(2); + var clipPoints2 = new Array(2); + var np; + np = b2ClipSegmentToLine(clipPoints1, b2CollidePolygons._local_incidentEdges, -tangentx, -tangenty, sideOffset1, iv1); + if (np < 2) { + return + } + np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangentx, tangenty, sideOffset2, iv2); + if (np < 2) { + return + } + manifold.localNormal.x = localNormalx; + manifold.localNormal.y = localNormaly; + manifold.localPoint.x = planePointx; + manifold.localPoint.y = planePointy; + var pointCount = 0; + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + var separation = (normalx * clipPoints2[i].v.x + normaly * clipPoints2[i].v.y) - frontOffset; + if (separation <= totalRadius) { + var cp = manifold.points[pointCount] = new b2ManifoldPoint(); + cp.localPoint.Assign(b2MulT_t_v2(xf2, clipPoints2[i].v)); + cp.id.Assign(clipPoints2[i].id); + if (flip) { + var cf = new b2ContactID(); + cf.Assign(cp.id); + cp.id.indexA = cf.indexB; + cp.id.indexB = cf.indexA; + cp.id.typeA = cf.typeB; + cp.id.typeB = cf.typeA + }++pointCount + } + } + manifold.pointCount = pointCount + } + b2CollidePolygons._localTangent = new b2Vec2(); + b2CollidePolygons._local_incidentEdges = [new b2ClipVertex(), new b2ClipVertex()]; + + function b2CollideEdgeAndCircle(manifold, edgeA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var Q = b2MulT_t_v2(xfA, b2Mul_t_v2(xfB, circleB.m_p)); + var A = edgeA.m_vertex1, + B = edgeA.m_vertex2; + var ex = B.x - A.x; + var ey = B.y - A.y; + var u = ex * (B.x - Q.x) + ey * (B.y - Q.y); + var v = ex * (Q.x - A.x) + ey * (Q.y - A.y); + var radius = edgeA.m_radius + circleB.m_radius; + var cf = new b2ContactID(); + cf.indexB = 0; + cf.typeB = b2ContactID.e_vertex; + if (v <= 0) { + var P = A; + var dx = Q.x - P.x; + var dy = Q.y - P.y; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + if (edgeA.m_hasVertex0) { + var A1 = edgeA.m_vertex0; + var B1 = A; + var e1x = B1.x - A1.x; + var e1y = B1.y - A1.y; + var u1 = e1x * (B1.x - Q.x) + e1y * (B1.y - Q.y); + if (u1 > 0) { + return + } + } + cf.indexA = 0; + cf.typeA = b2ContactID.e_vertex; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_circles; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.localPoint.x = P.x; + manifold.localPoint.y = P.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + return + } + if (u <= 0) { + var P = B; + var dx = Q.x - P.x; + var dy = Q.y - P.y; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + if (edgeA.m_hasVertex3) { + var B2 = edgeA.m_vertex3; + var A2 = B; + var e2x = B2.x - A2.x; + var e2y = B2.y - A2.y; + var v2 = e2x * (Q.x - A2.x) + e2y * (Q.y - A2.y); + if (v2 > 0) { + return + } + } + cf.indexA = 1; + cf.typeA = b2ContactID.e_vertex; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_circles; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.localPoint.x = P.x; + manifold.localPoint.y = P.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + return + } + var den = ex * ex + ey * ey; + var Px = (1 / den) * ((u * A.x) + (v * B.x)); + var Py = (1 / den) * ((u * A.y) + (v * B.y)); + var dx = Q.x - Px; + var dy = Q.y - Py; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + var nx = -ey; + var ny = ex; + if (nx * (Q.x - A.x) + ny * (Q.y - A.y) < 0) { + nx = -nx; + ny = -ny + } + cf.indexA = 0; + cf.typeA = b2ContactID.e_face; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = nx; + manifold.localNormal.y = ny; + manifold.localNormal.Normalize(); + manifold.localPoint.x = A.x; + manifold.localPoint.y = A.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y + } + + function b2EPAxis() { + this.type = 0; + this.index = 0; + this.separation = 0 + } + b2EPAxis.e_unknown = 0; + b2EPAxis.e_edgeA = 1; + b2EPAxis.e_edgeB = 2; + + function b2TempPolygon() { + this.vertices = new Array(b2_maxPolygonVertices); + this.normals = new Array(b2_maxPolygonVertices); + this.count = 0 + } + + function b2ReferenceFace() { + this.i1 = 0, this.i2 = 0; + this.v1 = new b2Vec2(), this.v2 = new b2Vec2(); + this.normal = new b2Vec2(); + this.sideNormal1 = new b2Vec2(); + this.sideOffset1 = 0; + this.sideNormal2 = new b2Vec2(); + this.sideOffset2 = 0 + } + + function b2EPCollider() { + this.m_polygonB = new b2TempPolygon(); + this.m_xf = new b2Transform(); + this.m_centroidB = new b2Vec2(); + this.m_v0 = new b2Vec2(), this.m_v1 = new b2Vec2(), this.m_v2 = new b2Vec2(), this.m_v3 = new b2Vec2(); + this.m_normal0 = new b2Vec2(), this.m_normal1 = new b2Vec2(), this.m_normal2 = new b2Vec2(); + this.m_normal = new b2Vec2(); + this.m_type1 = 0, this.m_type2 = 0; + this.m_lowerLimit = new b2Vec2(), this.m_upperLimit = new b2Vec2(); + this.m_radius = 0; + this.m_front = false + } + b2EPCollider._temp_edge = new b2Vec2(); + b2EPCollider._temp_edge0 = new b2Vec2(); + b2EPCollider._temp_edge2 = new b2Vec2(); + b2EPCollider.prototype = { + Collide: function (manifold, edgeA, xfA, polygonB, xfB) { + this.m_xf.Assign(b2MulT_t_t(xfA, xfB)); + this.m_centroidB.x = (this.m_xf.q.c * polygonB.m_centroid.x - this.m_xf.q.s * polygonB.m_centroid.y) + this.m_xf.p.x; + this.m_centroidB.y = (this.m_xf.q.s * polygonB.m_centroid.x + this.m_xf.q.c * polygonB.m_centroid.y) + this.m_xf.p.y; + this.m_v0.x = edgeA.m_vertex0.x; + this.m_v0.y = edgeA.m_vertex0.y; + this.m_v1.x = edgeA.m_vertex1.x; + this.m_v1.y = edgeA.m_vertex1.y; + this.m_v2.x = edgeA.m_vertex2.x; + this.m_v2.y = edgeA.m_vertex2.y; + this.m_v3.x = edgeA.m_vertex3.x; + this.m_v3.y = edgeA.m_vertex3.y; + var hasVertex0 = edgeA.m_hasVertex0; + var hasVertex3 = edgeA.m_hasVertex3; + b2EPCollider._temp_edge.x = this.m_v2.x - this.m_v1.x; + b2EPCollider._temp_edge.y = this.m_v2.y - this.m_v1.y; + b2EPCollider._temp_edge.Normalize(); + this.m_normal1.x = b2EPCollider._temp_edge.y; + this.m_normal1.y = -b2EPCollider._temp_edge.x; + var offset1 = this.m_normal1.x * (this.m_centroidB.x - this.m_v1.x) + this.m_normal1.y * (this.m_centroidB.y - this.m_v1.y); + var offset0 = 0, + offset2 = 0; + var convex1 = false, + convex2 = false; + if (hasVertex0) { + b2EPCollider._temp_edge0.x = this.m_v1.x - this.m_v0.x; + b2EPCollider._temp_edge0.y = this.m_v1.y - this.m_v0.y; + b2EPCollider._temp_edge0.Normalize(); + this.m_normal0.x = b2EPCollider._temp_edge0.y; + this.m_normal0.y = -b2EPCollider._temp_edge0.x; + convex1 = (b2EPCollider._temp_edge0.x * b2EPCollider._temp_edge.y - b2EPCollider._temp_edge0.y * b2EPCollider._temp_edge.x) >= 0; + offset0 = this.m_normal0.x * (this.m_centroidB.x - this.m_v0.x) + this.m_normal0.y * (this.m_centroidB.y - this.m_v0.y) + } + if (hasVertex3) { + b2EPCollider._temp_edge2.x = this.m_v3.x - this.m_v2.x; + b2EPCollider._temp_edge2.y = this.m_v3.y - this.m_v2.y; + b2EPCollider._temp_edge2.Normalize(); + this.m_normal2.x = b2EPCollider._temp_edge2.y; + this.m_normal2.y = -b2EPCollider._temp_edge2.x; + convex2 = (b2EPCollider._temp_edge.x * b2EPCollider._temp_edge2.y - b2EPCollider._temp_edge.y * b2EPCollider._temp_edge2.x) > 0; + offset2 = this.m_normal2.x * (this.m_centroidB.x - this.m_v2.x) + this.m_normal2.y * (this.m_centroidB.y - this.m_v2.y) + } + if (hasVertex0 && hasVertex3) { + if (convex1 && convex2) { + this.m_front = offset0 >= 0 || offset1 >= 0 || offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + if (convex1) { + this.m_front = offset0 >= 0 || (offset1 >= 0 && offset2 >= 0); + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + if (convex2) { + this.m_front = offset2 >= 0 || (offset0 >= 0 && offset1 >= 0); + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } else { + this.m_front = offset0 >= 0 && offset1 >= 0 && offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } + } + } + } else { + if (hasVertex0) { + if (convex1) { + this.m_front = offset0 >= 0 || offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + this.m_front = offset0 >= 0 && offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } + } else { + if (hasVertex3) { + if (convex2) { + this.m_front = offset1 >= 0 || offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } + } else { + this.m_front = offset1 >= 0 && offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } + } + } else { + this.m_front = offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } + } + } + } + this.m_polygonB.count = polygonB.m_count; + for (var i = 0; i < polygonB.m_count; ++i) { + this.m_polygonB.vertices[i] = b2Mul_t_v2(this.m_xf, polygonB.m_vertices[i]); + this.m_polygonB.normals[i] = b2Mul_r_v2(this.m_xf.q, polygonB.m_normals[i]) + } + this.m_radius = 2 * b2_polygonRadius; + manifold.pointCount = 0; + var edgeAxis = this.ComputeEdgeSeparation(); + if (edgeAxis.type == b2EPAxis.e_unknown) { + return + } + if (edgeAxis.separation > this.m_radius) { + return + } + var polygonAxis = this.ComputePolygonSeparation(); + if (polygonAxis.type != b2EPAxis.e_unknown && polygonAxis.separation > this.m_radius) { + return + } + var k_relativeTol = 0.98; + var k_absoluteTol = 0.001; + var primaryAxis = new b2EPAxis(); + if (polygonAxis.type == b2EPAxis.e_unknown) { + primaryAxis = edgeAxis + } else { + if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) { + primaryAxis = polygonAxis + } else { + primaryAxis = edgeAxis + } + } + var ie = new Array(2); + var rf = new b2ReferenceFace(); + if (primaryAxis.type == b2EPAxis.e_edgeA) { + manifold.type = b2Manifold.e_faceA; + var bestIndex = 0; + var bestValue = this.m_normal.x * this.m_polygonB.normals[0].x + this.m_normal.y * this.m_polygonB.normals[0].y; + for (var i = 1; i < this.m_polygonB.count; ++i) { + var value = this.m_normal.x * this.m_polygonB.normals[i].x + this.m_normal.y * this.m_polygonB.normals[i].y; + if (value < bestValue) { + bestValue = value; + bestIndex = i + } + } + var i1 = bestIndex; + var i2 = i1 + 1 < this.m_polygonB.count ? i1 + 1 : 0; + ie[0] = new b2ClipVertex(); + ie[0].v.x = this.m_polygonB.vertices[i1].x; + ie[0].v.y = this.m_polygonB.vertices[i1].y; + ie[0].id.indexA = 0; + ie[0].id.indexB = i1; + ie[0].id.typeA = b2ContactID.e_face; + ie[0].id.typeB = b2ContactID.e_vertex; + ie[1] = new b2ClipVertex(); + ie[1].v.x = this.m_polygonB.vertices[i2].x; + ie[1].v.y = this.m_polygonB.vertices[i2].y; + ie[1].id.indexA = 0; + ie[1].id.indexB = i2; + ie[1].id.typeA = b2ContactID.e_face; + ie[1].id.typeB = b2ContactID.e_vertex; + if (this.m_front) { + rf.i1 = 0; + rf.i2 = 1; + rf.v1.x = this.m_v1.x; + rf.v1.y = this.m_v1.y; + rf.v2.x = this.m_v2.x; + rf.v2.y = this.m_v2.y; + rf.normal.x = this.m_normal1.x; + rf.normal.y = this.m_normal1.y + } else { + rf.i1 = 1; + rf.i2 = 0; + rf.v1.x = this.m_v2.x; + rf.v1.y = this.m_v2.y; + rf.v2.x = this.m_v1.x; + rf.v2.y = this.m_v1.y; + rf.normal.x = -this.m_normal1.x; + rf.normal.y = -this.m_normal1.y + } + } else { + manifold.type = b2Manifold.e_faceB; + ie[0] = new b2ClipVertex(); + ie[0].v = this.m_v1; + ie[0].id.indexA = 0; + ie[0].id.indexB = primaryAxis.index; + ie[0].id.typeA = b2ContactID.e_vertex; + ie[0].id.typeB = b2ContactID.e_face; + ie[1] = new b2ClipVertex(); + ie[1].v = this.m_v2; + ie[1].id.indexA = 0; + ie[1].id.indexB = primaryAxis.index; + ie[1].id.typeA = b2ContactID.e_vertex; + ie[1].id.typeB = b2ContactID.e_face; + rf.i1 = primaryAxis.index; + rf.i2 = rf.i1 + 1 < this.m_polygonB.count ? rf.i1 + 1 : 0; + rf.v1.x = this.m_polygonB.vertices[rf.i1].x; + rf.v1.y = this.m_polygonB.vertices[rf.i1].y; + rf.v2.x = this.m_polygonB.vertices[rf.i2].x; + rf.v2.y = this.m_polygonB.vertices[rf.i2].y; + rf.normal.x = this.m_polygonB.normals[rf.i1].x; + rf.normal.y = this.m_polygonB.normals[rf.i1].y + } + rf.sideNormal1.x = rf.normal.y; + rf.sideNormal1.y = -rf.normal.x; + rf.sideNormal2.x = -rf.sideNormal1.x; + rf.sideNormal2.y = -rf.sideNormal1.y; + rf.sideOffset1 = rf.sideNormal1.x * rf.v1.x + rf.sideNormal1.y * rf.v1.y; + rf.sideOffset2 = rf.sideNormal2.x * rf.v2.x + rf.sideNormal2.y * rf.v2.y; + var clipPoints1 = new Array(2); + var clipPoints2 = new Array(2); + var np; + np = b2ClipSegmentToLine(clipPoints1, ie, rf.sideNormal1.x, rf.sideNormal1.y, rf.sideOffset1, rf.i1); + if (np < b2_maxManifoldPoints) { + return + } + np = b2ClipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2.x, rf.sideNormal2.y, rf.sideOffset2, rf.i2); + if (np < b2_maxManifoldPoints) { + return + } + if (primaryAxis.type == b2EPAxis.e_edgeA) { + manifold.localNormal.x = rf.normal.x; + manifold.localNormal.y = rf.normal.y; + manifold.localPoint.x = rf.v1.x; + manifold.localPoint.y = rf.v1.y + } else { + manifold.localNormal.x = polygonB.m_normals[rf.i1].x; + manifold.localNormal.y = polygonB.m_normals[rf.i1].y; + manifold.localPoint.x = polygonB.m_vertices[rf.i1].x; + manifold.localPoint.y = polygonB.m_vertices[rf.i1].y + } + var pointCount = 0; + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + var separation = rf.normal.x * (clipPoints2[i].v.x - rf.v1.x) + rf.normal.y * (clipPoints2[i].v.y - rf.v1.y); + if (separation <= this.m_radius) { + var cp = manifold.points[pointCount] = new b2ManifoldPoint(); + if (primaryAxis.type == b2EPAxis.e_edgeA) { + cp.localPoint.Assign(b2MulT_t_v2(this.m_xf, clipPoints2[i].v)); + cp.id.Assign(clipPoints2[i].id) + } else { + cp.localPoint.x = clipPoints2[i].v.x; + cp.localPoint.y = clipPoints2[i].v.y; + cp.id.typeA = clipPoints2[i].id.typeB; + cp.id.typeB = clipPoints2[i].id.typeA; + cp.id.indexA = clipPoints2[i].id.indexB; + cp.id.indexB = clipPoints2[i].id.indexA + }++pointCount + } + } + manifold.pointCount = pointCount + }, + ComputeEdgeSeparation: function () { + var axis = new b2EPAxis(); + axis.type = b2EPAxis.e_edgeA; + axis.index = this.m_front ? 0 : 1; + axis.separation = Number.MAX_VALUE; + for (var i = 0; i < this.m_polygonB.count; ++i) { + var s = this.m_normal.x * (this.m_polygonB.vertices[i].x - this.m_v1.x) + this.m_normal.y * (this.m_polygonB.vertices[i].y - this.m_v1.y); + if (s < axis.separation) { + axis.separation = s + } + } + return axis + }, + ComputePolygonSeparation: function () { + var axis = new b2EPAxis(); + axis.type = b2EPAxis.e_unknown; + axis.index = -1; + axis.separation = -Number.MAX_VALUE; + var perpx = -this.m_normal.y; + var perpy = this.m_normal.x; + for (var i = 0; i < this.m_polygonB.count; ++i) { + var nx = -this.m_polygonB.normals[i].x; + var ny = -this.m_polygonB.normals[i].y; + var s1 = nx * (this.m_polygonB.vertices[i].x - this.m_v1.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v1.y); + var s2 = nx * (this.m_polygonB.vertices[i].x - this.m_v2.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v2.y); + var s = b2Min(s1, s2); + if (s > this.m_radius) { + axis.type = b2EPAxis.e_edgeB; + axis.index = i; + axis.separation = s; + return axis + } + if (nx * perpx + ny * perpy >= 0) { + if ((nx - this.m_upperLimit.x) * this.m_normal.x + (ny - this.m_upperLimit.y) * this.m_normal.y < -b2_angularSlop) { + continue + } + } else { + if ((nx - this.m_lowerLimit.x) * this.m_normal.x + (ny - this.m_lowerLimit.y) * this.m_normal.y < -b2_angularSlop) { + continue + } + } + if (s > axis.separation) { + axis.type = b2EPAxis.e_edgeB; + axis.index = i; + axis.separation = s + } + } + return axis + } + }; + b2EPCollider.e_isolated = 0; + b2EPCollider.e_concave = 1; + b2EPCollider.e_convex = 2; + + function b2CollideEdgeAndPolygon(manifold, edgeA, xfA, polygonB, xfB) { + b2CollideEdgeAndPolygon.collider.Collide(manifold, edgeA, xfA, polygonB, xfB) + } + b2CollideEdgeAndPolygon.collider = new b2EPCollider(); + + function b2ClipSegmentToLine(vOut, vIn, normalx, normaly, offset, vertexIndexA) { + var numOut = 0; + var distance0 = (normalx * vIn[0].v.x + normaly * vIn[0].v.y) - offset; + var distance1 = (normalx * vIn[1].v.x + normaly * vIn[1].v.y) - offset; + if (distance0 <= 0) { + vOut[numOut++] = vIn[0] + } + if (distance1 <= 0) { + vOut[numOut++] = vIn[1] + } + if (distance0 * distance1 < 0) { + var interp = distance0 / (distance0 - distance1); + vOut[numOut] = new b2ClipVertex(); + vOut[numOut].v.x = vIn[0].v.x + (interp * (vIn[1].v.x - vIn[0].v.x)); + vOut[numOut].v.y = vIn[0].v.y + (interp * (vIn[1].v.y - vIn[0].v.y)); + vOut[numOut].id.indexA = vertexIndexA; + vOut[numOut].id.indexB = vIn[0].id.indexB; + vOut[numOut].id.typeA = b2ContactID.e_vertex; + vOut[numOut].id.typeB = b2ContactID.e_face; + ++numOut + } + return numOut + } + + function b2TestShapeOverlap(shapeA, indexA, shapeB, indexB, xfA, xfB) { + b2TestShapeOverlap.input.proxyA.Set(shapeA, indexA); + b2TestShapeOverlap.input.proxyB.Set(shapeB, indexB); + b2TestShapeOverlap.input.transformA = xfA; + b2TestShapeOverlap.input.transformB = xfB; + b2TestShapeOverlap.input.useRadii = true; + b2TestShapeOverlap.cache.count = 0; + b2DistanceFunc(b2TestShapeOverlap.output, b2TestShapeOverlap.cache, b2TestShapeOverlap.input); + return b2TestShapeOverlap.output.distance < 10 * b2_epsilon + } + b2TestShapeOverlap.input = new b2DistanceInput(); + b2TestShapeOverlap.cache = new b2SimplexCache(); + b2TestShapeOverlap.output = new b2DistanceOutput(); + + function b2TestOverlap(a, b) { + return !((b.lowerBound.x - a.upperBound.x) > 0 || (b.lowerBound.y - a.upperBound.y) > 0 || (a.lowerBound.x - b.upperBound.x) > 0 || (a.lowerBound.y - b.upperBound.y) > 0) + } + "use strict"; + var b2_nullNode = -1; + + function b2TreeNode() { + this.aabb = new b2AABB(); + this.userData = null; + this.parent = 0; + this.child1 = this.child2 = this.height = 0 + } + b2TreeNode.prototype = { + IsLeaf: function () { + return this.child1 == b2_nullNode + } + }; + + function b2DynamicTree() { + this.m_root = b2_nullNode; + this.m_nodeCapacity = 16; + this.m_nodeCount = 0; + this.m_nodes = new Array(this.m_nodeCapacity); + for (var i = 0; i < this.m_nodeCapacity - 1; ++i) { + this.m_nodes[i] = new b2TreeNode(); + this.m_nodes[i].parent = i + 1; + this.m_nodes[i].height = -1 + } + this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); + this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; + this.m_nodes[this.m_nodeCapacity - 1].height = -1; + this.m_freeList = 0; + this.m_path = 0; + this.m_insertionCount = 0 + } + b2DynamicTree.aabbExtensionFattener = new b2Vec2(b2_aabbExtension, b2_aabbExtension); + b2DynamicTree.prototype = { + CreateProxy: function (aabb, userData) { + var proxyId = this.AllocateNode(); + this.m_nodes[proxyId].aabb.lowerBound.Assign(b2Vec2.Subtract(aabb.lowerBound, b2DynamicTree.aabbExtensionFattener)); + this.m_nodes[proxyId].aabb.upperBound.Assign(b2Vec2.Add(aabb.upperBound, b2DynamicTree.aabbExtensionFattener)); + this.m_nodes[proxyId].userData = userData; + this.m_nodes[proxyId].height = 0; + this.InsertLeaf(proxyId); + return proxyId + }, + DestroyProxy: function (proxyId) { + this.RemoveLeaf(proxyId); + this.FreeNode(proxyId) + }, + MoveProxy: function (proxyId, aabb, displacement) { + if (this.m_nodes[proxyId].aabb.Contains(aabb)) { + return false + } + this.RemoveLeaf(proxyId); + this.m_nodes[proxyId].aabb.Assign(aabb); + this.m_nodes[proxyId].aabb.lowerBound.Subtract(b2DynamicTree.aabbExtensionFattener); + this.m_nodes[proxyId].aabb.upperBound.Add(b2DynamicTree.aabbExtensionFattener); + var d = b2Vec2.Multiply(b2_aabbMultiplier, displacement); + if (d.x < 0) { + this.m_nodes[proxyId].aabb.lowerBound.x += d.x + } else { + this.m_nodes[proxyId].aabb.upperBound.x += d.x + } + if (d.y < 0) { + this.m_nodes[proxyId].aabb.lowerBound.y += d.y + } else { + this.m_nodes[proxyId].aabb.upperBound.y += d.y + } + this.InsertLeaf(proxyId); + return true + }, + GetUserData: function (proxyId) { + return this.m_nodes[proxyId].userData + }, + GetFatAABB: function (proxyId) { + return this.m_nodes[proxyId].aabb + }, + Query: function (callback, aabb) { + var stack = []; + stack.push(this.m_root); + while (stack.length > 0) { + var nodeId = stack.pop(); + if (nodeId == b2_nullNode) { + continue + } + var node = this.m_nodes[nodeId]; + if (b2TestOverlap(node.aabb, aabb)) { + if (node.IsLeaf()) { + var proceed = callback.QueryCallback(nodeId); + if (proceed == false) { + return + } + } else { + stack.push(node.child1); + stack.push(node.child2) + } + } + } + }, + RayCast: function (callback, input) { + var p1 = input.p1; + var p2 = input.p2; + var r = b2Vec2.Subtract(p2, p1); + r.Normalize(); + var v = b2Cross_f_v2(1, r); + var abs_v = b2Abs_v2(v); + var maxFraction = input.maxFraction; + var segmentAABB = new b2AABB(); + var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); + segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); + segmentAABB.upperBound.Assign(b2Max_v2(p1, t)); + var stack = []; + stack.push(this.m_root); + while (stack.length > 0) { + var nodeId = stack.pop(); + if (nodeId == b2_nullNode) { + continue + } + var node = this.m_nodes[nodeId]; + if (b2TestOverlap(node.aabb, segmentAABB) == false) { + continue + } + var c = node.aabb.GetCenter(); + var h = node.aabb.GetExtents(); + var separation = b2Abs(b2Dot_v2_v2(v, b2Vec2.Subtract(p1, c))) - b2Dot_v2_v2(abs_v, h); + if (separation > 0) { + continue + } + if (node.IsLeaf()) { + var subInput = new b2RayCastInput(); + subInput.p1.Assign(input.p1); + subInput.p2.Assign(input.p2); + subInput.maxFraction = maxFraction; + var value = callback.RayCastCallback(subInput, nodeId); + if (value == 0) { + return + } + if (value > 0) { + maxFraction = value; + var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); + segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); + segmentAABB.upperBound.Assign(b2Max_v2(p1, t)) + } + } else { + stack.push(node.child1); + stack.push(node.child2) + } + } + }, + Validate: function () { + this.ValidateStructure(this.m_root); + this.ValidateMetrics(this.m_root); + var freeCount = 0; + var freeIndex = this.m_freeList; + while (freeIndex != b2_nullNode) { + freeIndex = this.m_nodes[freeIndex].parent; + ++freeCount + } + }, + GetHeight: function () { + if (this.m_root == b2_nullNode) { + return 0 + } + return this.m_nodes[this.m_root].height + }, + GetMaxBalance: function () { + var maxBalance = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + var node = this.m_nodes[i]; + if (node.height <= 1) { + continue + } + var child1 = node.child1; + var child2 = node.child2; + var balance = b2Abs(this.m_nodes[child2].height - this.m_nodes[child1].height); + maxBalance = b2Max(maxBalance, balance) + } + return maxBalance + }, + GetAreaRatio: function () { + if (this.m_root == b2_nullNode) { + return 0 + } + var root = this.m_nodes[this.m_root]; + var rootArea = root.aabb.GetPerimeter(); + var totalArea = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + var node = this.m_nodes[i]; + if (node.height < 0) { + continue + } + totalArea += node.aabb.GetPerimeter() + } + return totalArea / rootArea + }, + RebuildBottomUp: function () { + var nodes = new Array(this.m_nodeCount); + var count = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + if (this.m_nodes[i].height < 0) { + continue + } + if (this.m_nodes[i].IsLeaf()) { + this.m_nodes[i].parent = b2_nullNode; + nodes[count] = i; + ++count + } else { + this.FreeNode(i) + } + } + while (count > 1) { + var minCost = b2_maxFloat; + var iMin = -1, + jMin = -1; + for (i = 0; i < count; ++i) { + var aabbi = this.m_nodes[nodes[i]].aabb; + for (var j = i + 1; j < count; ++j) { + var aabbj = this.m_nodes[nodes[j]].aabb; + var b = new b2AABB(); + b.Combine(aabbi, aabbj); + var cost = b.GetPerimeter(); + if (cost < minCost) { + iMin = i; + jMin = j; + minCost = cost + } + } + } + var index1 = nodes[iMin]; + var index2 = nodes[jMin]; + var child1 = this.m_nodes[index1]; + var child2 = this.m_nodes[index2]; + var parentIndex = this.AllocateNode(); + var parent = this.m_nodes[parentIndex]; + parent.child1 = index1; + parent.child2 = index2; + parent.height = 1 + b2Max(child1.height, child2.height); + parent.aabb.Combine(child1.aabb, child2.aabb); + parent.parent = b2_nullNode; + child1.parent = parentIndex; + child2.parent = parentIndex; + nodes[jMin] = nodes[count - 1]; + nodes[iMin] = parentIndex; + --count + } + this.m_root = nodes[0]; + this.Validate() + }, + ShiftOrigin: function (newOrigin) { + for (var i = 0; i < this.m_nodeCapacity; ++i) { + this.m_nodes[i].aabb.lowerBound.Subtract(newOrigin); + this.m_nodes[i].aabb.upperBound.Subtract(newOrigin) + } + }, + AllocateNode: function () { + if (this.m_freeList == b2_nullNode) { + var oldNodes = this.m_nodes; + this.m_nodeCapacity *= 2; + this.m_nodes = oldNodes.concat(new Array(this.m_nodeCapacity - this.m_nodeCount)); + for (var i = this.m_nodeCount; i < this.m_nodeCapacity - 1; ++i) { + this.m_nodes[i] = new b2TreeNode(); + this.m_nodes[i].parent = i + 1; + this.m_nodes[i].height = -1 + } + this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); + this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; + this.m_nodes[this.m_nodeCapacity - 1].height = -1; + this.m_freeList = this.m_nodeCount + } + var nodeId = this.m_freeList; + this.m_freeList = this.m_nodes[nodeId].parent; + this.m_nodes[nodeId].parent = b2_nullNode; + this.m_nodes[nodeId].child1 = b2_nullNode; + this.m_nodes[nodeId].child2 = b2_nullNode; + this.m_nodes[nodeId].height = 0; + this.m_nodes[nodeId].userData = null; + ++this.m_nodeCount; + return nodeId + }, + FreeNode: function (nodeId) { + this.m_nodes[nodeId].parent = this.m_freeList; + this.m_nodes[nodeId].height = -1; + this.m_freeList = nodeId; + --this.m_nodeCount + }, + InsertLeaf: function (leaf) { + ++this.m_insertionCount; + if (this.m_root == b2_nullNode) { + this.m_root = leaf; + this.m_nodes[this.m_root].parent = b2_nullNode; + return + } + var leafAABB = this.m_nodes[leaf].aabb; + var index = this.m_root; + while (this.m_nodes[index].IsLeaf() == false) { + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + var area = this.m_nodes[index].aabb.GetPerimeter(); + var combinedAABB = new b2AABB(); + combinedAABB.Combine(this.m_nodes[index].aabb, leafAABB); + var combinedArea = combinedAABB.GetPerimeter(); + var cost = 2 * combinedArea; + var inheritanceCost = 2 * (combinedArea - area); + var cost1; + var aabb; + if (this.m_nodes[child1].IsLeaf()) { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child1].aabb); + cost1 = aabb.GetPerimeter() + inheritanceCost + } else { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child1].aabb); + var oldArea = this.m_nodes[child1].aabb.GetPerimeter(); + var newArea = aabb.GetPerimeter(); + cost1 = (newArea - oldArea) + inheritanceCost + } + var cost2; + if (this.m_nodes[child2].IsLeaf()) { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child2].aabb); + cost2 = aabb.GetPerimeter() + inheritanceCost + } else { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child2].aabb); + var oldArea = this.m_nodes[child2].aabb.GetPerimeter(); + var newArea = aabb.GetPerimeter(); + cost2 = newArea - oldArea + inheritanceCost + } + if (cost < cost1 && cost < cost2) { + break + } + if (cost1 < cost2) { + index = child1 + } else { + index = child2 + } + } + var sibling = index; + var oldParent = this.m_nodes[sibling].parent; + var newParent = this.AllocateNode(); + this.m_nodes[newParent].parent = oldParent; + this.m_nodes[newParent].userData = null; + this.m_nodes[newParent].aabb.Combine(leafAABB, this.m_nodes[sibling].aabb); + this.m_nodes[newParent].height = this.m_nodes[sibling].height + 1; + if (oldParent != b2_nullNode) { + if (this.m_nodes[oldParent].child1 == sibling) { + this.m_nodes[oldParent].child1 = newParent + } else { + this.m_nodes[oldParent].child2 = newParent + } + this.m_nodes[newParent].child1 = sibling; + this.m_nodes[newParent].child2 = leaf; + this.m_nodes[sibling].parent = newParent; + this.m_nodes[leaf].parent = newParent + } else { + this.m_nodes[newParent].child1 = sibling; + this.m_nodes[newParent].child2 = leaf; + this.m_nodes[sibling].parent = newParent; + this.m_nodes[leaf].parent = newParent; + this.m_root = newParent + } + index = this.m_nodes[leaf].parent; + while (index != b2_nullNode) { + index = this.Balance(index); + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); + this.m_nodes[index].aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + index = this.m_nodes[index].parent + } + }, + RemoveLeaf: function (leaf) { + if (leaf == this.m_root) { + this.m_root = b2_nullNode; + return + } + var parent = this.m_nodes[leaf].parent; + var grandParent = this.m_nodes[parent].parent; + var sibling; + if (this.m_nodes[parent].child1 == leaf) { + sibling = this.m_nodes[parent].child2 + } else { + sibling = this.m_nodes[parent].child1 + } + if (grandParent != b2_nullNode) { + if (this.m_nodes[grandParent].child1 == parent) { + this.m_nodes[grandParent].child1 = sibling + } else { + this.m_nodes[grandParent].child2 = sibling + } + this.m_nodes[sibling].parent = grandParent; + this.FreeNode(parent); + var index = grandParent; + while (index != b2_nullNode) { + index = this.Balance(index); + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + this.m_nodes[index].aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); + index = this.m_nodes[index].parent + } + } else { + this.m_root = sibling; + this.m_nodes[sibling].parent = b2_nullNode; + this.FreeNode(parent) + } + }, + Balance: function (iA) { + var A = this.m_nodes[iA]; + if (A.IsLeaf() || A.height < 2) { + return iA + } + var iB = A.child1; + var iC = A.child2; + var B = this.m_nodes[iB]; + var C = this.m_nodes[iC]; + var balance = C.height - B.height; + if (balance > 1) { + var iF = C.child1; + var iG = C.child2; + var F = this.m_nodes[iF]; + var G = this.m_nodes[iG]; + C.child1 = iA; + C.parent = A.parent; + A.parent = iC; + if (C.parent != b2_nullNode) { + if (this.m_nodes[C.parent].child1 == iA) { + this.m_nodes[C.parent].child1 = iC + } else { + this.m_nodes[C.parent].child2 = iC + } + } else { + this.m_root = iC + } + if (F.height > G.height) { + C.child2 = iF; + A.child2 = iG; + G.parent = iA; + A.aabb.Combine(B.aabb, G.aabb); + C.aabb.Combine(A.aabb, F.aabb); + A.height = 1 + b2Max(B.height, G.height); + C.height = 1 + b2Max(A.height, F.height) + } else { + C.child2 = iG; + A.child2 = iF; + F.parent = iA; + A.aabb.Combine(B.aabb, F.aabb); + C.aabb.Combine(A.aabb, G.aabb); + A.height = 1 + b2Max(B.height, F.height); + C.height = 1 + b2Max(A.height, G.height) + } + return iC + } + if (balance < -1) { + var iD = B.child1; + var iE = B.child2; + var D = this.m_nodes[iD]; + var E = this.m_nodes[iE]; + B.child1 = iA; + B.parent = A.parent; + A.parent = iB; + if (B.parent != b2_nullNode) { + if (this.m_nodes[B.parent].child1 == iA) { + this.m_nodes[B.parent].child1 = iB + } else { + this.m_nodes[B.parent].child2 = iB + } + } else { + this.m_root = iB + } + if (D.height > E.height) { + B.child2 = iD; + A.child1 = iE; + E.parent = iA; + A.aabb.Combine(C.aabb, E.aabb); + B.aabb.Combine(A.aabb, D.aabb); + A.height = 1 + b2Max(C.height, E.height); + B.height = 1 + b2Max(A.height, D.height) + } else { + B.child2 = iE; + A.child1 = iD; + D.parent = iA; + A.aabb.Combine(C.aabb, D.aabb); + B.aabb.Combine(A.aabb, E.aabb); + A.height = 1 + b2Max(C.height, D.height); + B.height = 1 + b2Max(A.height, E.height) + } + return iB + } + return iA + }, + ComputeHeight: function (nodeId) { + if (typeof (nodeId) === "undefined") { + nodeId = this.m_root + } + var node = this.m_nodes[nodeId]; + if (node.IsLeaf()) { + return 0 + } + var height1 = this.ComputeHeight(node.child1); + var height2 = this.ComputeHeight(node.child2); + return 1 + b2Max(height1, height2) + }, + ValidateStructure: function (index) { + if (index == b2_nullNode) { + return + } + var node = this.m_nodes[index]; + var child1 = node.child1; + var child2 = node.child2; + if (node.IsLeaf()) { + return + } + this.ValidateStructure(child1); + this.ValidateStructure(child2) + }, + ValidateMetrics: function (index) { + if (index == b2_nullNode) { + return + } + var node = this.m_nodes[index]; + var child1 = node.child1; + var child2 = node.child2; + if (node.IsLeaf()) { + return + } + var height1 = this.m_nodes[child1].height; + var height2 = this.m_nodes[child2].height; + var height; + height = 1 + b2Max(height1, height2); + var aabb = new b2AABB(); + aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + this.ValidateMetrics(child1); + this.ValidateMetrics(child2) + } + }; + "use strict"; + + function b2TOIInput() { + this.proxyA = new b2DistanceProxy(); + this.proxyB = new b2DistanceProxy(); + this.sweepA = new b2Sweep(); + this.sweepB = new b2Sweep(); + this.tMax = 0 + } + + function b2TOIOutput() { + this.state = 0; + this.t = 0 + } + b2TOIOutput.e_unknown = 0; + b2TOIOutput.e_failed = 1; + b2TOIOutput.e_overlapped = 2; + b2TOIOutput.e_touching = 3; + b2TOIOutput.e_separated = 4; + + function b2SeparationFunction() { + this.m_proxyA = null; + this.m_proxyB = null; + this.m_sweepA = null; + this.m_sweepB = null; + this.m_type = 0; + this.m_localPoint = new b2Vec2(); + this.m_axis = new b2Vec2() + } + var _local_xfA = new b2Transform(); + var _local_xfB = new b2Transform(); + b2SeparationFunction.prototype = { + Initialize: function (cache, proxyA, sweepA, proxyB, sweepB, t1) { + this.m_proxyA = proxyA; + this.m_proxyB = proxyB; + var count = cache.count; + this.m_sweepA = sweepA; + this.m_sweepB = sweepB; + this.m_sweepA.GetTransform(_local_xfA, t1); + this.m_sweepB.GetTransform(_local_xfB, t1); + if (count == 1) { + this.m_type = b2SeparationFunction.e_points; + var localPointA = this.m_proxyA.GetVertex(cache.indexA[0]); + var localPointB = this.m_proxyB.GetVertex(cache.indexB[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + this.m_axis.x = pointBx - pointAx; + this.m_axis.y = pointBy - pointAy; + var s = this.m_axis.Normalize(); + return s + } else { + if (cache.indexA[0] == cache.indexA[1]) { + this.m_type = b2SeparationFunction.e_faceB; + var localPointB1 = proxyB.GetVertex(cache.indexB[0]); + var localPointB2 = proxyB.GetVertex(cache.indexB[1]); + this.m_axis.x = 1 * (localPointB2.y - localPointB1.y); + this.m_axis.y = -1 * (localPointB2.x - localPointB1.x); + this.m_axis.Normalize(); + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + this.m_localPoint.x = 0.5 * (localPointB1.x + localPointB2.x); + this.m_localPoint.y = 0.5 * (localPointB1.y + localPointB2.y); + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var localPointA = proxyA.GetVertex(cache.indexA[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var s = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; + if (s < 0) { + this.m_axis.x = -this.m_axis.x; + this.m_axis.y = -this.m_axis.y; + s = -s + } + return s + } else { + this.m_type = b2SeparationFunction.e_faceA; + var localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]); + var localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]); + this.m_axis.x = 1 * (localPointA2.y - localPointA1.y); + this.m_axis.y = -1 * (localPointA2.x - localPointA1.x); + this.m_axis.Normalize(); + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + this.m_localPoint.x = 0.5 * (localPointA1.x + localPointA2.x); + this.m_localPoint.y = 0.5 * (localPointA1.y + localPointA2.y); + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var localPointB = this.m_proxyB.GetVertex(cache.indexB[0]); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var s = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + if (s < 0) { + this.m_axis.x = -this.m_axis.x; + this.m_axis.y = -this.m_axis.y; + s = -s + } + return s + } + } + }, + FindMinSeparation: function (indices, t) { + this.m_sweepA.GetTransform(_local_xfA, t); + this.m_sweepB.GetTransform(_local_xfB, t); + switch (this.m_type) { + case b2SeparationFunction.e_points: + var axisAx = _local_xfA.q.c * this.m_axis.x + _local_xfA.q.s * this.m_axis.y; + var axisAy = -_local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var axisBx = _local_xfB.q.c * -this.m_axis.x + _local_xfB.q.s * -this.m_axis.y; + var axisBy = -_local_xfB.q.s * -this.m_axis.x + _local_xfB.q.c * -this.m_axis.y; + indices[0] = this.m_proxyA.GetSupport(axisAx, axisAy); + indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); + var localPointA = this.m_proxyA.GetVertex(indices[0]); + var localPointB = this.m_proxyB.GetVertex(indices[1]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + return (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; + case b2SeparationFunction.e_faceA: + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var axisBx = _local_xfB.q.c * -normalx + _local_xfB.q.s * -normaly; + var axisBy = -_local_xfB.q.s * -normalx + _local_xfB.q.c * -normaly; + indices[0] = -1; + indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); + var localPointB = this.m_proxyB.GetVertex(indices[1]); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + return (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + case b2SeparationFunction.e_faceB: + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var axisAx = _local_xfA.q.c * -normalx + _local_xfA.q.s * -normaly; + var axisBy = -_local_xfA.q.s * -normalx + _local_xfA.q.c * -normaly; + indices[1] = -1; + indices[0] = this.m_proxyA.GetSupport(axisAx, axisBy); + var localPointA = this.m_proxyA.GetVertex(indices[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + return (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly + } + }, + Evaluate: function (indexA, indexB, t) { + this.m_sweepA.GetTransform(_local_xfA, t); + this.m_sweepB.GetTransform(_local_xfB, t); + switch (this.m_type) { + case b2SeparationFunction.e_points: + var localPointA = this.m_proxyA.GetVertex(indexA); + var localPointB = this.m_proxyB.GetVertex(indexB); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var separation = (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; + return separation; + case b2SeparationFunction.e_faceA: + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var localPointB = this.m_proxyB.GetVertex(indexB); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var separation = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + return separation; + case b2SeparationFunction.e_faceB: + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var localPointA = this.m_proxyA.GetVertex(indexA); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var separation = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; + return separation + } + } + }; + b2SeparationFunction.e_points = 0; + b2SeparationFunction.e_faceA = 1; + b2SeparationFunction.e_faceB = 2; + var profile_toi = b2Profiler.create("toi", "solveTOI"); + + function b2TimeOfImpact(output, input) { + profile_toi.start(); + ++b2TimeOfImpact.b2_toiCalls; + output.state = b2TOIOutput.e_unknown; + output.t = input.tMax; + var proxyA = input.proxyA; + var proxyB = input.proxyB; + b2TimeOfImpact._temp_sweepA.Assign(input.sweepA); + b2TimeOfImpact._temp_sweepB.Assign(input.sweepB); + b2TimeOfImpact._temp_sweepA.Normalize(); + b2TimeOfImpact._temp_sweepB.Normalize(); + var tMax = input.tMax; + var totalRadius = proxyA.m_radius + proxyB.m_radius; + var target = b2Max(b2_linearSlop, totalRadius - 3 * b2_linearSlop); + var tolerance = 0.25 * b2_linearSlop; + var t1 = 0; + var k_maxIterations = 20; + var iter = 0; + var cache = new b2SimplexCache(); + cache.count = 0; + var distanceInput = new b2DistanceInput(); + distanceInput.proxyA.Assign(input.proxyA); + distanceInput.proxyB.Assign(input.proxyB); + distanceInput.useRadii = false; + for (;;) { + b2TimeOfImpact._temp_sweepA.GetTransform(distanceInput.transformA, t1); + b2TimeOfImpact._temp_sweepB.GetTransform(distanceInput.transformB, t1); + var distanceOutput = new b2DistanceOutput(); + b2DistanceFunc(distanceOutput, cache, distanceInput); + if (distanceOutput.distance <= 0) { + output.state = b2TOIOutput.e_overlapped; + output.t = 0; + break + } + if (distanceOutput.distance < target + tolerance) { + output.state = b2TOIOutput.e_touching; + output.t = t1; + break + } + var fcn = new b2SeparationFunction(); + fcn.Initialize(cache, proxyA, b2TimeOfImpact._temp_sweepA, proxyB, b2TimeOfImpact._temp_sweepB, t1); + var done = false; + var t2 = tMax; + var pushBackIter = 0; + for (;;) { + var indices = []; + var s2 = fcn.FindMinSeparation(indices, t2); + if (s2 > target + tolerance) { + output.state = b2TOIOutput.e_separated; + output.t = tMax; + done = true; + break + } + if (s2 > target - tolerance) { + t1 = t2; + break + } + var s1 = fcn.Evaluate(indices[0], indices[1], t1); + if (s1 < target - tolerance) { + output.state = b2TOIOutput.e_failed; + output.t = t1; + done = true; + break + } + if (s1 <= target + tolerance) { + output.state = b2TOIOutput.e_touching; + output.t = t1; + done = true; + break + } + var rootIterCount = 0; + var a1 = t1, + a2 = t2; + for (;;) { + var t; + if (rootIterCount & 1) { + t = a1 + (target - s1) * (a2 - a1) / (s2 - s1) + } else { + t = 0.5 * (a1 + a2) + }++rootIterCount; + ++b2TimeOfImpact.b2_toiRootIters; + var s = fcn.Evaluate(indices[0], indices[1], t); + if (b2Abs(s - target) < tolerance) { + t2 = t; + break + } + if (s > target) { + a1 = t; + s1 = s + } else { + a2 = t; + s2 = s + } + if (rootIterCount == 50) { + break + } + } + b2TimeOfImpact.b2_toiMaxRootIters = b2Max(b2TimeOfImpact.b2_toiMaxRootIters, rootIterCount); + ++pushBackIter; + if (pushBackIter == b2_maxPolygonVertices) { + break + } + }++iter; + ++b2TimeOfImpact.b2_toiIters; + if (done) { + break + } + if (iter == k_maxIterations) { + output.state = b2TOIOutput.e_failed; + output.t = t1; + break + } + } + b2TimeOfImpact.b2_toiMaxIters = b2Max(b2TimeOfImpact.b2_toiMaxIters, iter); + profile_toi.stop(); + b2TimeOfImpact.b2_toiMaxTime = b2Max(b2TimeOfImpact.b2_toiMaxTime, profile_toi.elapsedTime); + b2TimeOfImpact.b2_toiTime += profile_toi.elapsedTime + } + b2TimeOfImpact._temp_sweepA = new b2Sweep(); + b2TimeOfImpact._temp_sweepB = new b2Sweep(); + b2TimeOfImpact.b2_toiTime = 0; + b2TimeOfImpact.b2_toiMaxTime = 0; + b2TimeOfImpact.b2_toiCalls = 0; + b2TimeOfImpact.b2_toiIters = 0; + b2TimeOfImpact.b2_toiMaxIters = 0; + b2TimeOfImpact.b2_toiRootIters = 0; + b2TimeOfImpact.b2_toiMaxRootIters = 0; + "use strict"; + + function b2BodyDef() { + this.type = b2Body.b2_staticBody; + this.position = new b2Vec2(0, 0); + this.angle = 0; + this.linearVelocity = new b2Vec2(0, 0); + this.angularVelocity = 0; + this.linearDamping = 0; + this.angularDamping = 0; + this.allowSleep = true; + this.awake = true; + this.fixedRotation = false; + this.bullet = false; + this.active = true; + this.userData = null; + this.gravityScale = 1; + Object.seal(this) + } + b2BodyDef.prototype = { + _deserialize: function (data) { + this.type = data.type; + this.position._deserialize(data.position); + this.angle = data.angle; + this.linearVelocity._deserialize(data.linearVelocity); + this.angularVelocity = data.angularVelocity; + this.linearDamping = data.linearDamping; + this.angularDamping = data.angularDamping; + this.allowSleep = data.allowSleep; + this.awake = data.awake; + this.fixedRotation = data.fixedRotation; + this.bullet = data.bullet; + this.active = data.active; + this.gravityScale = data.gravityScale + } + }; + + function b2Body(bd, world) { + this.m_islandIndex = 0; + this.m_flags = 0; + if (bd.bullet) { + this.m_flags |= b2Body.e_bulletFlag + } + if (bd.fixedRotation) { + this.m_flags |= b2Body.e_fixedRotationFlag + } + if (bd.allowSleep) { + this.m_flags |= b2Body.e_autoSleepFlag + } + if (bd.awake) { + this.m_flags |= b2Body.e_awakeFlag + } + if (bd.active) { + this.m_flags |= b2Body.e_activeFlag + } + this.m_world = world; + this.m_xf = new b2Transform(); + this.m_xf.p.Assign(bd.position); + this.m_xf.q.Set(bd.angle); + this.m_sweep = new b2Sweep(); + this.m_sweep.localCenter.SetZero(); + this.m_sweep.c0.Assign(this.m_xf.p); + this.m_sweep.c.Assign(this.m_xf.p); + this.m_sweep.a0 = bd.angle; + this.m_sweep.a = bd.angle; + this.m_sweep.alpha0 = 0; + this.m_jointList = null; + this.m_contactList = null; + this.m_prev = null; + this.m_next = null; + this.m_linearVelocity = bd.linearVelocity.Clone(); + this.m_angularVelocity = bd.angularVelocity; + this.m_linearDamping = bd.linearDamping; + this.m_angularDamping = bd.angularDamping; + this.m_gravityScale = bd.gravityScale; + this.m_force = new b2Vec2(); + this.m_torque = 0; + this.m_sleepTime = 0; + this.m_type = bd.type; + if (this.m_type == b2Body.b2_dynamicBody) { + this.m_mass = 1; + this.m_invMass = 1 + } else { + this.m_mass = 0; + this.m_invMass = 0 + } + this.m_I = 0; + this.m_invI = 0; + this.m_userData = bd.userData; + this.m_fixtureList = null; + this.m_fixtureCount = 0 + } + b2Body.b2_staticBody = 0; + b2Body.b2_kinematicBody = 1; + b2Body.b2_dynamicBody = 2; + b2Body.e_islandFlag = 1; + b2Body.e_awakeFlag = 2; + b2Body.e_autoSleepFlag = 4; + b2Body.e_bulletFlag = 8; + b2Body.e_fixedRotationFlag = 16; + b2Body.e_activeFlag = 32; + b2Body.e_toiFlag = 64; + b2Body.m_local_oldCenter = new b2Vec2(); + b2Body.m_local_xf1 = new b2Transform(); + b2Body.prototype = { + CreateFixture: function (def, density) { + if (typeof (density) !== "undefined") { + var ndef = new b2FixtureDef(); + ndef.shape = def; + ndef.density = density; + return this.CreateFixture(ndef) + } + if (this.m_world.IsLocked() == true) { + return null + } + var fixture = new b2Fixture(); + fixture.Create(this, def); + if (this.m_flags & b2Body.e_activeFlag) { + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + fixture.CreateProxies(broadPhase, this.m_xf) + } + fixture.m_next = this.m_fixtureList; + this.m_fixtureList = fixture; + ++this.m_fixtureCount; + fixture.m_body = this; + if (fixture.m_density > 0) { + this.ResetMassData() + } + this.m_world.m_flags |= b2World.e_newFixture; + return fixture + }, + DestroyFixture: function (fixture) { + if (this.m_world.IsLocked() == true) { + return + } + var node = this.m_fixtureList; + var found = false; + while (node != null) { + if (node == fixture) { + this.m_fixtureList = node = fixture.m_next; + found = true; + break + } + node = node.m_next + } + var edge = this.m_contactList; + while (edge) { + var c = edge.contact; + edge = edge.next; + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + if (fixture == fixtureA || fixture == fixtureB) { + this.m_world.m_contactManager.Destroy(c) + } + } + if (this.m_flags & b2Body.e_activeFlag) { + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + fixture.DestroyProxies(broadPhase) + } + fixture.Destroy(); + fixture.m_body = null; + fixture.m_next = null; + --this.m_fixtureCount; + this.ResetMassData() + }, + SetTransform: function (position, angle) { + if (this.m_world.IsLocked() == true) { + return + } + this.m_xf.q.Set(angle); + this.m_xf.p.Assign(position); + this.m_sweep.c.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.a = angle; + this.m_sweep.c0.Assign(this.m_sweep.c); + this.m_sweep.a0 = angle; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.Synchronize(broadPhase, this.m_xf, this.m_xf) + } + }, + GetTransform: function () { + return this.m_xf + }, + GetPosition: function () { + return this.m_xf.p + }, + GetAngle: function () { + return this.m_sweep.a + }, + GetWorldCenter: function () { + return this.m_sweep.c + }, + GetLocalCenter: function () { + return this.m_sweep.localCenter + }, + SetLinearVelocity: function (v) { + if (this.m_type == b2Body.b2_staticBody) { + return + } + if (b2Dot_v2_v2(v, v) > 0) { + this.SetAwake(true) + } + this.m_linearVelocity = v + }, + GetLinearVelocity: function () { + return this.m_linearVelocity + }, + SetAngularVelocity: function (w) { + if (this.m_type == b2Body.b2_staticBody) { + return + } + if (w * w > 0) { + this.SetAwake(true) + } + this.m_angularVelocity = w + }, + GetAngularVelocity: function () { + return this.m_angularVelocity + }, + ApplyForce: function (force, point, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_force.Add(force); + this.m_torque += b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), force) + } + }, + ApplyForceToCenter: function (force, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_force.Add(force) + } + }, + ApplyTorque: function (torque, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_torque += torque + } + }, + ApplyLinearImpulse: function (impulse, point, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_linearVelocity.Add(b2Vec2.Multiply(this.m_invMass, impulse)); + this.m_angularVelocity += this.m_invI * b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), impulse) + } + }, + ApplyAngularImpulse: function (impulse, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_angularVelocity += this.m_invI * impulse + } + }, + GetMass: function () { + return this.m_mass + }, + GetInertia: function () { + return this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter) + }, + GetMassData: function (data) { + data.mass = this.m_mass; + data.I = this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter); + data.center = this.m_sweep.localCenter + }, + SetMassData: function (massData) { + if (this.m_world.IsLocked() == true) { + return + } + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + this.m_invMass = 0; + this.m_I = 0; + this.m_invI = 0; + this.m_mass = massData.mass; + if (this.m_mass <= 0) { + this.m_mass = 1 + } + this.m_invMass = 1 / this.m_mass; + if (massData.I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { + this.m_I = massData.I - this.m_mass * b2Dot_v2_v2(massData.center, massData.center); + this.m_invI = 1 / this.m_I + } + b2Body.m_local_oldCenter.Assign(this.m_sweep.c); + this.m_sweep.localCenter.Assign(massData.center); + this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) + }, + ResetMassData: function () { + this.m_mass = 0; + this.m_invMass = 0; + this.m_I = 0; + this.m_invI = 0; + this.m_sweep.localCenter.SetZero(); + if (this.m_type == b2Body.b2_staticBody || this.m_type == b2Body.b2_kinematicBody) { + this.m_sweep.c0.Assign(this.m_xf.p); + this.m_sweep.c.Assign(this.m_xf.p); + this.m_sweep.a0 = this.m_sweep.a; + return + } + var localCenter = new b2Vec2(0, 0); + for (var f = this.m_fixtureList; f; f = f.m_next) { + if (f.m_density == 0) { + continue + } + var massData = new b2MassData(); + f.GetMassData(massData); + this.m_mass += massData.mass; + localCenter.Add(b2Vec2.Multiply(massData.mass, massData.center)); + this.m_I += massData.I + } + if (this.m_mass > 0) { + this.m_invMass = 1 / this.m_mass; + localCenter.Multiply(this.m_invMass) + } else { + this.m_mass = 1; + this.m_invMass = 1 + } + if (this.m_I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { + this.m_I -= this.m_mass * b2Dot_v2_v2(localCenter, localCenter); + this.m_invI = 1 / this.m_I + } else { + this.m_I = 0; + this.m_invI = 0 + } + b2Body.m_local_oldCenter.Assign(this.m_sweep.c); + this.m_sweep.localCenter.Assign(localCenter); + this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) + }, + GetWorldPoint: function (localPoint) { + return b2Mul_t_v2(this.m_xf, localPoint) + }, + GetWorldVector: function (localVector) { + return b2Mul_r_v2(this.m_xf.q, localVector) + }, + GetLocalPoint: function (worldPoint) { + return b2MulT_t_v2(this.m_xf, worldPoint) + }, + GetLocalVector: function (worldVector) { + return b2MulT_r_v2(this.m_xf.q, worldVector) + }, + GetLinearVelocityFromWorldPoint: function (worldPoint) { + return b2Vec2.Add(this.m_linearVelocity, b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(worldPoint, this.m_sweep.c))) + }, + GetLinearVelocityFromLocalPoint: function (localPoint) { + return this.GetLinearVelocityFromWorldPoint(this.GetWorldPoint(localPoint)) + }, + GetLinearDamping: function () { + return this.m_linearDamping + }, + SetLinearDamping: function (linearDamping) { + this.m_linearDamping = linearDamping + }, + GetAngularDamping: function () { + return this.m_angularDamping + }, + SetAngularDamping: function (angularDamping) { + this.m_angularDamping = angularDamping + }, + GetGravityScale: function () { + return this.m_gravityScale + }, + SetGravityScale: function (scale) { + this.m_gravityScale = scale + }, + SetType: function (type) { + if (this.m_world.IsLocked() == true) { + return + } + if (this.m_type == type) { + return + } + this.m_type = type; + this.ResetMassData(); + if (this.m_type == b2Body.b2_staticBody) { + this.m_linearVelocity.SetZero(); + this.m_angularVelocity = 0; + this.m_sweep.a0 = this.m_sweep.a; + this.m_sweep.c0.Assign(this.m_sweep.c); + this.SynchronizeFixtures() + } + this.SetAwake(true); + this.m_force.SetZero(); + this.m_torque = 0; + var ce = this.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_world.m_contactManager.Destroy(ce0.contact) + } + this.m_contactList = null; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + var proxyCount = f.m_proxyCount; + for (var i = 0; i < proxyCount; ++i) { + broadPhase.TouchProxy(f.m_proxies[i].proxyId) + } + } + }, + GetType: function () { + return this.m_type + }, + SetBullet: function (flag) { + if (flag) { + this.m_flags |= b2Body.e_bulletFlag + } else { + this.m_flags &= ~b2Body.e_bulletFlag + } + }, + IsBullet: function () { + return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag + }, + SetSleepingAllowed: function (flag) { + if (flag) { + this.m_flags |= b2Body.e_autoSleepFlag + } else { + this.m_flags &= ~b2Body.e_autoSleepFlag; + this.SetAwake(true) + } + }, + IsSleepingAllowed: function () { + return (this.m_flags & b2Body.e_autoSleepFlag) == b2Body.e_autoSleepFlag + }, + SetAwake: function (flag) { + if (flag) { + if ((this.m_flags & b2Body.e_awakeFlag) == 0) { + this.m_flags |= b2Body.e_awakeFlag; + this.m_sleepTime = 0 + } + } else { + this.m_flags &= ~b2Body.e_awakeFlag; + this.m_sleepTime = 0; + this.m_linearVelocity.SetZero(); + this.m_angularVelocity = 0; + this.m_force.SetZero(); + this.m_torque = 0 + } + }, + IsAwake: function () { + return (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag + }, + SetActive: function (flag) { + if (flag == this.IsActive()) { + return + } + if (flag) { + this.m_flags |= b2Body.e_activeFlag; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.CreateProxies(broadPhase, this.m_xf) + } + } else { + this.m_flags &= ~b2Body.e_activeFlag; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.DestroyProxies(broadPhase) + } + var ce = this.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_world.m_contactManager.Destroy(ce0.contact) + } + this.m_contactList = null + } + }, + IsActive: function () { + return (this.m_flags & b2Body.e_activeFlag) == b2Body.e_activeFlag + }, + SetFixedRotation: function (flag) { + var status = (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag; + if (status == flag) { + return + } + if (flag) { + this.m_flags |= b2Body.e_fixedRotationFlag + } else { + this.m_flags &= ~b2Body.e_fixedRotationFlag + } + this.m_angularVelocity = 0; + this.ResetMassData() + }, + IsFixedRotation: function () { + return (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag + }, + GetFixtureList: function () { + return this.m_fixtureList + }, + GetJointList: function () { + return this.m_jointList + }, + GetContactList: function () { + return this.m_contactList + }, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + GetWorld: function () { + return this.m_world + }, + SynchronizeFixtures: function () { + b2Body.m_local_xf1.q.Set(this.m_sweep.a0); + b2Body.m_local_xf1.p.Assign(b2Vec2.Subtract(this.m_sweep.c0, b2Mul_r_v2(b2Body.m_local_xf1.q, this.m_sweep.localCenter))); + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.Synchronize(broadPhase, b2Body.m_local_xf1, this.m_xf) + } + }, + SynchronizeTransform: function () { + this.m_xf.q.Set(this.m_sweep.a); + this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) + }, + ShouldCollide: function (other) { + if (this.m_type != b2Body.b2_dynamicBody && other.m_type != b2Body.b2_dynamicBody) { + return false + } + for (var jn = this.m_jointList; jn; jn = jn.next) { + if (jn.other == other) { + if (jn.joint.m_collideConnected == false) { + return false + } + } + } + return true + }, + Advance: function (alpha) { + this.m_sweep.Advance(alpha); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_sweep.a = this.m_sweep.a0; + this.m_xf.q.Set(this.m_sweep.a); + this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) + }, + _serialize: function (out) { + var obj = out || {}; + obj.fixtures = null; + obj.type = this.m_type; + obj.position = this.GetPosition()._serialize(); + obj.angle = this.GetAngle(); + obj.linearVelocity = this.GetLinearVelocity()._serialize(); + obj.angularVelocity = this.GetAngularVelocity(); + obj.linearDamping = this.GetLinearDamping(); + obj.angularDamping = this.GetAngularDamping(); + obj.allowSleep = this.IsSleepingAllowed(); + obj.awake = this.IsAwake(); + obj.fixedRotation = this.IsFixedRotation(); + obj.bullet = this.IsBullet(); + obj.active = this.IsActive(); + obj.gravityScale = this.GetGravityScale(); + return obj + } + }; + "use strict"; + + function b2Filter() { + this.categoryBits = 1; + this.maskBits = 65535; + this.groupIndex = 0 + } + b2Filter.prototype = { + Clone: function () { + var filter = new b2Filter(); + filter.categoryBits = this.categoryBits; + filter.maskBits = this.maskBits; + filter.groupIndex = this.groupIndex; + return filter + }, + Assign: function (filter) { + this.categoryBits = filter.categoryBits; + this.maskBits = filter.maskBits; + this.groupIndex = filter.groupIndex + }, + _serialize: function (out) { + var obj = out || {}; + obj.categoryBits = this.categoryBits; + obj.maskBits = this.maskBits; + obj.groupIndex = this.groupIndex; + return obj + }, + _deserialize: function (data) { + this.categoryBits = data.categoryBits; + this.maskBits = data.maskBits; + this.groupIndex = data.groupIndex + } + }; + + function b2FixtureDef() { + this.shape = null; + this.userData = null; + this.friction = 0.2; + this.restitution = 0; + this.density = 0; + this.isSensor = false; + this.filter = new b2Filter(); + Object.seal(this) + } + b2FixtureDef.prototype = { + _deserialize: function (data) { + this.friction = data.friction; + this.restitution = data.restitution; + this.density = data.density; + this.isSensor = data.isSensor; + this.filter._deserialize(data.filter) + } + }; + + function b2FixtureProxy() { + this.aabb = new b2AABB(); + this.fixture = null; + this.childIndex = 0; + this.proxyId = 0 + } + + function b2Fixture() { + this.m_userData = null; + this.m_body = null; + this.m_next = null; + this.m_proxies = null; + this.m_proxyCount = 0; + this.m_shape = null; + this.m_density = 0; + this.m_filter = new b2Filter(); + this.m_isSensor = false; + this.m_friction = 0; + this.m_restitution = 0 + } + b2Fixture.prototype = { + GetType: function () { + return this.m_shape.GetType() + }, + GetShape: function () { + return this.m_shape + }, + SetSensor: function (sensor) { + if (sensor != this.m_isSensor) { + this.m_body.SetAwake(true); + this.m_isSensor = sensor + } + }, + IsSensor: function () { + return this.m_isSensor + }, + SetFilterData: function (filter) { + this.m_filter = filter; + this.Refilter() + }, + GetFilterData: function () { + return this.m_filter + }, + Refilter: function () { + if (this.m_body == null) { + return + } + var edge = this.m_body.GetContactList(); + while (edge) { + var contact = edge.contact; + var fixtureA = contact.GetFixtureA(); + var fixtureB = contact.GetFixtureB(); + if (fixtureA == this || fixtureB == this) { + contact.FlagForFiltering() + } + edge = edge.next + } + var world = this.m_body.GetWorld(); + if (world == null) { + return + } + var broadPhase = world.m_contactManager.m_broadPhase; + for (var i = 0; i < this.m_proxyCount; ++i) { + broadPhase.TouchProxy(this.m_proxies[i].proxyId) + } + }, + GetBody: function () { + return this.m_body + }, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + TestPoint: function (p) { + return this.m_shape.TestPoint(this.m_body.GetTransform(), p) + }, + RayCast: function (output, input, childIndex) { + return this.m_shape.RayCast(output, input, this.m_body.GetTransform(), childIndex) + }, + GetMassData: function (massData) { + this.m_shape.ComputeMass(massData, this.m_density) + }, + SetDensity: function (density) { + this.m_density = density + }, + GetDensity: function () { + return this.m_density + }, + GetFriction: function () { + return this.m_friction + }, + SetFriction: function (friction) { + this.m_friction = friction + }, + GetRestitution: function () { + return this.m_restitution + }, + SetRestitution: function (restitution) { + this.m_restitution = restitution + }, + GetAABB: function (childIndex) { + return this.m_proxies[childIndex].aabb + }, + Create: function (body, def) { + this.m_userData = def.userData; + this.m_friction = def.friction; + this.m_restitution = def.restitution; + this.m_body = body; + this.m_next = null; + this.m_filter.Assign(def.filter); + this.m_isSensor = def.isSensor; + this.m_shape = def.shape.Clone(); + var childCount = this.m_shape.GetChildCount(); + this.m_proxies = new Array(childCount); + for (var i = 0; i < childCount; ++i) { + this.m_proxies[i] = new b2FixtureProxy(); + this.m_proxies[i].fixture = null; + this.m_proxies[i].proxyId = b2BroadPhase.e_nullProxy + } + this.m_proxyCount = 0; + this.m_density = def.density + }, + Destroy: function () { + this.m_proxies = null; + this.m_shape = null + }, + CreateProxies: function (broadPhase, xf) { + this.m_proxyCount = this.m_shape.GetChildCount(); + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + this.m_shape.ComputeAABB(proxy.aabb, xf, i); + proxy.proxyId = broadPhase.CreateProxy(proxy.aabb, proxy); + proxy.fixture = this; + proxy.childIndex = i + } + }, + DestroyProxies: function (broadPhase) { + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + broadPhase.DestroyProxy(proxy.proxyId); + proxy.proxyId = b2BroadPhase.e_nullProxy + } + this.m_proxyCount = 0 + }, + Synchronize: function (broadPhase, transform1, transform2) { + if (this.m_proxyCount == 0) { + return + } + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + var aabb1 = new b2AABB(), + aabb2 = new b2AABB(); + this.m_shape.ComputeAABB(aabb1, transform1, proxy.childIndex); + this.m_shape.ComputeAABB(aabb2, transform2, proxy.childIndex); + proxy.aabb.Combine(aabb1, aabb2); + var displacement = b2Vec2.Subtract(transform2.p, transform1.p); + broadPhase.MoveProxy(proxy.proxyId, proxy.aabb, displacement) + } + }, + _serialize: function (out) { + var obj = out || {}; + obj.shape = null; + obj.friction = this.m_friction; + obj.restitution = this.m_restitution; + obj.density = this.m_density; + obj.isSensor = this.m_isSensor; + obj.filter = this.m_filter._serialize(); + return obj + } + }; + "use strict"; + + function b2DestructionListener() {} + b2DestructionListener.prototype = { + SayGoodbyeJoint: function (joint) {}, + SayGoodbyeFixture: function (fixture) {} + }; + + function b2ContactFilter() {} + b2ContactFilter.prototype = { + ShouldCollide: function (fixtureA, fixtureB) { + var filterA = fixtureA.GetFilterData(); + var filterB = fixtureB.GetFilterData(); + if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) { + return filterA.groupIndex > 0 + } + var collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0; + return collide + } + }; + + function b2ContactImpulse() { + this.normalImpulses = new Array(b2_maxManifoldPoints); + this.tangentImpulses = new Array(b2_maxManifoldPoints); + this.count = 0 + } + + function b2ContactListener() {} + b2ContactListener.prototype = { + BeginContact: function (contact) {}, + EndContact: function (contact) {}, + PreSolve: function (contact, oldManifold) {}, + PostSolve: function (contact, impulse) {} + }; + + function b2QueryCallback() {} + b2QueryCallback.prototype = { + ReportFixture: function (fixture) {} + }; + + function b2RayCastCallback() {} + b2RayCastCallback.prototype = { + ReportFixture: function (fixture, point, normal, fraction) {} + }; + "use strict"; + + function b2TimeStep() { + this.dt = 0; + this.inv_dt = 0; + this.dtRatio = 0; + this.velocityIterations = 0; + this.positionIterations = 0; + this.warmStarting = false + } + + function b2Position() { + this.c = new b2Vec2(); + this.a = 0 + } + + function b2Velocity() { + this.v = new b2Vec2(); + this.w = 0 + } + + function b2SolverData() { + this.step = new b2TimeStep(); + this.positions = null; + this.velocities = null + } + "use strict"; + var profile_world_step = b2Profiler.create("step"); + var profile_world_collide = b2Profiler.create("collide", "step"); + var profile_world_solve = b2Profiler.create("solve", "step"); + var profile_world_solveTOI = b2Profiler.create("solveTOI", "step"); + var profile_world_broadphase = b2Profiler.create("broadphase", "step"); + + function b2World(gravity) { + this.m_contactManager = new b2ContactManager(); + this.m_destructionListener = null; + this.g_debugDraw = null; + this.m_bodyList = null; + this.m_jointList = null; + this.m_bodyCount = 0; + this.m_jointCount = 0; + this.m_warmStarting = true; + this.m_continuousPhysics = true; + this.m_subStepping = false; + this.m_stepComplete = true; + this.m_allowSleep = true; + this.m_gravity = gravity; + this.m_flags = b2World.e_clearForces; + this.m_inv_dt0 = 0; + this.p_step = new b2TimeStep(); + this.p_island = new b2Island() + } + + function b2WorldQueryWrapper() { + this.broadPhase = null; + this.callback = null + } + b2WorldQueryWrapper.prototype = { + QueryCallback: function (proxyId) { + var proxy = this.broadPhase.GetUserData(proxyId); + return this.callback.ReportFixture(proxy.fixture) + } + }; + + function b2WorldRayCastWrapper() { + this.broadPhase = null; + this.callback = null + } + b2WorldRayCastWrapper.prototype = { + RayCastCallback: function (input, proxyId) { + var userData = this.broadPhase.GetUserData(proxyId); + var proxy = userData; + var fixture = proxy.fixture; + var index = proxy.childIndex; + var output = new b2RayCastOutput(); + var hit = fixture.RayCast(output, input, index); + if (hit) { + var fraction = output.fraction; + var point = b2Vec2.Add(b2Vec2.Multiply((1 - fraction), input.p1), b2Vec2.Multiply(fraction, input.p2)); + return this.callback.ReportFixture(fixture, point, output.normal, fraction) + } + return input.maxFraction + } + }; + b2World.m_local_sweep_backupA = new b2Sweep(); + b2World.m_local_sweep_backupB = new b2Sweep(); + b2World.m_local_sweep_backupC = new b2Sweep(); + b2World.prototype = { + Destroy: function () { + var b = this.m_bodyList; + while (b) { + var bNext = b.m_next; + var f = b.m_fixtureList; + while (f) { + var fNext = f.m_next; + f.m_proxyCount = 0; + f.Destroy(); + f = fNext + } + b = bNext + } + }, + SetDestructionListener: function (listener) { + this.m_destructionListener = listener + }, + SetContactFilter: function (filter) { + this.m_contactManager.m_contactFilter = filter + }, + SetContactListener: function (listener) { + this.m_contactManager.m_contactListener = listener + }, + SetDebugDraw: function (debugDraw) { + this.g_debugDraw = debugDraw + }, + CreateBody: function (def) { + if (this.IsLocked()) { + 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 + }, + DestroyBody: function (b) { + if (this.IsLocked()) { + return + } + var je = b.m_jointList; + while (je) { + var je0 = je; + je = je.next; + if (this.m_destructionListener) { + this.m_destructionListener.SayGoodbyeJoint(je0.joint) + } + this.DestroyJoint(je0.joint); + b.m_jointList = je + } + b.m_jointList = null; + var ce = b.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_contactManager.Destroy(ce0.contact) + } + b.m_contactList = null; + var f = b.m_fixtureList; + while (f) { + var f0 = f; + f = f.m_next; + if (this.m_destructionListener) { + this.m_destructionListener.SayGoodbyeFixture(f0) + } + f0.DestroyProxies(this.m_contactManager.m_broadPhase); + f0.Destroy(); + b.m_fixtureList = f; + b.m_fixtureCount -= 1 + } + b.m_fixtureList = null; + b.m_fixtureCount = 0; + 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 + } + b.m_destroyed = true; + --this.m_bodyCount + }, + CreateJoint: function (def) { + if (this.IsLocked()) { + return null + } + var j = b2Joint.Create(def); + 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_edgeA.joint = j; + j.m_edgeA.other = j.m_bodyB; + j.m_edgeA.prev = null; + j.m_edgeA.next = j.m_bodyA.m_jointList; + if (j.m_bodyA.m_jointList) { + j.m_bodyA.m_jointList.prev = j.m_edgeA + } + j.m_bodyA.m_jointList = j.m_edgeA; + j.m_edgeB.joint = j; + j.m_edgeB.other = j.m_bodyA; + j.m_edgeB.prev = null; + j.m_edgeB.next = j.m_bodyB.m_jointList; + if (j.m_bodyB.m_jointList) { + j.m_bodyB.m_jointList.prev = j.m_edgeB + } + j.m_bodyB.m_jointList = j.m_edgeB; + var bodyA = def.bodyA; + var bodyB = def.bodyB; + if (def.collideConnected == false) { + var edge = bodyB.GetContactList(); + while (edge) { + if (edge.other == bodyA) { + edge.contact.FlagForFiltering() + } + edge = edge.next + } + } + return j + }, + DestroyJoint: function (j) { + if (this.IsLocked()) { + return + } + 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 bodyA = j.m_bodyA; + var bodyB = j.m_bodyB; + bodyA.SetAwake(true); + bodyB.SetAwake(true); + if (j.m_edgeA.prev) { + j.m_edgeA.prev.next = j.m_edgeA.next + } + if (j.m_edgeA.next) { + j.m_edgeA.next.prev = j.m_edgeA.prev + } + if (j.m_edgeA == bodyA.m_jointList) { + bodyA.m_jointList = j.m_edgeA.next + } + j.m_edgeA.prev = null; + j.m_edgeA.next = null; + if (j.m_edgeB.prev) { + j.m_edgeB.prev.next = j.m_edgeB.next + } + if (j.m_edgeB.next) { + j.m_edgeB.next.prev = j.m_edgeB.prev + } + if (j.m_edgeB == bodyB.m_jointList) { + bodyB.m_jointList = j.m_edgeB.next + } + j.m_edgeB.prev = null; + j.m_edgeB.next = null; + b2Joint.Destroy(j); + --this.m_jointCount; + if (collideConnected == false) { + var edge = bodyB.GetContactList(); + while (edge) { + if (edge.other == bodyA) { + edge.contact.FlagForFiltering() + } + edge = edge.next + } + } + }, + Step: function (dt, velocityIterations, positionIterations) { + profile_world_step.start(); + if (this.m_flags & b2World.e_newFixture) { + this.m_contactManager.FindNewContacts(); + this.m_flags &= ~b2World.e_newFixture + } + this.m_flags |= b2World.e_locked; + this.p_step.dt = dt; + this.p_step.velocityIterations = velocityIterations; + this.p_step.positionIterations = positionIterations; + if (dt > 0) { + this.p_step.inv_dt = 1 / dt + } else { + this.p_step.inv_dt = 0 + } + this.p_step.dtRatio = this.m_inv_dt0 * dt; + this.p_step.warmStarting = this.m_warmStarting; + profile_world_collide.start(); + this.m_contactManager.Collide(); + profile_world_collide.stop(); + if (this.m_stepComplete && this.p_step.dt > 0) { + profile_world_solve.start(); + this.Solve(this.p_step); + profile_world_solve.stop() + } + if (this.m_continuousPhysics && this.p_step.dt > 0) { + profile_world_solveTOI.start(); + this.SolveTOI(this.p_step); + profile_world_solveTOI.stop() + } + if (this.p_step.dt > 0) { + this.m_inv_dt0 = this.p_step.inv_dt + } + if (this.m_flags & b2World.e_clearForces) { + this.ClearForces() + } + this.m_flags &= ~b2World.e_locked; + profile_world_step.stop() + }, + ClearForces: function () { + for (var body = this.m_bodyList; body; body = body.GetNext()) { + body.m_force.x = body.m_force.y = 0; + body.m_torque = 0 + } + }, + DrawDebugData: function () { + if (this.g_debugDraw == null) { + return + } + var flags = this.g_debugDraw.GetFlags(); + if (flags & b2Draw.e_shapeBit) { + for (var b = this.m_bodyList; b; b = b.GetNext()) { + var xf = b.GetTransform(); + for (var f = b.GetFixtureList(); f; f = f.GetNext()) { + if (b.IsActive() == false) { + this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.3)) + } else { + if (b.GetType() == b2Body.b2_staticBody) { + this.DrawShape(f, xf, new b2Color(0.5, 0.9, 0.5)) + } else { + if (b.GetType() == b2Body.b2_kinematicBody) { + this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.9)) + } else { + if (b.IsAwake() == false) { + this.DrawShape(f, xf, new b2Color(0.6, 0.6, 0.6)) + } else { + this.DrawShape(f, xf, new b2Color(0.9, 0.7, 0.7)) + } + } + } + } + } + } + } + if (flags & b2Draw.e_jointBit) { + for (var j = this.m_jointList; j; j = j.GetNext()) { + this.DrawJoint(j) + } + } + if (flags & b2Draw.e_pairBit) { + var color = new b2Color(0.3, 0.9, 0.9); + for (var c = this.m_contactManager.m_contactList; c; c = c.GetNext()) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var cA = fixtureA.GetAABB(c.GetChildIndexA()).GetCenter(); + var cB = fixtureB.GetAABB(c.GetChildIndexB()).GetCenter(); + this.g_debugDraw.DrawSegment(cA, cB, color) + } + } + if (flags & b2Draw.e_aabbBit) { + var color = new b2Color(0.9, 0.3, 0.9); + var bp = this.m_contactManager.m_broadPhase; + for (var b = this.m_bodyList; b; b = b.GetNext()) { + if (b.IsActive() == false) { + continue + } + for (var f = b.GetFixtureList(); f; f = f.GetNext()) { + for (var i = 0; i < f.m_proxyCount; ++i) { + var proxy = f.m_proxies[i]; + var aabb = bp.GetFatAABB(proxy.proxyId); + var vs = []; + vs[0] = new b2Vec2(aabb.lowerBound.x, aabb.lowerBound.y); + vs[1] = new b2Vec2(aabb.upperBound.x, aabb.lowerBound.y); + vs[2] = new b2Vec2(aabb.upperBound.x, aabb.upperBound.y); + vs[3] = new b2Vec2(aabb.lowerBound.x, aabb.upperBound.y); + this.g_debugDraw.DrawPolygon(vs, 4, color) + } + } + } + } + if (flags & b2Draw.e_centerOfMassBit) { + for (var b = this.m_bodyList; b; b = b.GetNext()) { + var xf = b.GetTransform().Clone(); + xf.p = b.GetWorldCenter(); + this.g_debugDraw.DrawTransform(xf) + } + } + }, + QueryAABB: function (callback, aabb) { + var wrapper = new b2WorldQueryWrapper(); + wrapper.broadPhase = this.m_contactManager.m_broadPhase; + wrapper.callback = callback; + this.m_contactManager.m_broadPhase.Query(wrapper, aabb) + }, + RayCast: function (callback, point1, point2) { + var wrapper = new b2WorldRayCastWrapper(); + wrapper.broadPhase = this.m_contactManager.m_broadPhase; + wrapper.callback = callback; + var input = new b2RayCastInput(); + input.maxFraction = 1; + input.p1 = point1; + input.p2 = point2; + this.m_contactManager.m_broadPhase.RayCast(wrapper, input) + }, + GetBodyList: function () { + return this.m_bodyList + }, + GetJointList: function () { + return this.m_jointList + }, + GetContactList: function () { + return this.m_contactManager.m_contactList + }, + SetAllowSleeping: function (flag) { + if (flag == this.m_allowSleep) { + return + } + this.m_allowSleep = flag; + if (this.m_allowSleep == false) { + for (var b = this.m_bodyList; b; b = b.m_next) { + b.SetAwake(true) + } + } + }, + GetAllowSleeping: function () { + return this.m_allowSleep + }, + SetWarmStarting: function (flag) { + this.m_warmStarting = flag + }, + GetWarmStarting: function () { + return this.m_warmStarting + }, + SetContinuousPhysics: function (flag) { + this.m_continuousPhysics = flag + }, + GetContinuousPhysics: function () { + return this.m_continuousPhysics + }, + SetSubStepping: function (flag) { + this.m_subStepping = flag + }, + GetSubStepping: function () { + return this.m_subStepping + }, + GetProxyCount: function () { + return this.m_contactManager.m_broadPhase.GetProxyCount() + }, + GetBodyCount: function () { + return this.m_bodyCount + }, + GetJointCount: function () { + return this.m_jointCount + }, + GetContactCount: function () { + return this.m_contactManager.m_contactCount + }, + GetTreeHeight: function () { + return this.m_contactManager.m_broadPhase.GetTreeHeight() + }, + GetTreeBalance: function () { + return this.m_contactManager.m_broadPhase.GetTreeBalance() + }, + GetTreeQuality: function () { + return this.m_contactManager.m_broadPhase.GetTreeQuality() + }, + SetGravity: function (gravity) { + this.m_gravity = gravity + }, + GetGravity: function () { + return this.m_gravity + }, + IsLocked: function () { + return (this.m_flags & b2World.e_locked) == b2World.e_locked + }, + SetAutoClearForces: function (flag) { + if (flag) { + this.m_flags |= b2World.e_clearForces + } else { + this.m_flags &= ~b2World.e_clearForces + } + }, + GetAutoClearForces: function () { + return (this.m_flags & b2World.e_clearForces) == b2World.e_clearForces + }, + ShiftOrigin: function (newOrigin) { + if ((this.m_flags & b2World.e_locked) == b2World.e_locked) { + return + } + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_xf.p.Subtract(newOrigin); + b.m_sweep.c0.Subtract(newOrigin); + b.m_sweep.c.Subtract(newOrigin) + } + for (var j = this.m_jointList; j; j = j.m_next) { + j.ShiftOrigin(newOrigin) + } + this.m_contactManager.m_broadPhase.ShiftOrigin(newOrigin) + }, + GetContactManager: function () { + return this.m_contactManager + }, + Solve: function (step) { + this.p_island.Initialize(this.m_bodyCount, this.m_contactManager.m_contactCount, this.m_jointCount, this.m_contactManager.m_contactListener); + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_flags &= ~b2Body.e_islandFlag + } + for (var c = this.m_contactManager.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) { + continue + } + if (seed.IsAwake() == false || seed.IsActive() == false) { + continue + } + if (seed.GetType() == b2Body.b2_staticBody) { + continue + } + this.p_island.Clear(); + var stackCount = 0; + stack[stackCount++] = seed; + seed.m_flags |= b2Body.e_islandFlag; + while (stackCount > 0) { + var b = stack[--stackCount]; + this.p_island.AddBody(b); + b.SetAwake(true); + if (b.GetType() == b2Body.b2_staticBody) { + continue + } + for (var ce = b.m_contactList; ce; ce = ce.next) { + var contact = ce.contact; + if (contact.m_flags & b2Contact.e_islandFlag) { + continue + } + if (contact.IsEnabled() == false || contact.IsTouching() == false) { + continue + } + var sensorA = contact.m_fixtureA.m_isSensor; + var sensorB = contact.m_fixtureB.m_isSensor; + if (sensorA || sensorB) { + continue + } + this.p_island.AddContact(contact); + contact.m_flags |= b2Contact.e_islandFlag; + var other = ce.other; + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + stack[stackCount++] = other; + other.m_flags |= b2Body.e_islandFlag + } + for (var je = b.m_jointList; je; je = je.next) { + if (je.joint.m_islandFlag == true) { + continue + } + var other = je.other; + if (other.IsActive() == false) { + continue + } + this.p_island.AddJoint(je.joint); + je.joint.m_islandFlag = true; + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + stack[stackCount++] = other; + other.m_flags |= b2Body.e_islandFlag + } + } + this.p_island.Solve(step, this.m_gravity, this.m_allowSleep); + for (var i = 0; i < this.p_island.m_bodyCount; ++i) { + var b = this.p_island.m_bodies[i]; + if (b.GetType() == b2Body.b2_staticBody) { + b.m_flags &= ~b2Body.e_islandFlag + } + } + } + profile_world_broadphase.start(); + for (var b = this.m_bodyList; b; b = b.GetNext()) { + if ((b.m_flags & b2Body.e_islandFlag) == 0) { + continue + } + if (b.GetType() == b2Body.b2_staticBody) { + continue + } + b.SynchronizeFixtures() + } + this.m_contactManager.FindNewContacts(); + profile_world_broadphase.stop() + }, + SolveTOI: function (step) { + this.p_island.Initialize(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, this.m_contactManager.m_contactListener); + if (this.m_stepComplete) { + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_flags &= ~b2Body.e_islandFlag; + b.m_sweep.alpha0 = 0 + } + for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { + c.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag); + c.m_toiCount = 0; + c.m_toi = 1 + } + } + for (;;) { + var minContact = null; + var minAlpha = 1; + for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { + if (c.IsEnabled() == false) { + continue + } + if (c.m_toiCount > b2_maxSubSteps) { + continue + } + var alpha = 1; + if (c.m_flags & b2Contact.e_toiFlag) { + alpha = c.m_toi + } else { + var fA = c.GetFixtureA(); + var fB = c.GetFixtureB(); + if (fA.IsSensor() || fB.IsSensor()) { + continue + } + var bA = fA.GetBody(); + var bB = fB.GetBody(); + var typeA = bA.m_type; + var typeB = bB.m_type; + var activeA = bA.IsAwake() && typeA != b2Body.b2_staticBody; + var activeB = bB.IsAwake() && typeB != b2Body.b2_staticBody; + if (activeA == false && activeB == false) { + continue + } + var collideA = bA.IsBullet() || typeA != b2Body.b2_dynamicBody; + var collideB = bB.IsBullet() || typeB != b2Body.b2_dynamicBody; + if (collideA == false && collideB == false) { + continue + } + var alpha0 = bA.m_sweep.alpha0; + if (bA.m_sweep.alpha0 < bB.m_sweep.alpha0) { + alpha0 = bB.m_sweep.alpha0; + bA.m_sweep.Advance(alpha0) + } else { + if (bB.m_sweep.alpha0 < bA.m_sweep.alpha0) { + alpha0 = bA.m_sweep.alpha0; + bB.m_sweep.Advance(alpha0) + } + } + var indexA = c.GetChildIndexA(); + var indexB = c.GetChildIndexB(); + var input = new b2TOIInput(); + input.proxyA.Set(fA.GetShape(), indexA); + input.proxyB.Set(fB.GetShape(), indexB); + input.sweepA.Assign(bA.m_sweep); + input.sweepB.Assign(bB.m_sweep); + input.tMax = 1; + var output = new b2TOIOutput(); + b2TimeOfImpact(output, input); + var beta = output.t; + if (output.state == b2TOIOutput.e_touching) { + alpha = b2Min(alpha0 + (1 - alpha0) * beta, 1) + } else { + alpha = 1 + } + c.m_toi = alpha; + c.m_flags |= b2Contact.e_toiFlag + } + if (alpha < minAlpha) { + minContact = c; + minAlpha = alpha + } + } + if (minContact == null || 1 - 10 * b2_epsilon < minAlpha) { + this.m_stepComplete = true; + break + } + var fA = minContact.GetFixtureA(); + var fB = minContact.GetFixtureB(); + var bA = fA.GetBody(); + var bB = fB.GetBody(); + b2World.m_local_sweep_backupA.Assign(bA.m_sweep); + b2World.m_local_sweep_backupB.Assign(bB.m_sweep); + bA.Advance(minAlpha); + bB.Advance(minAlpha); + minContact.Update(this.m_contactManager.m_contactListener); + minContact.m_flags &= ~b2Contact.e_toiFlag; + ++minContact.m_toiCount; + if (minContact.IsEnabled() == false || minContact.IsTouching() == false) { + minContact.SetEnabled(false); + bA.m_sweep.Assign(b2World.m_local_sweep_backupA); + bB.m_sweep.Assign(b2World.m_local_sweep_backupB); + bA.SynchronizeTransform(); + bB.SynchronizeTransform(); + continue + } + bA.SetAwake(true); + bB.SetAwake(true); + this.p_island.Clear(); + this.p_island.AddBody(bA); + this.p_island.AddBody(bB); + this.p_island.AddContact(minContact); + bA.m_flags |= b2Body.e_islandFlag; + bB.m_flags |= b2Body.e_islandFlag; + minContact.m_flags |= b2Contact.e_islandFlag; + var bodies = [bA, bB]; + for (var i = 0; i < 2; ++i) { + var body = bodies[i]; + if (body.m_type == b2Body.b2_dynamicBody) { + for (var ce = body.m_contactList; ce; ce = ce.next) { + if (this.p_island.m_bodyCount == this.p_island.m_bodyCapacity) { + break + } + if (this.p_island.m_contactCount == this.p_island.m_contactCapacity) { + break + } + var contact = ce.contact; + if (contact.m_flags & b2Contact.e_islandFlag) { + continue + } + var other = ce.other; + if (other.m_type == b2Body.b2_dynamicBody && body.IsBullet() == false && other.IsBullet() == false) { + continue + } + var sensorA = contact.m_fixtureA.m_isSensor; + var sensorB = contact.m_fixtureB.m_isSensor; + if (sensorA || sensorB) { + continue + } + b2World.m_local_sweep_backupC.Assign(other.m_sweep); + if ((other.m_flags & b2Body.e_islandFlag) == 0) { + other.Advance(minAlpha) + } + contact.Update(this.m_contactManager.m_contactListener); + if (contact.IsEnabled() == false) { + other.m_sweep.Assign(b2World.m_local_sweep_backupC); + other.SynchronizeTransform(); + continue + } + if (contact.IsTouching() == false) { + other.m_sweep.Assign(b2World.m_local_sweep_backupC); + other.SynchronizeTransform(); + continue + } + contact.m_flags |= b2Contact.e_islandFlag; + this.p_island.AddContact(contact); + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + other.m_flags |= b2Body.e_islandFlag; + if (other.m_type != b2Body.b2_staticBody) { + other.SetAwake(true) + } + this.p_island.AddBody(other) + } + } + } + var subStep = new b2TimeStep(); + subStep.dt = (1 - minAlpha) * step.dt; + subStep.inv_dt = 1 / subStep.dt; + subStep.dtRatio = 1; + subStep.positionIterations = 20; + subStep.velocityIterations = step.velocityIterations; + subStep.warmStarting = false; + this.p_island.SolveTOI(subStep, bA.m_islandIndex, bB.m_islandIndex); + for (var i = 0; i < this.p_island.m_bodyCount; ++i) { + var body = this.p_island.m_bodies[i]; + body.m_flags &= ~b2Body.e_islandFlag; + if (body.m_type != b2Body.b2_dynamicBody) { + continue + } + body.SynchronizeFixtures(); + for (var ce = body.m_contactList; ce; ce = ce.next) { + ce.contact.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag) + } + } + this.m_contactManager.FindNewContacts(); + if (this.m_subStepping) { + this.m_stepComplete = false; + break + } + } + }, + DrawJoint: function (joint) { + var bodyA = joint.GetBodyA(); + var bodyB = joint.GetBodyB(); + var xf1 = bodyA.GetTransform(); + var xf2 = bodyB.GetTransform(); + var x1 = xf1.p; + var x2 = xf2.p; + var p1 = joint.GetAnchorA(); + var p2 = joint.GetAnchorB(); + var color = new b2Color(0.5, 0.8, 0.8); + switch (joint.GetType()) { + case b2Joint.e_distanceJoint: + this.g_debugDraw.DrawSegment(p1, p2, color); + break; + case b2Joint.e_pulleyJoint: + var pulley = joint; + var s1 = pulley.GetGroundAnchorA(); + var s2 = pulley.GetGroundAnchorB(); + this.g_debugDraw.DrawSegment(s1, p1, color); + this.g_debugDraw.DrawSegment(s2, p2, color); + this.g_debugDraw.DrawSegment(s1, s2, color); + break; + case b2Joint.e_mouseJoint: + break; + case b2Joint.e_motorJoint: + this.g_debugDraw.DrawPoint(joint.GetLinearOffset(), 5, color); + default: + this.g_debugDraw.DrawSegment(x1, p1, color); + this.g_debugDraw.DrawSegment(p1, p2, color); + this.g_debugDraw.DrawSegment(x2, p2, color) + } + }, + DrawShape: function (fixture, xf, color) { + switch (fixture.GetType()) { + case b2Shape.e_circle: + var circle = fixture.GetShape(); + var center = b2Mul_t_v2(xf, circle.m_p); + var radius = circle.m_radius; + var axis = b2Mul_r_v2(xf.q, new b2Vec2(1, 0)); + this.g_debugDraw.DrawSolidCircle(center, radius, axis, color); + break; + case b2Shape.e_edge: + var edge = fixture.GetShape(); + var v1 = b2Mul_t_v2(xf, edge.m_vertex1); + var v2 = b2Mul_t_v2(xf, edge.m_vertex2); + this.g_debugDraw.DrawSegment(v1, v2, color); + break; + case b2Shape.e_chain: + var chain = fixture.GetShape(); + var count = chain.m_count; + var vertices = chain.m_vertices; + var v1 = b2Mul_t_v2(xf, vertices[0]); + for (var i = 1; i < count; ++i) { + var v2 = b2Mul_t_v2(xf, vertices[i]); + this.g_debugDraw.DrawSegment(v1, v2, color); + v1 = v2 + } + break; + case b2Shape.e_polygon: + var poly = fixture.GetShape(); + var vertexCount = poly.m_count; + var vertices = new Array(b2_maxPolygonVertices); + for (var i = 0; i < vertexCount; ++i) { + vertices[i] = b2Mul_t_v2(xf, poly.m_vertices[i]) + } + this.g_debugDraw.DrawSolidPolygon(vertices, vertexCount, color); + break; + default: + break + } + } + }; + b2World.e_newFixture = 1; + b2World.e_locked = 2; + b2World.e_clearForces = 4; + "use strict"; + + function b2MixFriction(friction1, friction2) { + return b2Sqrt(friction1 * friction2) + } + + function b2MixRestitution(restitution1, restitution2) { + return restitution1 > restitution2 ? restitution1 : restitution2 + } + + function b2ContactRegister() { + this.fcn = null; + this.primary = false + } + + function b2ContactEdge() { + this.other = null; + this.contact = null; + this.prev = null; + this.next = null + } + + function b2Contact() { + this.m_nodeA = new b2ContactEdge(); + this.m_nodeB = new b2ContactEdge(); + this.m_manifold = new b2Manifold() + } + b2Contact.m_local_tempManifold = new b2Manifold(); + b2Contact.prototype = { + Create: function (fA, indexA, fB, indexB) { + this.m_toi = 0; + this.m_flags = b2Contact.e_enabledFlag; + this.m_fixtureA = fA || null; + this.m_fixtureB = fB || null; + this.m_indexA = indexA || 0; + this.m_indexB = indexB || 0; + this.m_manifold.pointCount = 0; + this.m_prev = null; + this.m_next = null; + this.m_nodeA.contact = null; + this.m_nodeA.prev = null; + this.m_nodeA.next = null; + this.m_nodeA.other = null; + this.m_nodeB.contact = null; + this.m_nodeB.prev = null; + this.m_nodeB.next = null; + this.m_nodeB.other = null; + this.m_toiCount = 0; + if (fA) { + this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction); + this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) + } else { + this.m_friction = 0; + this.m_restitution = 0 + } + this.m_tangentSpeed = 0 + }, + GetManifold: function () { + return this.m_manifold + }, + GetWorldManifold: function (worldManifold) { + var bodyA = this.m_fixtureA.GetBody(); + var bodyB = this.m_fixtureB.GetBody(); + var shapeA = this.m_fixtureA.GetShape(); + var shapeB = this.m_fixtureB.GetShape(); + worldManifold.Initialize(this.m_manifold, bodyA.GetTransform(), shapeA.m_radius, bodyB.GetTransform(), shapeB.m_radius) + }, + IsTouching: function () { + return (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag + }, + SetEnabled: function (flag) { + if (flag) { + this.m_flags |= b2Contact.e_enabledFlag + } else { + this.m_flags &= ~b2Contact.e_enabledFlag + } + }, + IsEnabled: function () { + return (this.m_flags & b2Contact.e_enabledFlag) == b2Contact.e_enabledFlag + }, + GetNext: function () { + return this.m_next + }, + GetFixtureA: function () { + return this.m_fixtureA + }, + GetChildIndexA: function () { + return this.m_indexA + }, + GetFixtureB: function () { + return this.m_fixtureB + }, + GetChildIndexB: function () { + return this.m_indexB + }, + SetFriction: function (friction) { + this.m_friction = friction + }, + GetFriction: function () { + return this.m_friction + }, + ResetFriction: function () { + this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction) + }, + SetRestitution: function (restitution) { + this.m_restitution = restitution + }, + GetRestitution: function () { + return this.m_restitution + }, + ResetRestitution: function () { + this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) + }, + SetTangentSpeed: function (speed) { + this.m_tangentSpeed = speed + }, + GetTangentSpeed: function () { + return this.m_tangentSpeed + }, + Evaluate: function (manifold, xfA, xfB) {}, + FlagForFiltering: function () { + this.m_flags |= b2Contact.e_filterFlag + }, + m_oldManifold: null, + Update: function (listener) { + b2Contact.m_local_tempManifold.Assign(this.m_manifold); + this.m_flags |= b2Contact.e_enabledFlag; + var touching = false; + var wasTouching = (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag; + var sensorA = this.m_fixtureA.IsSensor(); + var sensorB = this.m_fixtureB.IsSensor(); + var sensor = sensorA || sensorB; + var bodyA = this.m_fixtureA.GetBody(); + var bodyB = this.m_fixtureB.GetBody(); + var xfA = bodyA.GetTransform(); + var xfB = bodyB.GetTransform(); + if (sensor) { + var shapeA = this.m_fixtureA.GetShape(); + var shapeB = this.m_fixtureB.GetShape(); + touching = b2TestShapeOverlap(shapeA, this.m_indexA, shapeB, this.m_indexB, xfA, xfB); + this.m_manifold.pointCount = 0 + } else { + this.Evaluate(this.m_manifold, xfA, xfB); + touching = this.m_manifold.pointCount > 0; + for (var i = 0; i < this.m_manifold.pointCount; ++i) { + var mp2 = this.m_manifold.points[i]; + mp2.normalImpulse = 0; + mp2.tangentImpulse = 0; + var id2 = mp2.id; + for (var j = 0; j < b2Contact.m_local_tempManifold.pointCount; ++j) { + var mp1 = b2Contact.m_local_tempManifold.points[j]; + if (mp1.id.Get() == id2.Get()) { + mp2.normalImpulse = mp1.normalImpulse; + mp2.tangentImpulse = mp1.tangentImpulse; + break + } + } + } + if (touching != wasTouching) { + bodyA.SetAwake(true); + bodyB.SetAwake(true) + } + } + if (touching) { + this.m_flags |= b2Contact.e_touchingFlag + } else { + this.m_flags &= ~b2Contact.e_touchingFlag + } + if (wasTouching == false && touching == true && listener) { + listener.BeginContact(this) + } + if (wasTouching == true && touching == false && listener) { + listener.EndContact(this) + } + if (sensor == false && touching && listener) { + listener.PreSolve(this, b2Contact.m_local_tempManifold) + } + } + }; + b2Contact.e_islandFlag = 1; + b2Contact.e_touchingFlag = 2; + b2Contact.e_enabledFlag = 4; + b2Contact.e_filterFlag = 8; + b2Contact.e_bulletHitFlag = 16; + b2Contact.e_toiFlag = 32; + + function b2CircleContact() { + this.parent.call(this) + } + b2CircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideCircles(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, unused1, fixtureB, unused2) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } + }; + b2CircleContact._extend(b2Contact); + var _local_temp_edgeShape = new b2EdgeShape(); + + function b2ChainAndCircleContact() { + this.parent.call(this) + } + b2ChainAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + var chain = this.m_fixtureA.GetShape(); + chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); + b2CollideEdgeAndCircle(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) + } + }; + b2ChainAndCircleContact._extend(b2Contact); + + function b2ChainAndPolygonContact() { + this.parent.call(this) + } + b2ChainAndPolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + var chain = this.m_fixtureA.GetShape(); + chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); + b2CollideEdgeAndPolygon(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) + } + }; + b2ChainAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2ChainAndPolygonContact(fixtureA, indexA, fixtureB, indexB) + }; + b2ChainAndPolygonContact._extend(b2Contact); + + function b2EdgeAndCircleContact() { + this.parent.call(this) + } + b2EdgeAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideEdgeAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } + }; + b2EdgeAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2EdgeAndCircleContact(fixtureA, fixtureB) + }; + b2EdgeAndCircleContact._extend(b2Contact); + + function b2EdgeAndPolygonContact() { + this.parent.call(this) + } + b2EdgeAndPolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideEdgeAndPolygon(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } + }; + b2EdgeAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2EdgeAndPolygonContact(fixtureA, fixtureB) + }; + b2EdgeAndPolygonContact._extend(b2Contact); + + function b2PolygonAndCircleContact() { + this.parent.call(this) + } + b2PolygonAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollidePolygonAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } + }; + b2PolygonAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2PolygonAndCircleContact(fixtureA, fixtureB) + }; + b2PolygonAndCircleContact._extend(b2Contact); + + function b2PolygonContact() { + this.parent.call(this) + } + b2PolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollidePolygons(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } + }; + b2PolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2PolygonContact(fixtureA, fixtureB) + }; + b2PolygonContact._extend(b2Contact); + b2Contact.AddType = function (fcn, type1, type2) { + if (!b2Contact.s_registers[type1]) { + b2Contact.s_registers[type1] = [] + } + b2Contact.s_registers[type1][type2] = new b2ContactRegister(); + b2Contact.s_registers[type1][type2].fcn = fcn; + b2Contact.s_registers[type1][type2].primary = true; + if (type1 != type2) { + if (!b2Contact.s_registers[type2]) { + b2Contact.s_registers[type2] = [] + } + b2Contact.s_registers[type2][type1] = new b2ContactRegister(); + b2Contact.s_registers[type2][type1].fcn = fcn; + b2Contact.s_registers[type2][type1].primary = false + } + fcn.garbage = []; + fcn.alloc = 2 + }; + b2Contact.InitializeRegisters = function () { + b2Contact.AddType(b2CircleContact, b2Shape.e_circle, b2Shape.e_circle); + b2Contact.AddType(b2PolygonAndCircleContact, b2Shape.e_polygon, b2Shape.e_circle); + b2Contact.AddType(b2PolygonContact, b2Shape.e_polygon, b2Shape.e_polygon); + b2Contact.AddType(b2EdgeAndCircleContact, b2Shape.e_edge, b2Shape.e_circle); + b2Contact.AddType(b2EdgeAndPolygonContact, b2Shape.e_edge, b2Shape.e_polygon); + b2Contact.AddType(b2ChainAndCircleContact, b2Shape.e_chain, b2Shape.e_circle); + b2Contact.AddType(b2ChainAndPolygonContact, b2Shape.e_chain, b2Shape.e_polygon) + }; + b2Contact.RetrieveGarbage = function (fcn) { + var contact; + if (contact = fcn.garbage.pop()) { + return contact + } + for (var i = 0; i < fcn.alloc - 1; ++i) { + fcn.garbage.push(new fcn()) + } + fcn.alloc += 32; + return new fcn() + }; + b2Contact.Create = function (fixtureA, indexA, fixtureB, indexB) { + if (b2Contact.s_initialized == false) { + b2Contact.InitializeRegisters(); + b2Contact.s_initialized = true + } + var type1 = fixtureA.GetType(); + var type2 = fixtureB.GetType(); + var fcn = b2Contact.s_registers[type1][type2].fcn; + if (fcn) { + var contact = b2Contact.RetrieveGarbage(fcn); + if (b2Contact.s_registers[type1][type2].primary) { + contact.Create(fixtureA, indexA, fixtureB, indexB) + } else { + contact.Create(fixtureB, indexB, fixtureA, indexA) + } + return contact + } + return null + }; + b2Contact.Destroy = function (contact) { + var fixtureA = contact.m_fixtureA; + var fixtureB = contact.m_fixtureB; + if (contact.m_manifold.pointCount > 0 && fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { + fixtureA.GetBody().SetAwake(true); + fixtureB.GetBody().SetAwake(true) + } + var typeA = fixtureA.GetType(); + var typeB = fixtureB.GetType(); + b2Contact.s_registers[typeA][typeB].fcn.garbage.push(contact) + }; + b2Contact.s_registers = []; + b2Contact.s_initialized = false; + "use strict"; + var b2_defaultFilter = new b2ContactFilter(); + var b2_defaultListener = new b2ContactListener(); + + function b2ContactManager() { + this.m_broadPhase = new b2BroadPhase(); + this.m_contactList = null; + this.m_contactCount = 0; + this.m_contactFilter = b2_defaultFilter; + this.m_contactListener = b2_defaultListener + } + b2ContactManager.prototype = { + AddPair: function (proxyUserDataA, proxyUserDataB) { + var proxyA = proxyUserDataA; + var proxyB = proxyUserDataB; + var fixtureA = proxyA.fixture; + var fixtureB = proxyB.fixture; + var indexA = proxyA.childIndex; + var indexB = proxyB.childIndex; + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (bodyA == bodyB) { + return + } + var edge = bodyB.GetContactList(); + while (edge) { + if (edge.other == bodyA) { + var fA = edge.contact.GetFixtureA(); + var fB = edge.contact.GetFixtureB(); + var iA = edge.contact.GetChildIndexA(); + var iB = edge.contact.GetChildIndexB(); + if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) { + return + } + if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) { + return + } + } + edge = edge.next + } + if (bodyB.ShouldCollide(bodyA) == false) { + return + } + if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { + return + } + var c = b2Contact.Create(fixtureA, indexA, fixtureB, indexB); + if (c == null) { + return + } + fixtureA = c.GetFixtureA(); + fixtureB = c.GetFixtureB(); + indexA = c.GetChildIndexA(); + indexB = c.GetChildIndexB(); + bodyA = fixtureA.GetBody(); + bodyB = fixtureB.GetBody(); + c.m_prev = null; + c.m_next = this.m_contactList; + if (this.m_contactList != null) { + this.m_contactList.m_prev = c + } + this.m_contactList = c; + c.m_nodeA.contact = c; + c.m_nodeA.other = bodyB; + c.m_nodeA.prev = null; + c.m_nodeA.next = bodyA.m_contactList; + if (bodyA.m_contactList != null) { + bodyA.m_contactList.prev = c.m_nodeA + } + bodyA.m_contactList = c.m_nodeA; + c.m_nodeB.contact = c; + c.m_nodeB.other = bodyA; + c.m_nodeB.prev = null; + c.m_nodeB.next = bodyB.m_contactList; + if (bodyB.m_contactList != null) { + bodyB.m_contactList.prev = c.m_nodeB + } + bodyB.m_contactList = c.m_nodeB; + if (fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { + bodyA.SetAwake(true); + bodyB.SetAwake(true) + }++this.m_contactCount + }, + FindNewContacts: function () { + this.m_broadPhase.UpdatePairs(this) + }, + Destroy: function (c) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (this.m_contactListener && c.IsTouching()) { + this.m_contactListener.EndContact(c) + } + 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_contactList) { + this.m_contactList = c.m_next + } + if (c.m_nodeA.prev) { + c.m_nodeA.prev.next = c.m_nodeA.next + } + if (c.m_nodeA.next) { + c.m_nodeA.next.prev = c.m_nodeA.prev + } + if (c.m_nodeA == bodyA.m_contactList) { + bodyA.m_contactList = c.m_nodeA.next + } + if (c.m_nodeB.prev) { + c.m_nodeB.prev.next = c.m_nodeB.next + } + if (c.m_nodeB.next) { + c.m_nodeB.next.prev = c.m_nodeB.prev + } + if (c.m_nodeB == bodyB.m_contactList) { + bodyB.m_contactList = c.m_nodeB.next + } + b2Contact.Destroy(c); + --this.m_contactCount + }, + Collide: function () { + var c = this.m_contactList; + while (c) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var indexA = c.GetChildIndexA(); + var indexB = c.GetChildIndexB(); + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (c.m_flags & b2Contact.e_filterFlag) { + if (bodyB.ShouldCollide(bodyA) == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + c.m_flags &= ~b2Contact.e_filterFlag + } + var activeA = bodyA.IsAwake() && bodyA.m_type != b2Body.b2_staticBody; + var activeB = bodyB.IsAwake() && bodyB.m_type != b2Body.b2_staticBody; + if (activeA == false && activeB == false) { + c = c.GetNext(); + continue + } + var proxyIdA = fixtureA.m_proxies[indexA].proxyId; + var proxyIdB = fixtureB.m_proxies[indexB].proxyId; + var overlap = this.m_broadPhase.TestOverlap(proxyIdA, proxyIdB); + if (overlap == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + c.Update(this.m_contactListener); + c = c.GetNext() + } + } + }; + + function b2VelocityConstraintPoint() { + this.rA = new b2Vec2(); + this.rB = new b2Vec2(); + this.normalImpulse = 0; + this.tangentImpulse = 0; + this.normalMass = 0; + this.tangentMass = 0; + this.velocityBias = 0 + } + + function b2ContactPositionConstraint() { + this.localPoints = new Array(b2_maxManifoldPoints); + this.localNormal = new b2Vec2(); + this.localPoint = new b2Vec2(); + this.indexA = 0; + this.indexB = 0; + this.invMassA = 0, this.invMassB = 0; + this.localCenterA = new b2Vec2(), this.localCenterB = new b2Vec2(); + this.invIA = 0, this.invIB = 0; + this.type = 0; + this.radiusA = 0, this.radiusB = 0; + this.pointCount = 0 + } + + function b2ContactVelocityConstraint() { + this.points = new Array(b2_maxManifoldPoints); + for (var i = 0; i < this.points.length; ++i) { + this.points[i] = new b2VelocityConstraintPoint() + } + this.normal = new b2Vec2(); + this.normalMass = new b2Mat22(); + this.K = new b2Mat22(); + this.indexA = 0; + this.indexB = 0; + this.invMassA = 0, this.invMassB = 0; + this.invIA = 0, this.invIB = 0; + this.friction = 0; + this.restitution = 0; + this.tangentSpeed = 0; + this.pointCount = 0; + this.contactIndex = 0 + } + + function b2PositionSolverManifold() { + this.normal = new b2Vec2(); + this.point = new b2Vec2(); + this.separation = 0 + } + b2PositionSolverManifold.prototype = { + Initialize: function (pc, xfA, xfB, index) { + switch (pc.type) { + case b2Manifold.e_circles: + var pointAx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; + var pointAy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; + var pointBx = (xfB.q.c * pc.localPoints[0].x - xfB.q.s * pc.localPoints[0].y) + xfB.p.x; + var pointBy = (xfB.q.s * pc.localPoints[0].x + xfB.q.c * pc.localPoints[0].y) + xfB.p.y; + this.point.x = 0.5 * (pointAx + pointBx); + this.point.y = 0.5 * (pointAy + pointBy); + this.normal.x = pointBx - pointAx; + this.normal.y = pointBy - pointAy; + var tempnx = this.normal.x; + var tempny = this.normal.y; + this.normal.Normalize(); + this.separation = (tempnx * this.normal.x + tempny * this.normal.y) - pc.radiusA - pc.radiusB; + break; + case b2Manifold.e_faceA: + this.normal.x = xfA.q.c * pc.localNormal.x - xfA.q.s * pc.localNormal.y; + this.normal.y = xfA.q.s * pc.localNormal.x + xfA.q.c * pc.localNormal.y; + var planePointx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; + var planePointy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; + var clipPointx = (xfB.q.c * pc.localPoints[index].x - xfB.q.s * pc.localPoints[index].y) + xfB.p.x; + var clipPointy = (xfB.q.s * pc.localPoints[index].x + xfB.q.c * pc.localPoints[index].y) + xfB.p.y; + this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; + this.point.x = clipPointx; + this.point.y = clipPointy; + break; + case b2Manifold.e_faceB: + this.normal.x = xfB.q.c * pc.localNormal.x - xfB.q.s * pc.localNormal.y; + this.normal.y = xfB.q.s * pc.localNormal.x + xfB.q.c * pc.localNormal.y; + var planePointx = (xfB.q.c * pc.localPoint.x - xfB.q.s * pc.localPoint.y) + xfB.p.x; + var planePointy = (xfB.q.s * pc.localPoint.x + xfB.q.c * pc.localPoint.y) + xfB.p.y; + var clipPointx = (xfA.q.c * pc.localPoints[index].x - xfA.q.s * pc.localPoints[index].y) + xfA.p.x; + var clipPointy = (xfA.q.s * pc.localPoints[index].x + xfA.q.c * pc.localPoints[index].y) + xfA.p.y; + this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; + this.point.x = clipPointx; + this.point.y = clipPointy; + this.normal.x = -this.normal.x; + this.normal.y = -this.normal.y; + break + } + } + }; + + function b2ContactSolverDef() { + this.step = new b2TimeStep(); + this.contacts = null; + this.count = 0; + this.positions = null; + this.velocities = null + } + + function b2ContactSolver() { + this.m_positionConstraints = []; + this.m_velocityConstraints = [] + } + b2ContactSolver.cs_xfA = new b2Transform(); + b2ContactSolver.cs_xfB = new b2Transform(); + b2ContactSolver.temp_solver_manifold = new b2PositionSolverManifold(); + b2ContactSolver.prototype = { + Init: function (def) { + this.m_step = def.step; + this.m_count = def.count; + this.m_positionConstraints.length = this.m_count; + this.m_velocityConstraints.length = this.m_count; + this.m_positions = def.positions; + this.m_velocities = def.velocities; + this.m_contacts = def.contacts; + for (var i = 0; i < this.m_count; ++i) { + var contact = this.m_contacts[i]; + var fixtureA = contact.m_fixtureA; + var fixtureB = contact.m_fixtureB; + var shapeA = fixtureA.GetShape(); + var shapeB = fixtureB.GetShape(); + var radiusA = shapeA.m_radius; + var radiusB = shapeB.m_radius; + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + var manifold = contact.GetManifold(); + var pointCount = manifold.pointCount; + var vc = this.m_velocityConstraints[i] || new b2ContactVelocityConstraint(); + vc.friction = contact.m_friction; + vc.restitution = contact.m_restitution; + vc.tangentSpeed = contact.m_tangentSpeed; + vc.indexA = bodyA.m_islandIndex; + vc.indexB = bodyB.m_islandIndex; + vc.invMassA = bodyA.m_invMass; + vc.invMassB = bodyB.m_invMass; + vc.invIA = bodyA.m_invI; + vc.invIB = bodyB.m_invI; + vc.contactIndex = i; + vc.pointCount = pointCount; + vc.K.SetZero(); + vc.normalMass.SetZero(); + this.m_velocityConstraints[i] = vc; + var pc = this.m_positionConstraints[i] || new b2ContactPositionConstraint(); + pc.indexA = bodyA.m_islandIndex; + pc.indexB = bodyB.m_islandIndex; + pc.invMassA = bodyA.m_invMass; + pc.invMassB = bodyB.m_invMass; + pc.localCenterA.x = bodyA.m_sweep.localCenter.x; + pc.localCenterA.y = bodyA.m_sweep.localCenter.y; + pc.localCenterB.x = bodyB.m_sweep.localCenter.x; + pc.localCenterB.y = bodyB.m_sweep.localCenter.y; + pc.invIA = bodyA.m_invI; + pc.invIB = bodyB.m_invI; + pc.localNormal.x = manifold.localNormal.x; + pc.localNormal.y = manifold.localNormal.y; + pc.localPoint.x = manifold.localPoint.x; + pc.localPoint.y = manifold.localPoint.y; + pc.pointCount = pointCount; + pc.radiusA = radiusA; + pc.radiusB = radiusB; + pc.type = manifold.type; + this.m_positionConstraints[i] = pc; + for (var j = 0; j < pointCount; ++j) { + var cp = manifold.points[j]; + var vcp = vc.points[j]; + if (this.m_step.warmStarting) { + vcp.normalImpulse = this.m_step.dtRatio * cp.normalImpulse; + vcp.tangentImpulse = this.m_step.dtRatio * cp.tangentImpulse + } else { + vcp.normalImpulse = 0; + vcp.tangentImpulse = 0 + } + vcp.rA.SetZero(); + vcp.rB.SetZero(); + vcp.normalMass = 0; + vcp.tangentMass = 0; + vcp.velocityBias = 0; + pc.localPoints[j] = cp.localPoint + } + } + }, + InitializeVelocityConstraints: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var pc = this.m_positionConstraints[i]; + var radiusA = pc.radiusA; + var radiusB = pc.radiusB; + var manifold = this.m_contacts[vc.contactIndex].GetManifold(); + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var mB = vc.invMassB; + var iA = vc.invIA; + var iB = vc.invIB; + var localCenterA = pc.localCenterA; + var localCenterB = pc.localCenterB; + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.x = cA.x - (b2ContactSolver.cs_xfA.q.c * localCenterA.x - b2ContactSolver.cs_xfA.q.s * localCenterA.y); + b2ContactSolver.cs_xfA.p.y = cA.y - (b2ContactSolver.cs_xfA.q.s * localCenterA.x + b2ContactSolver.cs_xfA.q.c * localCenterA.y); + b2ContactSolver.cs_xfB.p.x = cB.x - (b2ContactSolver.cs_xfB.q.c * localCenterB.x - b2ContactSolver.cs_xfB.q.s * localCenterB.y); + b2ContactSolver.cs_xfB.p.y = cB.y - (b2ContactSolver.cs_xfB.q.s * localCenterB.x + b2ContactSolver.cs_xfB.q.c * localCenterB.y); + var worldManifold = new b2WorldManifold(); + worldManifold.Initialize(manifold, b2ContactSolver.cs_xfA, radiusA, b2ContactSolver.cs_xfB, radiusB); + vc.normal.x = worldManifold.normal.x; + vc.normal.y = worldManifold.normal.y; + var pointCount = vc.pointCount; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + vcp.rA.x = worldManifold.points[j].x - cA.x; + vcp.rA.y = worldManifold.points[j].y - cA.y; + vcp.rB.x = worldManifold.points[j].x - cB.x; + vcp.rB.y = worldManifold.points[j].y - cB.y; + var rnA = vcp.rA.x * vc.normal.y - vcp.rA.y * vc.normal.x; + var rnB = vcp.rB.x * vc.normal.y - vcp.rB.y * vc.normal.x; + var kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + vcp.normalMass = kNormal > 0 ? 1 / kNormal : 0; + var tangentx = 1 * vc.normal.y; + var tangenty = -1 * vc.normal.x; + var rtA = vcp.rA.x * tangenty - vcp.rA.y * tangentx; + var rtB = vcp.rB.x * tangenty - vcp.rB.y * tangentx; + var kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; + vcp.tangentMass = kTangent > 0 ? 1 / kTangent : 0; + vcp.velocityBias = 0; + var vRel = vc.normal.x * (((vB.x + (-wB * vcp.rB.y)) - vA.x) - (-wA * vcp.rA.y)) + vc.normal.y * (((vB.y + (wB * vcp.rB.x)) - vA.y) - (wA * vcp.rA.x)); + if (vRel < -b2_velocityThreshold) { + vcp.velocityBias = -vc.restitution * vRel + } + } + if (vc.pointCount == 2) { + var vcp1 = vc.points[0]; + var vcp2 = vc.points[1]; + var rn1A = vcp1.rA.x * vc.normal.y - vcp1.rA.y * vc.normal.x; + var rn1B = vcp1.rB.x * vc.normal.y - vcp1.rB.y * vc.normal.x; + var rn2A = vcp2.rA.x * vc.normal.y - vcp2.rA.y * vc.normal.x; + var rn2B = vcp2.rB.x * vc.normal.y - vcp2.rB.y * vc.normal.x; + var k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B; + var k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B; + var k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B; + var k_maxConditionNumber = 1000; + if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) { + vc.K.ex.x = k11; + vc.K.ex.y = k12; + vc.K.ey.x = k12; + vc.K.ey.y = k22; + vc.normalMass.Assign(vc.K.GetInverse()) + } else { + vc.pointCount = 1 + } + } + } + }, + WarmStart: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var iA = vc.invIA; + var mB = vc.invMassB; + var iB = vc.invIB; + var pointCount = vc.pointCount; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + var normal = vc.normal; + var tangentx = 1 * normal.y; + var tangenty = -1 * normal.x; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + var Px = (vcp.normalImpulse * normal.x) + (vcp.tangentImpulse * tangentx); + var Py = (vcp.normalImpulse * normal.y) + (vcp.tangentImpulse * tangenty); + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vA.x -= mA * Px; + vA.y -= mA * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px); + vB.x += mB * Px; + vB.y += mB * Py + } + this.m_velocities[indexA].w = wA; + this.m_velocities[indexB].w = wB + } + }, + SolveVelocityConstraints: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var iA = vc.invIA; + var mB = vc.invMassB; + var iB = vc.invIB; + var pointCount = vc.pointCount; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + var normal = vc.normal; + var tangentx = 1 * normal.y; + var tangenty = -1 * normal.x; + var friction = vc.friction; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + var dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); + var dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); + var vt = (dvx * tangentx + dvy * tangenty) - vc.tangentSpeed; + var lambda = vcp.tangentMass * (-vt); + var maxFriction = friction * vcp.normalImpulse; + var newImpulse = b2Clamp(vcp.tangentImpulse + lambda, -maxFriction, maxFriction); + lambda = newImpulse - vcp.tangentImpulse; + vcp.tangentImpulse = newImpulse; + var Px = lambda * tangentx; + var Py = lambda * tangenty; + vA.x -= mA * Px; + vA.y -= mA * Py; + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vB.x += mB * Px; + vB.y += mB * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) + } + if (vc.pointCount == 1) { + vcp = vc.points[0]; + dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); + dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); + var vn = dvx * normal.x + dvy * normal.y; + var lambda = -vcp.normalMass * (vn - vcp.velocityBias); + var newImpulse = b2Max(vcp.normalImpulse + lambda, 0); + lambda = newImpulse - vcp.normalImpulse; + vcp.normalImpulse = newImpulse; + Px = lambda * normal.x; + Py = lambda * normal.y; + vA.x -= mA * Px; + vA.y -= mA * Py; + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vB.x += mB * Px; + vB.y += mB * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) + } else { + var cp1 = vc.points[0]; + var cp2 = vc.points[1]; + var ax = cp1.normalImpulse; + var ay = cp2.normalImpulse; + var dv1x = vB.x + (-wB * cp1.rB.y) - vA.x - (-wA * cp1.rA.y); + var dv1y = vB.y + (wB * cp1.rB.x) - vA.y - (wA * cp1.rA.x); + var dv2x = vB.x + (-wB * cp2.rB.y) - vA.x - (-wA * cp2.rA.y); + var dv2y = vB.y + (wB * cp2.rB.x) - vA.y - (wA * cp2.rA.x); + var vn1 = dv1x * normal.x + dv1y * normal.y; + var vn2 = dv2x * normal.x + dv2y * normal.y; + var bx = vn1 - cp1.velocityBias; + var by = vn2 - cp2.velocityBias; + bx -= vc.K.ex.x * ax + vc.K.ey.x * ay; + by -= vc.K.ex.y * ax + vc.K.ey.y * ay; + for (;;) { + var xx = -(vc.normalMass.ex.x * bx + vc.normalMass.ey.x * by); + var xy = -(vc.normalMass.ex.y * bx + vc.normalMass.ey.y * by); + if (xx >= 0 && xy >= 0) { + var dx = xx - ax; + var dy = xy - ay; + var P1x = dx * normal.x; + var P1y = dx * normal.y; + var P2x = dy * normal.x; + var P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = -cp1.normalMass * bx; + xy = 0; + vn1 = 0; + vn2 = vc.K.ex.y * xx + by; + if (xx >= 0 && vn2 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = 0; + xy = -cp2.normalMass * by; + vn1 = vc.K.ey.x * xy + bx; + vn2 = 0; + if (xy >= 0 && vn1 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = 0; + xy = 0; + vn1 = bx; + vn2 = by; + if (vn1 >= 0 && vn2 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + break + } + } + this.m_velocities[indexA].w = wA; + this.m_velocities[indexB].w = wB + } + }, + StoreImpulses: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var manifold = this.m_contacts[vc.contactIndex].GetManifold(); + for (var j = 0; j < vc.pointCount; ++j) { + manifold.points[j].normalImpulse = vc.points[j].normalImpulse; + manifold.points[j].tangentImpulse = vc.points[j].tangentImpulse + } + } + }, + SolvePositionConstraints: function () { + var minSeparation = 0; + for (var i = 0; i < this.m_count; ++i) { + var pc = this.m_positionConstraints[i]; + var indexA = pc.indexA; + var indexB = pc.indexB; + var localCenterA = pc.localCenterA; + var mA = pc.invMassA; + var iA = pc.invIA; + var localCenterB = pc.localCenterB; + var mB = pc.invMassB; + var iB = pc.invIB; + var pointCount = pc.pointCount; + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + for (var j = 0; j < pointCount; ++j) { + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.x = cA.x - (b2ContactSolver.cs_xfA.q.c * localCenterA.x - b2ContactSolver.cs_xfA.q.s * localCenterA.y); + b2ContactSolver.cs_xfA.p.y = cA.y - (b2ContactSolver.cs_xfA.q.s * localCenterA.x + b2ContactSolver.cs_xfA.q.c * localCenterA.y); + b2ContactSolver.cs_xfB.p.x = cB.x - (b2ContactSolver.cs_xfB.q.c * localCenterB.x - b2ContactSolver.cs_xfB.q.s * localCenterB.y); + b2ContactSolver.cs_xfB.p.y = cB.y - (b2ContactSolver.cs_xfB.q.s * localCenterB.x + b2ContactSolver.cs_xfB.q.c * localCenterB.y); + b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); + var normal = b2ContactSolver.temp_solver_manifold.normal; + var point = b2ContactSolver.temp_solver_manifold.point; + var separation = b2ContactSolver.temp_solver_manifold.separation; + var rAx = point.x - cA.x; + var rAy = point.y - cA.y; + var rBx = point.x - cB.x; + var rBy = point.y - cB.y; + minSeparation = b2Min(minSeparation, separation); + var C = b2Clamp(b2_baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); + var rnA = rAx * normal.y - rAy * normal.x; + var rnB = rBx * normal.y - rBy * normal.x; + var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + var impulse = K > 0 ? -C / K : 0; + var Px = impulse * normal.x; + var Py = impulse * normal.y; + cA.x -= mA * Px; + cA.y -= mA * Py; + aA -= iA * (rAx * Py - rAy * Px); + cB.x += mB * Px; + cB.y += mB * Py; + aB += iB * (rBx * Py - rBy * Px) + } + this.m_positions[indexA].a = aA; + this.m_positions[indexB].a = aB + } + return minSeparation >= -3 * b2_linearSlop + }, + SolveTOIPositionConstraints: function (toiIndexA, toiIndexB) { + var minSeparation = 0; + for (var i = 0; i < this.m_count; ++i) { + var pc = this.m_positionConstraints[i]; + var indexA = pc.indexA; + var indexB = pc.indexB; + var localCenterA = pc.localCenterA; + var localCenterB = pc.localCenterB; + var pointCount = pc.pointCount; + var mA = 0; + var iA = 0; + if (indexA == toiIndexA || indexA == toiIndexB) { + mA = pc.invMassA; + iA = pc.invIA + } + var mB = 0; + var iB = 0; + if (indexB == toiIndexA || indexB == toiIndexB) { + mB = pc.invMassB; + iB = pc.invIB + } + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + for (var j = 0; j < pointCount; ++j) { + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.Assign(b2Vec2.Subtract(cA, b2Mul_r_v2(b2ContactSolver.cs_xfA.q, localCenterA))); + b2ContactSolver.cs_xfB.p.Assign(b2Vec2.Subtract(cB, b2Mul_r_v2(b2ContactSolver.cs_xfB.q, localCenterB))); + b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); + var normal = b2ContactSolver.temp_solver_manifold.normal; + var point = b2ContactSolver.temp_solver_manifold.point; + var separation = b2ContactSolver.temp_solver_manifold.separation; + var rA = b2Vec2.Subtract(point, cA); + var rB = b2Vec2.Subtract(point, cB); + minSeparation = b2Min(minSeparation, separation); + var C = b2Clamp(b2_toiBaugarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); + var rnA = b2Cross_v2_v2(rA, normal); + var rnB = b2Cross_v2_v2(rB, normal); + var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + var impulse = K > 0 ? -C / K : 0; + var P = b2Vec2.Multiply(impulse, normal); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * b2Cross_v2_v2(rB, P) + } + this.m_positions[indexA].a = aA; + this.m_positions[indexB].a = aB + } + return minSeparation >= -1.5 * b2_linearSlop + } + }; + "use strict"; + + function b2Island() { + this.m_bodies = []; + this.m_contacts = []; + this.m_joints = []; + this.m_velocities = []; + this.m_positions = [] + } + var profile_solve_init = b2Profiler.create("solve initialization", "solve"); + var profile_solve_init_warmStarting = b2Profiler.create("warm starting", "solve initialization"); + var profile_solve_velocity = b2Profiler.create("solve velocities", "solve"); + var profile_solve_position = b2Profiler.create("solve positions", "solve"); + b2Island._solverData = new b2SolverData(); + b2Island._solverDef = new b2ContactSolverDef(); + b2Island._solver = new b2ContactSolver(); + b2Island.prototype = { + Clear: function () { + this.m_bodyCount = 0; + this.m_contactCount = 0; + this.m_jointCount = 0 + }, + Initialize: function (bodyCapacity, contactCapacity, jointCapacity, listener) { + this.m_listener = listener; + 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_bodies.length = bodyCapacity; + this.m_contacts.length = contactCapacity; + this.m_joints.length = jointCapacity; + this.m_velocities.length = bodyCapacity; + this.m_positions.length = bodyCapacity + }, + Solve: function (step, gravity, allowSleep) { + profile_solve_init.start(); + var h = step.dt; + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + this.m_positions[i].c.Assign(b.m_sweep.c); + var a = b.m_sweep.a; + this.m_velocities[i].v.Assign(b.m_linearVelocity); + var w = b.m_angularVelocity; + b.m_sweep.c0.Assign(b.m_sweep.c); + b.m_sweep.a0 = b.m_sweep.a; + if (b.m_type == b2Body.b2_dynamicBody) { + this.m_velocities[i].v.x += h * ((b.m_gravityScale * gravity.x) + (b.m_invMass * b.m_force.x)); + this.m_velocities[i].v.y += h * ((b.m_gravityScale * gravity.y) + (b.m_invMass * b.m_force.y)); + w += h * b.m_invI * b.m_torque; + this.m_velocities[i].v.x *= 1 / (1 + h * b.m_linearDamping); + this.m_velocities[i].v.y *= 1 / (1 + h * b.m_linearDamping); + w *= 1 / (1 + h * b.m_angularDamping) + } + this.m_positions[i].a = a; + this.m_velocities[i].w = w + } + b2Island._solverData.step = step; + b2Island._solverData.positions = this.m_positions; + b2Island._solverData.velocities = this.m_velocities; + b2Island._solverDef.step = step; + b2Island._solverDef.contacts = this.m_contacts; + b2Island._solverDef.count = this.m_contactCount; + b2Island._solverDef.positions = this.m_positions; + b2Island._solverDef.velocities = this.m_velocities; + b2Island._solverDef.allocator = this.m_allocator; + b2Island._solver.Init(b2Island._solverDef); + b2Island._solver.InitializeVelocityConstraints(); + if (step.warmStarting) { + profile_solve_init_warmStarting.start(); + b2Island._solver.WarmStart(); + profile_solve_init_warmStarting.stop() + } + for (var i = 0; i < this.m_jointCount; ++i) { + this.m_joints[i].InitVelocityConstraints(b2Island._solverData) + } + profile_solve_init.stop(); + profile_solve_velocity.start(); + for (var i = 0; i < step.velocityIterations; ++i) { + for (var j = 0; j < this.m_jointCount; ++j) { + this.m_joints[j].SolveVelocityConstraints(b2Island._solverData) + } + b2Island._solver.SolveVelocityConstraints() + } + b2Island._solver.StoreImpulses(); + profile_solve_velocity.stop(); + profile_solve_position.start(); + for (var i = 0; i < this.m_bodyCount; ++i) { + var c = this.m_positions[i].c; + var a = this.m_positions[i].a; + var v = this.m_velocities[i].v; + var w = this.m_velocities[i].w; + var translationx = h * v.x; + var translationy = h * v.y; + var translationl = translationx * translationx + translationy * translationy; + if (translationl > b2_maxTranslationSquared) { + var ratio = b2_maxTranslation / b2Sqrt(translationl); + v.x *= ratio; + v.y *= ratio + } + var rotation = h * w; + if (rotation * rotation > b2_maxRotationSquared) { + var ratio = b2_maxRotation / b2Abs(rotation); + w *= ratio + } + c.x += h * v.x; + c.y += h * v.y; + a += h * w; + this.m_positions[i].a = a; + this.m_velocities[i].w = w + } + var positionSolved = false; + for (var i = 0; i < step.positionIterations; ++i) { + var contactsOkay = b2Island._solver.SolvePositionConstraints(); + var jointsOkay = true; + for (var j = 0; j < this.m_jointCount; ++j) { + var jointOkay = this.m_joints[j].SolvePositionConstraints(b2Island._solverData); + jointsOkay = jointsOkay && jointOkay + } + if (contactsOkay && jointsOkay) { + positionSolved = true; + break + } + } + for (var i = 0; i < this.m_bodyCount; ++i) { + var body = this.m_bodies[i]; + body.m_sweep.c.Assign(this.m_positions[i].c); + body.m_sweep.a = this.m_positions[i].a; + body.m_linearVelocity.Assign(this.m_velocities[i].v); + body.m_angularVelocity = this.m_velocities[i].w; + body.SynchronizeTransform() + } + profile_solve_position.stop(); + this.Report(b2Island._solver.m_velocityConstraints); + if (allowSleep) { + var minSleepTime = b2_maxFloat; + var linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance; + var angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance; + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + if (b.GetType() == b2Body.b2_staticBody) { + continue + } + if ((b.m_flags & b2Body.e_autoSleepFlag) == 0 || b.m_angularVelocity * b.m_angularVelocity > angTolSqr || b2Dot_v2_v2(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr) { + b.m_sleepTime = 0; + minSleepTime = 0 + } else { + b.m_sleepTime += h; + minSleepTime = b2Min(minSleepTime, b.m_sleepTime) + } + } + if (minSleepTime >= b2_timeToSleep && positionSolved) { + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + b.SetAwake(false) + } + } + } + }, + SolveTOI: function (subStep, toiIndexA, toiIndexB) { + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + this.m_positions[i].c.Assign(b.m_sweep.c); + this.m_positions[i].a = b.m_sweep.a; + this.m_velocities[i].v.Assign(b.m_linearVelocity); + this.m_velocities[i].w = b.m_angularVelocity + } + b2Island._solverDef.contacts = this.m_contacts; + b2Island._solverDef.count = this.m_contactCount; + b2Island._solverDef.step = subStep; + b2Island._solverDef.positions = this.m_positions; + b2Island._solverDef.velocities = this.m_velocities; + b2Island._solver.Init(b2Island._solverDef); + for (var i = 0; i < subStep.positionIterations; ++i) { + var contactsOkay = b2Island._solver.SolveTOIPositionConstraints(toiIndexA, toiIndexB); + if (contactsOkay) { + break + } + } + this.m_bodies[toiIndexA].m_sweep.c0.Assign(this.m_positions[toiIndexA].c); + this.m_bodies[toiIndexA].m_sweep.a0 = this.m_positions[toiIndexA].a; + this.m_bodies[toiIndexB].m_sweep.c0.Assign(this.m_positions[toiIndexB].c); + this.m_bodies[toiIndexB].m_sweep.a0 = this.m_positions[toiIndexB].a; + b2Island._solver.InitializeVelocityConstraints(); + for (var i = 0; i < subStep.velocityIterations; ++i) { + b2Island._solver.SolveVelocityConstraints() + } + var h = subStep.dt; + for (var i = 0; i < this.m_bodyCount; ++i) { + var c = this.m_positions[i].c; + var a = this.m_positions[i].a; + var v = this.m_velocities[i].v; + var w = this.m_velocities[i].w; + var translation = b2Vec2.Multiply(h, v); + if (b2Dot_v2_v2(translation, translation) > b2_maxTranslationSquared) { + var ratio = b2_maxTranslation / translation.Length(); + v.Multiply(ratio) + } + var rotation = h * w; + if (rotation * rotation > b2_maxRotationSquared) { + var ratio = b2_maxRotation / b2Abs(rotation); + w *= ratio + } + c.Add(b2Vec2.Multiply(h, v)); + a += h * w; + this.m_positions[i].a = a; + this.m_velocities[i].w = w; + var body = this.m_bodies[i]; + body.m_sweep.c.Assign(c); + body.m_sweep.a = a; + body.m_linearVelocity.Assign(v); + body.m_angularVelocity = w; + body.SynchronizeTransform() + } + this.Report(b2Island._solver.m_velocityConstraints) + }, + AddBody: function (body) { + body.m_islandIndex = this.m_bodyCount; + this.m_bodies[this.m_bodyCount] = body; + if (!this.m_positions[this.m_bodyCount]) { + this.m_positions[this.m_bodyCount] = new b2Position(); + this.m_velocities[this.m_bodyCount] = new b2Velocity() + }++this.m_bodyCount + }, + AddContact: function (contact) { + this.m_contacts[this.m_contactCount++] = contact + }, + AddJoint: function (joint) { + this.m_joints[this.m_jointCount++] = joint + }, + Report: function (constraints) { + if (this.m_listener == null) { + return + } + for (var i = 0; i < this.m_contactCount; ++i) { + var c = this.m_contacts[i]; + var vc = constraints[i]; + var impulse = new b2ContactImpulse(); + impulse.count = vc.pointCount; + for (var j = 0; j < vc.pointCount; ++j) { + impulse.normalImpulses[j] = vc.points[j].normalImpulse; + impulse.tangentImpulses[j] = vc.points[j].tangentImpulse + } + this.m_listener.PostSolve(c, impulse) + } + } + }; + + function b2Jacobian() { + this.linear = new b2Vec2(); + this.angularA = 0; + this.angularB = 0 + } + + function b2JointEdge() { + this.other = null; + this.joint = null; + this.prev = null; + this.next = null + } + + function b2JointDef() { + this.type = b2Joint.e_unknownJoint; + this.userData = null; + this.bodyA = null; + this.bodyB = null; + this.collideConnected = false + } + b2JointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.bodyA = bodies[data.bodyA]; + this.bodyB = bodies[data.bodyB]; + this.collideConnected = data.collideConnected + } + }; + + function b2Joint(def) { + this.m_type = def.type; + this.m_prev = null; + this.m_next = null; + this.m_bodyA = def.bodyA; + this.m_bodyB = def.bodyB; + this.m_index = 0; + this.m_collideConnected = def.collideConnected; + this.m_islandFlag = false; + this.m_userData = def.userData; + this.m_edgeA = new b2JointEdge(); + this.m_edgeA.joint = null; + this.m_edgeA.other = null; + this.m_edgeA.prev = null; + this.m_edgeA.next = null; + this.m_edgeB = new b2JointEdge(); + this.m_edgeB.joint = null; + this.m_edgeB.other = null; + this.m_edgeB.prev = null; + this.m_edgeB.next = null + } + b2Joint.prototype = { + GetType: function () { + return this.m_type + }, + GetBodyA: function () { + return this.m_bodyA + }, + GetBodyB: function () { + return this.m_bodyB + }, + GetAnchorA: function () {}, + GetAnchorB: function () {}, + GetReactionForce: function (inv_dt) {}, + GetReactionTorque: function (inv_dt) {}, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + IsActive: function () { + return this.m_bodyA.IsActive() && this.m_bodyB.IsActive() + }, + GetCollideConnected: function () { + return this.m_collideConnected + }, + ShiftOrigin: function (newOrigin) {}, + InitVelocityConstraints: function (data) {}, + SolveVelocityConstraints: function (data) {}, + SolvePositionConstraints: function (data) {}, + _serialize: function (out) { + var obj = out || {}; + obj.bodyA = null; + obj.bodyB = null; + obj.type = this.m_type; + obj.collideConnected = this.m_collideConnected; + return obj + } + }; + b2Joint.e_inactiveLimit = 0; + b2Joint.e_atLowerLimit = 1; + b2Joint.e_atUpperLimit = 2; + b2Joint.e_equalLimits = 3; + 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_wheelJoint = 7; + b2Joint.e_weldJoint = 8; + b2Joint.e_frictionJoint = 9; + b2Joint.e_ropeJoint = 10; + b2Joint.e_motorJoint = 11; + b2Joint.Create = function (def) { + 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; + case b2Joint.e_wheelJoint: + joint = new b2WheelJoint(def); + break; + case b2Joint.e_weldJoint: + joint = new b2WeldJoint(def); + break; + case b2Joint.e_frictionJoint: + joint = new b2FrictionJoint(def); + break; + case b2Joint.e_ropeJoint: + joint = new b2RopeJoint(def); + break; + case b2Joint.e_motorJoint: + joint = new b2MotorJoint(def); + break + } + return joint + }; + b2Joint.Destroy = function (joint) {}; + + function b2RevoluteJointDef() { + this.parent.call(this); + this.type = b2Joint.e_revoluteJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.referenceAngle = 0; + this.lowerAngle = 0; + this.upperAngle = 0; + this.maxMotorTorque = 0; + this.motorSpeed = 0; + this.enableLimit = false; + this.enableMotor = false; + Object.seal(this) + } + b2RevoluteJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.referenceAngle = data.referenceAngle; + this.lowerAngle = data.lowerAngle; + this.upperAngle = data.upperAngle; + this.maxMotorTorque = data.maxMotorTorque; + this.motorSpeed = data.motorSpeed; + this.enableLimit = data.enableLimit; + this.enableMotor = data.enableMotor + } + }; + b2RevoluteJointDef._extend(b2JointDef); + + function b2RevoluteJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_referenceAngle = def.referenceAngle; + this.m_impulse = new b2Vec3(); + this.m_motorImpulse = 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; + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat33(); + this.m_motorMass = 0 + } + b2RevoluteJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + GetJointAngle: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + return bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle + }, + GetJointSpeed: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + return bB.m_angularVelocity - bA.m_angularVelocity + }, + IsLimitEnabled: function () { + return this.m_enableLimit + }, + EnableLimit: function (flag) { + if (flag != this.m_enableLimit) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableLimit = flag; + this.m_impulse.z = 0 + } + }, + GetLowerLimit: function () { + return this.m_lowerAngle + }, + GetUpperLimit: function () { + return this.m_upperAngle + }, + SetLimits: function (lower, upper) { + if (lower != this.m_lowerAngle || upper != this.m_upperAngle) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_impulse.z = 0; + this.m_lowerAngle = lower; + this.m_upperAngle = upper + } + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorTorque: function (torque) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorTorque = torque + }, + GetMaxMotorTorque: function () { + return this.m_maxMotorTorque + }, + GetReactionForce: function (inv_dt) { + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.z + }, + GetMotorTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA = this.m_bodyA.m_sweep.localCenter; + this.m_localCenterB = this.m_bodyB.m_sweep.localCenter; + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var fixedRotation = (iA + iB == 0); + this.m_mass.ex.x = mA + mB + this.m_rA.y * this.m_rA.y * iA + this.m_rB.y * this.m_rB.y * iB; + this.m_mass.ey.x = -this.m_rA.y * this.m_rA.x * iA - this.m_rB.y * this.m_rB.x * iB; + this.m_mass.ez.x = -this.m_rA.y * iA - this.m_rB.y * iB; + this.m_mass.ex.y = this.m_mass.ey.x; + this.m_mass.ey.y = mA + mB + this.m_rA.x * this.m_rA.x * iA + this.m_rB.x * this.m_rB.x * iB; + this.m_mass.ez.y = this.m_rA.x * iA + this.m_rB.x * iB; + this.m_mass.ex.z = this.m_mass.ez.x; + this.m_mass.ey.z = this.m_mass.ez.y; + this.m_mass.ez.z = iA + iB; + this.m_motorMass = iA + iB; + if (this.m_motorMass > 0) { + this.m_motorMass = 1 / this.m_motorMass + } + if (this.m_enableMotor == false || fixedRotation) { + this.m_motorImpulse = 0 + } + if (this.m_enableLimit && fixedRotation == false) { + var jointAngle = aB - aA - this.m_referenceAngle; + if (b2Abs(this.m_upperAngle - this.m_lowerAngle) < 2 * b2_angularSlop) { + this.m_limitState = b2Joint.e_equalLimits + } else { + if (jointAngle <= this.m_lowerAngle) { + if (this.m_limitState != b2Joint.e_atLowerLimit) { + this.m_impulse.z = 0 + } + this.m_limitState = b2Joint.e_atLowerLimit + } else { + if (jointAngle >= this.m_upperAngle) { + if (this.m_limitState != b2Joint.e_atUpperLimit) { + this.m_impulse.z = 0 + } + this.m_limitState = b2Joint.e_atUpperLimit + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + } + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + this.m_motorImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_motorImpulse + this.m_impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_motorImpulse + this.m_impulse.z) + } else { + this.m_impulse.SetZero(); + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var fixedRotation = (iA + iB == 0); + if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits && fixedRotation == false) { + var Cdot = wB - wA - this.m_motorSpeed; + var impulse = -this.m_motorMass * Cdot; + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorTorque; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse + } + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var Cdot2 = wB - wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var impulse = this.m_mass.Solve33(Cdot).Negate(); + if (this.m_limitState == b2Joint.e_equalLimits) { + this.m_impulse.Add(impulse) + } else { + if (this.m_limitState == b2Joint.e_atLowerLimit) { + var newImpulse = this.m_impulse.z + impulse.z; + if (newImpulse < 0) { + var rhs = b2Vec2.Add(Cdot1.Negate(), b2Vec2.Multiply(this.m_impulse.z, new b2Vec2(this.m_mass.ez.x, this.m_mass.ez.y))); + var reduced = this.m_mass.Solve22(rhs); + impulse.x = reduced.x; + impulse.y = reduced.y; + impulse.z = -this.m_impulse.z; + this.m_impulse.x += reduced.x; + this.m_impulse.y += reduced.y; + this.m_impulse.z = 0 + } else { + this.m_impulse.Add(impulse) + } + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + var newImpulse = this.m_impulse.z + impulse.z; + if (newImpulse > 0) { + var rhs = b2Vec2.Add(Cdot1.Negate(), b2Vec2.Multiply(this.m_impulse.z, new b2Vec2(this.m_mass.ez.x, this.m_mass.ez.y))); + var reduced = this.m_mass.Solve22(rhs); + impulse.x = reduced.x; + impulse.y = reduced.y; + impulse.z = -this.m_impulse.z; + this.m_impulse.x += reduced.x; + this.m_impulse.y += reduced.y; + this.m_impulse.z = 0 + } else { + this.m_impulse.Add(impulse) + } + } + } + } + var P = new b2Vec2(impulse.x, impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) + } else { + var Cdot = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var impulse = this.m_mass.Solve22(Cdot.Negate()); + this.m_impulse.x += impulse.x; + this.m_impulse.y += impulse.y; + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse) + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var angularError = 0; + var positionError = 0; + var fixedRotation = (this.m_invIA + this.m_invIB == 0); + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { + var angle = aB - aA - this.m_referenceAngle; + var limitImpulse = 0; + if (this.m_limitState == b2Joint.e_equalLimits) { + var C = b2Clamp(angle - this.m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection); + limitImpulse = -this.m_motorMass * C; + angularError = b2Abs(C) + } else { + if (this.m_limitState == b2Joint.e_atLowerLimit) { + var C = angle - this.m_lowerAngle; + angularError = -C; + C = b2Clamp(C + b2_angularSlop, -b2_maxAngularCorrection, 0); + limitImpulse = -this.m_motorMass * C + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + var C = angle - this.m_upperAngle; + angularError = C; + C = b2Clamp(C - b2_angularSlop, 0, b2_maxAngularCorrection); + limitImpulse = -this.m_motorMass * C + } + } + } + aA -= this.m_invIA * limitImpulse; + aB += this.m_invIB * limitImpulse + } + qA.Set(aA); + qB.Set(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var C = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + positionError = C.Length(); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + K.ex.x = mA + mB + iA * rA.y * rA.y + iB * rB.y * rB.y; + K.ex.y = -iA * rA.x * rA.y - iB * rB.x * rB.y; + K.ey.x = K.ex.y; + K.ey.y = mA + mB + iA * rA.x * rA.x + iB * rB.x * rB.x; + var impulse = K.Solve(C).Negate(); + cA.Subtract(b2Vec2.Multiply(mA, impulse)); + aA -= iA * b2Cross_v2_v2(rA, impulse); + cB.Add(b2Vec2.Multiply(mB, impulse)); + aB += iB * b2Cross_v2_v2(rB, impulse); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return positionError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.lowerAngle = this.m_lowerAngle; + obj.upperAngle = this.m_upperAngle; + obj.maxMotorTorque = this.m_maxMotorTorque; + obj.motorSpeed = this.m_motorSpeed; + obj.enableLimit = this.m_enableLimit; + obj.enableMotor = this.m_enableMotor; + return obj + } + }; + b2RevoluteJoint._extend(b2Joint); + + function b2MouseJointDef() { + this.parent.call(this); + this.type = b2Joint.e_mouseJoint; + this.target = new b2Vec2(0, 0); + this.maxForce = 0; + this.frequencyHz = 5; + this.dampingRatio = 0.7; + Object.seal(this) + } + b2MouseJointDef._extend(b2JointDef); + + function b2MouseJoint(def) { + this.parent.call(this, def); + this.m_targetA = def.target.Clone(); + this.m_localAnchorB = b2MulT_t_v2(this.m_bodyB.GetTransform(), this.m_targetA); + this.m_maxForce = def.maxForce; + this.m_impulse = new b2Vec2(); + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_beta = 0; + this.m_gamma = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rB = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassB = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat22(); + this.m_C = new b2Vec2() + } + b2MouseJoint.prototype = { + GetAnchorA: function () { + return this.m_targetA + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_impulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * 0 + }, + SetTarget: function (target) { + if (this.m_bodyB.IsAwake() == false) { + this.m_bodyB.SetAwake(true) + } + this.m_targetA.Assign(target) + }, + GetTarget: function () { + return this.m_targetA + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + ShiftOrigin: function (newOrigin) { + this.m_targetA.Subtract(newOrigin) + }, + InitVelocityConstraints: function (data) { + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIB = this.m_bodyB.m_invI; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qB = new b2Rot(aB); + var mass = this.m_bodyB.GetMass(); + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * mass * this.m_dampingRatio * omega; + var k = mass * (omega * omega); + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + if (this.m_gamma != 0) { + this.m_gamma = 1 / this.m_gamma + } + this.m_beta = h * k * this.m_gamma; + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + var K = new b2Mat22(); + K.ex.x = this.m_invMassB + this.m_invIB * this.m_rB.y * this.m_rB.y + this.m_gamma; + K.ex.y = -this.m_invIB * this.m_rB.x * this.m_rB.y; + K.ey.x = K.ex.y; + K.ey.y = this.m_invMassB + this.m_invIB * this.m_rB.x * this.m_rB.x + this.m_gamma; + this.m_mass.Assign(K.GetInverse()); + this.m_C.Assign(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), this.m_targetA)); + this.m_C.Multiply(this.m_beta); + wB *= 0.98; + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + vB.Add(b2Vec2.Multiply(this.m_invMassB, this.m_impulse)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, this.m_impulse) + } else { + this.m_impulse.SetZero() + } + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var Cdot = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var impulse = b2Mul_m22_v2(this.m_mass, (b2Vec2.Add(b2Vec2.Add(Cdot, this.m_C), b2Vec2.Multiply(this.m_gamma, this.m_impulse))).Negate()); + var oldImpulse = this.m_impulse.Clone(); + this.m_impulse.Add(impulse); + var maxImpulse = data.step.dt * this.m_maxForce; + if (this.m_impulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_impulse.Multiply(maxImpulse / this.m_impulse.Length()) + } + impulse.Assign(b2Vec2.Subtract(this.m_impulse, oldImpulse)); + vB.Add(b2Vec2.Multiply(this.m_invMassB, impulse)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + } + }; + b2MouseJoint._extend(b2Joint); + + function b2DistanceJointDef() { + this.parent.call(this); + this.type = b2Joint.e_distanceJoint; + this.localAnchorA = new b2Vec2(0, 0); + this.localAnchorB = new b2Vec2(0, 0); + this.length = 1; + this.frequencyHz = 0; + this.dampingRatio = 0; + Object.seal(this) + } + b2DistanceJointDef.prototype = { + Initialize: function (b1, b2, anchor1, anchor2) { + this.bodyA = b1; + this.bodyB = b2; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor1); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor2); + var d = b2Vec2.Subtract(anchor2, anchor1); + this.length = d.Length() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.length = data.length; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } + }; + b2DistanceJointDef._extend(b2JointDef); + + function b2DistanceJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_length = def.length; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_impulse = 0; + this.m_gamma = 0; + this.m_bias = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_u = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = 0 + } + b2DistanceJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); + return F + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetLength: function (length) { + this.m_length = length + }, + GetLength: function () { + return this.m_length + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + this.m_u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA); + var length = this.m_u.Length(); + if (length > b2_linearSlop) { + this.m_u.Multiply(1 / length) + } else { + this.m_u.Set(0, 0) + } + var crAu = b2Cross_v2_v2(this.m_rA, this.m_u); + var crBu = b2Cross_v2_v2(this.m_rB, this.m_u); + var invMass = this.m_invMassA + this.m_invIA * crAu * crAu + this.m_invMassB + this.m_invIB * crBu * crBu; + this.m_mass = invMass != 0 ? 1 / invMass : 0; + if (this.m_frequencyHz > 0) { + var C = length - this.m_length; + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * this.m_mass * this.m_dampingRatio * omega; + var k = this.m_mass * omega * omega; + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; + this.m_bias = C * h * k * this.m_gamma; + invMass += this.m_gamma; + this.m_mass = invMass != 0 ? 1 / invMass : 0 + } else { + this.m_gamma = 0; + this.m_bias = 0 + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var P = b2Vec2.Multiply(this.m_impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); + var impulse = -this.m_mass * (Cdot + this.m_bias + this.m_gamma * this.m_impulse); + this.m_impulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + if (this.m_frequencyHz > 0) { + return true + } + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var length = u.Normalize(); + var C = length - this.m_length; + C = b2Clamp(C, -b2_maxLinearCorrection, b2_maxLinearCorrection); + var impulse = -this.m_mass * C; + var P = b2Vec2.Multiply(impulse, u); + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * b2Cross_v2_v2(rB, P); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return b2Abs(C) < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.length = this.m_length; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj + } + }; + b2DistanceJoint._extend(b2Joint); + + function b2PrismaticJointDef() { + this.parent.call(this); + this.type = b2Joint.e_prismaticJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.localAxisA = new b2Vec2(1, 0); + this.referenceAngle = 0; + this.enableLimit = false; + this.lowerTranslation = 0; + this.upperTranslation = 0; + this.enableMotor = false; + this.maxMotorForce = 0; + this.motorSpeed = 0; + Object.seal(this) + } + b2PrismaticJointDef.prototype = { + Initialize: function (bA, bB, anchor, axis) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor); + this.localAxisA = this.bodyA.GetLocalVector(axis); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.localAxisA._deserialize(data.localAxisA); + this.referenceAngle = data.referenceAngle; + this.enableLimit = data.enableLimit; + this.lowerTranslation = data.lowerTranslation; + this.upperTranslation = data.upperTranslation; + this.enableMotor = data.enableMotor; + this.maxMotorForce = data.maxMotorForce; + this.motorSpeed = data.motorSpeed + } + }; + b2PrismaticJointDef._extend(b2JointDef); + + function b2PrismaticJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_localXAxisA = def.localAxisA.Clone(); + this.m_localXAxisA.Normalize(); + this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); + this.m_referenceAngle = def.referenceAngle; + this.m_impulse = new b2Vec3(); + this.m_motorMass = 0; + this.m_motorImpulse = 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; + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_axis = new b2Vec2(); + this.m_perp = new b2Vec2(); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_s1 = 0, this.m_s2 = 0; + this.m_a1 = 0, this.m_a2 = 0; + this.m_K = new b2Mat33(); + this.m_motorMass = 0 + } + b2PrismaticJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((this.m_motorImpulse + this.m_impulse.z), this.m_axis))) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.y + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetLocalAxisA: function () { + return this.m_localXAxisA + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + GetJointTranslation: function () { + var pA = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); + var pB = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); + var d = b2Vec2.Subtract(pB, pA); + var axis = this.m_bodyA.GetWorldVector(this.m_localXAxisA); + var translation = b2Dot_v2_v2(d, axis); + return translation + }, + GetJointSpeed: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + var rA = b2Mul_r_v2(bA.m_xf.q, b2Vec2.Subtract(this.m_localAnchorA, bA.m_sweep.localCenter)); + var rB = b2Mul_r_v2(bB.m_xf.q, b2Vec2.Subtract(this.m_localAnchorB, bB.m_sweep.localCenter)); + var p1 = b2Vec2.Add(bA.m_sweep.c, rA); + var p2 = b2Vec2.Add(bB.m_sweep.c, rB); + var d = b2Vec2.Subtract(p2, p1); + var axis = b2Mul_r_v2(bA.m_xf.q, this.m_localXAxisA); + var vA = bA.m_linearVelocity; + var vB = bB.m_linearVelocity; + var wA = bA.m_angularVelocity; + var wB = bB.m_angularVelocity; + var speed = b2Dot_v2_v2(d, b2Cross_f_v2(wA, axis)) + b2Dot_v2_v2(axis, b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, rB)), vA), b2Cross_f_v2(wA, rA))); + return speed + }, + IsLimitEnabled: function () { + return this.m_enableLimit + }, + EnableLimit: function (flag) { + if (flag != this.m_enableLimit) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableLimit = flag; + this.m_impulse.z = 0 + } + }, + GetLowerLimit: function () { + return this.m_lowerTranslation + }, + GetUpperLimit: function () { + return this.m_upperTranslation + }, + SetLimits: function (lower, upper) { + if (lower != this.m_lowerTranslation || upper != this.m_upperTranslation) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_lowerTranslation = lower; + this.m_upperTranslation = upper; + this.m_impulse.z = 0 + } + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorForce: function (force) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorForce = force + }, + GetMaxMotorForce: function () { + return this.m_maxMotorForce + }, + GetMotorForce: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA = this.m_bodyA.m_sweep.localCenter; + this.m_localCenterB = this.m_bodyB.m_sweep.localCenter; + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + this.m_axis = b2Mul_r_v2(qA, this.m_localXAxisA); + this.m_a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_axis); + this.m_a2 = b2Cross_v2_v2(rB, this.m_axis); + this.m_motorMass = mA + mB + iA * this.m_a1 * this.m_a1 + iB * this.m_a2 * this.m_a2; + if (this.m_motorMass > 0) { + this.m_motorMass = 1 / this.m_motorMass + } + this.m_perp = b2Mul_r_v2(qA, this.m_localYAxisA); + this.m_s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_perp); + this.m_s2 = b2Cross_v2_v2(rB, this.m_perp); + var k11 = mA + mB + iA * this.m_s1 * this.m_s1 + iB * this.m_s2 * this.m_s2; + var k12 = iA * this.m_s1 + iB * this.m_s2; + var k13 = iA * this.m_s1 * this.m_a1 + iB * this.m_s2 * this.m_a2; + var k22 = iA + iB; + if (k22 == 0) { + k22 = 1 + } + var k23 = iA * this.m_a1 + iB * this.m_a2; + var k33 = mA + mB + iA * this.m_a1 * this.m_a1 + iB * this.m_a2 * this.m_a2; + this.m_K.ex.Set(k11, k12, k13); + this.m_K.ey.Set(k12, k22, k23); + this.m_K.ez.Set(k13, k23, k33); + if (this.m_enableLimit) { + var jointTranslation = b2Dot_v2_v2(this.m_axis, d); + if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { + this.m_limitState = b2Joint.e_equalLimits + } else { + if (jointTranslation <= this.m_lowerTranslation) { + if (this.m_limitState != b2Joint.e_atLowerLimit) { + this.m_limitState = b2Joint.e_atLowerLimit; + this.m_impulse.z = 0 + } + } else { + if (jointTranslation >= this.m_upperTranslation) { + if (this.m_limitState != b2Joint.e_atUpperLimit) { + this.m_limitState = b2Joint.e_atUpperLimit; + this.m_impulse.z = 0 + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + } + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + if (this.m_enableMotor == false) { + this.m_motorImpulse = 0 + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + this.m_motorImpulse *= data.step.dtRatio; + var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((this.m_motorImpulse + this.m_impulse.z), this.m_axis)); + var LA = this.m_impulse.x * this.m_s1 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a1; + var LB = this.m_impulse.x * this.m_s2 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } else { + this.m_impulse.SetZero(); + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits) { + var Cdot = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(vB, vA)) + this.m_a2 * wB - this.m_a1 * wA; + var impulse = this.m_motorMass * (this.m_motorSpeed - Cdot); + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorForce; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + var P = b2Vec2.Multiply(impulse, this.m_axis); + var LA = impulse * this.m_a1; + var LB = impulse * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } + var Cdot1 = new b2Vec2(); + Cdot1.x = b2Dot_v2_v2(this.m_perp, b2Vec2.Subtract(vB, vA)) + this.m_s2 * wB - this.m_s1 * wA; + Cdot1.y = wB - wA; + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) { + var Cdot2; + Cdot2 = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(vB, vA)) + this.m_a2 * wB - this.m_a1 * wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var f1 = this.m_impulse.Clone(); + var df = this.m_K.Solve33(Cdot.Negate()); + this.m_impulse.Add(df); + if (this.m_limitState == b2Joint.e_atLowerLimit) { + this.m_impulse.z = b2Max(this.m_impulse.z, 0) + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + this.m_impulse.z = b2Min(this.m_impulse.z, 0) + } + } + var b = b2Vec2.Subtract(Cdot1.Negate(), b2Vec2.Multiply((this.m_impulse.z - f1.z), new b2Vec2(this.m_K.ez.x, this.m_K.ez.y))); + var f2r = b2Vec2.Add(this.m_K.Solve22(b), new b2Vec2(f1.x, f1.y)); + this.m_impulse.x = f2r.x; + this.m_impulse.y = f2r.y; + df = b2Vec3.Subtract(this.m_impulse, f1); + var P = b2Vec2.Add(b2Vec2.Multiply(df.x, this.m_perp), b2Vec2.Multiply(df.z, this.m_axis)); + var LA = df.x * this.m_s1 + df.y + df.z * this.m_a1; + var LB = df.x * this.m_s2 + df.y + df.z * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } else { + var df = this.m_K.Solve22(Cdot1.Negate()); + this.m_impulse.x += df.x; + this.m_impulse.y += df.y; + var P = b2Vec2.Multiply(df.x, this.m_perp); + var LA = df.x * this.m_s1 + df.y; + var LB = df.x * this.m_s2 + df.y; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var axis = b2Mul_r_v2(qA, this.m_localXAxisA); + var a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), axis); + var a2 = b2Cross_v2_v2(rB, axis); + var perp = b2Mul_r_v2(qA, this.m_localYAxisA); + var s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), perp); + var s2 = b2Cross_v2_v2(rB, perp); + var impulse = new b2Vec3(); + var C1 = new b2Vec2(); + C1.x = b2Dot_v2_v2(perp, d); + C1.y = aB - aA - this.m_referenceAngle; + var linearError = b2Abs(C1.x); + var angularError = b2Abs(C1.y); + var active = false; + var C2 = 0; + if (this.m_enableLimit) { + var translation = b2Dot_v2_v2(axis, d); + if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { + C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection); + linearError = b2Max(linearError, b2Abs(translation)); + active = true + } else { + if (translation <= this.m_lowerTranslation) { + C2 = b2Clamp(translation - this.m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0); + linearError = b2Max(linearError, this.m_lowerTranslation - translation); + active = true + } else { + if (translation >= this.m_upperTranslation) { + C2 = b2Clamp(translation - this.m_upperTranslation - b2_linearSlop, 0, b2_maxLinearCorrection); + linearError = b2Max(linearError, translation - this.m_upperTranslation); + active = true + } + } + } + } + if (active) { + var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; + var k12 = iA * s1 + iB * s2; + var k13 = iA * s1 * a1 + iB * s2 * a2; + var k22 = iA + iB; + if (k22 == 0) { + k22 = 1 + } + var k23 = iA * a1 + iB * a2; + var k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; + var K = new b2Mat33(); + K.ex.Set(k11, k12, k13); + K.ey.Set(k12, k22, k23); + K.ez.Set(k13, k23, k33); + var C = new b2Vec3(); + C.x = C1.x; + C.y = C1.y; + C.z = C2; + impulse = K.Solve33(C.Negate()) + } else { + var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; + var k12 = iA * s1 + iB * s2; + var k22 = iA + iB; + if (k22 == 0) { + k22 = 1 + } + var K = new b2Mat22(); + K.ex.Set(k11, k12); + K.ey.Set(k12, k22); + var impulse1 = K.Solve(C1.Negate()); + impulse.x = impulse1.x; + impulse.y = impulse1.y; + impulse.z = 0 + } + var P = b2Vec2.Add(b2Vec2.Multiply(impulse.x, perp), b2Vec2.Multiply(impulse.z, axis)); + var LA = impulse.x * s1 + impulse.y + impulse.z * a1; + var LB = impulse.x * s2 + impulse.y + impulse.z * a2; + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * LA; + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * LB; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return linearError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.localAxisA = this.m_localXAxisA._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.enableLimit = this.m_enableLimit; + obj.lowerTranslation = this.m_lowerTranslation; + obj.upperTranslation = this.m_upperTranslation; + obj.enableMotor = this.m_enableMotor; + obj.maxMotorForce = this.m_maxMotorForce; + obj.motorSpeed = this.m_motorSpeed; + return obj + } + }; + b2PrismaticJoint._extend(b2Joint); + + function b2FrictionJointDef() { + this.parent.call(this); + this.type = b2Joint.e_frictionJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.maxForce = 0; + this.maxTorque = 0; + Object.seal(this) + } + b2FrictionJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)) + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.maxForce = data.maxForce; + this.maxTorque = data.maxTorque + } + }; + b2FrictionJointDef._extend(b2JointDef); + + function b2FrictionJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_linearImpulse = new b2Vec2(); + this.m_angularImpulse = 0; + this.m_maxForce = def.maxForce; + this.m_maxTorque = def.maxTorque; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_linearMass = new b2Mat22(); + this.m_angularMass = 0 + } + b2FrictionJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_angularImpulse + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetMaxTorque: function (torque) { + this.m_maxTorque = torque + }, + GetMaxTorque: function () { + return this.m_maxTorque + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + K.ex.x = mA + mB + iA * this.m_rA.y * this.m_rA.y + iB * this.m_rB.y * this.m_rB.y; + K.ex.y = -iA * this.m_rA.x * this.m_rA.y - iB * this.m_rB.x * this.m_rB.y; + K.ey.x = K.ex.y; + K.ey.y = mA + mB + iA * this.m_rA.x * this.m_rA.x + iB * this.m_rB.x * this.m_rB.x; + this.m_linearMass = K.GetInverse(); + this.m_angularMass = iA + iB; + if (this.m_angularMass > 0) { + this.m_angularMass = 1 / this.m_angularMass + } + if (data.step.warmStarting) { + this.m_linearImpulse.Multiply(data.step.dtRatio); + this.m_angularImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) + } else { + this.m_linearImpulse.SetZero(); + this.m_angularImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var h = data.step.dt; + var Cdot = wB - wA; + var impulse = -this.m_angularMass * Cdot; + var oldImpulse = this.m_angularImpulse; + var maxImpulse = h * this.m_maxTorque; + this.m_angularImpulse = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_angularImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Vec2.Add(vB, b2Vec2.Subtract(b2Cross_f_v2(wB, this.m_rB), b2Vec2.Subtract(vA, b2Cross_f_v2(wA, this.m_rA)))); + var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); + var oldImpulse = this.m_linearImpulse.Clone(); + this.m_linearImpulse.Add(impulse); + var maxImpulse = h * this.m_maxForce; + if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_linearImpulse.Normalize(); + this.m_linearImpulse.Multiply(maxImpulse) + } + impulse = b2Vec2.Subtract(this.m_linearImpulse, oldImpulse); + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.maxForce = this.m_maxForce; + obj.maxTorque = this.m_maxTorque; + return obj + } + }; + b2FrictionJoint._extend(b2Joint); + + function b2WeldJointDef() { + this.parent.call(this); + this.type = b2Joint.e_weldJoint; + this.localAnchorA = new b2Vec2(0, 0); + this.localAnchorB = new b2Vec2(0, 0); + this.referenceAngle = 0; + this.frequencyHz = 0; + this.dampingRatio = 0; + Object.seal(this) + } + b2WeldJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.referenceAngle = data.referenceAngle; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } + }; + b2WeldJointDef._extend(b2JointDef); + + function b2WeldJoint(def) { + this.parent.call(this, def); + this.m_bias = 0; + this.m_gamma = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat33(); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_referenceAngle = def.referenceAngle; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_impulse = new b2Vec3() + } + b2WeldJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.z + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat33(); + K.ex.x = mA + mB + this.m_rA.y * this.m_rA.y * iA + this.m_rB.y * this.m_rB.y * iB; + K.ey.x = -this.m_rA.y * this.m_rA.x * iA - this.m_rB.y * this.m_rB.x * iB; + K.ez.x = -this.m_rA.y * iA - this.m_rB.y * iB; + K.ex.y = K.ey.x; + K.ey.y = mA + mB + this.m_rA.x * this.m_rA.x * iA + this.m_rB.x * this.m_rB.x * iB; + K.ez.y = this.m_rA.x * iA + this.m_rB.x * iB; + K.ex.z = K.ez.x; + K.ey.z = K.ez.y; + K.ez.z = iA + iB; + if (this.m_frequencyHz > 0) { + K.GetInverse22(this.m_mass); + var invM = iA + iB; + var m = invM > 0 ? 1 / invM : 0; + var C = aB - aA - this.m_referenceAngle; + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * m * this.m_dampingRatio * omega; + var k = m * omega * omega; + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; + this.m_bias = C * h * k * this.m_gamma; + invM += this.m_gamma; + this.m_mass.ez.z = invM != 0 ? 1 / invM : 0 + } else { + K.GetSymInverse33(this.m_mass); + this.m_gamma = 0; + this.m_bias = 0 + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_impulse.z) + } else { + this.m_impulse.SetZero() + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + if (this.m_frequencyHz > 0) { + var Cdot2 = wB - wA; + var impulse2 = -this.m_mass.ez.z * (Cdot2 + this.m_bias + this.m_gamma * this.m_impulse.z); + this.m_impulse.z += impulse2; + wA -= iA * impulse2; + wB += iB * impulse2; + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var impulse1 = b2Mul22_m33_v2(this.m_mass, Cdot1).Negate(); + this.m_impulse.x += impulse1.x; + this.m_impulse.y += impulse1.y; + var P = impulse1.Clone(); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * b2Cross_v2_v2(this.m_rB, P) + } else { + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var Cdot2 = wB - wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var impulse = b2Mul_m33_v3(this.m_mass, Cdot).Negate(); + this.m_impulse.Add(impulse); + var P = new b2Vec2(impulse.x, impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var positionError, angularError; + var K = new b2Mat33(); + K.ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB; + K.ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB; + K.ez.x = -rA.y * iA - rB.y * iB; + K.ex.y = K.ey.x; + K.ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB; + K.ez.y = rA.x * iA + rB.x * iB; + K.ex.z = K.ez.x; + K.ey.z = K.ez.y; + K.ez.z = iA + iB; + if (this.m_frequencyHz > 0) { + var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + positionError = C1.Length(); + angularError = 0; + var P = K.Solve22(C1).Negate(); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * b2Cross_v2_v2(rB, P) + } else { + var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var C2 = aB - aA - this.m_referenceAngle; + positionError = C1.Length(); + angularError = b2Abs(C2); + var C = new b2Vec3(C1.x, C1.y, C2); + var impulse = K.Solve33(C).Negate(); + var P = new b2Vec2(impulse.x, impulse.y); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * (b2Cross_v2_v2(rA, P) + impulse.z); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * (b2Cross_v2_v2(rB, P) + impulse.z) + } + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return positionError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj + } + }; + b2WeldJoint._extend(b2Joint); + + function b2WheelJointDef() { + this.parent.call(this); + this.type = b2Joint.e_wheelJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.localAxisA = new b2Vec2(1, 0); + this.enableMotor = false; + this.maxMotorTorque = 0; + this.motorSpeed = 0; + this.frequencyHz = 2; + this.dampingRatio = 0.7; + Object.seal(this) + } + b2WheelJointDef.prototype = { + Initialize: function (bA, bB, anchor, axis) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); + this.localAxisA.Assign(this.bodyA.GetLocalVector(axis)) + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.localAxisA._deserialize(data.localAxisA); + this.enableMotor = data.enableMotor; + this.maxMotorTorque = data.maxMotorTorque; + this.motorSpeed = data.motorSpeed; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } + }; + b2WheelJointDef._extend(b2JointDef); + + function b2WheelJoint(def) { + this.parent.call(this, def); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_localXAxisA = def.localAxisA.Clone(); + this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); + this.m_mass = 0; + this.m_impulse = 0; + this.m_motorMass = 0; + this.m_motorImpulse = 0; + this.m_springMass = 0; + this.m_springImpulse = 0; + this.m_maxMotorTorque = def.maxMotorTorque; + this.m_motorSpeed = def.motorSpeed; + this.m_enableMotor = def.enableMotor; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_bias = 0; + this.m_gamma = 0; + this.m_ax = new b2Vec2(); + this.m_ay = new b2Vec2(); + this.m_sAx = this.m_sBx = 0; + this.m_sAy = this.m_sBy = 0 + } + b2WheelJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(this.m_springImpulse, this.m_ax))) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetLocalAxisA: function () { + return this.m_localXAxisA + }, + GetJointTranslation: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + var pA = bA.GetWorldPoint(this.m_localAnchorA); + var pB = bB.GetWorldPoint(this.m_localAnchorB); + var d = b2Vec2.Subtract(pB, pA); + var axis = bA.GetWorldVector(this.m_localXAxisA); + var translation = b2Dot_v2_v2(d, axis); + return translation + }, + GetJointSpeed: function () { + var wA = this.m_bodyA.m_angularVelocity; + var wB = this.m_bodyB.m_angularVelocity; + return wB - wA + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorTorque: function (torque) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorTorque = torque + }, + GetMaxMotorTorque: function () { + return this.m_maxMotorTorque + }, + GetMotorTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + SetSpringFrequencyHz: function (hz) { + this.m_frequencyHz = hz + }, + GetSpringFrequencyHz: function () { + return this.m_frequencyHz + }, + SetSpringDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetSpringDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + this.m_ay.Assign(b2Mul_r_v2(qA, this.m_localYAxisA)); + this.m_sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ay); + this.m_sBy = b2Cross_v2_v2(rB, this.m_ay); + this.m_mass = mA + mB + iA * this.m_sAy * this.m_sAy + iB * this.m_sBy * this.m_sBy; + if (this.m_mass > 0) { + this.m_mass = 1 / this.m_mass + } + this.m_springMass = 0; + this.m_bias = 0; + this.m_gamma = 0; + if (this.m_frequencyHz > 0) { + this.m_ax.Assign(b2Mul_r_v2(qA, this.m_localXAxisA)); + this.m_sAx = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ax); + this.m_sBx = b2Cross_v2_v2(rB, this.m_ax); + var invMass = mA + mB + iA * this.m_sAx * this.m_sAx + iB * this.m_sBx * this.m_sBx; + if (invMass > 0) { + this.m_springMass = 1 / invMass; + var C = b2Dot_v2_v2(d, this.m_ax); + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * this.m_springMass * this.m_dampingRatio * omega; + var k = this.m_springMass * omega * omega; + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + if (this.m_gamma > 0) { + this.m_gamma = 1 / this.m_gamma + } + this.m_bias = C * h * k * this.m_gamma; + this.m_springMass = invMass + this.m_gamma; + if (this.m_springMass > 0) { + this.m_springMass = 1 / this.m_springMass + } + } + } else { + this.m_springImpulse = 0 + } + if (this.m_enableMotor) { + this.m_motorMass = iA + iB; + if (this.m_motorMass > 0) { + this.m_motorMass = 1 / this.m_motorMass + } + } else { + this.m_motorMass = 0; + this.m_motorImpulse = 0 + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + this.m_springImpulse *= data.step.dtRatio; + this.m_motorImpulse *= data.step.dtRatio; + var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(this.m_springImpulse, this.m_ax)); + var LA = this.m_impulse * this.m_sAy + this.m_springImpulse * this.m_sAx + this.m_motorImpulse; + var LB = this.m_impulse * this.m_sBy + this.m_springImpulse * this.m_sBx + this.m_motorImpulse; + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * LA; + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * LB + } else { + this.m_impulse = 0; + this.m_springImpulse = 0; + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var Cdot = b2Dot_v2_v2(this.m_ax, b2Vec2.Subtract(vB, vA)) + this.m_sBx * wB - this.m_sAx * wA; + var impulse = -this.m_springMass * (Cdot + this.m_bias + this.m_gamma * this.m_springImpulse); + this.m_springImpulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_ax); + var LA = impulse * this.m_sAx; + var LB = impulse * this.m_sBx; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB; + var Cdot = wB - wA - this.m_motorSpeed; + var impulse = -this.m_motorMass * Cdot; + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorTorque; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Dot_v2_v2(this.m_ay, b2Vec2.Subtract(vB, vA)) + this.m_sBy * wB - this.m_sAy * wA; + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_ay); + var LA = impulse * this.m_sAy; + var LB = impulse * this.m_sBy; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB; + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); + var ay = b2Mul_r_v2(qA, this.m_localYAxisA); + var sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), ay); + var sBy = b2Cross_v2_v2(rB, ay); + var C = b2Dot_v2_v2(d, ay); + var k = this.m_invMassA + this.m_invMassB + this.m_invIA * this.m_sAy * this.m_sAy + this.m_invIB * this.m_sBy * this.m_sBy; + var impulse; + if (k != 0) { + impulse = -C / k + } else { + impulse = 0 + } + var P = b2Vec2.Multiply(impulse, ay); + var LA = impulse * sAy; + var LB = impulse * sBy; + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * LA; + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * LB; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return b2Abs(C) <= b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.localAxisA = this.m_localAxisA._serialize(); + obj.enableMotor = this.m_enableMotor; + obj.maxMotorTorque = this.m_maxMotorTorque; + obj.motorSpeed = this.m_motorSpeed; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj + } + }; + b2WheelJoint._extend(b2Joint); + + function b2GearJointDef() { + this.parent.call(this); + this.type = b2Joint.e_gearJoint; + this.joint1 = null; + this.joint2 = null; + this.ratio = 1; + Object.seal(this) + } + b2GearJointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.joint1 = data.joint1; + this.joint2 = data.joint2; + this.ratio = data.ratio + } + }; + b2GearJointDef._extend(b2JointDef); + + function b2GearJoint(def) { + this.parent.call(this, def); + this.m_joint1 = def.joint1; + this.m_joint2 = def.joint2; + this.m_typeA = this.m_joint1.GetType(); + this.m_typeB = this.m_joint2.GetType(); + var coordinateA, coordinateB; + this.m_bodyC = this.m_joint1.GetBodyA(); + this.m_bodyA = this.m_joint1.GetBodyB(); + var xfA = this.m_bodyA.m_xf; + var aA = this.m_bodyA.m_sweep.a; + var xfC = this.m_bodyC.m_xf; + var aC = this.m_bodyC.m_sweep.a; + this.m_localAnchorA = new b2Vec2(); + this.m_localAnchorB = new b2Vec2(); + this.m_localAnchorC = new b2Vec2(); + this.m_localAnchorD = new b2Vec2(); + this.m_localAxisC = new b2Vec2(); + this.m_localAxisD = new b2Vec2(); + if (this.m_typeA == b2Joint.e_revoluteJoint) { + var revolute = def.joint1; + this.m_localAnchorC.Assign(revolute.m_localAnchorA); + this.m_localAnchorA.Assign(revolute.m_localAnchorB); + this.m_referenceAngleA = revolute.m_referenceAngle; + this.m_localAxisC.SetZero(); + coordinateA = aA - aC - this.m_referenceAngleA + } else { + var prismatic = def.joint1; + this.m_localAnchorC.Assign(prismatic.m_localAnchorA); + this.m_localAnchorA.Assign(prismatic.m_localAnchorB); + this.m_referenceAngleA = prismatic.m_referenceAngle; + this.m_localAxisC.Assign(prismatic.m_localXAxisA); + var pC = this.m_localAnchorC; + var pA = b2MulT_r_v2(xfC.q, b2Vec2.Add(b2Mul_r_v2(xfA.q, this.m_localAnchorA), b2Vec2.Subtract(xfA.p, xfC.p))); + coordinateA = b2Dot_v2_v2(b2Vec2.Subtract(pA, pC), this.m_localAxisC) + } + this.m_bodyD = this.m_joint2.GetBodyA(); + this.m_bodyB = this.m_joint2.GetBodyB(); + var xfB = this.m_bodyB.m_xf; + var aB = this.m_bodyB.m_sweep.a; + var xfD = this.m_bodyD.m_xf; + var aD = this.m_bodyD.m_sweep.a; + if (this.m_typeB == b2Joint.e_revoluteJoint) { + var revolute = def.joint2; + this.m_localAnchorD.Assign(revolute.m_localAnchorA); + this.m_localAnchorB.Assign(revolute.m_localAnchorB); + this.m_referenceAngleB = revolute.m_referenceAngle; + this.m_localAxisD.SetZero(); + coordinateB = aB - aD - this.m_referenceAngleB + } else { + var prismatic = def.joint2; + this.m_localAnchorD.Assign(prismatic.m_localAnchorA); + this.m_localAnchorB.Assign(prismatic.m_localAnchorB); + this.m_referenceAngleB = prismatic.m_referenceAngle; + this.m_localAxisD.Assign(prismatic.m_localXAxisA); + var pD = this.m_localAnchorD; + var pB = b2MulT_r_v2(xfD.q, b2Vec2.Add(b2Mul_r_v2(xfB.q, this.m_localAnchorB), b2Vec2.Subtract(xfB.p, xfD.p))); + coordinateB = b2Dot_v2_v2(b2Vec2.Subtract(pB, pD), this.m_localAxisD) + } + this.m_ratio = def.ratio; + this.m_constant = coordinateA + this.m_ratio * coordinateB; + this.m_impulse = 0; + this.m_indexA = this.m_indexB = this.m_indexC = this.m_indexD = 0; + this.m_lcA = new b2Vec2(); + this.m_lcB = new b2Vec2(); + this.m_lcC = new b2Vec2(); + this.m_lcD = new b2Vec2(); + this.m_mA = this.m_mB = this.m_mC = this.m_mD = 0; + this.m_iA = this.m_iB = this.m_iC = this.m_iD = 0; + this.m_JvAC = new b2Vec2(), this.m_JvBD = new b2Vec2(); + this.m_JwA = this.m_JwB = this.m_JwC = this.m_JwD = 0; + this.m_mass = 0 + } + b2GearJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = b2Vec2.Multiply(this.m_impulse, this.m_JvAC); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + var L = this.m_impulse * this.m_JwA; + return inv_dt * L + }, + GetJoint1: function () { + return this.m_joint1 + }, + GetJoint2: function () { + return this.m_joint2 + }, + SetRatio: function (ratio) { + this.m_ratio = ratio + }, + GetRatio: function () { + return this.m_ratio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_indexC = this.m_bodyC.m_islandIndex; + this.m_indexD = this.m_bodyD.m_islandIndex; + this.m_lcA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_lcB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_lcC.Assign(this.m_bodyC.m_sweep.localCenter); + this.m_lcD.Assign(this.m_bodyD.m_sweep.localCenter); + this.m_mA = this.m_bodyA.m_invMass; + this.m_mB = this.m_bodyB.m_invMass; + this.m_mC = this.m_bodyC.m_invMass; + this.m_mD = this.m_bodyD.m_invMass; + this.m_iA = this.m_bodyA.m_invI; + this.m_iB = this.m_bodyB.m_invI; + this.m_iC = this.m_bodyC.m_invI; + this.m_iD = this.m_bodyD.m_invI; + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var aC = data.positions[this.m_indexC].a; + var vC = data.velocities[this.m_indexC].v.Clone(); + var wC = data.velocities[this.m_indexC].w; + var aD = data.positions[this.m_indexD].a; + var vD = data.velocities[this.m_indexD].v.Clone(); + var wD = data.velocities[this.m_indexD].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB), + qC = new b2Rot(aC), + qD = new b2Rot(aD); + this.m_mass = 0; + if (this.m_typeA == b2Joint.e_revoluteJoint) { + this.m_JvAC.SetZero(); + this.m_JwA = 1; + this.m_JwC = 1; + this.m_mass += this.m_iA + this.m_iC + } else { + var u = b2Mul_r_v2(qC, this.m_localAxisC); + var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); + this.m_JvAC.Assign(u); + this.m_JwC = b2Cross_v2_v2(rC, u); + this.m_JwA = b2Cross_v2_v2(rA, u); + this.m_mass += this.m_mC + this.m_mA + this.m_iC * this.m_JwC * this.m_JwC + this.m_iA * this.m_JwA * this.m_JwA + } + if (this.m_typeB == b2Joint.e_revoluteJoint) { + this.m_JvBD.SetZero(); + this.m_JwB = this.m_ratio; + this.m_JwD = this.m_ratio; + this.m_mass += this.m_ratio * this.m_ratio * (this.m_iB + this.m_iD) + } else { + var u = b2Mul_r_v2(qD, this.m_localAxisD); + var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); + this.m_JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); + this.m_JwD = this.m_ratio * b2Cross_v2_v2(rD, u); + this.m_JwB = this.m_ratio * b2Cross_v2_v2(rB, u); + this.m_mass += this.m_ratio * this.m_ratio * (this.m_mD + this.m_mB) + this.m_iD * this.m_JwD * this.m_JwD + this.m_iB * this.m_JwB * this.m_JwB + } + this.m_mass = this.m_mass > 0 ? 1 / this.m_mass : 0; + if (data.step.warmStarting) { + vA.Add(b2Vec2.Multiply((this.m_mA * this.m_impulse), this.m_JvAC)); + wA += this.m_iA * this.m_impulse * this.m_JwA; + vB.Add(b2Vec2.Multiply((this.m_mB * this.m_impulse), this.m_JvBD)); + wB += this.m_iB * this.m_impulse * this.m_JwB; + vC.Subtract(b2Vec2.Multiply((this.m_mC * this.m_impulse), this.m_JvAC)); + wC -= this.m_iC * this.m_impulse * this.m_JwC; + vD.Subtract(b2Vec2.Multiply((this.m_mD * this.m_impulse), this.m_JvBD)); + wD -= this.m_iD * this.m_impulse * this.m_JwD + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB; + data.velocities[this.m_indexC].v.Assign(vC); + data.velocities[this.m_indexC].w = wC; + data.velocities[this.m_indexD].v.Assign(vD); + data.velocities[this.m_indexD].w = wD + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vC = data.velocities[this.m_indexC].v.Clone(); + var wC = data.velocities[this.m_indexC].w; + var vD = data.velocities[this.m_indexD].v.Clone(); + var wD = data.velocities[this.m_indexD].w; + var Cdot = b2Dot_v2_v2(this.m_JvAC, b2Vec2.Subtract(vA, vC)) + b2Dot_v2_v2(this.m_JvBD, b2Vec2.Subtract(vB, vD)); + Cdot += (this.m_JwA * wA - this.m_JwC * wC) + (this.m_JwB * wB - this.m_JwD * wD); + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + vA.Add(b2Vec2.Multiply((this.m_mA * impulse), this.m_JvAC)); + wA += this.m_iA * impulse * this.m_JwA; + vB.Add(b2Vec2.Multiply((this.m_mB * impulse), this.m_JvBD)); + wB += this.m_iB * impulse * this.m_JwB; + vC.Subtract(b2Vec2.Multiply((this.m_mC * impulse), this.m_JvAC)); + wC -= this.m_iC * impulse * this.m_JwC; + vD.Subtract(b2Vec2.Multiply((this.m_mD * impulse), this.m_JvBD)); + wD -= this.m_iD * impulse * this.m_JwD; + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB; + data.velocities[this.m_indexC].v.Assign(vC); + data.velocities[this.m_indexC].w = wC; + data.velocities[this.m_indexD].v.Assign(vD); + data.velocities[this.m_indexD].w = wD + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var cC = data.positions[this.m_indexC].c.Clone(); + var aC = data.positions[this.m_indexC].a; + var cD = data.positions[this.m_indexD].c.Clone(); + var aD = data.positions[this.m_indexD].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB), + qC = new b2Rot(aC), + qD = new b2Rot(aD); + var linearError = 0; + var coordinateA, coordinateB; + var JvAC = new b2Vec2(), + JvBD = new b2Vec2(); + var JwA, JwB, JwC, JwD; + var mass = 0; + if (this.m_typeA == b2Joint.e_revoluteJoint) { + JvAC.SetZero(); + JwA = 1; + JwC = 1; + mass += this.m_iA + this.m_iC; + coordinateA = aA - aC - this.m_referenceAngleA + } else { + var u = b2Mul_r_v2(qC, this.m_localAxisC); + var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); + JvAC.Assign(u); + JwC = b2Cross_v2_v2(rC, u); + JwA = b2Cross_v2_v2(rA, u); + mass += this.m_mC + this.m_mA + this.m_iC * JwC * JwC + this.m_iA * JwA * JwA; + var pC = b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC); + var pA = b2MulT_r_v2(qC, b2Vec2.Add(rA, b2Vec2.Subtract(cA, cC))); + coordinateA = b2Dot_v2_v2(b2Vec2.Subtract(pA, pC), this.m_localAxisC) + } + if (this.m_typeB == b2Joint.e_revoluteJoint) { + JvBD.SetZero(); + JwB = this.m_ratio; + JwD = this.m_ratio; + mass += this.m_ratio * this.m_ratio * (this.m_iB + this.m_iD); + coordinateB = aB - aD - this.m_referenceAngleB + } else { + var u = b2Mul_r_v2(qD, this.m_localAxisD); + var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); + JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); + JwD = this.m_ratio * b2Cross_v2_v2(rD, u); + JwB = this.m_ratio * b2Cross_v2_v2(rB, u); + mass += this.m_ratio * this.m_ratio * (this.m_mD + this.m_mB) + this.m_iD * JwD * JwD + this.m_iB * JwB * JwB; + var pD = b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD); + var pB = b2MulT_r_v2(qD, b2Vec2.Add(rB, b2Vec2.Subtract(cB, cD))); + coordinateB = b2Dot_v2_v2(b2Vec2.Subtract(pB, pD), this.m_localAxisD) + } + var C = (coordinateA + this.m_ratio * coordinateB) - this.m_constant; + var impulse = 0; + if (mass > 0) { + impulse = -C / mass + } + cA.Add(b2Vec2.Multiply(this.m_mA, b2Vec2.Multiply(impulse, JvAC))); + aA += this.m_iA * impulse * JwA; + cB.Add(b2Vec2.Multiply(this.m_mB, b2Vec2.Multiply(impulse, JvBD))); + aB += this.m_iB * impulse * JwB; + cC.Subtract(b2Vec2.Multiply(this.m_mC, b2Vec2.Multiply(impulse, JvAC))); + aC -= this.m_iC * impulse * JwC; + cD.Subtract(b2Vec2.Multiply(this.m_mD, b2Vec2.Multiply(impulse, JvBD))); + aD -= this.m_iD * impulse * JwD; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + data.positions[this.m_indexC].c.Assign(cC); + data.positions[this.m_indexC].a = aC; + data.positions[this.m_indexD].c.Assign(cD); + data.positions[this.m_indexD].a = aD; + return linearError < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.joint1 = this.m_joint1.__temp_joint_id; + obj.joint2 = this.m_joint2.__temp_joint_id; + obj.ratio = this.m_ratio; + return obj + } + }; + b2GearJoint._extend(b2Joint); + + function b2MotorJointDef() { + this.parent.call(this); + this.type = b2Joint.e_motorJoint; + this.linearOffset = new b2Vec2(); + this.angularOffset = 0; + this.maxForce = 1; + this.maxTorque = 1; + this.correctionFactor = 0.3; + Object.seal(this) + } + b2MotorJointDef.prototype = { + Initialize: function (bA, bB) { + this.bodyA = bA; + this.bodyB = bB; + var xB = this.bodyB.GetPosition(); + this.linearOffset.Assign(this.bodyA.GetLocalPoint(xB)); + var angleA = this.bodyA.GetAngle(); + var angleB = this.bodyB.GetAngle(); + this.angularOffset = angleB - angleA + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.linearOffset._deserialize(data.linearOffset); + this.angularOffset = data.angularOffset; + this.maxForce = data.maxForce; + this.maxTorque = data.maxTorque; + this.correctionFactor = data.correctionFactor + } + }; + b2MotorJointDef._extend(b2JointDef); + + function b2MotorJoint(def) { + this.parent.call(this, def); + this.m_linearOffset = def.linearOffset.Clone(); + this.m_angularOffset = def.angularOffset; + this.m_linearImpulse = new b2Vec2(); + this.m_angularImpulse = 0; + this.m_maxForce = def.maxForce; + this.m_maxTorque = def.maxTorque; + this.m_correctionFactor = def.correctionFactor; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_linearError = new b2Vec2(); + this.m_angularError = 0; + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_linearMass = new b2Mat22(); + this.m_angularMass = 0 + } + b2MotorJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetPosition() + }, + GetAnchorB: function () { + return this.m_bodyB.GetPosition() + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_angularImpulse + }, + SetLinearOffset: function (linearOffset) { + if (linearOffset.x != this.m_linearOffset.x || linearOffset.y != this.m_linearOffset.y) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_linearOffset.Assign(linearOffset) + } + }, + GetLinearOffset: function () { + return this.m_linearOffset + }, + SetAngularOffset: function (angularOffset) { + if (angularOffset != this.m_angularOffset) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_angularOffset = angularOffset + } + }, + GetAngularOffset: function () { + return this.m_angularOffset + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetMaxTorque: function (torque) { + this.m_maxTorque = torque + }, + GetMaxTorque: function () { + return this.m_maxTorque + }, + SetCorrectionFactor: function (factor) { + this.m_correctionFactor = factor + }, + GetCorrectionFactor: function () { + return this.m_correctionFactor + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, this.m_localCenterA.Negate())); + this.m_rB.Assign(b2Mul_r_v2(qB, this.m_localCenterB.Negate())); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + K.ex.x = mA + mB + iA * this.m_rA.y * this.m_rA.y + iB * this.m_rB.y * this.m_rB.y; + K.ex.y = -iA * this.m_rA.x * this.m_rA.y - iB * this.m_rB.x * this.m_rB.y; + K.ey.x = K.ex.y; + K.ey.y = mA + mB + iA * this.m_rA.x * this.m_rA.x + iB * this.m_rB.x * this.m_rB.x; + this.m_linearMass.Assign(K.GetInverse()); + this.m_angularMass = iA + iB; + if (this.m_angularMass > 0) { + this.m_angularMass = 1 / this.m_angularMass + } + this.m_linearError.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA), b2Mul_r_v2(qA, this.m_linearOffset))); + this.m_angularError = aB - aA - this.m_angularOffset; + if (data.step.warmStarting) { + this.m_linearImpulse.Multiply(data.step.dtRatio); + this.m_angularImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) + } else { + this.m_linearImpulse.SetZero(); + this.m_angularImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var h = data.step.dt; + var inv_h = data.step.inv_dt; + var Cdot = wB - wA + inv_h * this.m_correctionFactor * this.m_angularError; + var impulse = -this.m_angularMass * Cdot; + var oldImpulse = this.m_angularImpulse; + var maxImpulse = h * this.m_maxTorque; + this.m_angularImpulse = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_angularImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Vec2.Add(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)), b2Vec2.Multiply(inv_h, b2Vec2.Multiply(this.m_correctionFactor, this.m_linearError))); + var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); + var oldImpulse = this.m_linearImpulse; + this.m_linearImpulse.Add(impulse); + var maxImpulse = h * this.m_maxForce; + if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_linearImpulse.Normalize(); + this.m_linearImpulse.Multiply(maxImpulse) + } + impulse.Assign(b2Vec2.Subtract(this.m_linearImpulse, oldImpulse)); + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.linearOffset = this.m_linearOffset._serialize(); + obj.angularOffset = this.m_angularOffset; + obj.maxForce = this.m_maxForce; + obj.maxTorque = this.m_maxTorque; + obj.correctionFactor = this.m_correctionFactor; + return obj + } + }; + b2MotorJoint._extend(b2Joint); + var b2_minPulleyLength = 2; + + function b2PulleyJointDef() { + this.parent.call(this); + this.type = b2Joint.e_pulleyJoint; + this.groundAnchorA = new b2Vec2(-1, 1); + this.groundAnchorB = new b2Vec2(1, 1); + this.localAnchorA = new b2Vec2(-1, 0); + this.localAnchorB = new b2Vec2(1, 0); + this.lengthA = 0; + this.lengthB = 0; + this.ratio = 1; + this.collideConnected = true; + Object.seal(this) + } + b2PulleyJointDef.prototype = { + Initialize: function (bA, bB, groundA, groundB, anchorA, anchorB, r) { + this.bodyA = bA; + this.bodyB = bB; + this.groundAnchorA.Assign(groundA); + this.groundAnchorB.Assign(groundB); + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchorA)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchorB)); + var dA = b2Vec2.Subtract(anchorA, groundA); + this.lengthA = dA.Length(); + var dB = b2Vec2.Subtract(anchorB, groundB); + this.lengthB = dB.Length(); + this.ratio = r + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.groundAnchorA._deserialize(data.groundAnchorA); + this.groundAnchorB._deserialize(data.groundAnchorB); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.lengthA = data.lengthA; + this.lengthB = data.lengthB; + this.ratio = data.ratio + } + }; + b2PulleyJointDef._extend(b2JointDef); + + function b2PulleyJoint(def) { + this.parent.call(this, def); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_uA = new b2Vec2(); + this.m_uB = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = 0; + this.m_groundAnchorA = def.groundAnchorA.Clone(); + this.m_groundAnchorB = def.groundAnchorB.Clone(); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_lengthA = def.lengthA; + this.m_lengthB = def.lengthB; + this.m_ratio = def.ratio; + this.m_constant = def.lengthA + this.m_ratio * def.lengthB; + this.m_impulse = 0 + } + b2PulleyJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = b2Vec2.Multiply(this.m_impulse, this.m_uB); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetGroundAnchorA: function () { + return this.m_groundAnchorA + }, + GetGroundAnchorB: function () { + return this.m_groundAnchorB + }, + GetLengthA: function () { + return this.m_lengthA + }, + GetLengthB: function () { + return this.m_lengthB + }, + GetRatio: function () { + return this.m_ratio + }, + GetCurrentLengthA: function () { + var p = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); + var s = this.m_groundAnchorA; + var d = b2Vec2.Subtract(p, s); + return d.Length() + }, + GetCurrentLengthB: function () { + var p = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); + var s = this.m_groundAnchorB; + var d = b2Vec2.Subtract(p, s); + return d.Length() + }, + ShiftOrigin: function (newOrigin) { + this.m_groundAnchorA.Subtract(newOrigin); + this.m_groundAnchorB.Subtract(newOrigin) + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + this.m_uA.Assign(b2Vec2.Add(cA, b2Vec2.Subtract(this.m_rA, this.m_groundAnchorA))); + this.m_uB.Assign(b2Vec2.Add(cB, b2Vec2.Subtract(this.m_rB, this.m_groundAnchorB))); + var lengthA = this.m_uA.Length(); + var lengthB = this.m_uB.Length(); + if (lengthA > 10 * b2_linearSlop) { + this.m_uA.Multiply(1 / lengthA) + } else { + this.m_uA.SetZero() + } + if (lengthB > 10 * b2_linearSlop) { + this.m_uB.Multiply(1 / lengthB) + } else { + this.m_uB.SetZero() + } + var ruA = b2Cross_v2_v2(this.m_rA, this.m_uA); + var ruB = b2Cross_v2_v2(this.m_rB, this.m_uB); + var mA = this.m_invMassA + this.m_invIA * ruA * ruA; + var mB = this.m_invMassB + this.m_invIB * ruB * ruB; + this.m_mass = mA + this.m_ratio * this.m_ratio * mB; + if (this.m_mass > 0) { + this.m_mass = 1 / this.m_mass + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var PA = b2Vec2.Multiply(-(this.m_impulse), this.m_uA); + var PB = b2Vec2.Multiply((-this.m_ratio * this.m_impulse), this.m_uB); + vA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + wA += this.m_invIA * b2Cross_v2_v2(this.m_rA, PA); + vB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB) + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var Cdot = -b2Dot_v2_v2(this.m_uA, vpA) - this.m_ratio * b2Dot_v2_v2(this.m_uB, vpB); + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + var PA = b2Vec2.Multiply(-impulse, this.m_uA); + var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, this.m_uB)); + vA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + wA += this.m_invIA * b2Cross_v2_v2(this.m_rA, PA); + vB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var uA = b2Vec2.Add(cA, b2Vec2.Subtract(rA, this.m_groundAnchorA)); + var uB = b2Vec2.Add(cB, b2Vec2.Subtract(rB, this.m_groundAnchorB)); + var lengthA = uA.Length(); + var lengthB = uB.Length(); + if (lengthA > 10 * b2_linearSlop) { + uA.Multiply(1 / lengthA) + } else { + uA.SetZero() + } + if (lengthB > 10 * b2_linearSlop) { + uB.Multiply(1 / lengthB) + } else { + uB.SetZero() + } + var ruA = b2Cross_v2_v2(rA, uA); + var ruB = b2Cross_v2_v2(rB, uB); + var mA = this.m_invMassA + this.m_invIA * ruA * ruA; + var mB = this.m_invMassB + this.m_invIB * ruB * ruB; + var mass = mA + this.m_ratio * this.m_ratio * mB; + if (mass > 0) { + mass = 1 / mass + } + var C = this.m_constant - lengthA - this.m_ratio * lengthB; + var linearError = b2Abs(C); + var impulse = -mass * C; + var PA = b2Vec2.Multiply(-impulse, uA); + var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, uB)); + cA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + aA += this.m_invIA * b2Cross_v2_v2(rA, PA); + cB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + aB += this.m_invIB * b2Cross_v2_v2(rB, PB); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return linearError < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.groundAnchorA = this.m_groundAnchorA._serialize(); + obj.groundAnchorB = this.m_groundAnchorB._serialize(); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.lengthA = this.m_lengthA; + obj.lengthB = this.m_lengthB; + obj.ratio = this.m_ratio; + return obj + } + }; + b2PulleyJoint._extend(b2Joint); + + function b2RopeJointDef() { + this.parent.call(this); + this.type = b2Joint.e_ropeJoint; + this.localAnchorA = new b2Vec2(-1, 0); + this.localAnchorB = new b2Vec2(1, 0); + this.maxLength = 0; + Object.seal(this) + } + b2RopeJointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.maxLength = data.maxLength + } + }; + b2RopeJointDef._extend(b2JointDef); + + function b2RopeJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_maxLength = def.maxLength; + this.m_mass = 0; + this.m_impulse = 0; + this.m_state = b2Joint.e_inactiveLimit; + this.m_length = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_u = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0 + } + b2RopeJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); + return F + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetMaxLength: function (length) { + this.m_maxLength = length + }, + GetMaxLength: function () { + return this.m_maxLength + }, + GetLimitState: function () { + return this.m_state + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassA = this.m_bodyA.m_invMass; + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIA = this.m_bodyA.m_invI; + this.m_invIB = this.m_bodyB.m_invI; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + this.m_u.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA)); + this.m_length = this.m_u.Length(); + var C = this.m_length - this.m_maxLength; + if (C > 0) { + this.m_state = b2Joint.e_atUpperLimit + } else { + this.m_state = b2Joint.e_inactiveLimit + } + if (this.m_length > b2_linearSlop) { + this.m_u.Multiply(1 / this.m_length) + } else { + this.m_u.SetZero(); + this.m_mass = 0; + this.m_impulse = 0; + return + } + var crA = b2Cross_v2_v2(this.m_rA, this.m_u); + var crB = b2Cross_v2_v2(this.m_rB, this.m_u); + var invMass = this.m_invMassA + this.m_invIA * crA * crA + this.m_invMassB + this.m_invIB * crB * crB; + this.m_mass = invMass != 0 ? 1 / invMass : 0; + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var P = b2Vec2.Multiply(this.m_impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var C = this.m_length - this.m_maxLength; + var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); + if (C < 0) { + Cdot += data.step.inv_dt * C + } + var impulse = -this.m_mass * Cdot; + var oldImpulse = this.m_impulse; + this.m_impulse = b2Min(0, this.m_impulse + impulse); + impulse = this.m_impulse - oldImpulse; + var P = b2Vec2.Multiply(impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var length = u.Normalize(); + var C = length - this.m_maxLength; + C = b2Clamp(C, 0, b2_maxLinearCorrection); + var impulse = -this.m_mass * C; + var P = b2Vec2.Multiply(impulse, u); + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * b2Cross_v2_v2(rB, P); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return length - this.m_maxLength < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.maxLength = this.m_maxLength; + return obj + } + }; + b2RopeJoint._extend(b2Joint); + var expf = Math.exp; + + function b2RopeDef() { + this.vertices = null; + this.count = 0; + this.masses = null; + this.gravity = new b2Vec2(); + this.damping = 0.1; + this.k2 = 0.9; + this.k3 = 0.1 + } + + function b2Rope() { + this.m_count = 0; + this.m_ps = null; + this.m_p0s = null; + this.m_vs = null; + this.m_ims = null; + this.m_Ls = null; + this.m_as = null; + this.m_damping = 0; + this.m_gravity = new b2Vec2(); + this.m_k2 = 1; + this.m_k3 = 0.1 + } + b2Rope.prototype = { + Initialize: function (def) { + this.m_count = def.count; + this.m_ps = new Array(this.m_count); + this.m_p0s = new Array(this.m_count); + this.m_vs = new Array(this.m_count); + this.m_ims = new Array(this.m_count); + for (var i = 0; i < this.m_count; ++i) { + this.m_ps[i] = def.vertices[i].Clone(); + this.m_p0s[i] = def.vertices[i].Clone(); + this.m_vs[i] = new b2Vec2(); + var m = def.masses[i]; + if (m > 0) { + this.m_ims[i] = 1 / m + } else { + this.m_ims[i] = 0 + } + } + var count2 = this.m_count - 1; + var count3 = this.m_count - 2; + this.m_Ls = new Array(count2); + this.m_as = new Array(count3); + for (var i = 0; i < count2; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + this.m_Ls[i] = b2Distance(p1, p2) + } + for (var i = 0; i < count3; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var p3 = this.m_ps[i + 2]; + var d1 = b2Vec2.Subtract(p2, p1); + var d2 = b2Vec2.Subtract(p3, p2); + var a = b2Cross_v2_v2(d1, d2); + var b = b2Dot_v2_v2(d1, d2); + this.m_as[i] = b2Atan2(a, b) + } + this.m_gravity = def.gravity.Clone(); + this.m_damping = def.damping; + this.m_k2 = def.k2; + this.m_k3 = def.k3 + }, + Step: function (h, iterations) { + if (h == 0) { + return + } + var d = expf(-h * this.m_damping); + for (var i = 0; i < this.m_count; ++i) { + this.m_p0s[i].Assign(this.m_ps[i]); + if (this.m_ims[i] > 0) { + this.m_vs[i].Add(b2Vec2.Multiply(h, this.m_gravity)) + } + this.m_vs[i].Multiply(d); + this.m_ps[i].Add(b2Vec2.Multiply(h, this.m_vs[i])) + } + for (var i = 0; i < iterations; ++i) { + this.SolveC2(); + this.SolveC3(); + this.SolveC2() + } + var inv_h = 1 / h; + for (var i = 0; i < this.m_count; ++i) { + this.m_vs[i] = b2Vec2.Multiply(inv_h, b2Vec2.Subtract(this.m_ps[i], this.m_p0s[i])) + } + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertices: function () { + return this.m_ps + }, + Draw: function (draw) { + var c = new b2Color(0.4, 0.5, 0.7); + for (var i = 0; i < this.m_count - 1; ++i) { + draw.DrawSegment(this.m_ps[i], this.m_ps[i + 1], c) + } + }, + SetAngle: function (angle) { + var count3 = this.m_count - 2; + for (var i = 0; i < count3; ++i) { + this.m_as[i] = angle + } + }, + SolveC2: function () { + var count2 = this.m_count - 1; + for (var i = 0; i < count2; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var d = b2Vec2.Subtract(p2, p1); + var L = d.Normalize(); + var im1 = this.m_ims[i]; + var im2 = this.m_ims[i + 1]; + if (im1 + im2 == 0) { + continue + } + var s1 = im1 / (im1 + im2); + var s2 = im2 / (im1 + im2); + p1.Subtract(b2Vec2.Multiply(this.m_k2 * s1 * (this.m_Ls[i] - L), d)); + p2.Add(b2Vec2.Multiply(this.m_k2 * s2 * (this.m_Ls[i] - L), d)) + } + }, + SolveC3: function () { + var count3 = this.m_count - 2; + for (var i = 0; i < count3; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var p3 = this.m_ps[i + 2]; + var m1 = this.m_ims[i]; + var m2 = this.m_ims[i + 1]; + var m3 = this.m_ims[i + 2]; + var d1 = b2Vec2.Subtract(p2, p1); + var d2 = b2Vec2.Subtract(p3, p2); + var L1sqr = d1.LengthSquared(); + var L2sqr = d2.LengthSquared(); + if (L1sqr * L2sqr == 0) { + continue + } + var a = b2Cross_v2_v2(d1, d2); + var b = b2Dot_v2_v2(d1, d2); + var angle = b2Atan2(a, b); + var Jd1 = b2Vec2.Multiply((-1 / L1sqr), d1.Skew()); + var Jd2 = b2Vec2.Multiply((1 / L2sqr), d2.Skew()); + var J1 = b2Vec2.Negate(Jd1); + var J2 = b2Vec2.Subtract(Jd1, Jd2); + var J3 = Jd2; + var mass = m1 * b2Dot_v2_v2(J1, J1) + m2 * b2Dot_v2_v2(J2, J2) + m3 * b2Dot_v2_v2(J3, J3); + if (mass == 0) { + continue + } + mass = 1 / mass; + var C = angle - this.m_as[i]; + while (C > b2_pi) { + angle -= 2 * b2_pi; + C = angle - this.m_as[i] + } + while (C < -b2_pi) { + angle += 2 * b2_pi; + C = angle - this.m_as[i] + } + var impulse = -this.m_k3 * mass * C; + p1.Add(b2Vec2.Multiply((m1 * impulse), J1)); + p2.Add(b2Vec2.Multiply((m2 * impulse), J2)); + p3.Add(b2Vec2.Multiply((m3 * impulse), J3)) + } + } + }; + var b2JsonSerializer = { + serialize: function (world) { + var shapes = []; + var i; + var serialized; + var b; + var f; + var shape; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + for (f = b.GetFixtureList(); f; f = f.GetNext()) { + shape = f.GetShape(); + f.__temp_shape_id = shapes.length; + shapes.push(shape._serialize()) + } + } + var fixtures = []; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + b.__temp_fixture_ids = []; + for (f = b.GetFixtureList(); f; f = f.GetNext()) { + serialized = f._serialize(); + serialized.shape = f.__temp_shape_id; + delete f.__temp_shape_id; + b.__temp_fixture_ids.push(fixtures.length); + fixtures.push(serialized) + } + } + var bodies = []; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + serialized = b._serialize(); + serialized.fixtures = []; + for (i = 0; i < b.__temp_fixture_ids.length; ++i) { + serialized.fixtures.push(b.__temp_fixture_ids[i]) + } + delete b.__temp_fixture_ids; + b.__temp_body_id = bodies.length; + bodies.push(serialized) + } + var joints = []; + var j; + for (j = world.GetJointList(), i = 0; j; j = j.GetNext(), ++i) { + j.__temp_joint_id = i + } + for (j = world.GetJointList(); j; j = j.GetNext()) { + if (j.GetType() === b2Joint.e_mouseJoint) { + continue + } + serialized = j._serialize(); + serialized.bodyA = j.GetBodyA().__temp_body_id; + serialized.bodyB = j.GetBodyB().__temp_body_id; + joints.push(serialized) + } + for (j = world.GetJointList(); j; j = j.GetNext()) { + delete j.__temp_joint_id + } + for (b = world.GetBodyList(); b; b = b.GetNext()) { + delete b.__temp_body_id + } + return { + shapes: shapes, + fixtures: fixtures, + bodies: bodies, + joints: joints + } + }, + deserialize: function (serialized, world, clear) { + var deserialized = JSON.parse(serialized); + if (clear) { + for (var b = world.GetBodyList(); b;) { + var next = b.GetNext(); + world.DestroyBody(b); + b = next + } + for (var j = world.GetJointList(); j;) { + var next = j.GetNext(); + world.DestroyJoint(j); + j = next + } + } + var shapes = []; + for (var i = 0; i < deserialized.shapes.length; ++i) { + var shapeData = deserialized.shapes[i]; + var shape; + switch (shapeData.m_type) { + case b2Shape.e_circle: + shape = new b2CircleShape(); + break; + case b2Shape.e_edge: + shape = new b2EdgeShape(); + break; + case b2Shape.e_chain: + shape = new b2ChainShape(); + break; + case b2Shape.e_polygon: + shape = new b2PolygonShape(); + break + } + shape._deserialize(shapeData); + shapes.push(shape) + } + var fixtures = []; + for (i = 0; i < deserialized.fixtures.length; ++i) { + var fixtureData = deserialized.fixtures[i]; + var fixture = new b2FixtureDef(); + fixture._deserialize(fixtureData); + fixture.shape = shapes[fixtureData.shape]; + fixtures.push(fixture) + } + var bodies = []; + for (i = 0; i < deserialized.bodies.length; ++i) { + var bodyData = deserialized.bodies[i]; + var def = new b2BodyDef(); + def._deserialize(bodyData); + var body = world.CreateBody(def); + for (var x = 0; x < bodyData.fixtures.length; ++x) { + body.CreateFixture(fixtures[bodyData.fixtures[x]]) + } + bodies.push(body) + } + var joints = []; + var gears = []; + for (i = 0; i < deserialized.joints.length; ++i) { + var jointData = deserialized.joints[i]; + var jointDef; + switch (jointData.type) { + case b2Joint.e_revoluteJoint: + jointDef = new b2RevoluteJointDef(); + break; + case b2Joint.e_prismaticJoint: + jointDef = new b2PrismaticJointDef(); + break; + case b2Joint.e_distanceJoint: + jointDef = new b2DistanceJointDef(); + break; + case b2Joint.e_pulleyJoint: + jointDef = new b2PulleyJointDef(); + break; + case b2Joint.e_gearJoint: + jointDef = new b2GearJointDef(); + break; + case b2Joint.e_wheelJoint: + jointDef = new b2WheelJointDef(); + break; + case b2Joint.e_weldJoint: + jointDef = new b2WeldJointDef(); + break; + case b2Joint.e_frictionJoint: + jointDef = new b2FrictionJointDef(); + break; + case b2Joint.e_ropeJoint: + jointDef = new b2RopeJointDef(); + break; + case b2Joint.e_motorJoint: + jointDef = new b2MotorJointDef(); + break; + default: + throw new Error("unknown joint") + } + jointDef._deserialize(jointData, bodies); + if (jointData.type === b2Joint.e_gearJoint) { + gears.push([jointDef, joints.length]); + joints.push(null) + } else { + var joint = world.CreateJoint(jointDef); + joints.push(joint) + } + } + for (i = 0; i < gears.length; ++i) { + gears[i][0].joint1 = joints[gears[i][0].joint1]; + gears[i][0].joint2 = joints[gears[i][0].joint2]; + joint = world.CreateJoint(gears[i][0]); + joints[gears[i][1]] = joint + } + } + }; + var b2RUBELoader = (function () { + function parseVector(obj) { + return new b2Vec2(obj ? (obj.x || 0) : 0, obj ? (obj.y || 0) : 0) + } + + function parseVectorArray(obj) { + var vals = new Array(obj.x.length); + for (var i = 0; i < vals.length; ++i) { + vals[i] = new b2Vec2(obj.x[i], obj.y[i]) + } + return vals + } + + function parseProperty(obj, instance) { + var name = obj.name; + var val; + if (typeof (obj["int"]) !== "undefined") { + val = obj["int"] + } else { + if (typeof (obj["float"]) !== "undefined") { + val = obj["float"] + } else { + if (typeof (obj.string) !== "undefined") { + val = obj.string + } else { + if (typeof (obj.bool) !== "undefined") { + val = obj.bool + } else { + if (typeof (obj.vec2) !== "undefined") { + val = parseVector(obj.vec2) + } else { + throw new Error("unknown property type") + } + } + } + } + } + if (instance.hasOwnProperty(name)) { + throw new Error("custom property possibly overwriting an existing one") + } + instance[name] = val + } + + function parseFixture(obj, body) { + var def = new b2FixtureDef(); + def.density = obj.density || 0; + def.filter.categoryBits = typeof (obj["filter-categoryBits"]) === "undefined" ? 1 : obj["filter-categoryBits"]; + def.filter.maskBits = typeof (obj["filter-maskBits"]) === "undefined" ? 65535 : obj["filter-maskBits"]; + def.filter.groupIndex = typeof (obj["filter-groupIndex"]) === "undefined" ? 0 : obj["filter-groupIndex"]; + def.friction = obj.friction || 0; + def.restitution = obj.restitution || 0; + def.isSensor = obj.sensor || 0; + var shape; + if (typeof (obj.circle) !== "undefined") { + shape = new b2CircleShape(); + shape.m_p = parseVector(obj.circle.center); + shape.m_radius = obj.circle.radius || 0 + } else { + if (typeof (obj.polygon) !== "undefined") { + var vertices = parseVectorArray(obj.polygon.vertices); + shape = new b2PolygonShape(); + shape.Set(vertices, vertices.length) + } else { + if (typeof (obj.chain) !== "undefined") { + var vertices = parseVectorArray(obj.chain.vertices); + shape = new b2ChainShape(); + shape.m_count = vertices.length; + shape.m_vertices = vertices; + if (shape.m_hasNextVertex = obj.chain.hasNextVertex) { + shape.m_nextVertex = parseVector(obj.chain.nextVertex) + } + if (shape.m_hasPrevVertex = obj.chain.hasPrevVertex) { + shape.m_prevVertex = parseVector(obj.chain.prevVertex) + } + } else { + throw new Error("unknown shape type") + } + } + } + def.shape = shape; + var fixture = body.CreateFixture(def); + fixture.name = obj.name; + if (obj.customProperties) { + for (var i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, fixture) + } + } + } + + function parseBody(obj, world) { + var def = new b2BodyDef(); + def.type = obj.type || b2Body.b2_staticBody; + def.angle = obj.angle || 0; + def.angularDamping = obj.angularDamping || 0; + def.angularVelocity = obj.angularVelocity || 0; + def.awake = obj.awake || false; + def.bullet = obj.bullet || false; + def.fixedRotation = obj.fixedRotation || false; + def.linearDamping = obj.linearDamping || false; + def.linearVelocity = parseVector(obj.linearVelocity); + def.gravityScale = typeof (obj.gravityScale) !== "undefined" ? obj.gravityScale : 1; + var md = new b2MassData(); + md.mass = obj["massData-mass"] || 0; + md.center = parseVector(obj["massData-center"]); + md.I = obj["massData-I"] || 0; + def.position = parseVector(obj.position); + var body = world.CreateBody(def); + body.name = obj.name; + body.SetMassData(md); + if (obj.fixture) { + for (var i = 0; i < obj.fixture.length; ++i) { + parseFixture(obj.fixture[i], body) + } + } + if (obj.customProperties) { + for (i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, body) + } + } + return body + } + var jointsList = { + revolute: b2RevoluteJointDef, + distance: b2DistanceJointDef, + prismatic: b2PrismaticJointDef, + wheel: b2WheelJointDef, + rope: b2RopeJointDef, + motor: b2MotorJointDef, + weld: b2WeldJointDef, + friction: b2FrictionJointDef + }; + + function parseJoint(obj, world, bodies) { + if (!jointsList[obj.type]) { + throw new Error("unknown joint type") + } + var jd = new jointsList[obj.type](); + switch (jd.type) { + case b2Joint.e_revoluteJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableLimit = obj.enableLimit || false; + jd.enableMotor = obj.enableMotor || false; + jd.lowerAngle = obj.lowerLimit || 0; + jd.maxMotorTorque = obj.maxMotorTorque || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.referenceAngle = obj.refAngle || 0; + jd.upperAngle = obj.upperLimit || 0; + break; + case b2Joint.e_distanceJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.dampingRatio = obj.dampingRatio || 0; + jd.frequencyHz = obj.frequency || 0; + jd.length = obj.length || 0; + break; + case b2Joint.e_prismaticJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableLimit = obj.enableLimit || false; + jd.enableMotor = obj.enableMotor || false; + jd.localAxisA = parseVector(obj.localAxisA); + jd.lowerTranslation = obj.lowerLimit || 0; + jd.maxMotorForce = obj.maxMotorForce || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.referenceAngle = obj.refAngle || 0; + jd.upperTranslation = obj.upperLimit || 0; + break; + case b2Joint.e_wheelJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableMotor = obj.enableMotor || false; + jd.localAxisA = parseVector(obj.localAxisA); + jd.maxMotorTorque = obj.maxMotorTorque || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.dampingRatio = obj.springDampingRatio || 0; + jd.frequencyHz = obj.springFrequency || 0; + break; + case b2Joint.e_ropeJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.maxLength = obj.maxLength || 0; + break; + case b2Joint.e_motorJoint: + jd.linearOffset = parseVector(obj.anchorA); + jd.angularOffset = obj.refAngle || 0; + jd.maxForce = obj.maxForce || 0; + jd.maxTorque = obj.maxTorque || 0; + jd.correctionFactor = obj.correctionFactor || 0; + break; + case b2Joint.e_weldJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.referenceAngle = obj.refAngle || 0; + jd.dampingRatio = obj.dampingRatio || 0; + jd.frequencyHz = obj.frequencyHz || 0; + break; + case b2Joint.e_frictionJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.maxForce = obj.maxForce || 0; + jd.maxTorque = obj.maxTorque || 0; + break; + default: + throw new Error("wat?") + } + jd.bodyA = bodies[obj.bodyA || 0]; + jd.bodyB = bodies[obj.bodyB || 0]; + jd.collideConnected = obj.collideConnected || false; + var joint = world.CreateJoint(jd); + joint.name = obj.name; + if (obj.customProperties) { + for (var i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, joint) + } + } + return joint + } + + function b2RubeParameters() { + this.world = null; + this.positionIterations = 0; + this.velocityIterations = 0; + this.stepsPerSecond = 0; + this.fixtures = {}; + this.bodies = {}; + this.joints = {}; + Object.seal(this) + } + + function parseWorld(obj, world) { + var params = new b2RubeParameters(); + params.world = world = world || new b2World(new b2Vec2(0, 0)); + params.positionIterations = obj.positionIterations || 0; + params.velocityIterations = obj.velocityIterations || 0; + params.stepsPerSecond = obj.stepsPerSecond || 0; + if (obj.gravity) { + world.SetGravity(parseVector(obj.gravity)) + } + world.SetAllowSleeping(obj.allowSleep || false); + world.SetAutoClearForces(obj.autoClearForces || false); + world.SetWarmStarting(obj.warmStarting || false); + world.SetContinuousPhysics(obj.continuousPhysics || false); + world.SetSubStepping(obj.subStepping || false); + var bodies = []; + var bl = obj.body; + if (bl) { + for (var i = 0; i < bl.length; ++i) { + var body = parseBody(bl[i], world); + bodies.push(body); + for (var f = body.GetFixtureList(); f; f = f.GetNext()) { + if (!params.fixtures[f.name]) { + params.fixtures[f.name] = [] + } + params.fixtures[f.name].push(f) + } + if (!params.bodies[body.name]) { + params.bodies[body.name] = [] + } + params.bodies[body.name].push(body) + } + } + var joints = []; + var jl = obj.joint; + if (jl) { + for (i = 0; i < jl.length; ++i) { + var joint = parseJoint(jl[i], world, bodies); + joints.push(joint); + if (!params.joints[joint.name]) { + params.joints[joint.name] = [] + } + params.joints[joint.name].push(joint) + } + } + return params + } + return { + parseWorld: parseWorld + } + })(); + var mappings = [{ + trimmed: "version", + name: "b2_version", + def: b2_version + }, { + trimmed: "Vec2", + name: "b2Vec2", + def: b2Vec2 + }, { + trimmed: "Vec3", + name: "b2Vec3", + def: b2Vec3 + }, { + trimmed: "Mat22", + name: "b2Mat22", + def: b2Mat22 + }, { + trimmed: "Mat33", + name: "b2Mat33", + def: b2Mat33 + }, { + trimmed: "Rot", + name: "b2Rot", + def: b2Rot + }, { + trimmed: "Transform", + name: "b2Transform", + def: b2Transform + }, { + trimmed: "Sweep", + name: "b2Sweep", + def: b2Sweep + }, { + trimmed: "Dot_v2_v2", + name: "b2Dot_v2_v2", + def: b2Dot_v2_v2 + }, { + trimmed: "Cross_v2_v2", + name: "b2Cross_v2_v2", + def: b2Cross_v2_v2 + }, { + trimmed: "Cross_v2_f", + name: "b2Cross_v2_f", + def: b2Cross_v2_f + }, { + trimmed: "Cross_f_v2", + name: "b2Cross_f_v2", + def: b2Cross_f_v2 + }, { + trimmed: "Mul_m22_v2", + name: "b2Mul_m22_v2", + def: b2Mul_m22_v2 + }, { + trimmed: "MulT_m22_v2", + name: "b2MulT_m22_v2", + def: b2MulT_m22_v2 + }, { + trimmed: "Distance", + name: "b2Distance", + def: b2Distance + }, { + trimmed: "DistanceSquared", + name: "b2DistanceSquared", + def: b2DistanceSquared + }, { + trimmed: "Dot_v3_v3", + name: "b2Dot_v3_v3", + def: b2Dot_v3_v3 + }, { + trimmed: "Cross_v3_v3", + name: "b2Cross_v3_v3", + def: b2Cross_v3_v3 + }, { + trimmed: "Mul_m22_m22", + name: "b2Mul_m22_m22", + def: b2Mul_m22_m22 + }, { + trimmed: "MulT_m22_m22", + name: "b2MulT_m22_m22", + def: b2MulT_m22_m22 + }, { + trimmed: "Mul_m33_v3", + name: "b2Mul_m33_v3", + def: b2Mul_m33_v3 + }, { + trimmed: "Mul22_m33_v2", + name: "b2Mul22_m33_v2", + def: b2Mul22_m33_v2 + }, { + trimmed: "Mul_r_r", + name: "b2Mul_r_r", + def: b2Mul_r_r + }, { + trimmed: "MulT_r_r", + name: "b2MulT_r_r", + def: b2MulT_r_r + }, { + trimmed: "Mul_r_v2", + name: "b2Mul_r_v2", + def: b2Mul_r_v2 + }, { + trimmed: "MulT_r_v2", + name: "b2MulT_r_v2", + def: b2MulT_r_v2 + }, { + trimmed: "Mul_t_v2", + name: "b2Mul_t_v2", + def: b2Mul_t_v2 + }, { + trimmed: "Min_v2", + name: "b2Min_v2", + def: b2Min_v2 + }, { + trimmed: "Max_v2", + name: "b2Max_v2", + def: b2Max_v2 + }, { + trimmed: "Clamp", + name: "b2Clamp", + def: b2Clamp + }, { + trimmed: "MulT_t_v2", + name: "b2MulT_t_v2", + def: b2MulT_t_v2 + }, { + trimmed: "Mul_t_t", + name: "b2Mul_t_t", + def: b2Mul_t_t + }, { + trimmed: "MulT_t_t", + name: "b2MulT_t_t", + def: b2MulT_t_t + }, { + trimmed: "Clamp_v2", + name: "b2Clamp_v2", + def: b2Clamp_v2 + }, { + trimmed: "NextPowerOfTwo", + name: "b2NextPowerOfTwo", + def: b2NextPowerOfTwo + }, { + trimmed: "Abs_v2", + name: "b2Abs_v2", + def: b2Abs_v2 + }, { + trimmed: "Abs_m22", + name: "b2Abs_m22", + def: b2Abs_m22 + }, { + trimmed: "IsPowerOfTwo", + name: "b2IsPowerOfTwo", + def: b2IsPowerOfTwo + }, { + trimmed: "RandomFloat", + name: "b2RandomFloat", + def: b2RandomFloat + }, { + trimmed: "Timer", + name: "b2Timer", + def: b2Timer + }, { + trimmed: "Color", + name: "b2Color", + def: b2Color + }, { + trimmed: "Draw", + name: "b2Draw", + def: b2Draw + }, { + trimmed: "ContactID", + name: "b2ContactID", + def: b2ContactID + }, { + trimmed: "ManifoldPoint", + name: "b2ManifoldPoint", + def: b2ManifoldPoint + }, { + trimmed: "Manifold", + name: "b2Manifold", + def: b2Manifold + }, { + trimmed: "WorldManifold", + name: "b2WorldManifold", + def: b2WorldManifold + }, { + trimmed: "GetPointStates", + name: "b2GetPointStates", + def: b2GetPointStates + }, { + trimmed: "ClipVertex", + name: "b2ClipVertex", + def: b2ClipVertex + }, { + trimmed: "RayCastInput", + name: "b2RayCastInput", + def: b2RayCastInput + }, { + trimmed: "RayCastOutput", + name: "b2RayCastOutput", + def: b2RayCastOutput + }, { + trimmed: "AABB", + name: "b2AABB", + def: b2AABB + }, { + trimmed: "CollideCircles", + name: "b2CollideCircles", + def: b2CollideCircles + }, { + trimmed: "CollidePolygonAndCircle", + name: "b2CollidePolygonAndCircle", + def: b2CollidePolygonAndCircle + }, { + trimmed: "FindMaxSeparation", + name: "b2FindMaxSeparation", + def: b2FindMaxSeparation + }, { + trimmed: "FindIncidentEdge", + name: "b2FindIncidentEdge", + def: b2FindIncidentEdge + }, { + trimmed: "CollidePolygons", + name: "b2CollidePolygons", + def: b2CollidePolygons + }, { + trimmed: "CollideEdgeAndCircle", + name: "b2CollideEdgeAndCircle", + def: b2CollideEdgeAndCircle + }, { + trimmed: "EPAxis", + name: "b2EPAxis", + def: b2EPAxis + }, { + trimmed: "TempPolygon", + name: "b2TempPolygon", + def: b2TempPolygon + }, { + trimmed: "ReferenceFace", + name: "b2ReferenceFace", + def: b2ReferenceFace + }, { + trimmed: "EPCollider", + name: "b2EPCollider", + def: b2EPCollider + }, { + trimmed: "CollideEdgeAndPolygon", + name: "b2CollideEdgeAndPolygon", + def: b2CollideEdgeAndPolygon + }, { + trimmed: "ClipSegmentToLine", + name: "b2ClipSegmentToLine", + def: b2ClipSegmentToLine + }, { + trimmed: "TestShapeOverlap", + name: "b2TestShapeOverlap", + def: b2TestShapeOverlap + }, { + trimmed: "TestOverlap", + name: "b2TestOverlap", + def: b2TestOverlap + }, { + trimmed: "Shape", + name: "b2Shape", + def: b2Shape + }, { + trimmed: "CircleShape", + name: "b2CircleShape", + def: b2CircleShape + }, { + trimmed: "EdgeShape", + name: "b2EdgeShape", + def: b2EdgeShape + }, { + trimmed: "ChainShape", + name: "b2ChainShape", + def: b2ChainShape + }, { + trimmed: "PolygonShape", + name: "b2PolygonShape", + def: b2PolygonShape + }, { + trimmed: "Pair", + name: "b2Pair", + def: b2Pair + }, { + trimmed: "PairLessThan", + name: "b2PairLessThan", + def: b2PairLessThan + }, { + trimmed: "BroadPhase", + name: "b2BroadPhase", + def: b2BroadPhase + }, { + trimmed: "DistanceProxy", + name: "b2DistanceProxy", + def: b2DistanceProxy + }, { + trimmed: "SimplexCache", + name: "b2SimplexCache", + def: b2SimplexCache + }, { + trimmed: "DistanceInput", + name: "b2DistanceInput", + def: b2DistanceInput + }, { + trimmed: "DistanceOutput", + name: "b2DistanceOutput", + def: b2DistanceOutput + }, { + trimmed: "SimplexVertex", + name: "b2SimplexVertex", + def: b2SimplexVertex + }, { + trimmed: "Simplex", + name: "b2Simplex", + def: b2Simplex + }, { + trimmed: "DistanceFunc", + name: "b2DistanceFunc", + def: b2DistanceFunc + }, { + trimmed: "TreeNode", + name: "b2TreeNode", + def: b2TreeNode + }, { + trimmed: "DynamicTree", + name: "b2DynamicTree", + def: b2DynamicTree + }, { + trimmed: "TOIInput", + name: "b2TOIInput", + def: b2TOIInput + }, { + trimmed: "TOIOutput", + name: "b2TOIOutput", + def: b2TOIOutput + }, { + trimmed: "SeparationFunction", + name: "b2SeparationFunction", + def: b2SeparationFunction + }, { + trimmed: "TimeOfImpact", + name: "b2TimeOfImpact", + def: b2TimeOfImpact + }, { + trimmed: "BodyDef", + name: "b2BodyDef", + def: b2BodyDef + }, { + trimmed: "Body", + name: "b2Body", + def: b2Body + }, { + trimmed: "Filter", + name: "b2Filter", + def: b2Filter + }, { + trimmed: "FixtureDef", + name: "b2FixtureDef", + def: b2FixtureDef + }, { + trimmed: "Fixture", + name: "b2Fixture", + def: b2Fixture + }, { + trimmed: "DestructionListener", + name: "b2DestructionListener", + def: b2DestructionListener + }, { + trimmed: "ContactFilter", + name: "b2ContactFilter", + def: b2ContactFilter + }, { + trimmed: "ContactImpulse", + name: "b2ContactImpulse", + def: b2ContactImpulse + }, { + trimmed: "ContactListener", + name: "b2ContactListener", + def: b2ContactListener + }, { + trimmed: "QueryCallback", + name: "b2QueryCallback", + def: b2QueryCallback + }, { + trimmed: "RayCastCallback", + name: "b2RayCastCallback", + def: b2RayCastCallback + }, { + trimmed: "TimeStep", + name: "b2TimeStep", + def: b2TimeStep + }, { + trimmed: "Position", + name: "b2Position", + def: b2Position + }, { + trimmed: "Velocity", + name: "b2Velocity", + def: b2Velocity + }, { + trimmed: "SolverData", + name: "b2SolverData", + def: b2SolverData + }, { + trimmed: "World", + name: "b2World", + def: b2World + }, { + trimmed: "MixFriction", + name: "b2MixFriction", + def: b2MixFriction + }, { + trimmed: "MixRestitution", + name: "b2MixRestitution", + def: b2MixRestitution + }, { + trimmed: "ContactRegister", + name: "b2ContactRegister", + def: b2ContactRegister + }, { + trimmed: "ContactEdge", + name: "b2ContactEdge", + def: b2ContactEdge + }, { + trimmed: "Contact", + name: "b2Contact", + def: b2Contact + }, { + trimmed: "CircleContact", + name: "b2CircleContact", + def: b2CircleContact + }, { + trimmed: "PolygonContact", + name: "b2PolygonContact", + def: b2PolygonContact + }, { + trimmed: "ChainAndCircleContact", + name: "b2ChainAndCircleContact", + def: b2ChainAndCircleContact + }, { + trimmed: "ChainAndPolygonContact", + name: "b2ChainAndPolygonContact", + def: b2ChainAndPolygonContact + }, { + trimmed: "EdgeAndCircleContact", + name: "b2EdgeAndCircleContact", + def: b2EdgeAndCircleContact + }, { + trimmed: "EdgeAndPolygonContact", + name: "b2EdgeAndPolygonContact", + def: b2EdgeAndPolygonContact + }, { + trimmed: "PolygonAndCircleContact", + name: "b2PolygonAndCircleContact", + def: b2PolygonAndCircleContact + }, { + trimmed: "defaultFilter", + name: "b2_defaultFilter", + def: b2_defaultFilter + }, { + trimmed: "defaultListener", + name: "b2_defaultListener", + def: b2_defaultListener + }, { + trimmed: "ContactManager", + name: "b2ContactManager", + def: b2ContactManager + }, { + trimmed: "VelocityConstraintPoint", + name: "b2VelocityConstraintPoint", + def: b2VelocityConstraintPoint + }, { + trimmed: "ContactPositionConstraint", + name: "b2ContactPositionConstraint", + def: b2ContactPositionConstraint + }, { + trimmed: "ContactVelocityConstraint", + name: "b2ContactVelocityConstraint", + def: b2ContactVelocityConstraint + }, { + trimmed: "PositionSolverManifold", + name: "b2PositionSolverManifold", + def: b2PositionSolverManifold + }, { + trimmed: "ContactSolverDef", + name: "b2ContactSolverDef", + def: b2ContactSolverDef + }, { + trimmed: "ContactSolver", + name: "b2ContactSolver", + def: b2ContactSolver + }, { + trimmed: "Island", + name: "b2Island", + def: b2Island + }, { + trimmed: "Jacobian", + name: "b2Jacobian", + def: b2Jacobian + }, { + trimmed: "JointEdge", + name: "b2JointEdge", + def: b2JointEdge + }, { + trimmed: "JointDef", + name: "b2JointDef", + def: b2JointDef + }, { + trimmed: "Joint", + name: "b2Joint", + def: b2Joint + }, { + trimmed: "RevoluteJointDef", + name: "b2RevoluteJointDef", + def: b2RevoluteJointDef + }, { + trimmed: "RevoluteJoint", + name: "b2RevoluteJoint", + def: b2RevoluteJoint + }, { + trimmed: "MouseJointDef", + name: "b2MouseJointDef", + def: b2MouseJointDef + }, { + trimmed: "MouseJoint", + name: "b2MouseJoint", + def: b2MouseJoint + }, { + trimmed: "DistanceJointDef", + name: "b2DistanceJointDef", + def: b2DistanceJointDef + }, { + trimmed: "DistanceJoint", + name: "b2DistanceJoint", + def: b2DistanceJoint + }, { + trimmed: "PrismaticJointDef", + name: "b2PrismaticJointDef", + def: b2PrismaticJointDef + }, { + trimmed: "PrismaticJoint", + name: "b2PrismaticJoint", + def: b2PrismaticJoint + }, { + trimmed: "FrictionJointDef", + name: "b2FrictionJointDef", + def: b2FrictionJointDef + }, { + trimmed: "FrictionJoint", + name: "b2FrictionJoint", + def: b2FrictionJoint + }, { + trimmed: "WeldJointDef", + name: "b2WeldJointDef", + def: b2WeldJointDef + }, { + trimmed: "WeldJoint", + name: "b2WeldJoint", + def: b2WeldJoint + }, { + trimmed: "WheelJointDef", + name: "b2WheelJointDef", + def: b2WheelJointDef + }, { + trimmed: "WheelJoint", + name: "b2WheelJoint", + def: b2WheelJoint + }, { + trimmed: "GearJointDef", + name: "b2GearJointDef", + def: b2GearJointDef + }, { + trimmed: "GearJoint", + name: "b2GearJoint", + def: b2GearJoint + }, { + trimmed: "MotorJointDef", + name: "b2MotorJointDef", + def: b2MotorJointDef + }, { + trimmed: "MotorJoint", + name: "b2MotorJoint", + def: b2MotorJoint + }, { + trimmed: "PulleyJointDef", + name: "b2PulleyJointDef", + def: b2PulleyJointDef + }, { + trimmed: "PulleyJoint", + name: "b2PulleyJoint", + def: b2PulleyJoint + }, { + trimmed: "RopeJointDef", + name: "b2RopeJointDef", + def: b2RopeJointDef + }, { + trimmed: "RopeJoint", + name: "b2RopeJoint", + def: b2RopeJoint + }, { + trimmed: "RopeDef", + name: "b2RopeDef", + def: b2RopeDef + }, { + trimmed: "Rope", + name: "b2Rope", + def: b2Rope + }, { + trimmed: "maxManifoldPoints", + name: "b2_maxManifoldPoints", + def: b2_maxManifoldPoints + }, { + trimmed: "maxPolygonVertices", + name: "b2_maxPolygonVertices", + def: b2_maxPolygonVertices + }, { + trimmed: "aabbExtension", + name: "b2_aabbExtension", + def: b2_aabbExtension + }, { + trimmed: "aabbMultiplier", + name: "b2_aabbMultiplier", + def: b2_aabbMultiplier + }, { + trimmed: "linearSlop", + name: "b2_linearSlop", + def: b2_linearSlop + }, { + trimmed: "angularSlop", + name: "b2_angularSlop", + def: b2_angularSlop + }, { + trimmed: "polygonRadius", + name: "b2_polygonRadius", + def: b2_polygonRadius + }, { + trimmed: "maxSubSteps", + name: "b2_maxSubSteps", + def: b2_maxSubSteps + }, { + trimmed: "maxTOIContacts", + name: "b2_maxTOIContacts", + def: b2_maxTOIContacts + }, { + trimmed: "velocityThreshold", + name: "b2_velocityThreshold", + def: b2_velocityThreshold + }, { + trimmed: "maxLinearCorrection", + name: "b2_maxLinearCorrection", + def: b2_maxLinearCorrection + }, { + trimmed: "maxAngularCorrection", + name: "b2_maxAngularCorrection", + def: b2_maxAngularCorrection + }, { + trimmed: "maxTranslation", + name: "b2_maxTranslation", + def: b2_maxTranslation + }, { + trimmed: "maxTranslationSquared", + name: "b2_maxTranslationSquared", + def: b2_maxTranslationSquared + }, { + trimmed: "maxRotation", + name: "b2_maxRotation", + def: b2_maxRotation + }, { + trimmed: "maxRotationSquared", + name: "b2_maxRotationSquared", + def: b2_maxRotationSquared + }, { + trimmed: "baumgarte", + name: "b2_baumgarte", + def: b2_baumgarte + }, { + trimmed: "toiBaugarte", + name: "b2_toiBaugarte", + def: b2_toiBaugarte + }, { + trimmed: "timeToSleep", + name: "b2_timeToSleep", + def: b2_timeToSleep + }, { + trimmed: "linearSleepTolerance", + name: "b2_linearSleepTolerance", + def: b2_linearSleepTolerance + }, { + trimmed: "angularSleepTolerance", + name: "b2_angularSleepTolerance", + def: b2_angularSleepTolerance + }, { + trimmed: "epsilon", + name: "b2_epsilon", + def: b2_epsilon + }, { + trimmed: "JsonSerializer", + name: "b2JsonSerializer", + def: b2JsonSerializer + }, { + trimmed: "RUBELoader", + name: "b2RUBELoader", + def: b2RUBELoader + }, { + trimmed: "Profiler", + name: "b2Profiler", + def: b2Profiler + }]; + + + if (typeof (b2_compatibility) !== "undefined" && typeof (window) !== "undefined") { + for (var i = 0; i < mappings.length; ++i) { + window[mappings[i].name] = mappings[i].def + } + } else { + var b2 = {}; + for (var i = 0; i < mappings.length; ++i) { + b2[mappings[i].trimmed] = mappings[i].def + } + if (typeof (module) !== "undefined") { + module.exports = b2 + } else { + window.b2 = b2 + } + } +})(); diff --git a/vendor/neurojs-v2.js b/vendor/neurojs-v2.js deleted file mode 100644 index f652415..0000000 --- a/vendor/neurojs-v2.js +++ /dev/null @@ -1,4908 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.l = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // identity function for calling harmony imports with the correct context -/******/ __webpack_require__.i = function(value) { return value; }; - -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; - -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; - -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 41); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - -The MIT License (MIT) - -Original Library - - Copyright (c) Marak Squires - -Additional functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var colors = {}; -module['exports'] = colors; - -colors.themes = {}; - -var ansiStyles = colors.styles = __webpack_require__(24); -var defineProps = Object.defineProperties; - -colors.supportsColor = __webpack_require__(25); - -if (typeof colors.enabled === "undefined") { - colors.enabled = colors.supportsColor; -} - -colors.stripColors = colors.strip = function(str){ - return ("" + str).replace(/\x1B\[\d+m/g, ''); -}; - - -var stylize = colors.stylize = function stylize (str, style) { - if (!colors.enabled) { - return str+''; - } - - return ansiStyles[style].open + str + ansiStyles[style].close; -} - -var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; -var escapeStringRegexp = function (str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } - return str.replace(matchOperatorsRe, '\\$&'); -} - -function build(_styles) { - var builder = function builder() { - return applyStyle.apply(builder, arguments); - }; - builder._styles = _styles; - // __proto__ is used because we must return a function, but there is - // no way to create a function with a different prototype. - builder.__proto__ = proto; - return builder; -} - -var styles = (function () { - var ret = {}; - ansiStyles.grey = ansiStyles.gray; - Object.keys(ansiStyles).forEach(function (key) { - ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); - ret[key] = { - get: function () { - return build(this._styles.concat(key)); - } - }; - }); - return ret; -})(); - -var proto = defineProps(function colors() {}, styles); - -function applyStyle() { - var args = arguments; - var argsLen = args.length; - var str = argsLen !== 0 && String(arguments[0]); - if (argsLen > 1) { - for (var a = 1; a < argsLen; a++) { - str += ' ' + args[a]; - } - } - - if (!colors.enabled || !str) { - return str; - } - - var nestedStyles = this._styles; - - var i = nestedStyles.length; - while (i--) { - var code = ansiStyles[nestedStyles[i]]; - str = code.open + str.replace(code.closeRe, code.open) + code.close; - } - - return str; -} - -function applyTheme (theme) { - for (var style in theme) { - (function(style){ - colors[style] = function(str){ - if (typeof theme[style] === 'object'){ - var out = str; - for (var i in theme[style]){ - out = colors[theme[style][i]](out); - } - return out; - } - return colors[theme[style]](str); - }; - })(style) - } -} - -colors.setTheme = function (theme) { - if (typeof theme === 'string') { - try { - colors.themes[theme] = !(function webpackMissingModule() { var e = new Error("Cannot find module \".\""); e.code = 'MODULE_NOT_FOUND';; throw e; }()); - applyTheme(colors.themes[theme]); - return colors.themes[theme]; - } catch (err) { - console.log(err); - return err; - } - } else { - applyTheme(theme); - } -}; - -function init() { - var ret = {}; - Object.keys(styles).forEach(function (name) { - ret[name] = { - get: function () { - return build([name]); - } - }; - }); - return ret; -} - -var sequencer = function sequencer (map, str) { - var exploded = str.split(""), i = 0; - exploded = exploded.map(map); - return exploded.join(""); -}; - -// custom formatter methods -colors.trap = __webpack_require__(16); -colors.zalgo = __webpack_require__(17); - -// maps -colors.maps = {}; -colors.maps.america = __webpack_require__(20); -colors.maps.zebra = __webpack_require__(23); -colors.maps.rainbow = __webpack_require__(21); -colors.maps.random = __webpack_require__(22) - -for (var map in colors.maps) { - (function(map){ - colors[map] = function (str) { - return sequencer(colors.maps[map], str); - } - })(map) -} - -defineProps(colors, init()); - -/***/ }), -/* 1 */ -/***/ (function(module, exports) { - -module.exports = class Size { - - static derive(val) { - if (val instanceof Size) { - return val; - } - - if (Number.isInteger(val)) { - return new Size(1, 1, val) - } - - if (val instanceof Object) { - return new Size(val.x, val.y, val.z) - } - - throw "Could not create size object"; - } - - constructor(x, y, z) { - this.x = x - this.y = y - this.z = z - } - - get length() { - return this.x * this.y * this.z - } - - get dimensions() { - if (this.x * this.y * this.z === 0) - return 0 - - if (this.x * this.y === 1) - return 1 - - if (this.x === 1) - return 2 - - return 3 - } - -} - -/***/ }), -/* 2 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var dot = __webpack_require__(28) -var dropout = __webpack_require__(29) -var nonlinear = __webpack_require__(32) -var input = __webpack_require__(30) -var regression = __webpack_require__(33) -var noise = __webpack_require__(31) -var bayesian = __webpack_require__(27) -var variational = __webpack_require__(34) - -var Size = __webpack_require__(1) -var Tensor = __webpack_require__(35) -var Optim = __webpack_require__(4) - -var SharedConfiguration = __webpack_require__(3) - -if (typeof window === 'undefined') { - __webpack_require__(19); -} - -// defines how the network looks; which layers etc. -class Model { - - constructor(opt) { - this.representation = opt - this.build(opt) - } - - build(opt) { - this.layers = [] - - var input = null - var desc = Model.expand(opt) - - for(var i = 0; i < desc.length; i++) { - var current = desc[i] - var layer = Model.create(input, current) - - layer.label = current.label || undefined - layer.index = i - layer.model = this - layer.options = current - - if (layer.dimensions.output) - layer.size = layer.dimensions.output.length // convenience - - this.layers.push(layer) - input = layer.dimensions.output - } - - this.input = this.layers[0] - this.output = this.layers[this.layers.length - 1] - } - - newConfiguration() { - return new Configuration(this) - } - - newState() { - return this.newConfiguration().newState() - } - - numericalGradientCheck() { - var config = this.newConfiguration() - var state = config.newState() - var diff = 1e-5 - - function clear() { - // clear gradients - for (var i = 0; i < config.parameters.length; i++) { - if (config.parameters[i]) - config.parameters[i].dw.fill(0.0) - } - } - - function analyse(param, index) { - clear.call(this) - - state.forward(input) - state.backward(output) - - return config.parameters[param].dw[index] - } - - function loss() { - state.forward(input) - return state.loss(output) - } - - function measure(param, index) { - var orig = config.parameters[param].w[index] - config.parameters[param].w[index] = orig - diff - var loss1 = loss.call(this) - config.parameters[param].w[index] = orig + diff - var loss2 = loss.call(this) - config.parameters[param].w[index] = orig - - return (loss2 - loss1) / (2 * diff) - } - - function checkWeight(param, index) { - var analytical = analyse.call(this, param, index) - var numerical = measure.call(this, param, index) - var divisor = Math.abs(analytical) - - return Math.abs(numerical - analytical) / (divisor !== 0 ? divisor : 1) - } - - - var input = Float64Array.filled(this.input.size, 1.0) - var output = Float64Array.filled(this.output.size, 1.0) - - console.log('Checking analytical gradients...'.magenta) - - var total = 0.0 - for (var i = config.parameters.length - 1; i >= 0; i--) { - var param = config.parameters[i] - if (param === undefined) - continue - - var offset = 0.0 - for (var j = 0; j < param.w.length; j++) { - var error = checkWeight.call(this, i, j) - if (isNaN(error)) { - console.log('Layer ' + i) - throw 'gradient is NaN' - } - - offset += error * error - } - - total += offset - offset = Math.sqrt(offset) / param.w.length - - console.log('Layer ' + i + ' with gradient error of ' + offset) - - if (offset > 1e-3) { - throw 'analytical gradient unusually faulty' - } - } - - total = Math.sqrt(total) / config.countOfParameters - - console.log(('Mean gradient error is ' + total).bold.cyan) - console.log('Gradients are looking good!'.bold.white) - } - - - static expand(opt) { - var description = [] - for (var i = 0; i < opt.length; i++) { - var current = opt[i] - - if (current.type === 'softmax' && current.classes) - description.push({ type: 'fc', size: current.classes }) - - description.push(current) - - if (current.activation) - description.push({ type: current.activation }) - - if (current.dropout) - description.push({ type: 'dropout', probability: current.dropout }) - } - - if (![ 'softmax', 'regression' ].includes(description[description.length - 1].type)) - description.push({ type: 'regression' }) - - return description - } - - static create(inp, opt) { - switch (opt.type) { - case 'fc': return new dot.FullyConnectedLayer(inp, opt) - case 'dropout': return new dropout.DropOutLayer(inp, opt) - case 'sigmoid': return new nonlinear.SigmoidLayer(inp, opt) - case 'tanh': return new nonlinear.TanhLayer(inp, opt) - case 'relu': return new nonlinear.ReLULayer(inp, opt) - case 'elu': return new nonlinear.ELULayer(inp, opt) - case 'input': return new input.InputLayer(inp, opt) - case 'regression': return new regression.RegressionLayer(inp, opt) - case 'softmax': return new regression.SoftmaxLayer(inp, opt) - case 'noise': return new noise.UhlenbeckOrnsteinNoiseLayer(inp, opt) - case 'bayesian': return new bayesian.VariationalBayesianLayer(inp, opt) - case 'variational': return new variational.VariationalLayer(inp, opt) - case 'binary': return new variational.VariationalBinaryLayer(inp, opt) - } - - throw 'error' - } - -} - -// defines how the network behaves; parameter/weights etc. -class Configuration { - - constructor(model, parameters, optimizer) { - this.model = model - this.parameters = [] - this.optimizer = null - this.countOfParameters = 0 - - for (var i = 0; i < this.model.layers.length; i++) { - var layer = this.model.layers[i] - if (!layer.dimensions.parameters) { - continue - } - - var param = this.parameters[i] = new Tensor(layer.dimensions.parameters) - if (parameters && i in parameters) // copy from - param.w.set(parameters[i].w) - else if (layer.initialize) // initialize as new parameters - layer.initialize(param) - else // random parameters - param.w.randf(-1, 1) - - this.countOfParameters += layer.dimensions.parameters - } - - if (optimizer) { - this.useOptimizer(optimizer) - } - } - - - useOptimizer(optimizer) { - if (optimizer.constructor === Object) - optimizer = new Optim(optimizer) - - this.optimizer = optimizer - this.forEachParameter(param => optimizer.initialize(param)) - - return optimizer - } - - freeze(val = true) { - this.freezed = val - } - - optimize(accu = true) { - if (accu) this.accumulate(Number.isInteger(accu) ? accu : undefined) - this.forEachParameter(param => this.optimizer.apply(param)) - } - - accumulate(weighted) { - this.forEachParameter(param => this.optimizer.accumulate(param, weighted)) - } - - - - forEachParameter(cb) { - if (this.freezed) return - for (var i = 0; i < this.parameters.length; i++) { - var param = this.parameters[i] - if (param === undefined) - continue - - cb(param, i) - } - } - - copyParametersFrom(config) { - if (config.model !== this.model) - throw 'models must match' - - this.forEachParameter((function (param, index) { - param.w.set(config.parameters[index].w) - }).bind(this)) - } - - - newState() { - return new State(this) - } - - clone() { - return new Configuration(this.model, this.parameters, this.optimizer) - } - - - putWeights(arr) { - var joined = arr - - if (arr.length !== this.countOfParameters) - throw 'array doesnt match' - - for (var i = 0, p = 0; i < this.parameters.length; i++) { - var param = this.parameters[i] - if (param === undefined) - continue - - param.w.set(joined.subarray(p, p + param.w.length)) - - p += param.w.length - } - } - - pullWeights() { - var joined = new Float64Array(this.countOfParameters) - - for (var i = 0, p = 0; i < this.parameters.length; i++) { - var param = this.parameters[i] - if (param === undefined) - continue - - joined.set(param.w, p) - - p += param.w.length - } - - return joined - } - - - share() { - return new SharedConfiguration(this) - } - -} - -// defines current network input/hidden/output-state; activations and gradients etc. -class State { - - constructor(configuration) { - this.configuration = configuration - this.model = this.configuration.model - this.layers = this.model.layers - - this.tensors = [] // array of layer tensors; this.tensors[i] = output tensor of layer i - this.contexts = [] - - // First input + output of every layer - for (var i = 0; i < this.layers.length + 1; i++) { - if (i > 0 && this.layers[i - 1].passthrough) // if passthrough, just use last tensor - this.tensors[i] = this.tensors[i - 1] - else // if at i = layers.length, then use output of last layer as tensor size - this.tensors[i] = new Tensor(i < this.layers.length ? this.layers[i].dimensions.input : this.layers[i - 1].dimensions.output) - } - - for (var i = 0; i < this.layers.length; i++) { - var layer = this.layers[i] - var context = this.contexts[i] = new LayerContext({ - input: this.tensors[i], - output: this.tensors[i + 1], - parameters: this.configuration.parameters[i], - state: this - }) - - Object.each(layer.storage || {}, function (k, v) { - context[k] = new Float64Array(!isNaN(v) ? v : v.length); - }) - } - - this.in = this.tensors[0] - this.out = this.tensors[this.layers.length] - - this.__target = new Float64Array(this.out.w.length) - this.__l_in = this.layers[0] - this.__l_out = this.layers[this.layers.length - 1] - } - - /** - * Evaluate network - * @param {Float64Array} input - * @return {Float64Array} - */ - forward(input, opt) { - if (input != null) { - this.__l_in.toInputVector(input, this.in.w) // use 'input' as input values, while converting it to a vector - } - - this.options = opt || {} // set pass options - this.activate() // activate all layers - - return this.output // return copy of output - } - - /** - * Propagates error back, error is provided by subtracting desired from actual output values. - * @param {Float64Array | Int} desired - * @return {Float} loss - */ - backward(desired) { - if (desired != null) { - this.__l_out.toGradientVector(desired, this.out.w, this.out.dw) // convert 'desired' to target vector - } - - this.propagate() // propagate errors backwards - - return this.loss(desired) // return loss - } - - /** - * Instead of regressing the network to have minimal error, you can provide your own gradient. - * @param {Float64Array} grad - */ - backwardWithGradient(grad) { - if (Array.isArray(grad)) - this.out.dw.set(grad) - else if (this.out.dw.length === 1) - this.out.dw[0] = grad - else - throw 'error grad not propagatable'; - - this.propagate() - } - - - // get copy of current output - get output() { - return this.__l_out.result(this.contexts[this.__l_out.index]) - } - - // get loss of current - loss(desired) { - if (desired === undefined) - return - - return this.__l_out.loss(this.contexts[this.__l_out.index], desired) - } - - - // not error gradient, but value gradient => how to increase/decrease n-th output value - derivatives(n, clone = true) { - this.out.dw.fill(0.0) - this.out.dw[n] = 1.0 - - this.propagate() - - if (clone) - return this.in.dw.clone() - - return this.in.dw - } - - - // forward pass - activate() { - for (var i = 0; i < this.layers.length; i++) { - if (this.layers[i].passthrough) - continue ; - - this.layers[i].forward(this.contexts[i]) - } - } - - // backwards pass - propagate() { - // safety check - for (var i = 0; i < this.out.dw.length; i++) { - if (isNaN(this.out.dw[i])) { - throw 'warning: terror!'; - } - } - - for (var i = this.layers.length - 1; i >= 0; i--) { - if (this.layers[i].passthrough) - continue ; - - this.layers[i].backward(this.contexts[i]) - } - } - -} - -class LayerContext { - - constructor(opt) { - this.input = opt.input - this.output = opt.output - this.params = opt.parameters - this.state = opt.state - } - -} - - -module.exports = { - Model, Configuration, State -}; - -/***/ }), -/* 3 */ -/***/ (function(module, exports) { - -class EventRadio { - - constructor() { - this.events = {} - } - - - on(event, callback) { - if (!(event in this.events)) { - this.events[event] = [] - } - - this.events[event].push(callback) - } - - trigger(event, args = []) { - if (event in this.events) { - for (var i = 0; i < this.events[event].length; i++) { - this.events[event][i].apply(undefined, [this].concat(args)); - } - } - } - -} - -class ConfigPool extends EventRadio { - - constructor(names) { - super() - this.states = {} - this.configs = {} - this.requested = [] - } - - add(name, wrapper) { - if (!(name in this.states)) { - this.states[name] = [] - } - - if (name in this.configs) { - wrapper.set(this.configs[name]) - } - - this.states[name].push(wrapper) - wrapper.pool = this - wrapper.__pool_name = name - - this.trigger('add', [ wrapper, name ]) - this.trigger('add ' + name, [ wrapper ]) - } - - set(name, config) { - if (name in this.states) { - - for (var i = 0; i < this.states[name].length; i++) { - this.states[name][i].set(config) - } - - } - - this.configs[name] = config - } - - step() { - for (var i = 0; i < this.requested.length; i++) { - var name = this.requested[i] - this.configs[name].optimize(false) - } - - this.requested = [] - } - - requestOptimisation(wrapper) { - if (wrapper.__pool_name === undefined || !(wrapper.__pool_name in this.configs)) - return false - - if (this.requested.indexOf(wrapper.__pool_name) >= 0) - return true - - this.requested.push(wrapper.__pool_name) - - return true - } - -} - -class NetworkWrapper extends EventRadio { - - constructor() { - super() - - this.on('set', () => { - if (this.optim !== undefined) - this.config.useOptimizer(this.optim) - }) - } - - set(value) { - var state - - if (!value) { - return - } - - if (value.constructor.name === 'State') { - state = value - } - - else if (value.constructor.name === 'Configuration' || value.constructor.name === 'Model') { - state = value.newState() - } - - this.net = state - this.config = state.configuration - this.model = state.model - - this.trigger('set', [ state ]) - } - - useOptimizer(optim) { - this.optim = optim - - if (this.config) { - this.config.useOptimizer(optim) - } - } - - optimize() { - if (this.pool && this.pool.requestOptimisation(this)) { - return - } - - this.config.optimize(false) - } - -} - -module.exports = { - NetworkWrapper, ConfigPool -} - -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.assign(RegExp, { - - escape(str) { - return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); - } - -}); - -Object.assign(Function.prototype, { - - getArguments() { - const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; - const ARGUMENT_NAMES = /([^\s,]+)/g; - - if (this.$args) - return this.$args; - - var fnStr = this.toString().replace(STRIP_COMMENTS, ''); - var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); - if (result === null) - result = []; - - return this.$args = result; - }, - - getSource() { - return this.toString().replace(/^[^{]+{/i, '').replace(/}[^}]*$/i, '') - }, - - decompile() { - return { arguments: this.getArguments(), source: this.getSource() }; - } - -}); - -Object.assign(Object, { - - each(obj, callback) { - for (var key in obj) - if (obj.hasOwnProperty(key)) - callback(key, obj[key]); - } - -}); - -Object.assign(String.prototype, { - - replaceAll(find, replace) { - return this.replace(new RegExp(RegExp.escape(find), 'g'), replace); - } - -}); - -/** - * How to use this optimizer: - * - * 1. First initialize with options e.g. - * var optimizer = new Optim({ - * method: 'adadelta', - * regularization: { l2: 1e-2 }, - * clipping: 5 - * }) - * 2. Then create a (weight) tensor: - * var toOptimize = new Tensor(100) - * 3. And prepare the tensor for optimization - * optimizer.initialize(toOptimize) - * 4. Then add a gradient to the tensor (not practical like this, but you get the hang of it) - * toOptimize.dw[50] = 1.0 - * 5. Accumulate gradient (do this n-times if n is your batch count) - * optimizer.accumulate(toOptimize) - * 6. Finally apply gradient optimization via - * optimizer.apply(toOptimize) - * - */ - -class Optim { - - constructor(opt) { - this.update(opt || {}); - this.uuid = ++Optim.INDEX - } - - update(opt) { - this.method = opt.method || 'sgd'; - this.options = Object.assign({ - - type: 'descent', - clipping: 0, - regularization: { - l1: 0, - l2: 0 - } - - }, Optim.methods[this.method].options, opt); - - delete this.options.method; - - this.options = Object.freeze(this.options); - - this.build(); - } - - build() { - if (this.options.type === 'descent') - this.apply = this.assemble('-') - else if (this.options.type === 'ascent') - this.apply = this.assemble('+') - else - throw 'unrecognized optimizer type' - } - - assemble(dir) { - var method = Optim.methods[this.method]; - var regDir = dir === '+' ? '-' : '+' - - var performer = (method.deliver ? method.deliver(this.options) : method.perform).decompile(); - var stateDefs = [], produceDefs = []; - - this.states = performer.arguments; - - for (var i = 0; i < this.states.length; i++) { - stateDefs.push(this.states[i] + '=' + 'dw.' + this.states[i]); - } - - function _definitions() { - var defs = ''; - if (stateDefs.length > 0) - defs += 'var ' + stateDefs.join(',') + ';'; - - if (produceDefs.length > 0) - defs += 'var ' + produceDefs.join(',') + ';'; - - return defs; - } - - function _gradient() { - var producer = ''; - if (this.options.clipping > 0) { - producer += 'grad = grad > opt.clipping ? opt.clipping : (grad < -opt.clipping ? -opt.clipping : grad);\n'; - } - - var sum = 'grad'; - if (this.options.regularization.l1 > 0) { - produceDefs.push('l1grad'); - producer += 'l1grad = opt.regularization.l1 * (w[i] > 0 ? ' + regDir + '1 : ' + dir + '1);\n'; - sum += '+l1grad'; - } - - if (this.options.regularization.l2 > 0) { - produceDefs.push('l2grad'); - producer += 'l2grad = opt.regularization.l2 * w[i] * ' + regDir + '1.0;\n'; - sum += '+l2grad'; - } - - producer += 'gij = ' + '(' + sum + ') / iteration' + ';\n'; - - return { source: producer }; - } - - function replaceOptionsWithConstants(k, v) { - if (typeof v === 'object') { - Object.each(v, replaceOptionsWithConstants.bind(this + k + '.')); - return; - } - - fn = fn.replaceAll(this + k, v); - } - - var grad = _gradient.call(this); - - var fn = - `"use strict"; - var w = tensor.w, dw = tensor.dw, accdw = dw.acc; - var dx, gij, grad, iteration = dw.iteration; - if (iteration < 1) return ; - ${ _definitions() } - for (var i = 0; i < w.length; ++i) { - grad = accdw[i]; - ${ grad.source } - ${ performer.source } - w[i] ${ dir }= dx; - accdw[i] = 0.0; - } - dw.iteration = 0;`; - - Object.each(this.options, replaceOptionsWithConstants.bind('opt.')); - return new Function('tensor', fn); - } - - accumulate(tensor, weighted) { - weighted = weighted || 1 - var w = tensor.w, dw = tensor.dw, accdw = dw.acc; - var dx, gij, grad, iteration = (dw.iteration += weighted); - for (var i = 0; i < w.length; ++i) accdw[i] += weighted * dw[i]; - } - - initialize(tensor, set, linked) { - if (!tensor.initialized) { // general initialization - tensor.dw.iteration = 0; - tensor.dw.acc = new Float64Array(tensor.dw.length) - } - - for (var i = 0; i < this.states.length; ++i) { // specific (algorithm dependent) initialization - if (this.states[i] in tensor.dw) - tensor.dw[this.states[i]] = tensor.dw[this.states[i]].fill(0.0) - else - tensor.dw[this.states[i]] = new Float64Array(tensor.dw.length) - } - - tensor.initialized = true - } - - static register(name, value) { - Optim.methods[name] = value; - } - -} - -Optim.methods = {}; - -Optim.register("sgd", { - - deliver(opt) { - if (opt.momentum === 0) { - return function() { dx = opt.rate * gij; } - } - - return this.perform; - }, - - perform(mom) { - dx = opt.rate * gij + opt.momentum * mom[i]; - mom[i] = dx; - }, - - options: { - rate: 0.01, - momentum: 0 - } - -}); - -Optim.register("adadelta", { - - perform(gsum, xsum) { - gsum[i] = opt.ro * gsum[i] + (1 - opt.ro) * gij * gij; - dx = Math.sqrt((xsum[i] + opt.eps) / (gsum[i] + opt.eps)) * gij; - xsum[i] = opt.ro * xsum[i] + (1 - opt.ro) * dx * dx; // yes, xsum lags behind gsum by 1. - }, - - options: { - ro: 0.95, - eps: 1e-8 - } - -}); - -Optim.register("adam", { - - perform(m, v) { - m[i] = opt.beta1 * m[i] + (1 - opt.beta1) * gij; // update biased first moment estimate - v[i] = opt.beta2 * v[i] + (1 - opt.beta2) * gij * gij; // update biased second moment estimate - var bcm = m[i] / (1 - Math.pow(opt.beta1, iteration)); // correct bias first moment estimate - var bcv = v[i] / (1 - Math.pow(opt.beta2, iteration)); // correct bias second moment estimate - dx = opt.rate * bcm / (Math.sqrt(bcv) + opt.eps); - }, - - options: { - rate: 0.01, - eps: 1e-8, - beta1: 0.9, - beta2: 0.999 - } - -}); - -Optim.INDEX = 0 - -module.exports = Optim; - - -/***/ }), -/* 5 */ -/***/ (function(module, exports) { - -class ReplayBuffer { - - add(e) { throw 'not implemented' } - sample(n) { throw 'not implemented' } - getAverageLoss() { throw 'not implemented' } - getImportanceSamplingWeight(e) { return 1.0 } - updateAfterLearning() {} - -} - -class UniformReplayBuffer extends ReplayBuffer { - - constructor(size) { - super() - this.buffer = [] - this.size = size - } - - add(e) { - - if (this.buffer.length >= this.size) { - this.buffer[Math.randi(0, this.buffer.length)] = e - } - - else { - this.buffer.push(e) - } - - } - - sample(n) { - var batch = [] - - if (this.buffer.length <= n) - return this.buffer - - for (var i = 0; i < n; i++) { - batch.push(Array.random(this.buffer)) - } - - return batch - } - - draw() { - return Array.random(this.buffer) - } - - getAverageLoss() { - return Array.sum(this.buffer, x => x.loss) / this.buffer.length - } - -} - -class PrioritizedReplayBuffer extends ReplayBuffer { - - constructor(N) { - super() - - this.root = new PrioritizedReplayBuffer.Node(null, null) - this.iterations = 0 - this.size = 0 - - this.maxISW = 1.0 - this.beta = 0.5 - - for (var i = 0; i < N - 1; ++i) { - this.root.add(null) - } - - this.leafs = this.root.getLeafs() - - if (this.leafs.length !== this.root.size) - throw 'could not create replay tree...' - } - - add(e) { - if (this.size === this.leafs.length) { - this.root.descent((a, b) => a.minimum < b.minimum ? 0 : 1).set(e) - } - - else { - this.leafs[this.size].set(e) - } - - this.iterations += 1 - this.size = Math.max(this.size, this.iterations % this.leafs.length) - } - - sample(n) { - var batch = [] - - this.maxISW = Math.pow(this.size * (this.root.minimum / this.root.value), -this.beta) - - if (this.size < 5 * n) - return [ ] - - while (batch.length < n) - batch.push(this.root.cumulativeSample(Math.random() * this.root.value).experience) - - return batch - } - - draw(prioritised) { - if (!prioritised) - return this.leafs[Math.randi(0, this.size)].experience - - return this.root.cumulativeSample(Math.random() * this.root.value).experience - } - - updateAfterLearning(batch) { - for (var i = 0; i < batch.length; i++) { - var e = batch[i] - if (e !== e.node.experience) - throw 'association error' - - e.node.revalue() - } - } - - getImportanceSamplingWeight(e) { - if (e.priority === undefined) - return 1.0 - - return Math.pow(this.size * (e.priority / this.root.value), -this.beta) - } - - getAverageLoss() { - return this.root.value / this.root.size - } - -} - -PrioritizedReplayBuffer.Node = class Node { - - constructor(parent, experience) { - this.parent = parent - this.children = [] - this.size = 1 - this.value = 0.0 - - this.maximum = -Infinity - this.minimum = Infinity - - this.experience = experience - this.revalue() - } - - - cumulativeSample(x) { - if (this.children.length === 0) - return this - - if (this.children[0].value < x) - return this.children[1].cumulativeSample(x - this.children[0].value) - else - return this.children[0].cumulativeSample(x) - } - - update() { - this.value = Array.sum(this.children, x => x.value) - this.maximum = this.children.reduce((a, b) => a.maximum > b.maximum ? a : b).maximum - this.minimum = this.children.reduce((a, b) => a.minimum < b.minimum ? a : b).minimum - - if (this.parent) - this.parent.update() - } - - revalue() { - if (this.children.length > 0) - throw 'not possible' - - if (!this.experience) - return - - this.value = this.experience.priority || Infinity - - this.maximum = this.value - this.minimum = this.value - - if (this.parent) - this.parent.update() - } - - set(experience) { - if (this.children.length > 0) - throw "can't set experience of node with children" - - experience.node = this - - this.experience = experience - this.revalue() - } - - add(experience) { - if (this.children.length === 0) { // branch off - this.children.push(new PrioritizedReplayBuffer.Node(this, this.experience)) - this.children.push(new PrioritizedReplayBuffer.Node(this, experience)) - this.experience = null - - // this.update() - } else { - this.children.reduce((a, b) => a.size < b.size ? a : b).add(experience) - } - - this.size++ - } - - descent(dir) { - if (this.children.length === 0) - return this - - return this.children[ dir(this.children[0], this.children[1]) ].descent(dir) - } - - getLeafs() { - if (this.children.length === 0) - return [ this ] - - var unfolded = [] - for (var i = 0; i < this.children.length; i++) { - unfolded.push(this.children[i].getLeafs()) - } - - return Array.prototype.concat.apply([], unfolded) - } - -} - -module.exports = { - - ReplayBuffer, - UniformReplayBuffer, - PrioritizedReplayBuffer - -} - -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { - -var binary = __webpack_require__(7); -var network = __webpack_require__(2); - -class NetOnDisk { - - static write(config) { - var contents = []; - - contents.push(config.model.representation) - contents.push(config.pullWeights()) - - return binary.Writer.write(contents) - } - - static read(buffer) { - var contents = binary.Reader.read(buffer) - - var model = new network.Model(contents[0]) - var config = model.newConfiguration() - - config.putWeights(contents[1]) - - return config - } - - - - static writeMultiPart(list) { - var contents = []; - - contents.push(Object.keys(list)) - - for (var name in list) { - var config = list[name] - - if (!config instanceof network.Configuration) { - throw 'config in list must be of type Network.Configuration' - } - - contents.push(name) - contents.push(config.model.representation) - contents.push(config.pullWeights()) - } - - return binary.Writer.write(contents) - } - - static readMultiPart(buffer) { - var contents = binary.Reader.read(buffer) - - var ptr = -1 - var names = contents[++ptr] - - var list = {} - - for (var i = 0; i < names.length; i++) { - var name = names[i] - - if (contents[++ptr] !== name) { - throw 'name does not match up' - } - - var model = new network.Model(contents[++ptr]) - var config = model.newConfiguration() - - config.putWeights(contents[++ptr]) - - list[name] = config - } - - return list - } - -} - -module.exports = NetOnDisk - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) {var StringView = __webpack_require__(40); - -function isObjLiteral(_obj) { - var _test = _obj; - return ( typeof _obj !== 'object' || _obj === null ? - false : - ( - (function () { - while (!false) { - if ( Object.getPrototypeOf( _test = Object.getPrototypeOf(_test) ) === null) { - break; - } - } - return Object.getPrototypeOf(_obj) === _test; - })() - ) - ); -} - -class BinaryWriter { - - /** - * Returns array buffer, which contains the binary data. - * @param {array} contents - * @return {ArrayBuffer} - */ - static write(contents) { - var toc = [], length = 0; - - for (var i = 0; i < contents.length; i++) { - var value = contents[i] - var isobject = false - - if (value.constructor === Object || value.constructor === Array) { - value = (contents[i] = JSON.stringify(value)) - isobject = true - } - - if (typeof value === 'string') { - toc.push({ - t: 's', - l: value.length - }); - - if (isobject) { - toc[toc.length - 1]['o'] = 1; - } - - length += value.length - } - - else if (ArrayBuffer.isView(value)) { - toc.push({ - t: 't', - l: value.byteLength, - i: value.constructor.name - }) - - length += value.byteLength - } - - else if (value instanceof ArrayBuffer) { - toc.push({ - t: 'b', - l: value.byteLength - }) - - length += value.byteLength - } - } - - var jsonified = JSON.stringify(toc) - - length += jsonified.length + Uint32Array.BYTES_PER_ELEMENT + 1 - - var writer = new BinaryWriter(length) - - writer.setUint8(BinaryWriter.validationByte) // validation byte - writer.setUint32(jsonified.length) // table of contents length - writer.setString(jsonified) // ToC - - for (var i = 0; i < toc.length; i++) { - switch(toc[i].t) { - case 's': writer.setString(contents[i]); break - case 't': writer.setTypedArray(contents[i]); break - case 'b': writer.setBuffer(contents[i]); break - } - } - - if (!writer.isAtEnd()) { - throw "The lengths don't match up"; - } - - return writer.raw - } - - - constructor(length) { - this.array = new Uint8Array(length) - this.buffer = this.array.buffer - this.dataView = new DataView(this.buffer) - this.index = 0 - } - - setUint8(val) { - this.dataView.setUint8(this.index, val) - this.index += Uint8Array.BYTES_PER_ELEMENT - } - - setUint32(val) { - this.dataView.setUint32(this.index, val) - this.index += Uint32Array.BYTES_PER_ELEMENT - } - - setString(string) { - var sv = new StringView(string); - this.array.set(sv.rawData, this.index); - this.index += sv.buffer.byteLength - } - - setTypedArray(arr) { - this.array.set(new Uint8Array(arr.buffer), this.index) - this.index += arr.byteLength - } - - setBuffer(buf) { - this.array.set(new Uint8Array(buf), this.index) - this.index += buf.byteLength - } - - isAtEnd() { - return this.buffer.byteLength === this.index - } - - get raw() { - return this.array.buffer - } - -} - - -class BinaryReader { - - /** - * Returns the contents read from the array buffer - * @param {ArrayBuffer} buffer - * @return {array} - */ - static read(buffer) { - var reader = new BinaryReader(buffer) - - var validation = reader.getUint8() - - if (validation !== BinaryWriter.validationByte) { - throw "validation byte doesn't match." - } - - var tocLength = reader.getUint32() - var tocString = reader.getString(tocLength) - var toc = JSON.parse(tocString) - var contents = [] - - for (var i = 0; i < toc.length; i++) { - switch (toc[i].t) { - case 's': contents.push(reader.getString(toc[i].l)); break - case 't': contents.push(new (typeof window !== 'undefined' ? window : global)[toc[i].i](reader.getBuffer(toc[i].l))); break - case 'b': contents.push(reader.getBuffer(toc[i].l)); break - } - - if (toc[i]['o'] === 1) { - contents[i] = JSON.parse(contents[i]); - } - } - - return contents - } - - - constructor(buffer) { - this.array = new Uint8Array(buffer) - this.buffer = buffer - this.dataView = new DataView(buffer) - this.index = 0 - } - - - getUint8() { - var val = this.dataView.getUint8(this.index) - this.index += Uint8Array.BYTES_PER_ELEMENT - - return val - } - - getUint32() { - var val = this.dataView.getUint32(this.index) - this.index += Uint32Array.BYTES_PER_ELEMENT - - return val - } - - getString(length) { - var arr = this.array.subarray(this.index, this.index + length) - var str = (new StringView(arr)).toString() - - this.index += arr.byteLength - - return str - } - - getBuffer(byteLength) { - var arr = this.array.slice(this.index, this.index + byteLength) - this.index += byteLength - - return arr.buffer - } - - isAtEnd() { - return this.buffer.byteLength === this.index - } - -} - -BinaryWriter.validationByte = 0x8F; - -module.exports = { - 'Writer' : BinaryWriter, - 'Reader' : BinaryReader -}; -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(26))) - -/***/ }), -/* 8 */ -/***/ (function(module, exports) { - -function webpackEmptyContext(req) { - throw new Error("Cannot find module '" + req + "'."); -} -webpackEmptyContext.keys = function() { return []; }; -webpackEmptyContext.resolve = webpackEmptyContext; -module.exports = webpackEmptyContext; -webpackEmptyContext.id = 8; - - -/***/ }), -/* 9 */ -/***/ (function(module, exports) { - -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - - -/***/ }), -/* 10 */ -/***/ (function(module, exports) { - - -class Algorithm { - - // what to do? - act(state, target) { throw 'Not implemented' } - - // how good is an action at state - value(state, action, target) { throw 'Not implemented' } - - // replay - optimize(e, descent = true) { throw 'Not implemented' } - - // adjust weights etc - learn() { throw 'Not implemented' } - - import(params) { throw 'Not implemented' } - export() { throw 'Not implemented' } - - - evaluate(state, target) { - return this.value(state, this.act(state, target), target) - } - -} - -module.exports = Algorithm - -/***/ }), -/* 11 */ -/***/ (function(module, exports) { - -class WebLoader { - - static load(path, completion) { - var request = new XMLHttpRequest() - request.open("GET", path, true) - request.responseType = "arraybuffer" - request.addEventListener('load', function(e) { - completion(request.response) - }) - - request.send(null) - } - - static loadConfig(path, model, completion) { - var config = model.newConfiguration() - WebLoader.loadConfigInto(path, config, completion.bind(null, config)) - } - - static loadConfigInto(path, config, completion) { - WebLoader.load(path, function (buffer) { - var weights = new Float64Array(buffer) - config.read(weights) - completion() - }) - } - - - static loadAgent(path, agent, completion) { - agent.ready = false - - WebLoader.load(path, function (buffer) { - var weights = new Float64Array(buffer) - agent.import(weights) - agent.ready = true - - if (completion) - completion(agent) - }) - } - -} - -module.exports = WebLoader - -/***/ }), -/* 12 */ -/***/ (function(module, exports) { - -if (Float64Array.prototype.fill === undefined) - Float64Array.prototype.fill = function (v) { - for (var i = 0; i < this.length; i++) { this[i] = v; } - }; - - -Object.assign(Math, { - - statistics: true, - - randn() { - var U1, U2 = this.randn.U2, W, mult; - if (U2) { - this.randn.U2 = null; // deactivate for next time - return U2; - } - - do { - U1 = -1 + this.random() * 2; - U2 = -1 + this.random() * 2; - W = U1 * U1 + U2 * U2; - } while (W >= 1 || W === 0); - - mult = Math.sqrt(-2 * Math.log(W) / W); - this.randn.U2 = U2 * mult; - - return U1 * mult; - }, - - randf(a, b) { - return this.random() * (b - a) + a; - }, - - randi(a, b) { - return a + Math.floor(Math.random() * (b - a)) - }, - - uhlenbeckOrnstein(old, theta, sigma, dt) { - return old - theta * old * dt + Math.sqrt(dt) * Math.randn(0.0, sigma) - } - -}) - -Object.assign(Array, { - - random(arr) { - return arr[Math.floor(Math.random() * arr.length)] - }, - - randomAndRemove() { - var index = Math.floor(Math.random() * this.length) - var value = this[index] - this.splice(index, 1) - - return value - }, - - sum(arr, valueFunc) { - valueFunc = valueFunc || (x => x); - var sum = 0.0 - for (var i = 0; i < arr.length; i++) { - sum += valueFunc(arr[i]) - } - - return sum - }, - - lowest(valueFunc) { - return this.reduce((a, b) => valueFunc(a) < valueFunc(b) ? a : b) - }, - - highest(valueFunc) { - return this.reduce((a, b) => valueFunc(a) > valueFunc(b) ? a : b) - }, - - sample(probFunc) { - var des = Math.random() - var pos = 0.0 - for (var i = 0; i < this.children.length; i++) { - if (des < (pos += prob[i])) - return this.children[i] - } - - return this.children[this.children.length - 1] - } - -}) - - -Object.assign(Float64Array, { - - filled(n, v) { - return (new Float64Array(n)).fill(v) - }, - - oneHot(n, N) { - var vec = new Float64Array(N) - vec[n] = 1.0 - return vec - }, - - noise(N, a, b) { - var vec = new Float64Array(N) - vec.randf(a || -1, b || 1) - return vec - } - -}); - - -Object.assign(Float64Array.prototype, { - - randn(mu, std) { - for (var i = 0; i < this.length; i++) { this[i] = mu + std * Math.randn(); } - }, - - randf(a, b) { - for (var i = 0; i < this.length; i++) { this[i] = Math.randf(a, b); } - }, - - maxi() { - var maxv = -Infinity, maxi = 0.0 - for (var i = 0; i < this.length; i++) { - if (this[i] > maxv) { - maxv = this[i]; maxi = i - } - } - - return maxi - }, - - clone() { - var copied = new Float64Array(this.length) - copied.set(this) - return copied - }, - - diff(x, y) { - for (var i = 0; i < this.length; i++) { this[i] = x[i] - y[i] } - }, - - add(x, y) { - for (var i = 0; i < this.length; i++) { this[i] = x[i] + y[i] } - }, - - mult(x, y) { - for (var i = 0; i < this.length; i++) { this[i] = x[i] * y } - } - -}); - - - -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { - -// var network = require('../network.js') -var Window = __webpack_require__(36) -var Experience = __webpack_require__(39) -var Buffers = __webpack_require__(5) -var DQN = __webpack_require__(38) -var DDPG = __webpack_require__(37) - -/** - * The Agent class represents the - * reinforcement-learner. - */ -class Agent { - - constructor(opt) { - - this.options = Object.assign({ - - type: 'q-learning', // sarsa or q-learning - experience: 25e3, - temporalWindow: 0, - - learningPerTick: 64, - startLearningAt: 1000, - - buffer: Buffers.PrioritizedReplayBuffer, - - algorithm: 'ddpg', - - discount: opt.discount || 0.9, - beta: 0.15, // how to prioritise experiences (0 = no prioritisation, 1 = full prioritisation) - - }, opt) - - // options - this.states = this.options.states // state space - this.actions = this.options.actions // action space - this.input = Agent.getInputDimension(this.states, this.actions, this.options.temporalWindow) // extended state (over time) - - // settings - this.buffer = new this.options.buffer(this.options.experience) - this.history = { - states: new Window(Math.max(2, this.options.temporalWindow)), - actions: new Window(Math.max(2, this.options.temporalWindow)), - inputs: new Window(2), - rewards: new Window(2), - } - - this.age = 1 - this.learning = true - this.ready = true - - switch (this.options.algorithm) { - case 'dqn': - this.algorithm = new DQN(this); break - case 'ddpg': - this.algorithm = new DDPG(this); break - default: - throw 'unknown algorithm' - } - } - - /** - * Let the agent make an action, includes exploration through noise - * @param {Array} state - * @return {Array} An action - */ - policy(state) { - if (!this.ready) - return - - var input = this.getStateInputVector(state) - var action = this.act(input) - - this.history.inputs.push(input) - this.history.states.push(state) - this.history.actions.push(action) - this.acted = true - - return action - } - - actionToVector(action) { - if (action instanceof Float64Array) { - return action - } - - if (Number.isInteger(action)) { - return Float64Array.oneHot(action, this.actions) - } - - throw 'Action is invalid' - } - - getStateInputVector(state) { - if (this.options.temporalWindow > 0) { - var input = new Float64Array(this.input) - var cursor = 0 - - for (var t = this.options.temporalWindow - 1; t >= 0; t--) { - if (this.history.states.size > t) { - input.set(this.history.states.get(t), cursor) - input.set(this.actionToVector( this.history.actions.get(t) ), cursor + this.states) - } - - cursor += this.states + this.actions - } - - input.set(state, cursor) - - return input - } - - return state - } - - /** - * Simulate that the agent did an action - * @param {Array} state - * @param {Array} action - */ - simulate(state, action) { - if (!this.ready) - return - - var input = this.getStateInputVector(state) - - this.history.inputs.push(input) - this.history.states.push(state) - this.history.actions.push(action) - this.acted = true - } - - /** - * Adds an experience to the buffer and replays a batch of experiences - * @param {Float} reward - * @return {Float} The loss - */ - learn(reward) { - if (!this.acted || !this.ready) - return - - this.acted = false - this.history.rewards.push(reward) - - // Learning happens always one step after actually experiencing - if (this.history.states.size < 2 || this.learning === false) - return - - // Create new experience - var e = new Experience(this) - e.action0 = this.history.actions.get(1) - e.state0 = this.history.inputs.get(1) - e.reward0 = this.history.rewards.get(1) - e.state1 = this.history.inputs.get(0) - e.action1 = this.history.actions.get(0) // for SARSA only - e.init() // set loss etc. - - // Add experience to replay buffer - this.buffer.add(e) - - // Get older - ++this.age - - return this.backward() - } - - backward() { - if (this.options.startLearningAt > this.age) - return false - - // Set training - this.training = true - - // Learn batch - var loss = this.replay() - - // Execute algorithm - this.algorithm.learn() - - return loss - } - - replay() { - var batch = this.buffer.sample(this.options.learningPerTick), loss = 0.0 - - for (var i = 0; i < batch.length; i++) { - loss += batch[i].step() - } - - this.buffer.updateAfterLearning(batch) - - return loss / batch.length - } - - - // - act(state, target) { - return this.algorithm.act(state, target) - } - - value(state, action, target) { - return this.algorithm.value(state, action, target) - } - - evaluate(state, target) { - return this.algorithm.evaluate(state, target) - } - - - - // utility functions - export() { - return this.algorithm.export() - } - - static getInputDimension(states, actions, temporalWindow) { - return states + temporalWindow * (states + actions) - } - -} - -module.exports = Agent - -/***/ }), -/* 14 */ -/***/ (function(module, exports) { - -class FileLoader { - - static download(file, callback) { - // Create XHR, Blob and FileReader objects - var xhr = new XMLHttpRequest(), blob, fileReader = new FileReader(); - - xhr.open("GET", file, true); - // Set the responseType to arraybuffer. "blob" is an option too, rendering manual Blob creation unnecessary, but the support for "blob" is not widespread enough yet - xhr.responseType = "arraybuffer"; - - xhr.addEventListener("load", function () { - if (xhr.status === 200) { - callback(null, xhr.response) - } - - else { - callback(xhr.status, null) - } - }, false); - - // Send XHR - xhr.send(); - } - -} - -module.exports = FileLoader; - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(process) {function CheckSupport() { - - if (process !== undefined && !process.browser) { - if (process.version.indexOf('v') !== 0) { - throw 'unknown node version.'; - } - - var vn = process.version.substring(1).split('.'); - var major = parseInt(vn[0]); - var minor = parseInt(vn[1]); - - if (major > 6) return true; - if (major === 6 && minor >= 6) return true; - - return false; - } - - else if (typeof window !== 'undefined') { - var supported = { - 'safari': 10, - 'chrome': 54 - }; - - return true; - } - - return true; - -} - -module.exports = CheckSupport; -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(9))) - -/***/ }), -/* 16 */ -/***/ (function(module, exports) { - -module['exports'] = function runTheTrap (text, options) { - var result = ""; - text = text || "Run the trap, drop the bass"; - text = text.split(''); - var trap = { - a: ["\u0040", "\u0104", "\u023a", "\u0245", "\u0394", "\u039b", "\u0414"], - b: ["\u00df", "\u0181", "\u0243", "\u026e", "\u03b2", "\u0e3f"], - c: ["\u00a9", "\u023b", "\u03fe"], - d: ["\u00d0", "\u018a", "\u0500" , "\u0501" ,"\u0502", "\u0503"], - e: ["\u00cb", "\u0115", "\u018e", "\u0258", "\u03a3", "\u03be", "\u04bc", "\u0a6c"], - f: ["\u04fa"], - g: ["\u0262"], - h: ["\u0126", "\u0195", "\u04a2", "\u04ba", "\u04c7", "\u050a"], - i: ["\u0f0f"], - j: ["\u0134"], - k: ["\u0138", "\u04a0", "\u04c3", "\u051e"], - l: ["\u0139"], - m: ["\u028d", "\u04cd", "\u04ce", "\u0520", "\u0521", "\u0d69"], - n: ["\u00d1", "\u014b", "\u019d", "\u0376", "\u03a0", "\u048a"], - o: ["\u00d8", "\u00f5", "\u00f8", "\u01fe", "\u0298", "\u047a", "\u05dd", "\u06dd", "\u0e4f"], - p: ["\u01f7", "\u048e"], - q: ["\u09cd"], - r: ["\u00ae", "\u01a6", "\u0210", "\u024c", "\u0280", "\u042f"], - s: ["\u00a7", "\u03de", "\u03df", "\u03e8"], - t: ["\u0141", "\u0166", "\u0373"], - u: ["\u01b1", "\u054d"], - v: ["\u05d8"], - w: ["\u0428", "\u0460", "\u047c", "\u0d70"], - x: ["\u04b2", "\u04fe", "\u04fc", "\u04fd"], - y: ["\u00a5", "\u04b0", "\u04cb"], - z: ["\u01b5", "\u0240"] - } - text.forEach(function(c){ - c = c.toLowerCase(); - var chars = trap[c] || [" "]; - var rand = Math.floor(Math.random() * chars.length); - if (typeof trap[c] !== "undefined") { - result += trap[c][rand]; - } else { - result += c; - } - }); - return result; - -} - - -/***/ }), -/* 17 */ -/***/ (function(module, exports) { - -// please no -module['exports'] = function zalgo(text, options) { - text = text || " he is here "; - var soul = { - "up" : [ - '̍', '̎', '̄', '̅', - '̿', '̑', '̆', '̐', - '͒', '͗', '͑', '̇', - '̈', '̊', '͂', '̓', - '̈', '͊', '͋', '͌', - '̃', '̂', '̌', '͐', - '̀', '́', '̋', '̏', - '̒', '̓', '̔', '̽', - '̉', 'ͣ', 'ͤ', 'ͥ', - 'ͦ', 'ͧ', 'ͨ', 'ͩ', - 'ͪ', 'ͫ', 'ͬ', 'ͭ', - 'ͮ', 'ͯ', '̾', '͛', - '͆', '̚' - ], - "down" : [ - '̖', '̗', '̘', '̙', - '̜', '̝', '̞', '̟', - '̠', '̤', '̥', '̦', - '̩', '̪', '̫', '̬', - '̭', '̮', '̯', '̰', - '̱', '̲', '̳', '̹', - '̺', '̻', '̼', 'ͅ', - '͇', '͈', '͉', '͍', - '͎', '͓', '͔', '͕', - '͖', '͙', '͚', '̣' - ], - "mid" : [ - '̕', '̛', '̀', '́', - '͘', '̡', '̢', '̧', - '̨', '̴', '̵', '̶', - '͜', '͝', '͞', - '͟', '͠', '͢', '̸', - '̷', '͡', ' ҉' - ] - }, - all = [].concat(soul.up, soul.down, soul.mid), - zalgo = {}; - - function randomNumber(range) { - var r = Math.floor(Math.random() * range); - return r; - } - - function is_char(character) { - var bool = false; - all.filter(function (i) { - bool = (i === character); - }); - return bool; - } - - - function heComes(text, options) { - var result = '', counts, l; - options = options || {}; - options["up"] = typeof options["up"] !== 'undefined' ? options["up"] : true; - options["mid"] = typeof options["mid"] !== 'undefined' ? options["mid"] : true; - options["down"] = typeof options["down"] !== 'undefined' ? options["down"] : true; - options["size"] = typeof options["size"] !== 'undefined' ? options["size"] : "maxi"; - text = text.split(''); - for (l in text) { - if (is_char(l)) { - continue; - } - result = result + text[l]; - counts = {"up" : 0, "down" : 0, "mid" : 0}; - switch (options.size) { - case 'mini': - counts.up = randomNumber(8); - counts.mid = randomNumber(2); - counts.down = randomNumber(8); - break; - case 'maxi': - counts.up = randomNumber(16) + 3; - counts.mid = randomNumber(4) + 1; - counts.down = randomNumber(64) + 3; - break; - default: - counts.up = randomNumber(8) + 1; - counts.mid = randomNumber(6) / 2; - counts.down = randomNumber(8) + 1; - break; - } - - var arr = ["up", "mid", "down"]; - for (var d in arr) { - var index = arr[d]; - for (var i = 0 ; i <= counts[index]; i++) { - if (options[index]) { - result = result + soul[index][randomNumber(soul[index].length)]; - } - } - } - } - return result; - } - // don't summon him - return heComes(text, options); -} - - -/***/ }), -/* 18 */ -/***/ (function(module, exports, __webpack_require__) { - -var colors = __webpack_require__(0); - -module['exports'] = function () { - - // - // Extends prototype of native string object to allow for "foo".red syntax - // - var addProperty = function (color, func) { - String.prototype.__defineGetter__(color, func); - }; - - var sequencer = function sequencer (map, str) { - return function () { - var exploded = this.split(""), i = 0; - exploded = exploded.map(map); - return exploded.join(""); - } - }; - - addProperty('strip', function () { - return colors.strip(this); - }); - - addProperty('stripColors', function () { - return colors.strip(this); - }); - - addProperty("trap", function(){ - return colors.trap(this); - }); - - addProperty("zalgo", function(){ - return colors.zalgo(this); - }); - - addProperty("zebra", function(){ - return colors.zebra(this); - }); - - addProperty("rainbow", function(){ - return colors.rainbow(this); - }); - - addProperty("random", function(){ - return colors.random(this); - }); - - addProperty("america", function(){ - return colors.america(this); - }); - - // - // Iterate through all default styles and colors - // - var x = Object.keys(colors.styles); - x.forEach(function (style) { - addProperty(style, function () { - return colors.stylize(this, style); - }); - }); - - function applyTheme(theme) { - // - // Remark: This is a list of methods that exist - // on String that you should not overwrite. - // - var stringPrototypeBlacklist = [ - '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'charAt', 'constructor', - 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf', 'charCodeAt', - 'indexOf', 'lastIndexof', 'length', 'localeCompare', 'match', 'replace', 'search', 'slice', 'split', 'substring', - 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight' - ]; - - Object.keys(theme).forEach(function (prop) { - if (stringPrototypeBlacklist.indexOf(prop) !== -1) { - console.log('warn: '.red + ('String.prototype' + prop).magenta + ' is probably something you don\'t want to override. Ignoring style name'); - } - else { - if (typeof(theme[prop]) === 'string') { - colors[prop] = colors[theme[prop]]; - addProperty(prop, function () { - return colors[theme[prop]](this); - }); - } - else { - addProperty(prop, function () { - var ret = this; - for (var t = 0; t < theme[prop].length; t++) { - ret = colors[theme[prop][t]](ret); - } - return ret; - }); - } - } - }); - } - - colors.setTheme = function (theme) { - if (typeof theme === 'string') { - try { - colors.themes[theme] = !(function webpackMissingModule() { var e = new Error("Cannot find module \".\""); e.code = 'MODULE_NOT_FOUND';; throw e; }()); - applyTheme(colors.themes[theme]); - return colors.themes[theme]; - } catch (err) { - console.log(err); - return err; - } - } else { - applyTheme(theme); - } - }; - -}; - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - -var colors = __webpack_require__(0); -module['exports'] = colors; - -// Remark: By default, colors will add style properties to String.prototype -// -// If you don't wish to extend String.prototype you can do this instead and native String will not be touched -// -// var colors = require('colors/safe); -// colors.red("foo") -// -// -__webpack_require__(18)(); - -/***/ }), -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { - -var colors = __webpack_require__(0); - -module['exports'] = (function() { - return function (letter, i, exploded) { - if(letter === " ") return letter; - switch(i%3) { - case 0: return colors.red(letter); - case 1: return colors.white(letter) - case 2: return colors.blue(letter) - } - } -})(); - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - -var colors = __webpack_require__(0); - -module['exports'] = (function () { - var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; //RoY G BiV - return function (letter, i, exploded) { - if (letter === " ") { - return letter; - } else { - return colors[rainbowColors[i++ % rainbowColors.length]](letter); - } - }; -})(); - - - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - -var colors = __webpack_require__(0); - -module['exports'] = (function () { - var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; - return function(letter, i, exploded) { - return letter === " " ? letter : colors[available[Math.round(Math.random() * (available.length - 1))]](letter); - }; -})(); - -/***/ }), -/* 23 */ -/***/ (function(module, exports, __webpack_require__) { - -var colors = __webpack_require__(0); - -module['exports'] = function (letter, i, exploded) { - return i % 2 === 0 ? letter : colors.inverse(letter); -}; - -/***/ }), -/* 24 */ -/***/ (function(module, exports) { - -/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var styles = {}; -module['exports'] = styles; - -var codes = { - reset: [0, 0], - - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29], - - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], - gray: [90, 39], - grey: [90, 39], - - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - - // legacy styles for colors pre v1.0.0 - blackBG: [40, 49], - redBG: [41, 49], - greenBG: [42, 49], - yellowBG: [43, 49], - blueBG: [44, 49], - magentaBG: [45, 49], - cyanBG: [46, 49], - whiteBG: [47, 49] - -}; - -Object.keys(codes).forEach(function (key) { - var val = codes[key]; - var style = styles[key] = []; - style.open = '\u001b[' + val[0] + 'm'; - style.close = '\u001b[' + val[1] + 'm'; -}); - -/***/ }), -/* 25 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(process) {/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var argv = process.argv; - -module.exports = (function () { - if (argv.indexOf('--no-color') !== -1 || - argv.indexOf('--color=false') !== -1) { - return false; - } - - if (argv.indexOf('--color') !== -1 || - argv.indexOf('--color=true') !== -1 || - argv.indexOf('--color=always') !== -1) { - return true; - } - - if (process.stdout && !process.stdout.isTTY) { - return false; - } - - if (process.platform === 'win32') { - return true; - } - - if ('COLORTERM' in process.env) { - return true; - } - - if (process.env.TERM === 'dumb') { - return false; - } - - if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { - return true; - } - - return false; -})(); -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(9))) - -/***/ }), -/* 26 */ -/***/ (function(module, exports) { - -var g; - -// This works in non-strict mode -g = (function() { - return this; -})(); - -try { - // This works if eval is allowed (see CSP) - g = g || Function("return this")() || (1,eval)("this"); -} catch(e) { - // This works if the window reference is available - if(typeof window === "object") - g = window; -} - -// g can still be undefined, but nothing to do about it... -// We return undefined, instead of nothing here, so it's -// easier to handle this case. if(!global) { ...} - -module.exports = g; - - -/***/ }), -/* 27 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Size = __webpack_require__(1); - -// http://arxiv.org/pdf/1505.05424.pdf -class VariationalBayesianLayer { - - constructor(input, opt) { - opt.size = Size.derive(opt.size) - - this.dimensions = { - input, - output: opt.size, - parameters: 2 * (input.length * opt.size.length + opt.size.length) // mean and std - } - - this.storage = { - sample: input.length * opt.size.length + opt.size.length, - weights: input.length * opt.size.length + opt.size.length - } - - - } - - forward(ctx) { - var sum = 0.0, X = this.dimensions.input.length, Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w, paramw = ctx.params.w - var sampled = ctx.sample, weights = ctx.weights, epsilon = 0 - var mu, std, w, b - - for (var i = 0; i < Y; i++) { - sum = 0.0 - for (var j = 0; j < X; j++) { - mu = paramw[(i * X + j) * 2 + 0] - std = Math.log(1 + Math.exp( paramw[(i * X + j) * 2 + 1] )) - - sampled[i * X + j] = epsilon = Math.randn() - weights[i * X + j] = w = mu + std * epsilon - - sum += inpw[j] * w - } - - mu = paramw[(X * Y + i) * 2 + 0] - std = Math.log(1 + Math.exp( paramw[(X * Y + i) * 2 + 1] )) - - sampled[X * Y + i] = epsilon = Math.randn() - weights[X * Y + i] = b = mu + std * epsilon - - outw[i] = sum + b - } - - } - - backward(ctx) { - var sum = 0.0, X = this.dimensions.input.length, Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w, paramw = ctx.params.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw, paramdw = ctx.params.dw - var sampled = ctx.sample, weights = ctx.weights - - for (var i = 0; i < X; i++) { - sum = 0.0 - for (var j = 0; j < Y; j++) { - paramdw[(j * X + i) * 2 + 0] = inpw[i] * outdw[j] - paramdw[(j * X + i) * 2 + 1] = inpw[i] * outdw[j] * sampled[j * X + i] / (1.0 + Math.exp(-paramw[(j * X + i) * 2 + 1])) - sum += weights[j * X + i] * outdw[j] - } - - inpdw[i] = sum - } - - for (var i = 0; i < Y; i++) { - paramdw[(X * Y + i) * 2 + 0] = outdw[i] - paramdw[(X * Y + i) * 2 + 1] = outdw[i] * sampled[X * Y + i] / (1.0 + Math.exp(-paramw[(X * Y + i) * 2 + 1])) - } - } - - initialize(params) { - var H = this.dimensions.parameters / 2 - var elements = (this.dimensions.input.length + this.dimensions.output.length) - var scale = Math.sqrt(2.0 / elements) - - for (var i = 0; i < H; i+=2) { - params.w[i] = Math.randn() * scale - params.w[i + 1] = Math.randn() - } - } - -} - -module.exports = { - VariationalBayesianLayer -} - -/***/ }), -/* 28 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Size = __webpack_require__(1); - -class FullyConnectedLayer { - - constructor(input, opt) { - opt.size = Size.derive(opt.size) - - this.dimensions = { - input, - output: opt.size, - parameters: input.length * opt.size.length + opt.size.length - } - - } - - forward(ctx) { - var sum = 0.0, X = this.dimensions.input.length, Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w, paramw = ctx.params.w - - - for (var i = 0; i < Y; i++) { - sum = 0.0 - for (var j = 0; j < X; j++) { - sum += inpw[j] * paramw[i * X + j] - } - - outw[i] = sum + paramw[X * Y + i] - } - - // outw.set(this.fwd(inpw, paramw)); - } - - backward(ctx) { - var sum = 0.0, X = this.dimensions.input.length, Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w, paramw = ctx.params.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw, paramdw = ctx.params.dw - - for (var i = 0; i < X; i++) { - sum = 0.0 - for (var j = 0; j < Y; j++) { - sum += paramw[j * X + i] * outdw[j] - paramdw[j * X + i] = inpw[i] * outdw[j] - } - - inpdw[i] = sum - } - - for (var i = 0; i < Y; i++) { - paramdw[X * Y + i] = outdw[i] - } - } - - initialize(params) { - var X = this.dimensions.input.length, Y = this.dimensions.output.length - - if (this.options.init) { - params.w.randn(0.0, this.options.init) - } - - else { - // var dropout = this.options.dropout || 0 - // var elements = (1 - dropout) * (this.dimensions.input.length + this.dimensions.output.length) - var scale = Math.sqrt(1.0 / X) - params.w.randn((this.options.mean / X) || 0.0, scale) - } - - // biases should be zero - for (var i = 0; i < Y; i++) { - params.w[X * Y + i] = 0.0 - } - } - -} - -module.exports = { - FullyConnectedLayer -} - -/***/ }), -/* 29 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -class DropOutLayer { - - constructor(input, opt) { - this.dimensions = { - input, - output: input, - parameters: 0 - } - - this.probability = opt.probability - this.storage = { - activations: input - } - } - - forward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var prob = this.probability, act = ctx.activations - - // if (ctx.state.options.learning !== true) { - // for (var i = 0; i < X; i++) - // outw[i] = inpw[i] * prob - - // return - // } - - for (var i = 0; i < X; i++) { - if (Math.random() < prob) { // dropping out - outw[i] = 0.0 - act[i] = 0.0 - } - - else { - outw[i] = inpw[i] / (1.0 - prob) - act[i] = 1.0 - } - } - } - - backward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw - var prob = this.probability, act = ctx.activations - - // if (ctx.state.options.learning !== true) { - // // for (var i = 0; i < X; i++) - // // inpdw[i] = outdw[i] * prob - - // return - // } - - for (var i = 0; i < X; i++) { - inpdw[i] = act[i] * outdw[i] / (1.0 - prob) - } - } - -} - -module.exports = { - DropOutLayer -}; - -/***/ }), -/* 30 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Size = __webpack_require__(1); - -class InputLayer { - - constructor(inp, opt) { - this.dimensions = { - input: Size.derive(opt.size), - output: Size.derive(opt.size), - parameters: 0 - }; - - this.input = true - this.passthrough = true - } - - toInputVector(input, out) { - if (input === undefined) - return - - if (Number.isInteger(input) && input < this.dimensions.intrinsic) { - out.fill(0.0) - out[input] = 1.0 - } - - else if (input.length === out.length) { - out.set(input) - } - - else { - throw 'invalid input format'; - } - } - -} - -module.exports = { - InputLayer -} - -/***/ }), -/* 31 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - - -class UhlenbeckOrnsteinNoiseLayer { - - constructor(input, opt) { - this.dimensions = { - input, - output: input, - parameters: 0 - } - - this.theta = opt.theta || 0.15 - this.sigma = opt.sigma || 0.3 - this.delta = opt.delta || 0.1 - - this.storage = { - noise: input - } - } - - forward(ctx) { - var X = this.dimensions.input.length - var outw = ctx.output.w, inpw = ctx.input.w - - var alpha = 0.3 - for (var i = 0; i < X; i++) { - outw[i] = (1-alpha) * inpw[i] + alpha * (ctx.noise[i] = Math.uhlenbeckOrnstein(ctx.noise[i], this.theta, this.sigma, this.delta)) - } - } - - backward(ctx) { - ctx.input.dw.set(ctx.output.dw) - } - -} - -module.exports = { - UhlenbeckOrnsteinNoiseLayer -}; - - -/***/ }), -/* 32 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -class NonLinearityLayer { - - constructor(input, opt) { - this.dimensions = { - input, - output: input, - parameters: 0 - }; - } - -} - -class SigmoidLayer extends NonLinearityLayer { - - forward(ctx) { - var X = this.dimensions.input.length; - var inpw = ctx.input.w, outw = ctx.output.w - - for (var i = 0; i < X; i++) { - outw[i] = 1 / (1 + Math.exp(-inpw[i])) - } - } - - backward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw - - for (var i = 0; i < X; i++) { - inpdw[i] = outw[i] * (1.0 - outw[i]) * outdw[i] - } - } - -} - -class TanhLayer extends NonLinearityLayer { - - forward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var y = 0.0; - - for (var i = 0; i < X; i++) { - y = Math.exp(2 * inpw[i]); - outw[i] = (y - 1) / (y + 1); - } - } - - backward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw - - for (var i = 0; i < X; i++) { - inpdw[i] = (1 - outw[i] * outw[i]) * outdw[i]; - } - } - -} - -class ReLULayer extends NonLinearityLayer { - - constructor(input, opt) { - super(input, opt) - this.leaky = opt.leaky || 0 - } - - forward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var y = 0.0; - - for (var i = 0; i < X; i++) { - outw[i] = (inpw[i] > 0.0 ? inpw[i] : this.leaky * inpw[i]); - } - } - - backward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw - - for (var i = 0; i < X; i++) { - inpdw[i] = (inpw[i] > 0.0 ? 1.0 : this.leaky) * outdw[i]; - } - } - -} - -class ELULayer extends NonLinearityLayer { - - constructor(input, opt) { - super(input, opt) - this.alpha = opt.alpha || 1.0 - } - - forward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var y = 0.0; - - for (var i = 0; i < X; i++) { - outw[i] = (inpw[i] > 0.0 ? inpw[i] : this.alpha * (Math.exp(inpw[i]) - 1)); - } - } - - backward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw - - for (var i = 0; i < X; i++) { - inpdw[i] = (inpw[i] > 0.0 ? 1.0 : outw[i] + this.alpha) * outdw[i]; - } - } - -} - -module.exports = { - SigmoidLayer, TanhLayer, ReLULayer, ELULayer -}; - -/***/ }), -/* 33 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -class OutputLayer { - - constructor(inp, opt) { - this.dimensions = { - input: inp, - output: inp, - parameters: 0 - }; - - this.output = true - } - - result(ctx) { - return ctx.output.w.clone() - } - - -} - -class SoftmaxLayer extends OutputLayer { - - forward(ctx) { - var X = this.dimensions.input.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpmax = -Infinity - - for (var i = 0; i < X; ++i) - if (inpw[i] > inpmax) inpmax = inpw[i] - - var expsum = 0.0 - for (var i = 0; i < X; ++i) - expsum += outw[i] = Math.exp(inpw[i] - inpmax) - - for (var i = 0; i < X; ++i) - outw[i] /= expsum - } - - backward(ctx) { - var X = this.dimensions.input.length - var inpdw = ctx.input.dw - var outdw = ctx.output.dw, outw = ctx.output.w - - for (var i = 0; i < X; i++) { - var sum = outw[i] * (1 - outw[i]) * outdw[i] - - for (var j = 0; j < X; j++) { - if (i !== j) sum -= outw[j] * outw[i] * outdw[j] - } - - inpdw[i] = sum - } - } - - loss(ctx, desired, target) { - return -Math.log(ctx.output.w[desired]) - } - - toGradientVector(desired, actual, out) { - if (Number.isInteger(desired) !== true || desired >= this.size) - throw 'target must be class index in softmax' - - for (var i = 0; i < this.size; i++) { - out[i] = actual[i] - (desired === i ? 1.0 : 0.0) - } - } - -} - -class RegressionLayer extends OutputLayer { - - constructor(inp, opt) { - super(inp, opt) - this.passthrough = true - } - - loss(ctx, desired) { - var loss = 0.0 - var grads = this.toGradientVector(desired, ctx.output.w) - - for (var i = 0; i < this.dimensions.input.length; i++) { - loss += 0.5 * grads[i] * grads[i] - } - - return loss - } - - toGradientVector(desired, actual, out) { - var X = this.dimensions.input.length - - if (out === undefined) { - out = new Float64Array(X) - } - - // target is maximizing argmax, set n-th value to 1, rest to 0 - if (X > 1 && !isNaN(desired) && Number.isInteger(desired) && desired < X) { - for (var i = 0; i < X; ++i) { - out[i] = actual[i] - (i === desired ? 1.0 : 0.0) - } - } - - // single value output - else if (X === 1 && !isNaN(desired)) { - out[0] = actual[0] - desired - } - - else if (desired instanceof Array || desired instanceof Float64Array) { - for (var i = 0; i < out.length; ++i) { - out[i] = actual[i] - desired[i] - } - } - - else { - throw 'invalid target' - } - - return out - } - -} - -module.exports = { - RegressionLayer, SoftmaxLayer -}; - - -/***/ }), -/* 34 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Size = __webpack_require__(1); - -function sigm(x) { - return 1 / (1 + Math.exp(-x)) -} - -function dsigm(fx) { - return fx * (1.0 - fx) -} - -class VariationalLayer { - - constructor(input, opt) { - if (input.length % 2 !== 0) { - throw 'input must be divisible by two.' - } - - this.dimensions = { - input: input, - output: new Size(1, 1, input.length / 2), - parameters: 0 - } - - this.storage = { - samples: this.dimensions.output.length - } - - this.variance_decay = opt.variance_decay || 0.0 - - } - - forward(ctx) { - var Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w - var samples = ctx.samples - - for (var i = 0; i < Y; i++) { - var eps = Math.randn(0.0, 1.0) - outw[i] = inpw[2 * i + 0] + inpw[2 * i + 1] * eps - samples[i] = eps - } - } - - backward(ctx) { - var Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw - var samples = ctx.samples - - for (var i = 0; i < Y; i++) { - inpdw[2 * i + 0] += outdw[i] - inpdw[2 * i + 1] += samples[i] * outdw[i] - } - } - -} - - -class VariationalBinaryLayer { - - constructor(input, opt) { - this.dimensions = { - input: input, - output: new Size(1, 1, input.length), - parameters: 0 - } - - this.storage = { - probs: this.dimensions.output.length - } - - } - - forward(ctx) { - var Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w - var probs = ctx.probs - - for (var i = 0; i < Y; i++) { - var eps = Math.random() - probs[i] = sigm(inpw[i]) // activate with probability - outw[i] = eps <= probs[i] ? 1.0 : 0.0 - } - } - - backward(ctx) { - var Y = this.dimensions.output.length - var inpw = ctx.input.w, outw = ctx.output.w - var inpdw = ctx.input.dw, outdw = ctx.output.dw - var probs = ctx.probs - - for (var i = 0; i < Y; i++) { - inpdw[i] = dsigm( probs[i] ) * outdw[i] - } - } - -} - - -module.exports = { - VariationalBinaryLayer -} - -/***/ }), -/* 35 */ -/***/ (function(module, exports, __webpack_require__) { - -var Size = __webpack_require__(1); - -module.exports = class Tensor { - - constructor(size) { - this.size = Size.derive(size) - this.w = new Float64Array(this.size.length); - this.dw = new Float64Array(this.size.length); - } - -} - -/***/ }), -/* 36 */ -/***/ (function(module, exports) { - -class Window { - - constructor(n) { - this.list = [] - this.length = n - } - - push(value) { - this.list.unshift(value) - - if (this.list.length > this.length) { - this.list.pop() - } - } - - get(nth) { - return this.list[nth] - } - - get size() { - return this.list.length - } - -} - -module.exports = Window - -/***/ }), -/* 37 */ -/***/ (function(module, exports, __webpack_require__) { - -var network = __webpack_require__(2) -var shared = __webpack_require__(3) - -var NetOnDisk = __webpack_require__(6) -var Algorithm = __webpack_require__(10) - - -/* Deep deterministic policy gradient */ -class DDPG extends Algorithm { - - constructor(agent) { - super() - // options - this.options = Object.assign({ - alpha: 0, // advantage learning (AL) http://arxiv.org/pdf/1512.04860v1.pdf; increase action-gap - theta: 0.001, // soft target updates - }, agent.options) - - - this.actor = new shared.NetworkWrapper() - this.critic = new shared.NetworkWrapper() - - // target networks - - var targetCreate = (wrapper, state) => { - wrapper.live = state - - if (this.options.theta < 1) { - wrapper.target = wrapper.live.model.newState() - } - - else { - wrapper.target = wrapper.live - } - } - - this.actor.on('set', targetCreate) - this.critic.on('set', targetCreate) - - // network validations - - this.actor.on('set', (wrapper, state) => { - if (state.in.w.length !== this.agent.input) { - throw 'actor input length insufficient' - } - - if (state.out.w.length !== this.agent.actions) { - throw 'actor output insufficient' - } - }) - - this.critic.on('set', (wrapper, state) => { - if (state.in.w.length !== this.agent.input + this.agent.actions) { - throw 'critic input length insufficient' - } - - if (state.out.w.length !== 1) { - throw 'critic output length insufficient' - } - }) - - // optimizer - - this.actor.useOptimizer({ - type: 'ascent', - method: 'adadelta', - regularization: { l2: 1e-2 } - }) - - this.critic.useOptimizer({ - type: 'descent', - method: 'adadelta', - regularization: { l2: 1e-3 } - }) - - // agent - this.agent = agent - - this.input = agent.input - this.buffer = agent.buffer - - // network weight updates - this.targetActorUpdate = this.progressiveCopy.bind(this, this.actor) - this.targetCriticUpdate = this.progressiveCopy.bind(this, this.critic) - - // adopt networks - this.actor.set(this.options.actor) - this.critic.set(this.options.critic) - } - - act(state, target) { - if (target) { - return this.actor.target.forward(state) - } - - return this.actor.live.forward(state) - } - - value(state, action, target) { - var net = target ? this.critic.target : this.critic.live - - net.in.w.set(state, 0) - net.in.w.set(action, this.input) - - return net.forward()[0] - } - - optimize(e, descent = true) { - var target = e.target() - var value = e.estimate() - - var grad = value - target - var gradAL = grad - - if (this.options.alpha > 0) { - gradAL = grad + this.options.alpha * (value - this.evaluate(e.state0, true)) // advantage learning - } - - if (descent) { - var isw = this.buffer.getImportanceSamplingWeight(e) - this.critic.live.backwardWithGradient(gradAL * isw) - this.critic.live.configuration.accumulate() - this.teach(e, isw) - } - - return 0.5 * gradAL * gradAL // Math.pow(this.teach(e, isw, descent) - target, 2) - } - - teach(e, isw = 1.0, descent = true) { - var action = this.actor.live.forward(e.state0) // which action to take? - var val = this.value(e.state0, action) // how good will the future be, if i take this action? - var grad = this.critic.live.derivatives(0, false) // how will the future change, if i change this action - - for (var i = 0; i < this.options.actions; i++) { - this.actor.live.out.dw[i] = grad[this.input + i] * isw - } - - if (descent) { - this.actor.live.backward() // propagate change - this.actor.config.accumulate() - } - } - - learn() { - // Improve through batch accumuluated gradients - this.actor.optimize() - this.critic.optimize() - - // Copy actor and critic to target networks slowly - this.targetNetworkUpdates() - } - - targetNetworkUpdates() { - this.actor.target.configuration.forEachParameter(this.targetActorUpdate) - this.critic.target.configuration.forEachParameter(this.targetCriticUpdate) - } - - progressiveCopy(net, param, index) { - if (this.options.theta >= 1) { - return - } - - // _ = network in use, no _ = target network - var _theta = this.options.theta, _paramw = net.config.parameters[index].w - var theta = 1.0 - _theta, paramw = param.w - - for (var i = 0; i < param.w.length; i++) { - paramw[i] = _theta * _paramw[i] + theta * paramw[i] - } - } - - - import(file) { - var multiPart = NetOnDisk.readMultiPart(file) - this.actor.set(multiPart.actor) - this.critic.set(multiPart.critic) - } - - export() { - return NetOnDisk.writeMultiPart({ - 'actor': this.actor.config, - 'critic': this.critic.config - }) - } - -} - -module.exports = DDPG; - -/***/ }), -/* 38 */ -/***/ (function(module, exports, __webpack_require__) { - -var Algorithm = __webpack_require__(10) - -class DQN extends Algorithm { - - constructor(agent) { - // options - this.options = Object.assign({ - - alpha: 0.1, // advantage learning (AL) http://arxiv.org/pdf/1512.04860v1.pdf; increase action-gap - theta: 0.001, // soft target updates - - learningSteps: 100e3, - learningStepsBurnin: 3e3, - - epsilonMin: 0.05, - epsilonAtTestTime: 0.05 - - - }, agent.options) - - // - this.net = agent.options.network.newState() - this.target = this.net.model.newState() // agent.options.target.actor.newState() - // this.target.configuration.copyParametersFrom(this.net.configuration) - - // - this.targetWeightCopy = this.progressiveCopy.bind(this, this.net.configuration) - - this.net.configuration.useOptimizer({ - type: 'descent', - method: 'adadelta', - regularization: { l2: 1e-3 } - }) - - // agent - this.agent = agent - this.buffer = agent.buffer - - this.states = this.agent.states - this.actions = this.agent.actions - this.input = this.agent.input - } - - // what to do? - act(state, target) { - - if (this.agent.learning) - this.epsilon = Math.max(1.0 - Math.max((this.agent.age - this.options.learningStepsBurnin) / this.options.learningSteps, 0.0), this.options.epsilonMin) - else - this.epsilon = this.options.epsilonAtTestTime - - if (Math.random() <= this.epsilon) { - return Math.randi(0, this.actions) - } - - this.net.forward(state) - - return this.net.out.w.maxi() - - } - - // how good is an action at state - value(state, action, target) { - target = target == null ? this.net : this.target - target.forward(state) - return target.out.w[action] - } - - // replay - optimize(e, descent = true) { - var target = e.target() - var value = e.estimate() - - var grad = value - target - var gradAL = grad + this.options.alpha * (value - this.agent.evaluate(e.state0, true)) // advantage learning - var isw = this.buffer.getImportanceSamplingWeight(e) - - this.net.out.dw.fill(0.0) - this.net.out.dw[e.action0] = gradAL * isw - - if (descent) { - this.net.backward() - this.net.configuration.accumulate() - } - - return gradAL * gradAL * 0.5 - } - - // adjust weights etc - learn() { - this.net.configuration.optimize(false) - this.targetUpdate() - } - - - targetUpdate() { - if (this.options.theta < 1) { - this.target.configuration.forEachParameter(this.targetWeightCopy) - } - } - - progressiveCopy(net, param, index) { - var _theta = this.options.theta - for (var i = 0; i < param.w.length; i++) { - param.w[i] = _theta * net.parameters[index].w[i] + (1.0 - _theta) * param.w[i] - } - } - - - import(params) { - if (params.length !== this.net.configuration.countOfParameters) - return false - - this.net.configuration.read(params) - - return true - } - - export() { - return this.net.configuration.write() - } - -} - -module.exports = DQN; - -/***/ }), -/* 39 */ -/***/ (function(module, exports) { - -class Experience { - - constructor(agent) { - this.agent = agent - this.learnSteps = 0 - - if (agent.options.type === 'sarsa') - this.target = this.__sarsa_target - else - this.target = this.__q_target - } - - __q_target() { - return this.reward0 + this.agent.options.discount * this.agent.evaluate(this.state1, true) // this.agent.value(this.state1, this.agent.act(this.state1, true), true) - } - - __sarsa_target() { - return this.reward0 + this.agent.options.discount * this.agent.value(this.state1, this.action1, true) - } - - estimate() { - return this.value = this.agent.value(this.state0, this.action0) - } - - step() { - this.loss = this.agent.algorithm.optimize(this) - - this.learnSteps++ - this.lastLearnedAt = this.agent.age - - return this.loss - } - - init() { - this.loss = this.agent.algorithm.optimize(this, false) - this.atAge = this.agent.age - } - - get priority() { - if (this.loss === undefined) - return undefined - - return Math.pow(this.loss, this.agent.options.beta || 0.5) - } - -} - -module.exports = Experience - -/***/ }), -/* 40 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/*\ -|*| -|*| :: Number.isInteger() polyfill :: -|*| -|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger -|*| -\*/ - -if (!Number.isInteger) { - Number.isInteger = function isInteger (nVal) { - return typeof nVal === "number" && isFinite(nVal) && nVal > -9007199254740992 && nVal < 9007199254740992 && Math.floor(nVal) === nVal; - }; -} - -/*\ -|*| -|*| StringView - Mozilla Developer Network -|*| -|*| Revision #9, October 30, 2016 -|*| -|*| https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView -|*| https://developer.mozilla.org/en-US/docs/User:fusionchess -|*| https://github.com/madmurphy/stringview.js -|*| -|*| This framework is released under the GNU Lesser General Public License, version 3 or later. -|*| http://www.gnu.org/licenses/lgpl-3.0.html -|*| -\*/ - -function StringView (vInput, sEncoding /* optional (default: UTF-8) */, nOffset /* optional */, nLength /* optional */) { - - var fTAView, aWhole, aRaw, fPutOutptCode, fGetOutptChrSize, nInptLen, nStartIdx = isFinite(nOffset) ? nOffset : 0, nTranscrType = 15; - - if (sEncoding) { this.encoding = sEncoding.toString(); } - - encSwitch: switch (this.encoding) { - case "UTF-8": - fPutOutptCode = StringView.putUTF8CharCode; - fGetOutptChrSize = StringView.getUTF8CharLength; - fTAView = Uint8Array; - break encSwitch; - case "UTF-16": - fPutOutptCode = StringView.putUTF16CharCode; - fGetOutptChrSize = StringView.getUTF16CharLength; - fTAView = Uint16Array; - break encSwitch; - case "UTF-32": - fTAView = Uint32Array; - nTranscrType &= 14; - break encSwitch; - default: - /* case "ASCII", or case "BinaryString" or unknown cases */ - fTAView = Uint8Array; - nTranscrType &= 14; - } - - typeSwitch: switch (typeof vInput) { - case "string": - /* the input argument is a primitive string: a new buffer will be created. */ - nTranscrType &= 7; - break typeSwitch; - case "object": - classSwitch: switch (vInput.constructor) { - case StringView: - /* the input argument is a stringView: a new buffer will be created. */ - nTranscrType &= 3; - break typeSwitch; - case String: - /* the input argument is an objectified string: a new buffer will be created. */ - nTranscrType &= 7; - break typeSwitch; - case ArrayBuffer: - /* the input argument is an arrayBuffer: the buffer will be shared. */ - aWhole = new fTAView(vInput); - nInptLen = this.encoding === "UTF-32" ? - vInput.byteLength >>> 2 - : this.encoding === "UTF-16" ? - vInput.byteLength >>> 1 - : - vInput.byteLength; - aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ? - aWhole - : new fTAView(vInput, nStartIdx, !isFinite(nLength) ? nInptLen - nStartIdx : nLength); - - break typeSwitch; - case Uint32Array: - case Uint16Array: - case Uint8Array: - /* the input argument is a typedArray: the buffer, and possibly the array itself, will be shared. */ - fTAView = vInput.constructor; - nInptLen = vInput.length; - aWhole = vInput.byteOffset === 0 && vInput.length === ( - fTAView === Uint32Array ? - vInput.buffer.byteLength >>> 2 - : fTAView === Uint16Array ? - vInput.buffer.byteLength >>> 1 - : - vInput.buffer.byteLength - ) ? vInput : new fTAView(vInput.buffer); - aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ? - vInput - : vInput.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen); - - break typeSwitch; - default: - /* the input argument is an array or another serializable object: a new typedArray will be created. */ - aWhole = new fTAView(vInput); - nInptLen = aWhole.length; - aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ? - aWhole - : aWhole.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen); - } - break typeSwitch; - default: - /* the input argument is a number, a boolean or a function: a new typedArray will be created. */ - aWhole = aRaw = new fTAView(Number(vInput) || 0); - - } - - if (nTranscrType < 8) { - - var vSource, nOutptLen, nCharStart, nCharEnd, nEndIdx, fGetInptChrSize, fGetInptChrCode; - - if (nTranscrType & 4) { /* input is string */ - - vSource = vInput; - nOutptLen = nInptLen = vSource.length; - nTranscrType ^= this.encoding === "UTF-32" ? 0 : 2; - /* ...or...: nTranscrType ^= Number(this.encoding !== "UTF-32") << 1; */ - nStartIdx = nCharStart = nOffset ? Math.max((nOutptLen + nOffset) % nOutptLen, 0) : 0; - nEndIdx = nCharEnd = (Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0) + nStartIdx, nOutptLen) : nOutptLen) - 1; - - } else { /* input is stringView */ - - vSource = vInput.rawData; - nInptLen = vInput.makeIndex(); - nStartIdx = nCharStart = nOffset ? Math.max((nInptLen + nOffset) % nInptLen, 0) : 0; - nOutptLen = Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0), nInptLen - nCharStart) : nInptLen; - nEndIdx = nCharEnd = nOutptLen + nCharStart; - - if (vInput.encoding === "UTF-8") { - fGetInptChrSize = StringView.getUTF8CharLength; - fGetInptChrCode = StringView.loadUTF8CharCode; - } else if (vInput.encoding === "UTF-16") { - fGetInptChrSize = StringView.getUTF16CharLength; - fGetInptChrCode = StringView.loadUTF16CharCode; - } else { - nTranscrType &= 1; - } - - } - - if (nOutptLen === 0 || nTranscrType < 4 && vSource.encoding === this.encoding && nCharStart === 0 && nOutptLen === nInptLen) { - - /* the encoding is the same, the length too and the offset is 0... or the input is empty! */ - - nTranscrType = 7; - - } - - conversionSwitch: switch (nTranscrType) { - - case 0: - - /* both the source and the new StringView have a fixed-length encoding... */ - - aWhole = new fTAView(nOutptLen); - for (var nOutptIdx = 0; nOutptIdx < nOutptLen; aWhole[nOutptIdx] = vSource[nStartIdx + nOutptIdx++]); - break conversionSwitch; - - case 1: - - /* the source has a fixed-length encoding but the new StringView has a variable-length encoding... */ - - /* mapping... */ - - nOutptLen = 0; - - for (var nInptIdx = nStartIdx; nInptIdx < nEndIdx; nInptIdx++) { - nOutptLen += fGetOutptChrSize(vSource[nInptIdx]); - } - - aWhole = new fTAView(nOutptLen); - - /* transcription of the source... */ - - for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx++) { - nOutptIdx = fPutOutptCode(aWhole, vSource[nInptIdx], nOutptIdx); - } - - break conversionSwitch; - - case 2: - - /* the source has a variable-length encoding but the new StringView has a fixed-length encoding... */ - - /* mapping... */ - - nStartIdx = 0; - - var nChrCode; - - for (nChrIdx = 0; nChrIdx < nCharStart; nChrIdx++) { - nChrCode = fGetInptChrCode(vSource, nStartIdx); - nStartIdx += fGetInptChrSize(nChrCode); - } - - aWhole = new fTAView(nOutptLen); - - /* transcription of the source... */ - - for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx += fGetInptChrSize(nChrCode), nOutptIdx++) { - nChrCode = fGetInptChrCode(vSource, nInptIdx); - aWhole[nOutptIdx] = nChrCode; - } - - break conversionSwitch; - - case 3: - - /* both the source and the new StringView have a variable-length encoding... */ - - /* mapping... */ - - nOutptLen = 0; - - var nChrCode; - - for (var nChrIdx = 0, nInptIdx = 0; nChrIdx < nCharEnd; nInptIdx += fGetInptChrSize(nChrCode)) { - nChrCode = fGetInptChrCode(vSource, nInptIdx); - if (nChrIdx === nCharStart) { nStartIdx = nInptIdx; } - if (++nChrIdx > nCharStart) { nOutptLen += fGetOutptChrSize(nChrCode); } - } - - aWhole = new fTAView(nOutptLen); - - /* transcription... */ - - for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx += fGetInptChrSize(nChrCode)) { - nChrCode = fGetInptChrCode(vSource, nInptIdx); - nOutptIdx = fPutOutptCode(aWhole, nChrCode, nOutptIdx); - } - - break conversionSwitch; - - case 4: - - /* DOMString to ASCII or BinaryString or other unknown encodings */ - - aWhole = new fTAView(nOutptLen); - - /* transcription... */ - - for (var nIdx = 0; nIdx < nOutptLen; nIdx++) { - aWhole[nIdx] = vSource.charCodeAt(nIdx) & 0xff; - } - - break conversionSwitch; - - case 5: - - /* DOMString to UTF-8 or to UTF-16 */ - - /* mapping... */ - - nOutptLen = 0; - - for (var nMapIdx = 0; nMapIdx < nInptLen; nMapIdx++) { - if (nMapIdx === nCharStart) { nStartIdx = nOutptLen; } - nOutptLen += fGetOutptChrSize(vSource.charCodeAt(nMapIdx)); - if (nMapIdx === nCharEnd) { nEndIdx = nOutptLen; } - } - - aWhole = new fTAView(nOutptLen); - - /* transcription... */ - - for (var nOutptIdx = 0, nChrIdx = 0; nOutptIdx < nOutptLen; nChrIdx++) { - nOutptIdx = fPutOutptCode(aWhole, vSource.charCodeAt(nChrIdx), nOutptIdx); - } - - break conversionSwitch; - - case 6: - - /* DOMString to UTF-32 */ - - aWhole = new fTAView(nOutptLen); - - /* transcription... */ - - for (var nIdx = 0; nIdx < nOutptLen; nIdx++) { - aWhole[nIdx] = vSource.charCodeAt(nIdx); - } - - break conversionSwitch; - - case 7: - - aWhole = new fTAView(nOutptLen ? vSource : 0); - break conversionSwitch; - - } - - aRaw = nTranscrType > 3 && (nStartIdx > 0 || nEndIdx < aWhole.length - 1) ? aWhole.subarray(nStartIdx, nEndIdx) : aWhole; - - } - - this.buffer = aWhole.buffer; - this.bufferView = aWhole; - this.rawData = aRaw; - - Object.freeze(this); - -} - -/* CONSTRUCTOR'S METHODS */ - -StringView.loadUTF8CharCode = function (aChars, nIdx) { - - var nLen = aChars.length, nPart = aChars[nIdx]; - - return nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? - /* (nPart - 252 << 30) may be not safe in ECMAScript! So...: */ - /* six bytes */ (nPart - 252) * 1073741824 + (aChars[nIdx + 1] - 128 << 24) + (aChars[nIdx + 2] - 128 << 18) + (aChars[nIdx + 3] - 128 << 12) + (aChars[nIdx + 4] - 128 << 6) + aChars[nIdx + 5] - 128 - : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? - /* five bytes */ (nPart - 248 << 24) + (aChars[nIdx + 1] - 128 << 18) + (aChars[nIdx + 2] - 128 << 12) + (aChars[nIdx + 3] - 128 << 6) + aChars[nIdx + 4] - 128 - : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? - /* four bytes */(nPart - 240 << 18) + (aChars[nIdx + 1] - 128 << 12) + (aChars[nIdx + 2] - 128 << 6) + aChars[nIdx + 3] - 128 - : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? - /* three bytes */ (nPart - 224 << 12) + (aChars[nIdx + 1] - 128 << 6) + aChars[nIdx + 2] - 128 - : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? - /* two bytes */ (nPart - 192 << 6) + aChars[nIdx + 1] - 128 - : - /* one byte */ nPart; - -}; - -StringView.putUTF8CharCode = function (aTarget, nChar, nPutAt) { - - var nIdx = nPutAt; - - if (nChar < 0x80 /* 128 */) { - /* one byte */ - aTarget[nIdx++] = nChar; - } else if (nChar < 0x800 /* 2048 */) { - /* two bytes */ - aTarget[nIdx++] = 0xc0 /* 192 */ + (nChar >>> 6); - aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */); - } else if (nChar < 0x10000 /* 65536 */) { - /* three bytes */ - aTarget[nIdx++] = 0xe0 /* 224 */ + (nChar >>> 12); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */); - } else if (nChar < 0x200000 /* 2097152 */) { - /* four bytes */ - aTarget[nIdx++] = 0xf0 /* 240 */ + (nChar >>> 18); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */); - } else if (nChar < 0x4000000 /* 67108864 */) { - /* five bytes */ - aTarget[nIdx++] = 0xf8 /* 248 */ + (nChar >>> 24); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 18) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */); - } else /* if (nChar <= 0x7fffffff) */ { /* 2147483647 */ - /* six bytes */ - aTarget[nIdx++] = 0xfc /* 252 */ + /* (nChar >>> 30) may be not safe in ECMAScript! So...: */ (nChar / 1073741824); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 24) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 18) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */); - aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */); - } - - return nIdx; - -}; - -StringView.getUTF8CharLength = function (nChar) { - return nChar < 0x80 ? 1 : nChar < 0x800 ? 2 : nChar < 0x10000 ? 3 : nChar < 0x200000 ? 4 : nChar < 0x4000000 ? 5 : 6; -}; - -StringView.loadUTF16CharCode = function (aChars, nIdx) { - - /* UTF-16 to DOMString decoding algorithm */ - var nFrstChr = aChars[nIdx]; - - return nFrstChr > 0xD7BF /* 55231 */ && nIdx + 1 < aChars.length ? - (nFrstChr - 0xD800 /* 55296 */ << 10) + aChars[nIdx + 1] + 0x2400 /* 9216 */ - : nFrstChr; - -}; - -StringView.putUTF16CharCode = function (aTarget, nChar, nPutAt) { - - var nIdx = nPutAt; - - if (nChar < 0x10000 /* 65536 */) { - /* one element */ - aTarget[nIdx++] = nChar; - } else { - /* two elements */ - aTarget[nIdx++] = 0xD7C0 /* 55232 */ + (nChar >>> 10); - aTarget[nIdx++] = 0xDC00 /* 56320 */ + (nChar & 0x3FF /* 1023 */); - } - - return nIdx; - -}; - -StringView.getUTF16CharLength = function (nChar) { - return nChar < 0x10000 ? 1 : 2; -}; - -/* Array of bytes to base64 string decoding */ - -StringView.b64ToUint6 = function (nChr) { - - return nChr > 64 && nChr < 91 ? - nChr - 65 - : nChr > 96 && nChr < 123 ? - nChr - 71 - : nChr > 47 && nChr < 58 ? - nChr + 4 - : nChr === 43 ? - 62 - : nChr === 47 ? - 63 - : - 0; - -}; - -StringView.uint6ToB64 = function (nUint6) { - - return nUint6 < 26 ? - nUint6 + 65 - : nUint6 < 52 ? - nUint6 + 71 - : nUint6 < 62 ? - nUint6 - 4 - : nUint6 === 62 ? - 43 - : nUint6 === 63 ? - 47 - : - 65; - -}; - -/* Base64 string to array encoding */ - -StringView.bytesToBase64 = function (aBytes) { - - var eqLen = (3 - (aBytes.length % 3)) % 3, sB64Enc = ""; - - for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { - nMod3 = nIdx % 3; - /* Uncomment the following line in order to split the output in lines 76-character long: */ - /* - if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; } - */ - nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24); - if (nMod3 === 2 || aBytes.length - nIdx === 1) { - sB64Enc += String.fromCharCode(StringView.uint6ToB64(nUint24 >>> 18 & 63), StringView.uint6ToB64(nUint24 >>> 12 & 63), StringView.uint6ToB64(nUint24 >>> 6 & 63), StringView.uint6ToB64(nUint24 & 63)); - nUint24 = 0; - } - } - - return eqLen === 0 ? - sB64Enc - : - sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? "=" : "=="); - - -}; - - -StringView.base64ToBytes = function (sBase64, nBlockBytes) { - - var - sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length, - nOutLen = nBlockBytes ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockBytes) * nBlockBytes : nInLen * 3 + 1 >>> 2, aBytes = new Uint8Array(nOutLen); - - for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) { - nMod4 = nInIdx & 3; - nUint24 |= StringView.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4; - if (nMod4 === 3 || nInLen - nInIdx === 1) { - for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { - aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255; - } - nUint24 = 0; - } - } - - return aBytes; - -}; - -StringView.makeFromBase64 = function (sB64Inpt, sEncoding, nByteOffset, nLength) { - - return new StringView(sEncoding === "UTF-16" || sEncoding === "UTF-32" ? StringView.base64ToBytes(sB64Inpt, sEncoding === "UTF-16" ? 2 : 4).buffer : StringView.base64ToBytes(sB64Inpt), sEncoding, nByteOffset, nLength); - -}; - -/* DEFAULT VALUES */ - -StringView.prototype.encoding = "UTF-8"; /* Default encoding... */ - -/* INSTANCES' METHODS */ - -StringView.prototype.makeIndex = function (nChrLength, nStartFrom) { - - var - - aTarget = this.rawData, nChrEnd, nRawLength = aTarget.length, - nStartIdx = nStartFrom || 0, nIdxEnd = nStartIdx, nStopAtChr = isNaN(nChrLength) ? Infinity : nChrLength; - - if (nChrLength + 1 > aTarget.length) { throw new RangeError("StringView.prototype.makeIndex - The offset can\'t be major than the length of the array - 1."); } - - switch (this.encoding) { - - case "UTF-8": - - var nPart; - - for (nChrEnd = 0; nIdxEnd < nRawLength && nChrEnd < nStopAtChr; nChrEnd++) { - nPart = aTarget[nIdxEnd]; - nIdxEnd += nPart > 251 && nPart < 254 && nIdxEnd + 5 < nRawLength ? 6 - : nPart > 247 && nPart < 252 && nIdxEnd + 4 < nRawLength ? 5 - : nPart > 239 && nPart < 248 && nIdxEnd + 3 < nRawLength ? 4 - : nPart > 223 && nPart < 240 && nIdxEnd + 2 < nRawLength ? 3 - : nPart > 191 && nPart < 224 && nIdxEnd + 1 < nRawLength ? 2 - : 1; - } - - break; - - case "UTF-16": - - for (nChrEnd = nStartIdx; nIdxEnd < nRawLength && nChrEnd < nStopAtChr; nChrEnd++) { - nIdxEnd += aTarget[nIdxEnd] > 0xD7BF /* 55231 */ && nIdxEnd + 1 < aTarget.length ? 2 : 1; - } - - break; - - default: - - nIdxEnd = nChrEnd = isFinite(nChrLength) ? nChrLength : nRawLength - 1; - - } - - if (nChrLength) { return nIdxEnd; } - - return nChrEnd; - -}; - -StringView.prototype.toBase64 = function (bWholeBuffer) { - - return StringView.bytesToBase64( - bWholeBuffer ? - ( - this.bufferView.constructor === Uint8Array ? - this.bufferView - : - new Uint8Array(this.buffer) - ) - : this.rawData.constructor === Uint8Array ? - this.rawData - : - new Uint8Array(this.buffer, this.rawData.byteOffset, this.rawData.length << (this.rawData.constructor === Uint16Array ? 1 : 2)) - ); - -}; - -StringView.prototype.subview = function (nCharOffset /* optional */, nCharLength /* optional */) { - - var - - nChrLen, nCharStart, nStrLen, bVariableLen = this.encoding === "UTF-8" || this.encoding === "UTF-16", - nStartOffset = nCharOffset, nStringLength, nRawLen = this.rawData.length; - - if (nRawLen === 0) { - return new StringView(this.buffer, this.encoding); - } - - nStringLength = bVariableLen ? this.makeIndex() : nRawLen; - nCharStart = nCharOffset ? Math.max((nStringLength + nCharOffset) % nStringLength, 0) : 0; - nStrLen = Number.isInteger(nCharLength) ? Math.max(nCharLength, 0) + nCharStart > nStringLength ? nStringLength - nCharStart : nCharLength : nStringLength; - - if (nCharStart === 0 && nStrLen === nStringLength) { return this; } - - if (bVariableLen) { - nStartOffset = this.makeIndex(nCharStart); - nChrLen = this.makeIndex(nStrLen, nStartOffset) - nStartOffset; - } else { - nStartOffset = nCharStart; - nChrLen = nStrLen - nCharStart; - } - - if (this.encoding === "UTF-16") { - nStartOffset <<= 1; - } else if (this.encoding === "UTF-32") { - nStartOffset <<= 2; - } - - return new StringView(this.buffer, this.encoding, nStartOffset, nChrLen); - -}; - -StringView.prototype.forEachChar = function (fCallback, oThat, nChrOffset, nChrLen) { - - var aSource = this.rawData, nRawEnd, nRawIdx; - - if (this.encoding === "UTF-8" || this.encoding === "UTF-16") { - - var fGetInptChrSize, fGetInptChrCode; - - if (this.encoding === "UTF-8") { - fGetInptChrSize = StringView.getUTF8CharLength; - fGetInptChrCode = StringView.loadUTF8CharCode; - } else if (this.encoding === "UTF-16") { - fGetInptChrSize = StringView.getUTF16CharLength; - fGetInptChrCode = StringView.loadUTF16CharCode; - } - - nRawIdx = isFinite(nChrOffset) ? this.makeIndex(nChrOffset) : 0; - nRawEnd = isFinite(nChrLen) ? this.makeIndex(nChrLen, nRawIdx) : aSource.length; - - for (var nChrCode, nChrIdx = 0; nRawIdx < nRawEnd; nChrIdx++) { - nChrCode = fGetInptChrCode(aSource, nRawIdx); - fCallback.call(oThat || null, nChrCode, nChrIdx, nRawIdx, aSource); - nRawIdx += fGetInptChrSize(nChrCode); - } - - } else { - - nRawIdx = isFinite(nChrOffset) ? nChrOffset : 0; - nRawEnd = isFinite(nChrLen) ? nChrLen + nRawIdx : aSource.length; - - for (nRawIdx; nRawIdx < nRawEnd; nRawIdx++) { - fCallback.call(oThat || null, aSource[nRawIdx], nRawIdx, nRawIdx, aSource); - } - - } - -}; - -StringView.prototype.valueOf = StringView.prototype.toString = function () { - - if (this.encoding !== "UTF-8" && this.encoding !== "UTF-16") { - /* ASCII, UTF-32 or BinaryString to DOMString */ - return String.fromCharCode.apply(null, this.rawData); - } - - var fGetCode, fGetIncr, sView = ""; - - if (this.encoding === "UTF-8") { - fGetIncr = StringView.getUTF8CharLength; - fGetCode = StringView.loadUTF8CharCode; - } else if (this.encoding === "UTF-16") { - fGetIncr = StringView.getUTF16CharLength; - fGetCode = StringView.loadUTF16CharCode; - } - - for (var nChr, nLen = this.rawData.length, nIdx = 0; nIdx < nLen; nIdx += fGetIncr(nChr)) { - nChr = fGetCode(this.rawData, nIdx); - sView += String.fromCharCode(nChr); - } - - return sView; - -}; - -module.exports = StringView; - -/***/ }), -/* 41 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -if (!__webpack_require__(15)()) { - throw 'env unsupported'; -} - -__webpack_require__(12) - -var neurojs = { - - Network: __webpack_require__(2), - Agent: __webpack_require__(13), - Optim: __webpack_require__(4), - Loader: __webpack_require__(11), - Buffers: __webpack_require__(5), - NetOnDisk: __webpack_require__(6), - FileLoader: __webpack_require__(14), - Binary: __webpack_require__(7), - Shared: __webpack_require__(3) - -} - -if (typeof window !== 'undefined') { - window.neurojs = neurojs -} else { - module.exports = neurojs -} - - -/***/ }) -/******/ ]); \ No newline at end of file