update
@ -32,8 +32,8 @@
|
||||
stroke("rgba(128,128,255,0.8)");
|
||||
fill("rgba(128,128,255,0.8)");
|
||||
beginShape();
|
||||
for (let θ = 0; θ < 360; θ+=3) {
|
||||
let d = r * sin(θ * 3);
|
||||
for (let θ = 0; θ < 360; θ += 3) {
|
||||
let d = r * sin(θ * 2);
|
||||
vertex(cos(θ) * d, -sin(θ) * d);
|
||||
}
|
||||
endShape(CLOSE);
|
||||
|
24
README.md
@ -1,5 +1,29 @@
|
||||
# p5js 学习仓库
|
||||
|
||||
## 待做
|
||||
|
||||
- [分形树1](https://www.youtube.com/watch?v=0jjeOYMjmDU)
|
||||
- [分形树5](https://www.youtube.com/watch?v=JcopTKXt8L8)
|
||||
- [最小跨越树](https://www.youtube.com/watch?v=BxabnKrOjT0)
|
||||
- [迷宫](https://www.youtube.com/watch?v=HyK_Q5rrcr4)
|
||||
- [三维地形](https://www.youtube.com/watch?v=IKB1hWWedMk)
|
||||
- [洛伦兹吸引子](https://www.youtube.com/watch?v=f0lkz2gSsIk)
|
||||
- [反应扩散算法](https://www.youtube.com/watch?v=BV9ny785UNc)
|
||||
- [超级椭圆](https://www.youtube.com/watch?v=z86cx2A4_3E)
|
||||
- [3D织物](https://www.youtube.com/watch?v=jrk_lOg_pVA)
|
||||
- [曼波集](https://www.youtube.com/watch?v=6z7GQewK-Ks)
|
||||
- [茱莉亚集](https://www.youtube.com/watch?v=fAsaSkmbF5s)
|
||||
- [合成器](https://www.youtube.com/watch?v=Bk8rLzzSink)
|
||||
- [焰火](https://www.youtube.com/watch?v=ATWOjXdRIoo)
|
||||
- [焰火2](https://www.youtube.com/watch?v=CKeyIbT3vXI)
|
||||
- [计算机视觉](https://www.youtube.com/watch?v=nCVZHROb_dE)
|
||||
- [WEBGL](https://www.youtube.com/watch?v=BrFZ5RkywcY)
|
||||
- [遗传算法](https://www.youtube.com/watch?v=bGz7mv2vD6g)
|
||||
- [Phyllotaxis](https://www.youtube.com/watch?v=KWoJgHFYWxY)
|
||||
- [Flappy Bird and Agar.io Clones](https://www.youtube.com/watch?v=eOii4P7WYbY)
|
||||
- [遗传算法:连续进化系统](https://www.youtube.com/watch?v=Sx_l2GxBC5w)
|
||||
- [邮差算法](https://www.youtube.com/watch?v=r_SpBy9fQuo)
|
||||
|
||||
## 链接
|
||||
|
||||
- [p5js官方网站](https://p5js.org/zh-Hans/)
|
||||
|
23
TEST.html
@ -5,19 +5,34 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="stylesheet" href="/css/style.css" />
|
||||
<title>风扇</title>
|
||||
<title>测试</title>
|
||||
<script src="/p5/p5.min.js"></script>
|
||||
<script src="/p5/addons/p5.sound.min.js"></script>
|
||||
<script src="/lib/utils.js"></script>
|
||||
<script>
|
||||
function setup() {
|
||||
createCanvas(300, 500);
|
||||
background(255);
|
||||
createCanvas(600, 600);
|
||||
background("#33DDFF");
|
||||
drawGrid(0);
|
||||
noLoop();
|
||||
}
|
||||
|
||||
function mousePressed() {
|
||||
circle(mouseX, mouseY, 20);
|
||||
push();
|
||||
noFill();
|
||||
stroke("#FFDD33");
|
||||
strokeWeight(4);
|
||||
translate(mouseX, mouseY);
|
||||
beginShape();
|
||||
for (let θ = 0; θ < PI * 6; θ += 0.1) {
|
||||
let a = 0;
|
||||
let b = 2;
|
||||
let r = a + b * θ;
|
||||
let v = polarToCartesian(r, θ);
|
||||
vertex(v.x, v.y);
|
||||
}
|
||||
endShape();
|
||||
pop();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
14
lib/box2d-js/LICENSE.txt
Normal file
@ -0,0 +1,14 @@
|
||||
The zlib/libpng License
|
||||
|
||||
Copyright (c) 2008 ANDO Yasushi
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
3
lib/box2d-js/README.txt
Normal file
@ -0,0 +1,3 @@
|
||||
How to use
|
||||
1. put js/ and lib/ in your app dir
|
||||
2. add script tags refering the header of index.html
|
57
lib/box2d-js/demos/compound.js
Normal file
@ -0,0 +1,57 @@
|
||||
demos.compound = {};
|
||||
demos.compound.createCompoundBall = function(world, x, y) {
|
||||
var ballSd1 = new b2CircleDef();
|
||||
ballSd1.density = 1.0;
|
||||
ballSd1.radius = 20;
|
||||
ballSd1.restitution = 0.2;
|
||||
ballSd1.localPosition.Set(-20, 0);
|
||||
var ballSd2 = new b2CircleDef();
|
||||
ballSd2.density = 1.0;
|
||||
ballSd2.radius = 20;
|
||||
ballSd2.restitution = 0.2;
|
||||
ballSd2.localPosition.Set(20, 0);
|
||||
var ballBd = new b2BodyDef();
|
||||
ballBd.AddShape(ballSd1);
|
||||
ballBd.AddShape(ballSd2);
|
||||
ballBd.position.Set(x, y);
|
||||
return world.CreateBody(ballBd);
|
||||
}
|
||||
|
||||
demos.compound.createCompoundPoly = function(world, x, y) {
|
||||
var points = [[-30, 0], [30, 0], [0, 15]];
|
||||
var polySd1 = new b2PolyDef();
|
||||
polySd1.vertexCount = points.length;
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
polySd1.vertices[i].Set(points[i][0], points[i][1]);
|
||||
}
|
||||
polySd1.localRotation = 0.3524 * Math.PI;
|
||||
var R1 = new b2Mat22(polySd1.localRotation);
|
||||
polySd1.localPosition = b2Math.b2MulMV(R1, new b2Vec2(30, 0));
|
||||
polySd1.density = 1.0;
|
||||
var polySd2 = new b2PolyDef();
|
||||
polySd2.vertexCount = points.length;
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
polySd2.vertices[i].Set(points[i][0], points[i][1]);
|
||||
}
|
||||
polySd2.localRotation = -0.3524 * Math.PI;
|
||||
var R2 = new b2Mat22(polySd2.localRotation);
|
||||
polySd2.localPosition = b2Math.b2MulMV(R2, new b2Vec2(-30, 0));
|
||||
var polyBd = new b2BodyDef();
|
||||
polyBd.AddShape(polySd1);
|
||||
polyBd.AddShape(polySd2);
|
||||
polyBd.position.Set(x,y);
|
||||
return world.CreateBody(polyBd)
|
||||
}
|
||||
|
||||
demos.compound.initWorld = function(world) {
|
||||
var i;
|
||||
for (i = 1; i <= 4; i++) {
|
||||
demos.compound.createCompoundPoly(world, 150 + 3 * Math.random(), 40 * i);
|
||||
}
|
||||
for (i = 1; i <= 4; i++) {
|
||||
demos.compound.createCompoundBall(world, 350 + 3 * Math.random(), 45 * i);
|
||||
}
|
||||
}
|
||||
demos.InitWorlds.push(demos.compound.initWorld);
|
||||
|
||||
|
69
lib/box2d-js/demos/crank.js
Normal file
@ -0,0 +1,69 @@
|
||||
demos.crank = {};
|
||||
demos.crank.initWorld = function(world) {
|
||||
var ground = world.m_groundBody;
|
||||
|
||||
// Define crank.
|
||||
var sd = new b2BoxDef();
|
||||
sd.extents.Set(5, 25);
|
||||
sd.density = 1.0;
|
||||
|
||||
var bd = new b2BodyDef();
|
||||
bd.AddShape(sd);
|
||||
|
||||
var rjd = new b2RevoluteJointDef();
|
||||
|
||||
var prevBody = ground;
|
||||
|
||||
bd.position.Set(500/2, 210);
|
||||
var body = world.CreateBody(bd);
|
||||
|
||||
rjd.anchorPoint.Set(500/2, 235);
|
||||
rjd.body1 = prevBody;
|
||||
rjd.body2 = body;
|
||||
rjd.motorSpeed = -1.0 * Math.PI;
|
||||
rjd.motorTorque = 500000000.0;
|
||||
rjd.enableMotor = true;
|
||||
world.CreateJoint(rjd);
|
||||
|
||||
prevBody = body;
|
||||
|
||||
// Define follower.
|
||||
sd.extents.Set(5, 45);
|
||||
bd.position.Set(500/2, 140);
|
||||
body = world.CreateBody(bd);
|
||||
|
||||
rjd.anchorPoint.Set(500/2, 185);
|
||||
rjd.body1 = prevBody;
|
||||
rjd.body2 = body;
|
||||
rjd.enableMotor = false;
|
||||
world.CreateJoint(rjd);
|
||||
|
||||
prevBody = body;
|
||||
|
||||
// Define piston
|
||||
sd.extents.Set(20, 20);
|
||||
bd.position.Set(500/2, 95);
|
||||
body = world.CreateBody(bd);
|
||||
|
||||
rjd.anchorPoint.Set(500/2, 95);
|
||||
rjd.body1 = prevBody;
|
||||
rjd.body2 = body;
|
||||
world.CreateJoint(rjd);
|
||||
|
||||
var pjd = new b2PrismaticJointDef();
|
||||
pjd.anchorPoint.Set(500/2, 95);
|
||||
pjd.body1 = ground;
|
||||
pjd.body2 = body;
|
||||
pjd.axis.Set(0.0, 1.0);
|
||||
pjd.motorSpeed = 0.0; // joint friction
|
||||
pjd.motorForce = 100000.0;
|
||||
pjd.enableMotor = true;
|
||||
|
||||
world.CreateJoint(pjd);
|
||||
|
||||
// Create a payload
|
||||
sd.density = 2.0;
|
||||
bd.position.Set(500/2, 10);
|
||||
world.CreateBody(bd);
|
||||
}
|
||||
demos.InitWorlds.push(demos.crank.initWorld);
|
48
lib/box2d-js/demos/demo_base.js
Normal file
@ -0,0 +1,48 @@
|
||||
function createWorld() {
|
||||
var worldAABB = new b2AABB();
|
||||
worldAABB.minVertex.Set(-1000, -1000);
|
||||
worldAABB.maxVertex.Set(1000, 1000);
|
||||
var gravity = new b2Vec2(0, 300);
|
||||
var doSleep = true;
|
||||
var world = new b2World(worldAABB, gravity, doSleep);
|
||||
createGround(world);
|
||||
createBox(world, 0, 125, 10, 250);
|
||||
createBox(world, 500, 125, 10, 250);
|
||||
return world;
|
||||
}
|
||||
|
||||
function createGround(world) {
|
||||
var groundSd = new b2BoxDef();
|
||||
groundSd.extents.Set(1000, 50);
|
||||
groundSd.restitution = 0.2;
|
||||
var groundBd = new b2BodyDef();
|
||||
groundBd.AddShape(groundSd);
|
||||
groundBd.position.Set(-500, 340);
|
||||
return world.CreateBody(groundBd)
|
||||
}
|
||||
|
||||
function createBall(world, x, y) {
|
||||
var ballSd = new b2CircleDef();
|
||||
ballSd.density = 1.0;
|
||||
ballSd.radius = 20;
|
||||
ballSd.restitution = 1.0;
|
||||
ballSd.friction = 0;
|
||||
var ballBd = new b2BodyDef();
|
||||
ballBd.AddShape(ballSd);
|
||||
ballBd.position.Set(x,y);
|
||||
return world.CreateBody(ballBd);
|
||||
}
|
||||
|
||||
function createBox(world, x, y, width, height, fixed) {
|
||||
if (typeof(fixed) == 'undefined') fixed = true;
|
||||
var boxSd = new b2BoxDef();
|
||||
if (!fixed) boxSd.density = 1.0;
|
||||
boxSd.extents.Set(width, height);
|
||||
var boxBd = new b2BodyDef();
|
||||
boxBd.AddShape(boxSd);
|
||||
boxBd.position.Set(x,y);
|
||||
return world.CreateBody(boxBd)
|
||||
}
|
||||
|
||||
var demos = {};
|
||||
demos.InitWorlds = [];
|
49
lib/box2d-js/demos/demos.js
Normal file
@ -0,0 +1,49 @@
|
||||
var initId = 0;
|
||||
var world = createWorld();
|
||||
var ctx;
|
||||
var canvasWidth;
|
||||
var canvasHeight;
|
||||
var canvasTop;
|
||||
var canvasLeft;
|
||||
|
||||
function setupWorld(did) {
|
||||
if (!did) did = 0;
|
||||
world = createWorld();
|
||||
initId += did;
|
||||
initId %= demos.InitWorlds.length;
|
||||
if (initId < 0) initId = demos.InitWorlds.length + initId;
|
||||
demos.InitWorlds[initId](world);
|
||||
}
|
||||
function setupNextWorld() { setupWorld(1); }
|
||||
function setupPrevWorld() { setupWorld(-1); }
|
||||
function step(cnt) {
|
||||
var stepping = false;
|
||||
var timeStep = 1.0/60;
|
||||
var iteration = 1;
|
||||
world.Step(timeStep, iteration);
|
||||
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
|
||||
drawWorld(world, ctx);
|
||||
setTimeout('step(' + (cnt || 0) + ')', 10);
|
||||
}
|
||||
Event.observe(window, 'load', function() {
|
||||
setupWorld();
|
||||
ctx = $('canvas').getContext('2d');
|
||||
var canvasElm = $('canvas');
|
||||
canvasWidth = parseInt(canvasElm.width);
|
||||
canvasHeight = parseInt(canvasElm.height);
|
||||
canvasTop = parseInt(canvasElm.style.top);
|
||||
canvasLeft = parseInt(canvasElm.style.left);
|
||||
Event.observe('canvas', 'click', function(e) {
|
||||
//setupNextWorld();
|
||||
if (Math.random() < 0.5)
|
||||
demos.top.createBall(world, Event.pointerX(e) - canvasLeft, Event.pointerY(e) - canvasTop);
|
||||
else
|
||||
createBox(world, Event.pointerX(e) - canvasLeft, Event.pointerY(e) - canvasTop, 10, 10, false);
|
||||
});
|
||||
Event.observe('canvas', 'contextmenu', function(e) {
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
setupPrevWorld();
|
||||
return false;
|
||||
});
|
||||
step();
|
||||
});
|
93
lib/box2d-js/demos/draw_world.js
Normal file
@ -0,0 +1,93 @@
|
||||
function drawWorld(world, context) {
|
||||
for (var j = world.m_jointList; j; j = j.m_next) {
|
||||
drawJoint(j, context);
|
||||
}
|
||||
for (var b = world.m_bodyList; b; b = b.m_next) {
|
||||
for (var s = b.GetShapeList(); s != null; s = s.GetNext()) {
|
||||
drawShape(s, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
function drawJoint(joint, context) {
|
||||
var b1 = joint.m_body1;
|
||||
var b2 = joint.m_body2;
|
||||
var x1 = b1.m_position;
|
||||
var x2 = b2.m_position;
|
||||
var p1 = joint.GetAnchor1();
|
||||
var p2 = joint.GetAnchor2();
|
||||
context.strokeStyle = '#00eeee';
|
||||
context.beginPath();
|
||||
switch (joint.m_type) {
|
||||
case b2Joint.e_distanceJoint:
|
||||
context.moveTo(p1.x, p1.y);
|
||||
context.lineTo(p2.x, p2.y);
|
||||
break;
|
||||
|
||||
case b2Joint.e_pulleyJoint:
|
||||
// TODO
|
||||
break;
|
||||
|
||||
default:
|
||||
if (b1 == world.m_groundBody) {
|
||||
context.moveTo(p1.x, p1.y);
|
||||
context.lineTo(x2.x, x2.y);
|
||||
}
|
||||
else if (b2 == world.m_groundBody) {
|
||||
context.moveTo(p1.x, p1.y);
|
||||
context.lineTo(x1.x, x1.y);
|
||||
}
|
||||
else {
|
||||
context.moveTo(x1.x, x1.y);
|
||||
context.lineTo(p1.x, p1.y);
|
||||
context.lineTo(x2.x, x2.y);
|
||||
context.lineTo(p2.x, p2.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
context.stroke();
|
||||
}
|
||||
function drawShape(shape, context) {
|
||||
context.strokeStyle = '#ffffff';
|
||||
context.beginPath();
|
||||
switch (shape.m_type) {
|
||||
case b2Shape.e_circleShape:
|
||||
{
|
||||
var circle = shape;
|
||||
var pos = circle.m_position;
|
||||
var r = circle.m_radius;
|
||||
var segments = 16.0;
|
||||
var theta = 0.0;
|
||||
var dtheta = 2.0 * Math.PI / segments;
|
||||
// draw circle
|
||||
context.moveTo(pos.x + r, pos.y);
|
||||
for (var i = 0; i < segments; i++) {
|
||||
var d = new b2Vec2(r * Math.cos(theta), r * Math.sin(theta));
|
||||
var v = b2Math.AddVV(pos, d);
|
||||
context.lineTo(v.x, v.y);
|
||||
theta += dtheta;
|
||||
}
|
||||
context.lineTo(pos.x + r, pos.y);
|
||||
|
||||
// draw radius
|
||||
context.moveTo(pos.x, pos.y);
|
||||
var ax = circle.m_R.col1;
|
||||
var pos2 = new b2Vec2(pos.x + r * ax.x, pos.y + r * ax.y);
|
||||
context.lineTo(pos2.x, pos2.y);
|
||||
}
|
||||
break;
|
||||
case b2Shape.e_polyShape:
|
||||
{
|
||||
var poly = shape;
|
||||
var tV = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[0]));
|
||||
context.moveTo(tV.x, tV.y);
|
||||
for (var i = 0; i < poly.m_vertexCount; i++) {
|
||||
var v = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
|
||||
context.lineTo(v.x, v.y);
|
||||
}
|
||||
context.lineTo(tV.x, tV.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
context.stroke();
|
||||
}
|
||||
|
20
lib/box2d-js/demos/pendulum.js
Normal file
@ -0,0 +1,20 @@
|
||||
demos.pendulum = {};
|
||||
demos.pendulum.initWorld = function(world) {
|
||||
var i;
|
||||
var ground = world.GetGroundBody();
|
||||
var jointDef = new b2RevoluteJointDef();
|
||||
var L = 150;
|
||||
for (i = 0; i < 4; i++) {
|
||||
jointDef.anchorPoint.Set(250 + 40 * i, 200 - L);
|
||||
jointDef.body1 = ground;
|
||||
jointDef.body2 = createBall(world, 250 + 40 * i, 200);
|
||||
world.CreateJoint(jointDef);
|
||||
}
|
||||
jointDef.anchorPoint.Set(250 - 40, 200 - L);
|
||||
jointDef.body1 = ground;
|
||||
jointDef.body2 = createBall(world, 250 - 40 - L, 200 - L);
|
||||
world.CreateJoint(jointDef);
|
||||
}
|
||||
demos.InitWorlds.push(demos.pendulum.initWorld);
|
||||
|
||||
|
26
lib/box2d-js/demos/stack.js
Normal file
@ -0,0 +1,26 @@
|
||||
demos.stack = {};
|
||||
demos.stack.initWorld = function(world) {
|
||||
var sd = new b2BoxDef();
|
||||
var bd = new b2BodyDef();
|
||||
bd.AddShape(sd);
|
||||
sd.density = 1.0;
|
||||
sd.friction = 0.5;
|
||||
sd.extents.Set(10, 10);
|
||||
|
||||
var i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
bd.position.Set(500/2-Math.random()*2-1, (250-5-i*22));
|
||||
world.CreateBody(bd);
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
bd.position.Set(500/2-100-Math.random()*5+i, (250-5-i*22));
|
||||
world.CreateBody(bd);
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
bd.position.Set(500/2+100+Math.random()*5-i, (250-5-i*22));
|
||||
world.CreateBody(bd);
|
||||
}
|
||||
}
|
||||
demos.InitWorlds.push(demos.stack.initWorld);
|
||||
|
||||
|
42
lib/box2d-js/demos/top.js
Normal file
@ -0,0 +1,42 @@
|
||||
demos.top = {};
|
||||
demos.top.createBall = function(world, x, y, rad, fixed) {
|
||||
var ballSd = new b2CircleDef();
|
||||
if (!fixed) ballSd.density = 1.0;
|
||||
ballSd.radius = rad || 10;
|
||||
ballSd.restitution = 0.2;
|
||||
var ballBd = new b2BodyDef();
|
||||
ballBd.AddShape(ballSd);
|
||||
ballBd.position.Set(x,y);
|
||||
return world.CreateBody(ballBd);
|
||||
};
|
||||
demos.top.createPoly = function(world, x, y, points, fixed) {
|
||||
var polySd = new b2PolyDef();
|
||||
if (!fixed) polySd.density = 1.0;
|
||||
polySd.vertexCount = points.length;
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
polySd.vertices[i].Set(points[i][0], points[i][1]);
|
||||
}
|
||||
var polyBd = new b2BodyDef();
|
||||
polyBd.AddShape(polySd);
|
||||
polyBd.position.Set(x,y);
|
||||
return world.CreateBody(polyBd)
|
||||
};
|
||||
demos.top.initWorld = function(world) {
|
||||
demos.top.createBall(world, 350, 100, 50, true);
|
||||
demos.top.createPoly(world, 100, 100, [[0, 0], [10, 30], [-10, 30]], true);
|
||||
demos.top.createPoly(world, 150, 150, [[0, 0], [10, 30], [-10, 30]], true);
|
||||
var pendulum = createBox(world, 150, 100, 20, 20, false);
|
||||
var jointDef = new b2RevoluteJointDef();
|
||||
jointDef.body1 = pendulum;
|
||||
jointDef.body2 = world.GetGroundBody();
|
||||
jointDef.anchorPoint = pendulum.GetCenterPosition();
|
||||
world.CreateJoint(jointDef);
|
||||
|
||||
var seesaw = demos.top.createPoly(world, 300, 200, [[0, 0], [100, 30], [-100, 30]]);
|
||||
jointDef.body1 = seesaw;
|
||||
jointDef.anchorPoint = seesaw.GetCenterPosition();
|
||||
world.CreateJoint(jointDef);
|
||||
};
|
||||
demos.InitWorlds.push(demos.top.initWorld);
|
||||
|
||||
|
213
lib/box2d-js/index.html
Normal file
@ -0,0 +1,213 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Box2DJS - Physics Engine for JavaScript</title>
|
||||
|
||||
<!--=============================-->
|
||||
<!-- Copy this part to your app. -->
|
||||
<!-- START -->
|
||||
<!--=============================-->
|
||||
<!-- libs -->
|
||||
<!--[if IE]><script type="text/javascript" src="lib/excanvas.js"></script><![endif]-->
|
||||
<script src="lib/prototype-1.6.0.2.js"></script>
|
||||
|
||||
<!-- box2djs -->
|
||||
<script src='js/box2d/common/b2Settings.js'></script>
|
||||
<script src='js/box2d/common/math/b2Vec2.js'></script>
|
||||
<script src='js/box2d/common/math/b2Mat22.js'></script>
|
||||
<script src='js/box2d/common/math/b2Math.js'></script>
|
||||
<script src='js/box2d/collision/b2AABB.js'></script>
|
||||
<script src='js/box2d/collision/b2Bound.js'></script>
|
||||
<script src='js/box2d/collision/b2BoundValues.js'></script>
|
||||
<script src='js/box2d/collision/b2Pair.js'></script>
|
||||
<script src='js/box2d/collision/b2PairCallback.js'></script>
|
||||
<script src='js/box2d/collision/b2BufferedPair.js'></script>
|
||||
<script src='js/box2d/collision/b2PairManager.js'></script>
|
||||
<script src='js/box2d/collision/b2BroadPhase.js'></script>
|
||||
<script src='js/box2d/collision/b2Collision.js'></script>
|
||||
<script src='js/box2d/collision/Features.js'></script>
|
||||
<script src='js/box2d/collision/b2ContactID.js'></script>
|
||||
<script src='js/box2d/collision/b2ContactPoint.js'></script>
|
||||
<script src='js/box2d/collision/b2Distance.js'></script>
|
||||
<script src='js/box2d/collision/b2Manifold.js'></script>
|
||||
<script src='js/box2d/collision/b2OBB.js'></script>
|
||||
<script src='js/box2d/collision/b2Proxy.js'></script>
|
||||
<script src='js/box2d/collision/ClipVertex.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2Shape.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2ShapeDef.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2BoxDef.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2CircleDef.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2CircleShape.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2MassData.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2PolyDef.js'></script>
|
||||
<script src='js/box2d/collision/shapes/b2PolyShape.js'></script>
|
||||
<script src='js/box2d/dynamics/b2Body.js'></script>
|
||||
<script src='js/box2d/dynamics/b2BodyDef.js'></script>
|
||||
<script src='js/box2d/dynamics/b2CollisionFilter.js'></script>
|
||||
<script src='js/box2d/dynamics/b2Island.js'></script>
|
||||
<script src='js/box2d/dynamics/b2TimeStep.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2ContactNode.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2Contact.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2ContactConstraint.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2ContactConstraintPoint.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2ContactRegister.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2ContactSolver.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2CircleContact.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2Conservative.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2NullContact.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2PolyAndCircleContact.js'></script>
|
||||
<script src='js/box2d/dynamics/contacts/b2PolyContact.js'></script>
|
||||
<script src='js/box2d/dynamics/b2ContactManager.js'></script>
|
||||
<script src='js/box2d/dynamics/b2World.js'></script>
|
||||
<script src='js/box2d/dynamics/b2WorldListener.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2JointNode.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2Joint.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2JointDef.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2DistanceJoint.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2DistanceJointDef.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2Jacobian.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2GearJoint.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2GearJointDef.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2MouseJoint.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2MouseJointDef.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2PrismaticJoint.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2PrismaticJointDef.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2PulleyJoint.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2PulleyJointDef.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2RevoluteJoint.js'></script>
|
||||
<script src='js/box2d/dynamics/joints/b2RevoluteJointDef.js'></script>
|
||||
<!--=============================-->
|
||||
<!-- Copy this part to your app. -->
|
||||
<!-- END -->
|
||||
<!--=============================-->
|
||||
|
||||
<!-- demos -->
|
||||
<script src='demos/draw_world.js'></script>
|
||||
<script src='demos/demo_base.js'></script>
|
||||
<script src='demos/top.js'></script>
|
||||
<script src='demos/stack.js'></script>
|
||||
<script src='demos/compound.js'></script>
|
||||
<script src='demos/pendulum.js'></script>
|
||||
<script src='demos/crank.js'></script>
|
||||
<script src='demos/demos.js'></script>
|
||||
|
||||
<script src='style/prettify.js'></script>
|
||||
<link href="style/prettify.css" rel="stylesheet" type="text/css" />
|
||||
<script>Event.observe(window, 'load', function() {prettyPrint()});</script>
|
||||
|
||||
<link href="style/distant-planet.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/box2d.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="CONTAINER">
|
||||
<div id="HEADER">
|
||||
<h1>Box2D<br/><b>JS</b></h1>
|
||||
</div>
|
||||
<div id="NAVIGATION">
|
||||
<div class="Nav">
|
||||
<span class="links">
|
||||
<a href="http://sourceforge.net/projects/box2d-js/">Home</a>
|
||||
- <a href="http://sourceforge.net/project/showfiles.php?group_id=227549">Download</a>
|
||||
- <a href="#about">About</a>
|
||||
- <a href="#howto">Howto</a>
|
||||
- <a href="#links">Links</a>
|
||||
- <a href="#contact">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="BODYBOX">
|
||||
<div class="LEFT"></div>
|
||||
<div class="MIDDLE">
|
||||
<canvas id="canvas" width='500' height='300' style="top:260px; left:125px;"></canvas>
|
||||
<div id="spacer"> </div>
|
||||
<p style="text-align:center">
|
||||
<span class="key">Left-click</span> to create an object.
|
||||
<span class="key">Right-click</span> to show next example.
|
||||
</p>
|
||||
|
||||
<a name="about"></a>
|
||||
<h1>What's this</h1>
|
||||
<p>
|
||||
Box2DJS is a JavaScript port of <a href="http://www.box2d.org/">Box2D Physics Engine</a>.
|
||||
To tell the truth, this is converted from <a href="http://box2dflash.sourceforge.net/">Box2DFlashAS3</a>_1.4.3.1 in an automatic manner.
|
||||
(The reason why not Box2DFlashAS3_2.0.0 based is simply because I overlooked the renewal.)
|
||||
</p>
|
||||
|
||||
<a name="howto"></a>
|
||||
<h1>How to use</h1>
|
||||
<p>
|
||||
Because this libray does not have a lazy-loading system now, you should load all classes before starting your simulation.
|
||||
To make things worse, each library has a bit complecated dependency each other so that loading libraries in wrong order may cause a fatal error.
|
||||
To avoid such a trouble, it is strongly recomended to copy the header part of this file or `index.html' including the downloaded zip file.
|
||||
</p>
|
||||
<p>
|
||||
Concerning the Box2D APIs of the library, they are completely same as Box2DFlashAS3. Please google information about it.
|
||||
</p>
|
||||
|
||||
<h2>Sample code</h2>
|
||||
<h3>Create a world</h3>
|
||||
<pre class="prettyprint">var worldAABB = new b2AABB();
|
||||
worldAABB.minVertex.Set(-1000, -1000);
|
||||
worldAABB.maxVertex.Set(1000, 1000);
|
||||
var gravity = new b2Vec2(0, 300);
|
||||
var doSleep = true;
|
||||
var world = new b2World(worldAABB, gravity, doSleep); </pre>
|
||||
|
||||
<h3>Create a circle body</h3>
|
||||
<pre class="prettyprint">var circleSd = new b2CircleDef();
|
||||
circleSd.density = 1.0;
|
||||
circleSd.radius = 20;
|
||||
circleSd.restitution = 1.0;
|
||||
circleSd.friction = 0;
|
||||
var circleBd = new b2BodyDef();
|
||||
circleBd.AddShape(circleSd);
|
||||
circleBd.position.Set(x,y);
|
||||
var circleBody = world.CreateBody(circleBd);</pre>
|
||||
|
||||
<h3>Create a revolute joint</h3>
|
||||
<pre class="prettyprint">var jointDef = new b2RevoluteJointDef();
|
||||
jointDef.anchorPoint.Set(250, 200);
|
||||
jointDef.body1 = world.GetGroundBody();
|
||||
jointDef.body2 = circleBody;
|
||||
world.CreateJoint(jointDef);</pre>
|
||||
|
||||
<h3>Step a world</h3>
|
||||
<pre class="prettyprint">world.Step();</pre>
|
||||
|
||||
<a name="dependencies"></a>
|
||||
<h1>Dependencies</h1>
|
||||
<ul>
|
||||
<li><a href="http://www.prototypejs.org/">prototype.js</a></li>
|
||||
<li><a href="http://sourceforge.net/projects/iecanvas">IECanvas</a> (when you use a canvas tag to display the result of your physics simulation)</li>
|
||||
</ul>
|
||||
|
||||
<a name="links"></a>
|
||||
<h1>Links</h1>
|
||||
<ul>
|
||||
<li><a href="http://sourceforge.net/projects/box2d-js/">Project Page (SF)</a></li>
|
||||
<li><a href="http://sourceforge.net/project/showfiles.php?group_id=227549">Download Page (SF)</a></li>
|
||||
<li><a href="http://www.box2d.org/">Box2D</a></li>
|
||||
<li><a href="http://box2dflash.sourceforge.net/">Box2DFlashAS3</a></li>
|
||||
<li><a href="http://www.kyucon.com/doc/box2d/">API Doc (Box2DFlashAS3)</a></li>
|
||||
</ul>
|
||||
|
||||
<a name="contact"></a>
|
||||
<h1>Contact</h1>
|
||||
<p>
|
||||
If you have some requests or find any bugs, please tell me about them.<br />
|
||||
<div class="contact">
|
||||
E-mail: andyjpn _at_ gmail _dot_ com<br />
|
||||
Blog: <a href="http://d.hatena.ne.jp/technohippy/">http://d.hatena.ne.jp/technohippy/</a> (written in Japanese)
|
||||
</div>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div class="RIGHT"></div>
|
||||
<div id="FOOTER">
|
||||
<div class="footertext"><span class="links">©Copyright 2008 ANDO Yasushi - <a href="http://www.rankrover.com">Website Design & SEO by RankRover</a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
35
lib/box2d-js/js/box2d/collision/ClipVertex.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var ClipVertex = Class.create();
|
||||
ClipVertex.prototype =
|
||||
{
|
||||
v: new b2Vec2(),
|
||||
id: new b2ContactID(),
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.v = new b2Vec2();
|
||||
this.id = new b2ContactID();
|
||||
//
|
||||
}};
|
||||
|
||||
|
61
lib/box2d-js/js/box2d/collision/Features.js
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
// We use contact ids to facilitate warm starting.
|
||||
var Features = Class.create();
|
||||
Features.prototype =
|
||||
{
|
||||
//
|
||||
set_referenceFace: function(value){
|
||||
this._referenceFace = value;
|
||||
this._m_id._key = (this._m_id._key & 0xffffff00) | (this._referenceFace & 0x000000ff)
|
||||
},
|
||||
get_referenceFace: function(){
|
||||
return this._referenceFace;
|
||||
},
|
||||
_referenceFace: 0,
|
||||
//
|
||||
set_incidentEdge: function(value){
|
||||
this._incidentEdge = value;
|
||||
this._m_id._key = (this._m_id._key & 0xffff00ff) | ((this._incidentEdge << 8) & 0x0000ff00)
|
||||
},
|
||||
get_incidentEdge: function(){
|
||||
return this._incidentEdge;
|
||||
},
|
||||
_incidentEdge: 0,
|
||||
//
|
||||
set_incidentVertex: function(value){
|
||||
this._incidentVertex = value;
|
||||
this._m_id._key = (this._m_id._key & 0xff00ffff) | ((this._incidentVertex << 16) & 0x00ff0000)
|
||||
},
|
||||
get_incidentVertex: function(){
|
||||
return this._incidentVertex;
|
||||
},
|
||||
_incidentVertex: 0,
|
||||
//
|
||||
set_flip: function(value){
|
||||
this._flip = value;
|
||||
this._m_id._key = (this._m_id._key & 0x00ffffff) | ((this._flip << 24) & 0xff000000)
|
||||
},
|
||||
get_flip: function(){
|
||||
return this._flip;
|
||||
},
|
||||
_flip: 0,
|
||||
_m_id: null,
|
||||
initialize: function() {}};
|
45
lib/box2d-js/js/box2d/collision/b2AABB.js
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// A manifold for two touching convex shapes.
|
||||
var b2AABB = Class.create();
|
||||
b2AABB.prototype =
|
||||
{
|
||||
IsValid: function(){
|
||||
//var d = b2Math.SubtractVV(this.maxVertex, this.minVertex);
|
||||
var dX = this.maxVertex.x;
|
||||
var dY = this.maxVertex.y;
|
||||
dX = this.maxVertex.x;
|
||||
dY = this.maxVertex.y;
|
||||
dX -= this.minVertex.x;
|
||||
dY -= this.minVertex.y;
|
||||
var valid = dX >= 0.0 && dY >= 0.0;
|
||||
valid = valid && this.minVertex.IsValid() && this.maxVertex.IsValid();
|
||||
return valid;
|
||||
},
|
||||
|
||||
minVertex: new b2Vec2(),
|
||||
maxVertex: new b2Vec2(),
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.minVertex = new b2Vec2();
|
||||
this.maxVertex = new b2Vec2();
|
||||
//
|
||||
}};
|
43
lib/box2d-js/js/box2d/collision/b2Bound.js
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2Bound = Class.create();
|
||||
b2Bound.prototype = {
|
||||
IsLower: function(){ return (this.value & 1) == 0; },
|
||||
IsUpper: function(){ return (this.value & 1) == 1; },
|
||||
Swap: function(b){
|
||||
var tempValue = this.value;
|
||||
var tempProxyId = this.proxyId;
|
||||
var tempStabbingCount = this.stabbingCount;
|
||||
|
||||
this.value = b.value;
|
||||
this.proxyId = b.proxyId;
|
||||
this.stabbingCount = b.stabbingCount;
|
||||
|
||||
b.value = tempValue;
|
||||
b.proxyId = tempProxyId;
|
||||
b.stabbingCount = tempStabbingCount;
|
||||
},
|
||||
|
||||
value: 0,
|
||||
proxyId: 0,
|
||||
stabbingCount: 0,
|
||||
|
||||
initialize: function() {}}
|
31
lib/box2d-js/js/box2d/collision/b2BoundValues.js
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2BoundValues = Class.create();
|
||||
b2BoundValues.prototype = {
|
||||
lowerValues: [0,0],
|
||||
upperValues: [0,0],
|
||||
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.lowerValues = [0,0];
|
||||
this.upperValues = [0,0];
|
||||
//
|
||||
}}
|
898
lib/box2d-js/js/box2d/collision/b2BroadPhase.js
Normal file
@ -0,0 +1,898 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
This broad phase uses the Sweep and Prune algorithm in:
|
||||
Collision Detection in Interactive 3D Environments by Gino van den Bergen
|
||||
Also, some ideas, such integral values for fast compares comes from
|
||||
Bullet (http:/www.bulletphysics.com).
|
||||
*/
|
||||
|
||||
|
||||
// Notes:
|
||||
// - we use bound arrays instead of linked lists for cache coherence.
|
||||
// - we use quantized integral values for fast compares.
|
||||
// - we use short indices rather than pointers to save memory.
|
||||
// - we use a stabbing count for fast overlap queries (less than order N).
|
||||
// - we also use a time stamp on each proxy to speed up the registration of
|
||||
// overlap query results.
|
||||
// - where possible, we compare bound indices instead of values to reduce
|
||||
// cache misses (TODO_ERIN).
|
||||
// - no broadphase is perfect and neither is this one: it is not great for huge
|
||||
// worlds (use a multi-SAP instead), it is not great for large objects.
|
||||
|
||||
var b2BroadPhase = Class.create();
|
||||
b2BroadPhase.prototype =
|
||||
{
|
||||
//public:
|
||||
initialize: function(worldAABB, callback){
|
||||
// initialize instance variables for references
|
||||
this.m_pairManager = new b2PairManager();
|
||||
this.m_proxyPool = new Array(b2Settings.b2_maxPairs);
|
||||
this.m_bounds = new Array(2*b2Settings.b2_maxProxies);
|
||||
this.m_queryResults = new Array(b2Settings.b2_maxProxies);
|
||||
this.m_quantizationFactor = new b2Vec2();
|
||||
//
|
||||
|
||||
//b2Settings.b2Assert(worldAABB.IsValid());
|
||||
var i = 0;
|
||||
|
||||
this.m_pairManager.Initialize(this, callback);
|
||||
|
||||
this.m_worldAABB = worldAABB;
|
||||
|
||||
this.m_proxyCount = 0;
|
||||
|
||||
// query results
|
||||
for (i = 0; i < b2Settings.b2_maxProxies; i++){
|
||||
this.m_queryResults[i] = 0;
|
||||
}
|
||||
|
||||
// bounds array
|
||||
this.m_bounds = new Array(2);
|
||||
for (i = 0; i < 2; i++){
|
||||
this.m_bounds[i] = new Array(2*b2Settings.b2_maxProxies);
|
||||
for (var j = 0; j < 2*b2Settings.b2_maxProxies; j++){
|
||||
this.m_bounds[i][j] = new b2Bound();
|
||||
}
|
||||
}
|
||||
|
||||
//var d = b2Math.SubtractVV(worldAABB.maxVertex, worldAABB.minVertex);
|
||||
var dX = worldAABB.maxVertex.x;
|
||||
var dY = worldAABB.maxVertex.y;
|
||||
dX -= worldAABB.minVertex.x;
|
||||
dY -= worldAABB.minVertex.y;
|
||||
|
||||
this.m_quantizationFactor.x = b2Settings.USHRT_MAX / dX;
|
||||
this.m_quantizationFactor.y = b2Settings.USHRT_MAX / dY;
|
||||
|
||||
var tProxy;
|
||||
for (i = 0; i < b2Settings.b2_maxProxies - 1; ++i)
|
||||
{
|
||||
tProxy = new b2Proxy();
|
||||
this.m_proxyPool[i] = tProxy;
|
||||
tProxy.SetNext(i + 1);
|
||||
tProxy.timeStamp = 0;
|
||||
tProxy.overlapCount = b2BroadPhase.b2_invalid;
|
||||
tProxy.userData = null;
|
||||
}
|
||||
tProxy = new b2Proxy();
|
||||
this.m_proxyPool[b2Settings.b2_maxProxies-1] = tProxy;
|
||||
tProxy.SetNext(b2Pair.b2_nullProxy);
|
||||
tProxy.timeStamp = 0;
|
||||
tProxy.overlapCount = b2BroadPhase.b2_invalid;
|
||||
tProxy.userData = null;
|
||||
this.m_freeProxy = 0;
|
||||
|
||||
this.m_timeStamp = 1;
|
||||
this.m_queryResultCount = 0;
|
||||
},
|
||||
//~b2BroadPhase();
|
||||
|
||||
// Use this to see if your proxy is in range. If it is not in range,
|
||||
// it should be destroyed. Otherwise you may get O(m^2) pairs, where m
|
||||
// is the number of proxies that are out of range.
|
||||
InRange: function(aabb){
|
||||
//var d = b2Math.b2MaxV(b2Math.SubtractVV(aabb.minVertex, this.m_worldAABB.maxVertex), b2Math.SubtractVV(this.m_worldAABB.minVertex, aabb.maxVertex));
|
||||
var dX;
|
||||
var dY;
|
||||
var d2X;
|
||||
var d2Y;
|
||||
|
||||
dX = aabb.minVertex.x;
|
||||
dY = aabb.minVertex.y;
|
||||
dX -= this.m_worldAABB.maxVertex.x;
|
||||
dY -= this.m_worldAABB.maxVertex.y;
|
||||
|
||||
d2X = this.m_worldAABB.minVertex.x;
|
||||
d2Y = this.m_worldAABB.minVertex.y;
|
||||
d2X -= aabb.maxVertex.x;
|
||||
d2Y -= aabb.maxVertex.y;
|
||||
|
||||
dX = b2Math.b2Max(dX, d2X);
|
||||
dY = b2Math.b2Max(dY, d2Y);
|
||||
|
||||
return b2Math.b2Max(dX, dY) < 0.0;
|
||||
},
|
||||
|
||||
// Get a single proxy. Returns NULL if the id is invalid.
|
||||
GetProxy: function(proxyId){
|
||||
if (proxyId == b2Pair.b2_nullProxy || this.m_proxyPool[proxyId].IsValid() == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.m_proxyPool[ proxyId ];
|
||||
},
|
||||
|
||||
// Create and destroy proxies. These call Flush first.
|
||||
CreateProxy: function(aabb, userData){
|
||||
var index = 0;
|
||||
var proxy;
|
||||
|
||||
//b2Settings.b2Assert(this.m_proxyCount < b2_maxProxies);
|
||||
//b2Settings.b2Assert(this.m_freeProxy != b2Pair.b2_nullProxy);
|
||||
|
||||
var proxyId = this.m_freeProxy;
|
||||
proxy = this.m_proxyPool[ proxyId ];
|
||||
this.m_freeProxy = proxy.GetNext();
|
||||
|
||||
proxy.overlapCount = 0;
|
||||
proxy.userData = userData;
|
||||
|
||||
var boundCount = 2 * this.m_proxyCount;
|
||||
|
||||
var lowerValues = new Array();
|
||||
var upperValues = new Array();
|
||||
this.ComputeBounds(lowerValues, upperValues, aabb);
|
||||
|
||||
for (var axis = 0; axis < 2; ++axis)
|
||||
{
|
||||
var bounds = this.m_bounds[axis];
|
||||
var lowerIndex = 0;
|
||||
var upperIndex = 0;
|
||||
var lowerIndexOut = [lowerIndex];
|
||||
var upperIndexOut = [upperIndex];
|
||||
this.Query(lowerIndexOut, upperIndexOut, lowerValues[axis], upperValues[axis], bounds, boundCount, axis);
|
||||
lowerIndex = lowerIndexOut[0];
|
||||
upperIndex = upperIndexOut[0];
|
||||
|
||||
// Replace memmove calls
|
||||
//memmove(bounds + upperIndex + 2, bounds + upperIndex, (edgeCount - upperIndex) * sizeof(b2Bound));
|
||||
var tArr = new Array();
|
||||
var j = 0;
|
||||
var tEnd = boundCount - upperIndex
|
||||
var tBound1;
|
||||
var tBound2;
|
||||
// make temp array
|
||||
for (j = 0; j < tEnd; j++){
|
||||
tArr[j] = new b2Bound();
|
||||
tBound1 = tArr[j];
|
||||
tBound2 = bounds[upperIndex+j];
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
// move temp array back in to bounds
|
||||
tEnd = tArr.length;
|
||||
var tIndex = upperIndex+2;
|
||||
for (j = 0; j < tEnd; j++){
|
||||
//bounds[tIndex+j] = tArr[j];
|
||||
tBound2 = tArr[j];
|
||||
tBound1 = bounds[tIndex+j]
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
//memmove(bounds + lowerIndex + 1, bounds + lowerIndex, (upperIndex - lowerIndex) * sizeof(b2Bound));
|
||||
// make temp array
|
||||
tArr = new Array();
|
||||
tEnd = upperIndex - lowerIndex;
|
||||
for (j = 0; j < tEnd; j++){
|
||||
tArr[j] = new b2Bound();
|
||||
tBound1 = tArr[j];
|
||||
tBound2 = bounds[lowerIndex+j];
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
// move temp array back in to bounds
|
||||
tEnd = tArr.length;
|
||||
tIndex = lowerIndex+1;
|
||||
for (j = 0; j < tEnd; j++){
|
||||
//bounds[tIndex+j] = tArr[j];
|
||||
tBound2 = tArr[j];
|
||||
tBound1 = bounds[tIndex+j]
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
|
||||
// The upper index has increased because of the lower bound insertion.
|
||||
++upperIndex;
|
||||
|
||||
// Copy in the new bounds.
|
||||
bounds[lowerIndex].value = lowerValues[axis];
|
||||
bounds[lowerIndex].proxyId = proxyId;
|
||||
bounds[upperIndex].value = upperValues[axis];
|
||||
bounds[upperIndex].proxyId = proxyId;
|
||||
|
||||
bounds[lowerIndex].stabbingCount = lowerIndex == 0 ? 0 : bounds[lowerIndex-1].stabbingCount;
|
||||
bounds[upperIndex].stabbingCount = bounds[upperIndex-1].stabbingCount;
|
||||
|
||||
// Adjust the stabbing count between the new bounds.
|
||||
for (index = lowerIndex; index < upperIndex; ++index)
|
||||
{
|
||||
bounds[index].stabbingCount++;
|
||||
}
|
||||
|
||||
// Adjust the all the affected bound indices.
|
||||
for (index = lowerIndex; index < boundCount + 2; ++index)
|
||||
{
|
||||
var proxy2 = this.m_proxyPool[ bounds[index].proxyId ];
|
||||
if (bounds[index].IsLower())
|
||||
{
|
||||
proxy2.lowerBounds[axis] = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy2.upperBounds[axis] = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++this.m_proxyCount;
|
||||
|
||||
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
||||
|
||||
for (var i = 0; i < this.m_queryResultCount; ++i)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_queryResults[i] < b2_maxProxies);
|
||||
//b2Settings.b2Assert(this.m_proxyPool[this.m_queryResults[i]].IsValid());
|
||||
|
||||
this.m_pairManager.AddBufferedPair(proxyId, this.m_queryResults[i]);
|
||||
}
|
||||
|
||||
this.m_pairManager.Commit();
|
||||
|
||||
// Prepare for next query.
|
||||
this.m_queryResultCount = 0;
|
||||
this.IncrementTimeStamp();
|
||||
|
||||
return proxyId;
|
||||
},
|
||||
|
||||
DestroyProxy: function(proxyId){
|
||||
|
||||
//b2Settings.b2Assert(0 < this.m_proxyCount && this.m_proxyCount <= b2_maxProxies);
|
||||
|
||||
var proxy = this.m_proxyPool[ proxyId ];
|
||||
//b2Settings.b2Assert(proxy.IsValid());
|
||||
|
||||
var boundCount = 2 * this.m_proxyCount;
|
||||
|
||||
for (var axis = 0; axis < 2; ++axis)
|
||||
{
|
||||
var bounds = this.m_bounds[axis];
|
||||
|
||||
var lowerIndex = proxy.lowerBounds[axis];
|
||||
var upperIndex = proxy.upperBounds[axis];
|
||||
var lowerValue = bounds[lowerIndex].value;
|
||||
var upperValue = bounds[upperIndex].value;
|
||||
|
||||
// replace memmove calls
|
||||
//memmove(bounds + lowerIndex, bounds + lowerIndex + 1, (upperIndex - lowerIndex - 1) * sizeof(b2Bound));
|
||||
var tArr = new Array();
|
||||
var j = 0;
|
||||
var tEnd = upperIndex - lowerIndex - 1;
|
||||
var tBound1;
|
||||
var tBound2;
|
||||
// make temp array
|
||||
for (j = 0; j < tEnd; j++){
|
||||
tArr[j] = new b2Bound();
|
||||
tBound1 = tArr[j];
|
||||
tBound2 = bounds[lowerIndex+1+j];
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
// move temp array back in to bounds
|
||||
tEnd = tArr.length;
|
||||
var tIndex = lowerIndex;
|
||||
for (j = 0; j < tEnd; j++){
|
||||
//bounds[tIndex+j] = tArr[j];
|
||||
tBound2 = tArr[j];
|
||||
tBound1 = bounds[tIndex+j]
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
//memmove(bounds + upperIndex-1, bounds + upperIndex + 1, (edgeCount - upperIndex - 1) * sizeof(b2Bound));
|
||||
// make temp array
|
||||
tArr = new Array();
|
||||
tEnd = boundCount - upperIndex - 1;
|
||||
for (j = 0; j < tEnd; j++){
|
||||
tArr[j] = new b2Bound();
|
||||
tBound1 = tArr[j];
|
||||
tBound2 = bounds[upperIndex+1+j];
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
// move temp array back in to bounds
|
||||
tEnd = tArr.length;
|
||||
tIndex = upperIndex-1;
|
||||
for (j = 0; j < tEnd; j++){
|
||||
//bounds[tIndex+j] = tArr[j];
|
||||
tBound2 = tArr[j];
|
||||
tBound1 = bounds[tIndex+j]
|
||||
tBound1.value = tBound2.value;
|
||||
tBound1.proxyId = tBound2.proxyId;
|
||||
tBound1.stabbingCount = tBound2.stabbingCount;
|
||||
}
|
||||
|
||||
// Fix bound indices.
|
||||
tEnd = boundCount - 2;
|
||||
for (var index = lowerIndex; index < tEnd; ++index)
|
||||
{
|
||||
var proxy2 = this.m_proxyPool[ bounds[index].proxyId ];
|
||||
if (bounds[index].IsLower())
|
||||
{
|
||||
proxy2.lowerBounds[axis] = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy2.upperBounds[axis] = index;
|
||||
}
|
||||
}
|
||||
|
||||
// Fix stabbing count.
|
||||
tEnd = upperIndex - 1;
|
||||
for (var index2 = lowerIndex; index2 < tEnd; ++index2)
|
||||
{
|
||||
bounds[index2].stabbingCount--;
|
||||
}
|
||||
|
||||
// this.Query for pairs to be removed. lowerIndex and upperIndex are not needed.
|
||||
// make lowerIndex and upper output using an array and do this for others if compiler doesn't pick them up
|
||||
this.Query([0], [0], lowerValue, upperValue, bounds, boundCount - 2, axis);
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
||||
|
||||
for (var i = 0; i < this.m_queryResultCount; ++i)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_proxyPool[this.m_queryResults[i]].IsValid());
|
||||
|
||||
this.m_pairManager.RemoveBufferedPair(proxyId, this.m_queryResults[i]);
|
||||
}
|
||||
|
||||
this.m_pairManager.Commit();
|
||||
|
||||
// Prepare for next query.
|
||||
this.m_queryResultCount = 0;
|
||||
this.IncrementTimeStamp();
|
||||
|
||||
// Return the proxy to the pool.
|
||||
proxy.userData = null;
|
||||
proxy.overlapCount = b2BroadPhase.b2_invalid;
|
||||
proxy.lowerBounds[0] = b2BroadPhase.b2_invalid;
|
||||
proxy.lowerBounds[1] = b2BroadPhase.b2_invalid;
|
||||
proxy.upperBounds[0] = b2BroadPhase.b2_invalid;
|
||||
proxy.upperBounds[1] = b2BroadPhase.b2_invalid;
|
||||
|
||||
proxy.SetNext(this.m_freeProxy);
|
||||
this.m_freeProxy = proxyId;
|
||||
--this.m_proxyCount;
|
||||
},
|
||||
|
||||
|
||||
// Call this.MoveProxy times like, then when you are done
|
||||
// call this.Commit to finalized the proxy pairs (for your time step).
|
||||
MoveProxy: function(proxyId, aabb){
|
||||
var axis = 0;
|
||||
var index = 0;
|
||||
var bound;
|
||||
var prevBound
|
||||
var nextBound
|
||||
var nextProxyId = 0;
|
||||
var nextProxy;
|
||||
|
||||
if (proxyId == b2Pair.b2_nullProxy || b2Settings.b2_maxProxies <= proxyId)
|
||||
{
|
||||
//b2Settings.b2Assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aabb.IsValid() == false)
|
||||
{
|
||||
//b2Settings.b2Assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var boundCount = 2 * this.m_proxyCount;
|
||||
|
||||
var proxy = this.m_proxyPool[ proxyId ];
|
||||
// Get new bound values
|
||||
var newValues = new b2BoundValues();
|
||||
this.ComputeBounds(newValues.lowerValues, newValues.upperValues, aabb);
|
||||
|
||||
// Get old bound values
|
||||
var oldValues = new b2BoundValues();
|
||||
for (axis = 0; axis < 2; ++axis)
|
||||
{
|
||||
oldValues.lowerValues[axis] = this.m_bounds[axis][proxy.lowerBounds[axis]].value;
|
||||
oldValues.upperValues[axis] = this.m_bounds[axis][proxy.upperBounds[axis]].value;
|
||||
}
|
||||
|
||||
for (axis = 0; axis < 2; ++axis)
|
||||
{
|
||||
var bounds = this.m_bounds[axis];
|
||||
|
||||
var lowerIndex = proxy.lowerBounds[axis];
|
||||
var upperIndex = proxy.upperBounds[axis];
|
||||
|
||||
var lowerValue = newValues.lowerValues[axis];
|
||||
var upperValue = newValues.upperValues[axis];
|
||||
|
||||
var deltaLower = lowerValue - bounds[lowerIndex].value;
|
||||
var deltaUpper = upperValue - bounds[upperIndex].value;
|
||||
|
||||
bounds[lowerIndex].value = lowerValue;
|
||||
bounds[upperIndex].value = upperValue;
|
||||
|
||||
//
|
||||
// Expanding adds overlaps
|
||||
//
|
||||
|
||||
// Should we move the lower bound down?
|
||||
if (deltaLower < 0)
|
||||
{
|
||||
index = lowerIndex;
|
||||
while (index > 0 && lowerValue < bounds[index-1].value)
|
||||
{
|
||||
bound = bounds[index];
|
||||
prevBound = bounds[index - 1];
|
||||
|
||||
var prevProxyId = prevBound.proxyId;
|
||||
var prevProxy = this.m_proxyPool[ prevBound.proxyId ];
|
||||
|
||||
prevBound.stabbingCount++;
|
||||
|
||||
if (prevBound.IsUpper() == true)
|
||||
{
|
||||
if (this.TestOverlap(newValues, prevProxy))
|
||||
{
|
||||
this.m_pairManager.AddBufferedPair(proxyId, prevProxyId);
|
||||
}
|
||||
|
||||
prevProxy.upperBounds[axis]++;
|
||||
bound.stabbingCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevProxy.lowerBounds[axis]++;
|
||||
bound.stabbingCount--;
|
||||
}
|
||||
|
||||
proxy.lowerBounds[axis]--;
|
||||
|
||||
// swap
|
||||
//var temp = bound;
|
||||
//bound = prevEdge;
|
||||
//prevEdge = temp;
|
||||
bound.Swap(prevBound);
|
||||
//b2Math.b2Swap(bound, prevEdge);
|
||||
--index;
|
||||
}
|
||||
}
|
||||
|
||||
// Should we move the upper bound up?
|
||||
if (deltaUpper > 0)
|
||||
{
|
||||
index = upperIndex;
|
||||
while (index < boundCount-1 && bounds[index+1].value <= upperValue)
|
||||
{
|
||||
bound = bounds[ index ];
|
||||
nextBound = bounds[ index + 1 ];
|
||||
nextProxyId = nextBound.proxyId;
|
||||
nextProxy = this.m_proxyPool[ nextProxyId ];
|
||||
|
||||
nextBound.stabbingCount++;
|
||||
|
||||
if (nextBound.IsLower() == true)
|
||||
{
|
||||
if (this.TestOverlap(newValues, nextProxy))
|
||||
{
|
||||
this.m_pairManager.AddBufferedPair(proxyId, nextProxyId);
|
||||
}
|
||||
|
||||
nextProxy.lowerBounds[axis]--;
|
||||
bound.stabbingCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextProxy.upperBounds[axis]--;
|
||||
bound.stabbingCount--;
|
||||
}
|
||||
|
||||
proxy.upperBounds[axis]++;
|
||||
// swap
|
||||
//var temp = bound;
|
||||
//bound = nextEdge;
|
||||
//nextEdge = temp;
|
||||
bound.Swap(nextBound);
|
||||
//b2Math.b2Swap(bound, nextEdge);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Shrinking removes overlaps
|
||||
//
|
||||
|
||||
// Should we move the lower bound up?
|
||||
if (deltaLower > 0)
|
||||
{
|
||||
index = lowerIndex;
|
||||
while (index < boundCount-1 && bounds[index+1].value <= lowerValue)
|
||||
{
|
||||
bound = bounds[ index ];
|
||||
nextBound = bounds[ index + 1 ];
|
||||
|
||||
nextProxyId = nextBound.proxyId;
|
||||
nextProxy = this.m_proxyPool[ nextProxyId ];
|
||||
|
||||
nextBound.stabbingCount--;
|
||||
|
||||
if (nextBound.IsUpper())
|
||||
{
|
||||
if (this.TestOverlap(oldValues, nextProxy))
|
||||
{
|
||||
this.m_pairManager.RemoveBufferedPair(proxyId, nextProxyId);
|
||||
}
|
||||
|
||||
nextProxy.upperBounds[axis]--;
|
||||
bound.stabbingCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextProxy.lowerBounds[axis]--;
|
||||
bound.stabbingCount++;
|
||||
}
|
||||
|
||||
proxy.lowerBounds[axis]++;
|
||||
// swap
|
||||
//var temp = bound;
|
||||
//bound = nextEdge;
|
||||
//nextEdge = temp;
|
||||
bound.Swap(nextBound);
|
||||
//b2Math.b2Swap(bound, nextEdge);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Should we move the upper bound down?
|
||||
if (deltaUpper < 0)
|
||||
{
|
||||
index = upperIndex;
|
||||
while (index > 0 && upperValue < bounds[index-1].value)
|
||||
{
|
||||
bound = bounds[index];
|
||||
prevBound = bounds[index - 1];
|
||||
|
||||
prevProxyId = prevBound.proxyId;
|
||||
prevProxy = this.m_proxyPool[ prevProxyId ];
|
||||
|
||||
prevBound.stabbingCount--;
|
||||
|
||||
if (prevBound.IsLower() == true)
|
||||
{
|
||||
if (this.TestOverlap(oldValues, prevProxy))
|
||||
{
|
||||
this.m_pairManager.RemoveBufferedPair(proxyId, prevProxyId);
|
||||
}
|
||||
|
||||
prevProxy.lowerBounds[axis]++;
|
||||
bound.stabbingCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevProxy.upperBounds[axis]++;
|
||||
bound.stabbingCount++;
|
||||
}
|
||||
|
||||
proxy.upperBounds[axis]--;
|
||||
// swap
|
||||
//var temp = bound;
|
||||
//bound = prevEdge;
|
||||
//prevEdge = temp;
|
||||
bound.Swap(prevBound);
|
||||
//b2Math.b2Swap(bound, prevEdge);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Commit: function(){
|
||||
this.m_pairManager.Commit();
|
||||
},
|
||||
|
||||
// this.Query an AABB for overlapping proxies, returns the user data and
|
||||
// the count, up to the supplied maximum count.
|
||||
QueryAABB: function(aabb, userData, maxCount){
|
||||
var lowerValues = new Array();
|
||||
var upperValues = new Array();
|
||||
this.ComputeBounds(lowerValues, upperValues, aabb);
|
||||
|
||||
var lowerIndex = 0;
|
||||
var upperIndex = 0;
|
||||
var lowerIndexOut = [lowerIndex];
|
||||
var upperIndexOut = [upperIndex];
|
||||
this.Query(lowerIndexOut, upperIndexOut, lowerValues[0], upperValues[0], this.m_bounds[0], 2*this.m_proxyCount, 0);
|
||||
this.Query(lowerIndexOut, upperIndexOut, lowerValues[1], upperValues[1], this.m_bounds[1], 2*this.m_proxyCount, 1);
|
||||
|
||||
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
||||
|
||||
var count = 0;
|
||||
for (var i = 0; i < this.m_queryResultCount && count < maxCount; ++i, ++count)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_queryResults[i] < b2Settings.b2_maxProxies);
|
||||
var proxy = this.m_proxyPool[ this.m_queryResults[i] ];
|
||||
//b2Settings.b2Assert(proxy.IsValid());
|
||||
userData[i] = proxy.userData;
|
||||
}
|
||||
|
||||
// Prepare for next query.
|
||||
this.m_queryResultCount = 0;
|
||||
this.IncrementTimeStamp();
|
||||
|
||||
return count;
|
||||
},
|
||||
|
||||
Validate: function(){
|
||||
var pair;
|
||||
var proxy1;
|
||||
var proxy2;
|
||||
var overlap;
|
||||
|
||||
for (var axis = 0; axis < 2; ++axis)
|
||||
{
|
||||
var bounds = this.m_bounds[axis];
|
||||
|
||||
var boundCount = 2 * this.m_proxyCount;
|
||||
var stabbingCount = 0;
|
||||
|
||||
for (var i = 0; i < boundCount; ++i)
|
||||
{
|
||||
var bound = bounds[i];
|
||||
//b2Settings.b2Assert(i == 0 || bounds[i-1].value <= bound->value);
|
||||
//b2Settings.b2Assert(bound->proxyId != b2_nullProxy);
|
||||
//b2Settings.b2Assert(this.m_proxyPool[bound->proxyId].IsValid());
|
||||
|
||||
if (bound.IsLower() == true)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_proxyPool[bound.proxyId].lowerBounds[axis] == i);
|
||||
stabbingCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_proxyPool[bound.proxyId].upperBounds[axis] == i);
|
||||
stabbingCount--;
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(bound.stabbingCount == stabbingCount);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
//private:
|
||||
ComputeBounds: function(lowerValues, upperValues, aabb)
|
||||
{
|
||||
//b2Settings.b2Assert(aabb.maxVertex.x > aabb.minVertex.x);
|
||||
//b2Settings.b2Assert(aabb.maxVertex.y > aabb.minVertex.y);
|
||||
|
||||
//var minVertex = b2Math.b2ClampV(aabb.minVertex, this.m_worldAABB.minVertex, this.m_worldAABB.maxVertex);
|
||||
var minVertexX = aabb.minVertex.x;
|
||||
var minVertexY = aabb.minVertex.y;
|
||||
minVertexX = b2Math.b2Min(minVertexX, this.m_worldAABB.maxVertex.x);
|
||||
minVertexY = b2Math.b2Min(minVertexY, this.m_worldAABB.maxVertex.y);
|
||||
minVertexX = b2Math.b2Max(minVertexX, this.m_worldAABB.minVertex.x);
|
||||
minVertexY = b2Math.b2Max(minVertexY, this.m_worldAABB.minVertex.y);
|
||||
|
||||
//var maxVertex = b2Math.b2ClampV(aabb.maxVertex, this.m_worldAABB.minVertex, this.m_worldAABB.maxVertex);
|
||||
var maxVertexX = aabb.maxVertex.x;
|
||||
var maxVertexY = aabb.maxVertex.y;
|
||||
maxVertexX = b2Math.b2Min(maxVertexX, this.m_worldAABB.maxVertex.x);
|
||||
maxVertexY = b2Math.b2Min(maxVertexY, this.m_worldAABB.maxVertex.y);
|
||||
maxVertexX = b2Math.b2Max(maxVertexX, this.m_worldAABB.minVertex.x);
|
||||
maxVertexY = b2Math.b2Max(maxVertexY, this.m_worldAABB.minVertex.y);
|
||||
|
||||
// Bump lower bounds downs and upper bounds up. This ensures correct sorting of
|
||||
// lower/upper bounds that would have equal values.
|
||||
// TODO_ERIN implement fast float to uint16 conversion.
|
||||
lowerValues[0] = /*uint*/(this.m_quantizationFactor.x * (minVertexX - this.m_worldAABB.minVertex.x)) & (b2Settings.USHRT_MAX - 1);
|
||||
upperValues[0] = (/*uint*/(this.m_quantizationFactor.x * (maxVertexX - this.m_worldAABB.minVertex.x))& 0x0000ffff) | 1;
|
||||
|
||||
lowerValues[1] = /*uint*/(this.m_quantizationFactor.y * (minVertexY - this.m_worldAABB.minVertex.y)) & (b2Settings.USHRT_MAX - 1);
|
||||
upperValues[1] = (/*uint*/(this.m_quantizationFactor.y * (maxVertexY - this.m_worldAABB.minVertex.y))& 0x0000ffff) | 1;
|
||||
},
|
||||
|
||||
// This one is only used for validation.
|
||||
TestOverlapValidate: function(p1, p2){
|
||||
|
||||
for (var axis = 0; axis < 2; ++axis)
|
||||
{
|
||||
var bounds = this.m_bounds[axis];
|
||||
|
||||
//b2Settings.b2Assert(p1.lowerBounds[axis] < 2 * this.m_proxyCount);
|
||||
//b2Settings.b2Assert(p1.upperBounds[axis] < 2 * this.m_proxyCount);
|
||||
//b2Settings.b2Assert(p2.lowerBounds[axis] < 2 * this.m_proxyCount);
|
||||
//b2Settings.b2Assert(p2.upperBounds[axis] < 2 * this.m_proxyCount);
|
||||
|
||||
if (bounds[p1.lowerBounds[axis]].value > bounds[p2.upperBounds[axis]].value)
|
||||
return false;
|
||||
|
||||
if (bounds[p1.upperBounds[axis]].value < bounds[p2.lowerBounds[axis]].value)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
TestOverlap: function(b, p)
|
||||
{
|
||||
for (var axis = 0; axis < 2; ++axis)
|
||||
{
|
||||
var bounds = this.m_bounds[axis];
|
||||
|
||||
//b2Settings.b2Assert(p.lowerBounds[axis] < 2 * this.m_proxyCount);
|
||||
//b2Settings.b2Assert(p.upperBounds[axis] < 2 * this.m_proxyCount);
|
||||
|
||||
if (b.lowerValues[axis] > bounds[p.upperBounds[axis]].value)
|
||||
return false;
|
||||
|
||||
if (b.upperValues[axis] < bounds[p.lowerBounds[axis]].value)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
Query: function(lowerQueryOut, upperQueryOut, lowerValue, upperValue, bounds, boundCount, axis){
|
||||
|
||||
var lowerQuery = b2BroadPhase.BinarySearch(bounds, boundCount, lowerValue);
|
||||
var upperQuery = b2BroadPhase.BinarySearch(bounds, boundCount, upperValue);
|
||||
|
||||
// Easy case: lowerQuery <= lowerIndex(i) < upperQuery
|
||||
// Solution: search query range for min bounds.
|
||||
for (var j = lowerQuery; j < upperQuery; ++j)
|
||||
{
|
||||
if (bounds[j].IsLower())
|
||||
{
|
||||
this.IncrementOverlapCount(bounds[j].proxyId);
|
||||
}
|
||||
}
|
||||
|
||||
// Hard case: lowerIndex(i) < lowerQuery < upperIndex(i)
|
||||
// Solution: use the stabbing count to search down the bound array.
|
||||
if (lowerQuery > 0)
|
||||
{
|
||||
var i = lowerQuery - 1;
|
||||
var s = bounds[i].stabbingCount;
|
||||
|
||||
// Find the s overlaps.
|
||||
while (s)
|
||||
{
|
||||
//b2Settings.b2Assert(i >= 0);
|
||||
|
||||
if (bounds[i].IsLower())
|
||||
{
|
||||
var proxy = this.m_proxyPool[ bounds[i].proxyId ];
|
||||
if (lowerQuery <= proxy.upperBounds[axis])
|
||||
{
|
||||
this.IncrementOverlapCount(bounds[i].proxyId);
|
||||
--s;
|
||||
}
|
||||
}
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
lowerQueryOut[0] = lowerQuery;
|
||||
upperQueryOut[0] = upperQuery;
|
||||
},
|
||||
|
||||
|
||||
IncrementOverlapCount: function(proxyId){
|
||||
var proxy = this.m_proxyPool[ proxyId ];
|
||||
if (proxy.timeStamp < this.m_timeStamp)
|
||||
{
|
||||
proxy.timeStamp = this.m_timeStamp;
|
||||
proxy.overlapCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy.overlapCount = 2;
|
||||
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
||||
this.m_queryResults[this.m_queryResultCount] = proxyId;
|
||||
++this.m_queryResultCount;
|
||||
}
|
||||
},
|
||||
IncrementTimeStamp: function(){
|
||||
if (this.m_timeStamp == b2Settings.USHRT_MAX)
|
||||
{
|
||||
for (var i = 0; i < b2Settings.b2_maxProxies; ++i)
|
||||
{
|
||||
this.m_proxyPool[i].timeStamp = 0;
|
||||
}
|
||||
this.m_timeStamp = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++this.m_timeStamp;
|
||||
}
|
||||
},
|
||||
|
||||
//public:
|
||||
m_pairManager: new b2PairManager(),
|
||||
|
||||
m_proxyPool: new Array(b2Settings.b2_maxPairs),
|
||||
m_freeProxy: 0,
|
||||
|
||||
m_bounds: new Array(2*b2Settings.b2_maxProxies),
|
||||
|
||||
m_queryResults: new Array(b2Settings.b2_maxProxies),
|
||||
m_queryResultCount: 0,
|
||||
|
||||
m_worldAABB: null,
|
||||
m_quantizationFactor: new b2Vec2(),
|
||||
m_proxyCount: 0,
|
||||
m_timeStamp: 0};
|
||||
b2BroadPhase.s_validate = false;
|
||||
b2BroadPhase.b2_invalid = b2Settings.USHRT_MAX;
|
||||
b2BroadPhase.b2_nullEdge = b2Settings.USHRT_MAX;
|
||||
b2BroadPhase.BinarySearch = function(bounds, count, value)
|
||||
{
|
||||
var low = 0;
|
||||
var high = count - 1;
|
||||
while (low <= high)
|
||||
{
|
||||
var mid = Math.floor((low + high) / 2);
|
||||
if (bounds[mid].value > value)
|
||||
{
|
||||
high = mid - 1;
|
||||
}
|
||||
else if (bounds[mid].value < value)
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return /*uint*/(mid);
|
||||
}
|
||||
}
|
||||
|
||||
return /*uint*/(low);
|
||||
};
|
26
lib/box2d-js/js/box2d/collision/b2BufferedPair.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2BufferedPair = Class.create();
|
||||
b2BufferedPair.prototype = {
|
||||
proxyId1: 0,
|
||||
proxyId2: 0,
|
||||
|
||||
initialize: function() {}}
|
738
lib/box2d-js/js/box2d/collision/b2Collision.js
Normal file
@ -0,0 +1,738 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
var b2Collision = Class.create();
|
||||
b2Collision.prototype = {
|
||||
|
||||
// Null feature
|
||||
|
||||
|
||||
|
||||
|
||||
// Find the separation between poly1 and poly2 for a give edge normal on poly1.
|
||||
|
||||
|
||||
|
||||
|
||||
// Find the max separation between poly1 and poly2 using edge normals
|
||||
// from poly1.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Find edge normal of max separation on A - return if separating axis is found
|
||||
// Find edge normal of max separation on B - return if separation axis is found
|
||||
// Choose reference edge(minA, minB)
|
||||
// Find incident edge
|
||||
// Clip
|
||||
// The normal points from 1 to 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initialize: function() {}}
|
||||
b2Collision.b2_nullFeature = 0x000000ff;
|
||||
b2Collision.ClipSegmentToLine = function(vOut, vIn, normal, offset)
|
||||
{
|
||||
// Start with no output points
|
||||
var numOut = 0;
|
||||
|
||||
var vIn0 = vIn[0].v;
|
||||
var vIn1 = vIn[1].v;
|
||||
|
||||
// Calculate the distance of end points to the line
|
||||
var distance0 = b2Math.b2Dot(normal, vIn[0].v) - offset;
|
||||
var distance1 = b2Math.b2Dot(normal, vIn[1].v) - offset;
|
||||
|
||||
// If the points are behind the plane
|
||||
if (distance0 <= 0.0) vOut[numOut++] = vIn[0];
|
||||
if (distance1 <= 0.0) vOut[numOut++] = vIn[1];
|
||||
|
||||
// If the points are on different sides of the plane
|
||||
if (distance0 * distance1 < 0.0)
|
||||
{
|
||||
// Find intersection point of edge and plane
|
||||
var interp = distance0 / (distance0 - distance1);
|
||||
// expanded for performance
|
||||
var tVec = vOut[numOut].v;
|
||||
tVec.x = vIn0.x + interp * (vIn1.x - vIn0.x);
|
||||
tVec.y = vIn0.y + interp * (vIn1.y - vIn0.y);
|
||||
if (distance0 > 0.0)
|
||||
{
|
||||
vOut[numOut].id = vIn[0].id;
|
||||
}
|
||||
else
|
||||
{
|
||||
vOut[numOut].id = vIn[1].id;
|
||||
}
|
||||
++numOut;
|
||||
}
|
||||
|
||||
return numOut;
|
||||
};
|
||||
b2Collision.EdgeSeparation = function(poly1, edge1, poly2)
|
||||
{
|
||||
var vert1s = poly1.m_vertices;
|
||||
var count2 = poly2.m_vertexCount;
|
||||
var vert2s = poly2.m_vertices;
|
||||
|
||||
// Convert normal from into poly2's frame.
|
||||
//b2Settings.b2Assert(edge1 < poly1.m_vertexCount);
|
||||
|
||||
//var normal = b2Math.b2MulMV(poly1.m_R, poly1->m_normals[edge1]);
|
||||
var normalX = poly1.m_normals[edge1].x;
|
||||
var normalY = poly1.m_normals[edge1].y;
|
||||
var tX = normalX;
|
||||
var tMat = poly1.m_R;
|
||||
normalX = tMat.col1.x * tX + tMat.col2.x * normalY;
|
||||
normalY = tMat.col1.y * tX + tMat.col2.y * normalY;
|
||||
// ^^^^^^^ normal.MulM(poly1.m_R);
|
||||
|
||||
//var normalLocal2 = b2Math.b2MulTMV(poly2.m_R, normal);
|
||||
var normalLocal2X = normalX;
|
||||
var normalLocal2Y = normalY;
|
||||
tMat = poly2.m_R;
|
||||
tX = normalLocal2X * tMat.col1.x + normalLocal2Y * tMat.col1.y;
|
||||
normalLocal2Y = normalLocal2X * tMat.col2.x + normalLocal2Y * tMat.col2.y;
|
||||
normalLocal2X = tX;
|
||||
// ^^^^^ normalLocal2.MulTM(poly2.m_R);
|
||||
|
||||
// Find support vertex on poly2 for -normal.
|
||||
var vertexIndex2 = 0;
|
||||
var minDot = Number.MAX_VALUE;
|
||||
for (var i = 0; i < count2; ++i)
|
||||
{
|
||||
//var dot = b2Math.b2Dot(vert2s[i], normalLocal2);
|
||||
var tVec = vert2s[i];
|
||||
var dot = tVec.x * normalLocal2X + tVec.y * normalLocal2Y;
|
||||
if (dot < minDot)
|
||||
{
|
||||
minDot = dot;
|
||||
vertexIndex2 = i;
|
||||
}
|
||||
}
|
||||
|
||||
//b2Vec2 v1 = poly1->m_position + b2Mul(poly1->m_R, vert1s[edge1]);
|
||||
tMat = poly1.m_R;
|
||||
var v1X = poly1.m_position.x + (tMat.col1.x * vert1s[edge1].x + tMat.col2.x * vert1s[edge1].y)
|
||||
var v1Y = poly1.m_position.y + (tMat.col1.y * vert1s[edge1].x + tMat.col2.y * vert1s[edge1].y)
|
||||
|
||||
//b2Vec2 v2 = poly2->m_position + b2Mul(poly2->m_R, vert2s[vertexIndex2]);
|
||||
tMat = poly2.m_R;
|
||||
var v2X = poly2.m_position.x + (tMat.col1.x * vert2s[vertexIndex2].x + tMat.col2.x * vert2s[vertexIndex2].y)
|
||||
var v2Y = poly2.m_position.y + (tMat.col1.y * vert2s[vertexIndex2].x + tMat.col2.y * vert2s[vertexIndex2].y)
|
||||
|
||||
//var separation = b2Math.b2Dot( b2Math.SubtractVV( v2, v1 ) , normal);
|
||||
v2X -= v1X;
|
||||
v2Y -= v1Y;
|
||||
//var separation = b2Math.b2Dot( v2 , normal);
|
||||
var separation = v2X * normalX + v2Y * normalY;
|
||||
return separation;
|
||||
};
|
||||
b2Collision.FindMaxSeparation = function(edgeIndex /*int ptr*/, poly1, poly2, conservative)
|
||||
{
|
||||
var count1 = poly1.m_vertexCount;
|
||||
|
||||
// Vector pointing from the origin of poly1 to the origin of poly2.
|
||||
//var d = b2Math.SubtractVV( poly2.m_position, poly1.m_position );
|
||||
var dX = poly2.m_position.x - poly1.m_position.x;
|
||||
var dY = poly2.m_position.y - poly1.m_position.y;
|
||||
|
||||
//var dLocal1 = b2Math.b2MulTMV(poly1.m_R, d);
|
||||
var dLocal1X = (dX * poly1.m_R.col1.x + dY * poly1.m_R.col1.y);
|
||||
var dLocal1Y = (dX * poly1.m_R.col2.x + dY * poly1.m_R.col2.y);
|
||||
|
||||
// Get support vertex hint for our search
|
||||
var edge = 0;
|
||||
var maxDot = -Number.MAX_VALUE;
|
||||
for (var i = 0; i < count1; ++i)
|
||||
{
|
||||
//var dot = b2Math.b2Dot(poly.m_normals[i], dLocal1);
|
||||
var dot = (poly1.m_normals[i].x * dLocal1X + poly1.m_normals[i].y * dLocal1Y);
|
||||
if (dot > maxDot)
|
||||
{
|
||||
maxDot = dot;
|
||||
edge = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the separation for the edge normal.
|
||||
var s = b2Collision.EdgeSeparation(poly1, edge, poly2);
|
||||
if (s > 0.0 && conservative == false)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
// Check the separation for the neighboring edges.
|
||||
var prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
|
||||
var sPrev = b2Collision.EdgeSeparation(poly1, prevEdge, poly2);
|
||||
if (sPrev > 0.0 && conservative == false)
|
||||
{
|
||||
return sPrev;
|
||||
}
|
||||
|
||||
var nextEdge = edge + 1 < count1 ? edge + 1 : 0;
|
||||
var sNext = b2Collision.EdgeSeparation(poly1, nextEdge, poly2);
|
||||
if (sNext > 0.0 && conservative == false)
|
||||
{
|
||||
return sNext;
|
||||
}
|
||||
|
||||
// Find the best edge and the search direction.
|
||||
var bestEdge = 0;
|
||||
var bestSeparation;
|
||||
var increment = 0;
|
||||
if (sPrev > s && sPrev > sNext)
|
||||
{
|
||||
increment = -1;
|
||||
bestEdge = prevEdge;
|
||||
bestSeparation = sPrev;
|
||||
}
|
||||
else if (sNext > s)
|
||||
{
|
||||
increment = 1;
|
||||
bestEdge = nextEdge;
|
||||
bestSeparation = sNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
// pointer out
|
||||
edgeIndex[0] = edge;
|
||||
return s;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
if (increment == -1)
|
||||
edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
|
||||
else
|
||||
edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
|
||||
|
||||
s = b2Collision.EdgeSeparation(poly1, edge, poly2);
|
||||
if (s > 0.0 && conservative == false)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
if (s > bestSeparation)
|
||||
{
|
||||
bestEdge = edge;
|
||||
bestSeparation = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// pointer out
|
||||
edgeIndex[0] = bestEdge;
|
||||
return bestSeparation;
|
||||
};
|
||||
b2Collision.FindIncidentEdge = function(c, poly1, edge1, poly2)
|
||||
{
|
||||
var count1 = poly1.m_vertexCount;
|
||||
var vert1s = poly1.m_vertices;
|
||||
var count2 = poly2.m_vertexCount;
|
||||
var vert2s = poly2.m_vertices;
|
||||
|
||||
// Get the vertices associated with edge1.
|
||||
var vertex11 = edge1;
|
||||
var vertex12 = edge1 + 1 == count1 ? 0 : edge1 + 1;
|
||||
|
||||
// Get the normal of edge1.
|
||||
var tVec = vert1s[vertex12];
|
||||
//var normal1Local1 = b2Math.b2CrossVF( b2Math.SubtractVV( vert1s[vertex12], vert1s[vertex11] ), 1.0);
|
||||
var normal1Local1X = tVec.x;
|
||||
var normal1Local1Y = tVec.y;
|
||||
tVec = vert1s[vertex11];
|
||||
normal1Local1X -= tVec.x;
|
||||
normal1Local1Y -= tVec.y;
|
||||
var tX = normal1Local1X;
|
||||
normal1Local1X = normal1Local1Y;
|
||||
normal1Local1Y = -tX;
|
||||
// ^^^^ normal1Local1.CrossVF(1.0);
|
||||
|
||||
var invLength = 1.0 / Math.sqrt(normal1Local1X*normal1Local1X + normal1Local1Y*normal1Local1Y);
|
||||
normal1Local1X *= invLength;
|
||||
normal1Local1Y *= invLength;
|
||||
// ^^^^normal1Local1.Normalize();
|
||||
//var normal1 = b2Math.b2MulMV(poly1.m_R, normal1Local1);
|
||||
var normal1X = normal1Local1X;
|
||||
var normal1Y = normal1Local1Y;
|
||||
|
||||
tX = normal1X;
|
||||
var tMat = poly1.m_R;
|
||||
normal1X = tMat.col1.x * tX + tMat.col2.x * normal1Y;
|
||||
normal1Y = tMat.col1.y * tX + tMat.col2.y * normal1Y;
|
||||
// ^^^^ normal1.MulM(poly1.m_R);
|
||||
|
||||
//var normal1Local2 = b2Math.b2MulTMV(poly2.m_R, normal1);
|
||||
var normal1Local2X = normal1X;
|
||||
var normal1Local2Y = normal1Y;
|
||||
tMat = poly2.m_R;
|
||||
tX = normal1Local2X * tMat.col1.x + normal1Local2Y * tMat.col1.y;
|
||||
normal1Local2Y = normal1Local2X * tMat.col2.x + normal1Local2Y * tMat.col2.y;
|
||||
normal1Local2X = tX;
|
||||
// ^^^^ normal1Local2.MulTM(poly2.m_R);
|
||||
|
||||
// Find the incident edge on poly2.
|
||||
var vertex21 = 0;
|
||||
var vertex22 = 0;
|
||||
var minDot = Number.MAX_VALUE;
|
||||
for (var i = 0; i < count2; ++i)
|
||||
{
|
||||
var i1 = i;
|
||||
var i2 = i + 1 < count2 ? i + 1 : 0;
|
||||
|
||||
//var normal2Local2 = b2Math.b2CrossVF( b2Math.SubtractVV( vert2s[i2], vert2s[i1] ), 1.0);
|
||||
tVec = vert2s[i2];
|
||||
var normal2Local2X = tVec.x;
|
||||
var normal2Local2Y = tVec.y;
|
||||
tVec = vert2s[i1];
|
||||
normal2Local2X -= tVec.x;
|
||||
normal2Local2Y -= tVec.y;
|
||||
tX = normal2Local2X;
|
||||
normal2Local2X = normal2Local2Y;
|
||||
normal2Local2Y = -tX;
|
||||
// ^^^^ normal2Local2.CrossVF(1.0);
|
||||
|
||||
invLength = 1.0 / Math.sqrt(normal2Local2X*normal2Local2X + normal2Local2Y*normal2Local2Y);
|
||||
normal2Local2X *= invLength;
|
||||
normal2Local2Y *= invLength;
|
||||
// ^^^^ normal2Local2.Normalize();
|
||||
|
||||
//var dot = b2Math.b2Dot(normal2Local2, normal1Local2);
|
||||
var dot = normal2Local2X * normal1Local2X + normal2Local2Y * normal1Local2Y;
|
||||
if (dot < minDot)
|
||||
{
|
||||
minDot = dot;
|
||||
vertex21 = i1;
|
||||
vertex22 = i2;
|
||||
}
|
||||
}
|
||||
|
||||
var tClip;
|
||||
// Build the clip vertices for the incident edge.
|
||||
tClip = c[0];
|
||||
//tClip.v = b2Math.AddVV(poly2.m_position, b2Math.b2MulMV(poly2.m_R, vert2s[vertex21]));
|
||||
tVec = tClip.v;
|
||||
tVec.SetV(vert2s[vertex21]);
|
||||
tVec.MulM(poly2.m_R);
|
||||
tVec.Add(poly2.m_position);
|
||||
|
||||
tClip.id.features.referenceFace = edge1;
|
||||
tClip.id.features.incidentEdge = vertex21;
|
||||
tClip.id.features.incidentVertex = vertex21;
|
||||
|
||||
tClip = c[1];
|
||||
//tClip.v = b2Math.AddVV(poly2.m_position, b2Math.b2MulMV(poly2.m_R, vert2s[vertex22]));
|
||||
tVec = tClip.v;
|
||||
tVec.SetV(vert2s[vertex22]);
|
||||
tVec.MulM(poly2.m_R);
|
||||
tVec.Add(poly2.m_position);
|
||||
tClip.id.features.referenceFace = edge1;
|
||||
tClip.id.features.incidentEdge = vertex21;
|
||||
tClip.id.features.incidentVertex = vertex22;
|
||||
};
|
||||
b2Collision.b2CollidePolyTempVec = new b2Vec2();
|
||||
b2Collision.b2CollidePoly = function(manifold, polyA, polyB, conservative)
|
||||
{
|
||||
manifold.pointCount = 0;
|
||||
|
||||
var edgeA = 0;
|
||||
var edgeAOut = [edgeA];
|
||||
var separationA = b2Collision.FindMaxSeparation(edgeAOut, polyA, polyB, conservative);
|
||||
edgeA = edgeAOut[0];
|
||||
if (separationA > 0.0 && conservative == false)
|
||||
return;
|
||||
|
||||
var edgeB = 0;
|
||||
var edgeBOut = [edgeB];
|
||||
var separationB = b2Collision.FindMaxSeparation(edgeBOut, polyB, polyA, conservative);
|
||||
edgeB = edgeBOut[0];
|
||||
if (separationB > 0.0 && conservative == false)
|
||||
return;
|
||||
|
||||
var poly1;
|
||||
var poly2;
|
||||
var edge1 = 0;
|
||||
var flip = 0;
|
||||
var k_relativeTol = 0.98;
|
||||
var k_absoluteTol = 0.001;
|
||||
|
||||
// TODO_ERIN use "radius" of poly for absolute tolerance.
|
||||
if (separationB > k_relativeTol * separationA + k_absoluteTol)
|
||||
{
|
||||
poly1 = polyB;
|
||||
poly2 = polyA;
|
||||
edge1 = edgeB;
|
||||
flip = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
poly1 = polyA;
|
||||
poly2 = polyB;
|
||||
edge1 = edgeA;
|
||||
flip = 0;
|
||||
}
|
||||
|
||||
var incidentEdge = [new ClipVertex(), new ClipVertex()];
|
||||
b2Collision.FindIncidentEdge(incidentEdge, poly1, edge1, poly2);
|
||||
|
||||
var count1 = poly1.m_vertexCount;
|
||||
var vert1s = poly1.m_vertices;
|
||||
|
||||
var v11 = vert1s[edge1];
|
||||
var v12 = edge1 + 1 < count1 ? vert1s[edge1+1] : vert1s[0];
|
||||
|
||||
//var dv = b2Math.SubtractVV(v12, v11);
|
||||
var dvX = v12.x - v11.x;
|
||||
var dvY = v12.y - v11.y;
|
||||
|
||||
//var sideNormal = b2Math.b2MulMV(poly1.m_R, b2Math.SubtractVV(v12, v11));
|
||||
var sideNormalX = v12.x - v11.x;
|
||||
var sideNormalY = v12.y - v11.y;
|
||||
|
||||
var tX = sideNormalX;
|
||||
var tMat = poly1.m_R;
|
||||
sideNormalX = tMat.col1.x * tX + tMat.col2.x * sideNormalY;
|
||||
sideNormalY = tMat.col1.y * tX + tMat.col2.y * sideNormalY;
|
||||
// ^^^^ sideNormal.MulM(poly1.m_R);
|
||||
|
||||
var invLength = 1.0 / Math.sqrt(sideNormalX*sideNormalX + sideNormalY*sideNormalY);
|
||||
sideNormalX *= invLength;
|
||||
sideNormalY *= invLength;
|
||||
// ^^^^ sideNormal.Normalize();
|
||||
|
||||
//var frontNormal = b2Math.b2CrossVF(sideNormal, 1.0);
|
||||
var frontNormalX = sideNormalX;
|
||||
var frontNormalY = sideNormalY;
|
||||
tX = frontNormalX;
|
||||
frontNormalX = frontNormalY;
|
||||
frontNormalY = -tX;
|
||||
// ^^^^ frontNormal.CrossVF(1.0);
|
||||
|
||||
// Expanded for performance
|
||||
//v11 = b2Math.AddVV(poly1.m_position, b2Math.b2MulMV(poly1.m_R, v11));
|
||||
var v11X = v11.x;
|
||||
var v11Y = v11.y;
|
||||
tX = v11X;
|
||||
tMat = poly1.m_R;
|
||||
v11X = tMat.col1.x * tX + tMat.col2.x * v11Y;
|
||||
v11Y = tMat.col1.y * tX + tMat.col2.y * v11Y;
|
||||
// ^^^^ v11.MulM(poly1.m_R);
|
||||
v11X += poly1.m_position.x;
|
||||
v11Y += poly1.m_position.y;
|
||||
//v12 = b2Math.AddVV(poly1.m_position, b2Math.b2MulMV(poly1.m_R, v12));
|
||||
var v12X = v12.x;
|
||||
var v12Y = v12.y;
|
||||
tX = v12X;
|
||||
tMat = poly1.m_R;
|
||||
v12X = tMat.col1.x * tX + tMat.col2.x * v12Y;
|
||||
v12Y = tMat.col1.y * tX + tMat.col2.y * v12Y;
|
||||
// ^^^^ v12.MulM(poly1.m_R);
|
||||
v12X += poly1.m_position.x;
|
||||
v12Y += poly1.m_position.y;
|
||||
|
||||
//var frontOffset = b2Math.b2Dot(frontNormal, v11);
|
||||
var frontOffset = frontNormalX * v11X + frontNormalY * v11Y;
|
||||
//var sideOffset1 = -b2Math.b2Dot(sideNormal, v11);
|
||||
var sideOffset1 = -(sideNormalX * v11X + sideNormalY * v11Y);
|
||||
//var sideOffset2 = b2Math.b2Dot(sideNormal, v12);
|
||||
var sideOffset2 = sideNormalX * v12X + sideNormalY * v12Y;
|
||||
|
||||
// Clip incident edge against extruded edge1 side edges.
|
||||
var clipPoints1 = [new ClipVertex(), new ClipVertex()];
|
||||
var clipPoints2 = [new ClipVertex(), new ClipVertex()];
|
||||
|
||||
var np = 0;
|
||||
|
||||
// Clip to box side 1
|
||||
b2Collision.b2CollidePolyTempVec.Set(-sideNormalX, -sideNormalY);
|
||||
np = b2Collision.ClipSegmentToLine(clipPoints1, incidentEdge, b2Collision.b2CollidePolyTempVec, sideOffset1);
|
||||
|
||||
if (np < 2)
|
||||
return;
|
||||
|
||||
// Clip to negative box side 1
|
||||
b2Collision.b2CollidePolyTempVec.Set(sideNormalX, sideNormalY);
|
||||
np = b2Collision.ClipSegmentToLine(clipPoints2, clipPoints1, b2Collision.b2CollidePolyTempVec, sideOffset2);
|
||||
|
||||
if (np < 2)
|
||||
return;
|
||||
|
||||
// Now clipPoints2 contains the clipped points.
|
||||
if (flip){
|
||||
manifold.normal.Set(-frontNormalX, -frontNormalY);
|
||||
}
|
||||
else{
|
||||
manifold.normal.Set(frontNormalX, frontNormalY);
|
||||
}
|
||||
// ^^^^ manifold.normal = flip ? frontNormal.Negative() : frontNormal;
|
||||
|
||||
var pointCount = 0;
|
||||
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; ++i)
|
||||
{
|
||||
//var separation = b2Math.b2Dot(frontNormal, clipPoints2[i].v) - frontOffset;
|
||||
var tVec = clipPoints2[i].v;
|
||||
var separation = (frontNormalX * tVec.x + frontNormalY * tVec.y) - frontOffset;
|
||||
|
||||
if (separation <= 0.0 || conservative == true)
|
||||
{
|
||||
var cp = manifold.points[ pointCount ];
|
||||
cp.separation = separation;
|
||||
cp.position.SetV( clipPoints2[i].v );
|
||||
cp.id.Set( clipPoints2[i].id );
|
||||
cp.id.features.flip = flip;
|
||||
++pointCount;
|
||||
}
|
||||
}
|
||||
|
||||
manifold.pointCount = pointCount;
|
||||
};
|
||||
b2Collision.b2CollideCircle = function(manifold, circle1, circle2, conservative)
|
||||
{
|
||||
manifold.pointCount = 0;
|
||||
|
||||
//var d = b2Math.SubtractVV(circle2.m_position, circle1.m_position);
|
||||
var dX = circle2.m_position.x - circle1.m_position.x;
|
||||
var dY = circle2.m_position.y - circle1.m_position.y;
|
||||
//var distSqr = b2Math.b2Dot(d, d);
|
||||
var distSqr = dX * dX + dY * dY;
|
||||
var radiusSum = circle1.m_radius + circle2.m_radius;
|
||||
if (distSqr > radiusSum * radiusSum && conservative == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var separation;
|
||||
if (distSqr < Number.MIN_VALUE)
|
||||
{
|
||||
separation = -radiusSum;
|
||||
manifold.normal.Set(0.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dist = Math.sqrt(distSqr);
|
||||
separation = dist - radiusSum;
|
||||
var a = 1.0 / dist;
|
||||
manifold.normal.x = a * dX;
|
||||
manifold.normal.y = a * dY;
|
||||
}
|
||||
|
||||
manifold.pointCount = 1;
|
||||
var tPoint = manifold.points[0];
|
||||
tPoint.id.set_key(0);
|
||||
tPoint.separation = separation;
|
||||
//tPoint.position = b2Math.SubtractVV(circle2.m_position, b2Math.MulFV(circle2.m_radius, manifold.normal));
|
||||
tPoint.position.x = circle2.m_position.x - (circle2.m_radius * manifold.normal.x);
|
||||
tPoint.position.y = circle2.m_position.y - (circle2.m_radius * manifold.normal.y);
|
||||
};
|
||||
b2Collision.b2CollidePolyAndCircle = function(manifold, poly, circle, conservative)
|
||||
{
|
||||
manifold.pointCount = 0;
|
||||
var tPoint;
|
||||
|
||||
var dX;
|
||||
var dY;
|
||||
|
||||
// Compute circle position in the frame of the polygon.
|
||||
//var xLocal = b2Math.b2MulTMV(poly.m_R, b2Math.SubtractVV(circle.m_position, poly.m_position));
|
||||
var xLocalX = circle.m_position.x - poly.m_position.x;
|
||||
var xLocalY = circle.m_position.y - poly.m_position.y;
|
||||
var tMat = poly.m_R;
|
||||
var tX = xLocalX * tMat.col1.x + xLocalY * tMat.col1.y;
|
||||
xLocalY = xLocalX * tMat.col2.x + xLocalY * tMat.col2.y;
|
||||
xLocalX = tX;
|
||||
|
||||
var dist;
|
||||
|
||||
// Find the min separating edge.
|
||||
var normalIndex = 0;
|
||||
var separation = -Number.MAX_VALUE;
|
||||
var radius = circle.m_radius;
|
||||
for (var i = 0; i < poly.m_vertexCount; ++i)
|
||||
{
|
||||
//var s = b2Math.b2Dot(poly.m_normals[i], b2Math.SubtractVV(xLocal, poly.m_vertices[i]));
|
||||
var s = poly.m_normals[i].x * (xLocalX-poly.m_vertices[i].x) + poly.m_normals[i].y * (xLocalY-poly.m_vertices[i].y);
|
||||
if (s > radius)
|
||||
{
|
||||
// Early out.
|
||||
return;
|
||||
}
|
||||
|
||||
if (s > separation)
|
||||
{
|
||||
separation = s;
|
||||
normalIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// If the center is inside the polygon ...
|
||||
if (separation < Number.MIN_VALUE)
|
||||
{
|
||||
manifold.pointCount = 1;
|
||||
//manifold.normal = b2Math.b2MulMV(poly.m_R, poly.m_normals[normalIndex]);
|
||||
var tVec = poly.m_normals[normalIndex];
|
||||
manifold.normal.x = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
|
||||
manifold.normal.y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
|
||||
|
||||
tPoint = manifold.points[0];
|
||||
tPoint.id.features.incidentEdge = normalIndex;
|
||||
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
|
||||
tPoint.id.features.referenceFace = b2Collision.b2_nullFeature;
|
||||
tPoint.id.features.flip = 0;
|
||||
tPoint.position.x = circle.m_position.x - radius * manifold.normal.x;
|
||||
tPoint.position.y = circle.m_position.y - radius * manifold.normal.y;
|
||||
//tPoint.position = b2Math.SubtractVV(circle.m_position , b2Math.MulFV(radius , manifold.normal));
|
||||
tPoint.separation = separation - radius;
|
||||
return;
|
||||
}
|
||||
|
||||
// Project the circle center onto the edge segment.
|
||||
var vertIndex1 = normalIndex;
|
||||
var vertIndex2 = vertIndex1 + 1 < poly.m_vertexCount ? vertIndex1 + 1 : 0;
|
||||
//var e = b2Math.SubtractVV(poly.m_vertices[vertIndex2] , poly.m_vertices[vertIndex1]);
|
||||
var eX = poly.m_vertices[vertIndex2].x - poly.m_vertices[vertIndex1].x;
|
||||
var eY = poly.m_vertices[vertIndex2].y - poly.m_vertices[vertIndex1].y;
|
||||
//var length = e.Normalize();
|
||||
var length = Math.sqrt(eX*eX + eY*eY);
|
||||
eX /= length;
|
||||
eY /= length;
|
||||
|
||||
// If the edge length is zero ...
|
||||
if (length < Number.MIN_VALUE)
|
||||
{
|
||||
//d = b2Math.SubtractVV(xLocal , poly.m_vertices[vertIndex1]);
|
||||
dX = xLocalX - poly.m_vertices[vertIndex1].x;
|
||||
dY = xLocalY - poly.m_vertices[vertIndex1].y;
|
||||
//dist = d.Normalize();
|
||||
dist = Math.sqrt(dX*dX + dY*dY);
|
||||
dX /= dist;
|
||||
dY /= dist;
|
||||
if (dist > radius)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
manifold.pointCount = 1;
|
||||
//manifold.normal = b2Math.b2MulMV(poly.m_R, d);
|
||||
manifold.normal.Set(tMat.col1.x * dX + tMat.col2.x * dY, tMat.col1.y * dX + tMat.col2.y * dY);
|
||||
tPoint = manifold.points[0];
|
||||
tPoint.id.features.incidentEdge = b2Collision.b2_nullFeature;
|
||||
tPoint.id.features.incidentVertex = vertIndex1;
|
||||
tPoint.id.features.referenceFace = b2Collision.b2_nullFeature;
|
||||
tPoint.id.features.flip = 0;
|
||||
//tPoint.position = b2Math.SubtractVV(circle.m_position , b2Math.MulFV(radius , manifold.normal));
|
||||
tPoint.position.x = circle.m_position.x - radius * manifold.normal.x;
|
||||
tPoint.position.y = circle.m_position.y - radius * manifold.normal.y;
|
||||
tPoint.separation = dist - radius;
|
||||
return;
|
||||
}
|
||||
|
||||
// Project the center onto the edge.
|
||||
//var u = b2Math.b2Dot(b2Math.SubtractVV(xLocal , poly.m_vertices[vertIndex1]) , e);
|
||||
var u = (xLocalX-poly.m_vertices[vertIndex1].x) * eX + (xLocalY-poly.m_vertices[vertIndex1].y) * eY;
|
||||
|
||||
tPoint = manifold.points[0];
|
||||
tPoint.id.features.incidentEdge = b2Collision.b2_nullFeature;
|
||||
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
|
||||
tPoint.id.features.referenceFace = b2Collision.b2_nullFeature;
|
||||
tPoint.id.features.flip = 0;
|
||||
|
||||
var pX, pY;
|
||||
if (u <= 0.0)
|
||||
{
|
||||
pX = poly.m_vertices[vertIndex1].x;
|
||||
pY = poly.m_vertices[vertIndex1].y;
|
||||
tPoint.id.features.incidentVertex = vertIndex1;
|
||||
}
|
||||
else if (u >= length)
|
||||
{
|
||||
pX = poly.m_vertices[vertIndex2].x;
|
||||
pY = poly.m_vertices[vertIndex2].y;
|
||||
tPoint.id.features.incidentVertex = vertIndex2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//p = b2Math.AddVV(poly.m_vertices[vertIndex1] , b2Math.MulFV(u, e));
|
||||
pX = eX * u + poly.m_vertices[vertIndex1].x;
|
||||
pY = eY * u + poly.m_vertices[vertIndex1].y;
|
||||
tPoint.id.features.incidentEdge = vertIndex1;
|
||||
}
|
||||
|
||||
//d = b2Math.SubtractVV(xLocal , p);
|
||||
dX = xLocalX - pX;
|
||||
dY = xLocalY - pY;
|
||||
//dist = d.Normalize();
|
||||
dist = Math.sqrt(dX*dX + dY*dY);
|
||||
dX /= dist;
|
||||
dY /= dist;
|
||||
if (dist > radius)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
manifold.pointCount = 1;
|
||||
//manifold.normal = b2Math.b2MulMV(poly.m_R, d);
|
||||
manifold.normal.Set(tMat.col1.x * dX + tMat.col2.x * dY, tMat.col1.y * dX + tMat.col2.y * dY);
|
||||
//tPoint.position = b2Math.SubtractVV(circle.m_position , b2Math.MulFV(radius , manifold.normal));
|
||||
tPoint.position.x = circle.m_position.x - radius * manifold.normal.x;
|
||||
tPoint.position.y = circle.m_position.y - radius * manifold.normal.y;
|
||||
tPoint.separation = dist - radius;
|
||||
};
|
||||
b2Collision.b2TestOverlap = function(a, b)
|
||||
{
|
||||
var t1 = b.minVertex;
|
||||
var t2 = a.maxVertex;
|
||||
//d1 = b2Math.SubtractVV(b.minVertex, a.maxVertex);
|
||||
var d1X = t1.x - t2.x;
|
||||
var d1Y = t1.y - t2.y;
|
||||
//d2 = b2Math.SubtractVV(a.minVertex, b.maxVertex);
|
||||
t1 = a.minVertex;
|
||||
t2 = b.maxVertex;
|
||||
var d2X = t1.x - t2.x;
|
||||
var d2Y = t1.y - t2.y;
|
||||
|
||||
if (d1X > 0.0 || d1Y > 0.0)
|
||||
return false;
|
||||
|
||||
if (d2X > 0.0 || d2Y > 0.0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
52
lib/box2d-js/js/box2d/collision/b2ContactID.js
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// We use contact ids to facilitate warm starting.
|
||||
var b2ContactID = Class.create();
|
||||
b2ContactID.prototype =
|
||||
{
|
||||
initialize: function(){
|
||||
// initialize instance variables for references
|
||||
this.features = new Features();
|
||||
//
|
||||
|
||||
this.features._m_id = this;
|
||||
|
||||
},
|
||||
Set: function(id){
|
||||
this.set_key(id._key);
|
||||
},
|
||||
Copy: function(){
|
||||
var id = new b2ContactID();
|
||||
id.set_key(this._key);
|
||||
return id;
|
||||
},
|
||||
get_key: function(){
|
||||
return this._key;
|
||||
},
|
||||
set_key: function(value) {
|
||||
this._key = value;
|
||||
this.features._referenceFace = this._key & 0x000000ff;
|
||||
this.features._incidentEdge = ((this._key & 0x0000ff00) >> 8) & 0x000000ff;
|
||||
this.features._incidentVertex = ((this._key & 0x00ff0000) >> 16) & 0x000000ff;
|
||||
this.features._flip = ((this._key & 0xff000000) >> 24) & 0x000000ff;
|
||||
},
|
||||
features: new Features(),
|
||||
_key: 0};
|
35
lib/box2d-js/js/box2d/collision/b2ContactPoint.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// We use contact ids to facilitate warm starting.
|
||||
var b2ContactPoint = Class.create();
|
||||
b2ContactPoint.prototype =
|
||||
{
|
||||
position: new b2Vec2(),
|
||||
separation: null,
|
||||
normalImpulse: null,
|
||||
tangentImpulse: null,
|
||||
id: new b2ContactID(),
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.position = new b2Vec2();
|
||||
this.id = new b2ContactID();
|
||||
//
|
||||
}};
|
333
lib/box2d-js/js/box2d/collision/b2Distance.js
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2Distance = Class.create();
|
||||
b2Distance.prototype =
|
||||
{
|
||||
|
||||
// GJK using Voronoi regions (Christer Ericson) and region selection
|
||||
// optimizations (Casey Muratori).
|
||||
|
||||
// The origin is either in the region of points[1] or in the edge region. The origin is
|
||||
// not in region of points[0] because that is the old point.
|
||||
|
||||
// Possible regions:
|
||||
// - points[2]
|
||||
// - edge points[0]-points[2]
|
||||
// - edge points[1]-points[2]
|
||||
// - inside the triangle
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initialize: function() {}};
|
||||
b2Distance.ProcessTwo = function(p1Out, p2Out, p1s, p2s, points)
|
||||
{
|
||||
// If in point[1] region
|
||||
//b2Vec2 r = -points[1];
|
||||
var rX = -points[1].x;
|
||||
var rY = -points[1].y;
|
||||
//b2Vec2 d = points[1] - points[0];
|
||||
var dX = points[0].x - points[1].x;
|
||||
var dY = points[0].y - points[1].y;
|
||||
//float32 length = d.Normalize();
|
||||
var length = Math.sqrt(dX*dX + dY*dY);
|
||||
dX /= length;
|
||||
dY /= length;
|
||||
|
||||
//float32 lambda = b2Dot(r, d);
|
||||
var lambda = rX * dX + rY * dY;
|
||||
if (lambda <= 0.0 || length < Number.MIN_VALUE)
|
||||
{
|
||||
// The simplex is reduced to a point.
|
||||
//*p1Out = p1s[1];
|
||||
p1Out.SetV(p1s[1]);
|
||||
//*p2Out = p2s[1];
|
||||
p2Out.SetV(p2s[1]);
|
||||
//p1s[0] = p1s[1];
|
||||
p1s[0].SetV(p1s[1]);
|
||||
//p2s[0] = p2s[1];
|
||||
p2s[0].SetV(p2s[1]);
|
||||
points[0].SetV(points[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Else in edge region
|
||||
lambda /= length;
|
||||
//*p1Out = p1s[1] + lambda * (p1s[0] - p1s[1]);
|
||||
p1Out.x = p1s[1].x + lambda * (p1s[0].x - p1s[1].x);
|
||||
p1Out.y = p1s[1].y + lambda * (p1s[0].y - p1s[1].y);
|
||||
//*p2Out = p2s[1] + lambda * (p2s[0] - p2s[1]);
|
||||
p2Out.x = p2s[1].x + lambda * (p2s[0].x - p2s[1].x);
|
||||
p2Out.y = p2s[1].y + lambda * (p2s[0].y - p2s[1].y);
|
||||
return 2;
|
||||
};
|
||||
b2Distance.ProcessThree = function(p1Out, p2Out, p1s, p2s, points)
|
||||
{
|
||||
//b2Vec2 a = points[0];
|
||||
var aX = points[0].x;
|
||||
var aY = points[0].y;
|
||||
//b2Vec2 b = points[1];
|
||||
var bX = points[1].x;
|
||||
var bY = points[1].y;
|
||||
//b2Vec2 c = points[2];
|
||||
var cX = points[2].x;
|
||||
var cY = points[2].y;
|
||||
|
||||
//b2Vec2 ab = b - a;
|
||||
var abX = bX - aX;
|
||||
var abY = bY - aY;
|
||||
//b2Vec2 ac = c - a;
|
||||
var acX = cX - aX;
|
||||
var acY = cY - aY;
|
||||
//b2Vec2 bc = c - b;
|
||||
var bcX = cX - bX;
|
||||
var bcY = cY - bY;
|
||||
|
||||
//float32 sn = -b2Dot(a, ab), sd = b2Dot(b, ab);
|
||||
var sn = -(aX * abX + aY * abY);
|
||||
var sd = (bX * abX + bY * abY);
|
||||
//float32 tn = -b2Dot(a, ac), td = b2Dot(c, ac);
|
||||
var tn = -(aX * acX + aY * acY);
|
||||
var td = (cX * acX + cY * acY);
|
||||
//float32 un = -b2Dot(b, bc), ud = b2Dot(c, bc);
|
||||
var un = -(bX * bcX + bY * bcY);
|
||||
var ud = (cX * bcX + cY * bcY);
|
||||
|
||||
// In vertex c region?
|
||||
if (td <= 0.0 && ud <= 0.0)
|
||||
{
|
||||
// Single point
|
||||
//*p1Out = p1s[2];
|
||||
p1Out.SetV(p1s[2]);
|
||||
//*p2Out = p2s[2];
|
||||
p2Out.SetV(p2s[2]);
|
||||
//p1s[0] = p1s[2];
|
||||
p1s[0].SetV(p1s[2]);
|
||||
//p2s[0] = p2s[2];
|
||||
p2s[0].SetV(p2s[2]);
|
||||
points[0].SetV(points[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Should not be in vertex a or b region.
|
||||
//b2Settings.b2Assert(sn > 0.0 || tn > 0.0);
|
||||
//b2Settings.b2Assert(sd > 0.0 || un > 0.0);
|
||||
|
||||
//float32 n = b2Cross(ab, ac);
|
||||
var n = abX * acY - abY * acX;
|
||||
|
||||
// Should not be in edge ab region.
|
||||
//float32 vc = n * b2Cross(a, b);
|
||||
var vc = n * (aX * bY - aY * bX);
|
||||
//b2Settings.b2Assert(vc > 0.0 || sn > 0.0 || sd > 0.0);
|
||||
|
||||
// In edge bc region?
|
||||
//float32 va = n * b2Cross(b, c);
|
||||
var va = n * (bX * cY - bY * cX);
|
||||
if (va <= 0.0 && un >= 0.0 && ud >= 0.0)
|
||||
{
|
||||
//b2Settings.b2Assert(un + ud > 0.0);
|
||||
|
||||
//float32 lambda = un / (un + ud);
|
||||
var lambda = un / (un + ud);
|
||||
//*p1Out = p1s[1] + lambda * (p1s[2] - p1s[1]);
|
||||
p1Out.x = p1s[1].x + lambda * (p1s[2].x - p1s[1].x);
|
||||
p1Out.y = p1s[1].y + lambda * (p1s[2].y - p1s[1].y);
|
||||
//*p2Out = p2s[1] + lambda * (p2s[2] - p2s[1]);
|
||||
p2Out.x = p2s[1].x + lambda * (p2s[2].x - p2s[1].x);
|
||||
p2Out.y = p2s[1].y + lambda * (p2s[2].y - p2s[1].y);
|
||||
//p1s[0] = p1s[2];
|
||||
p1s[0].SetV(p1s[2]);
|
||||
//p2s[0] = p2s[2];
|
||||
p2s[0].SetV(p2s[2]);
|
||||
//points[0] = points[2];
|
||||
points[0].SetV(points[2]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// In edge ac region?
|
||||
//float32 vb = n * b2Cross(c, a);
|
||||
var vb = n * (cX * aY - cY * aX);
|
||||
if (vb <= 0.0 && tn >= 0.0 && td >= 0.0)
|
||||
{
|
||||
//b2Settings.b2Assert(tn + td > 0.0);
|
||||
|
||||
//float32 lambda = tn / (tn + td);
|
||||
var lambda = tn / (tn + td);
|
||||
//*p1Out = p1s[0] + lambda * (p1s[2] - p1s[0]);
|
||||
p1Out.x = p1s[0].x + lambda * (p1s[2].x - p1s[0].x);
|
||||
p1Out.y = p1s[0].y + lambda * (p1s[2].y - p1s[0].y);
|
||||
//*p2Out = p2s[0] + lambda * (p2s[2] - p2s[0]);
|
||||
p2Out.x = p2s[0].x + lambda * (p2s[2].x - p2s[0].x);
|
||||
p2Out.y = p2s[0].y + lambda * (p2s[2].y - p2s[0].y);
|
||||
//p1s[1] = p1s[2];
|
||||
p1s[1].SetV(p1s[2]);
|
||||
//p2s[1] = p2s[2];
|
||||
p2s[1].SetV(p2s[2]);
|
||||
//points[1] = points[2];
|
||||
points[1].SetV(points[2]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Inside the triangle, compute barycentric coordinates
|
||||
//float32 denom = va + vb + vc;
|
||||
var denom = va + vb + vc;
|
||||
//b2Settings.b2Assert(denom > 0.0);
|
||||
denom = 1.0 / denom;
|
||||
//float32 u = va * denom;
|
||||
var u = va * denom;
|
||||
//float32 v = vb * denom;
|
||||
var v = vb * denom;
|
||||
//float32 w = 1.0f - u - v;
|
||||
var w = 1.0 - u - v;
|
||||
//*p1Out = u * p1s[0] + v * p1s[1] + w * p1s[2];
|
||||
p1Out.x = u * p1s[0].x + v * p1s[1].x + w * p1s[2].x;
|
||||
p1Out.y = u * p1s[0].y + v * p1s[1].y + w * p1s[2].y;
|
||||
//*p2Out = u * p2s[0] + v * p2s[1] + w * p2s[2];
|
||||
p2Out.x = u * p2s[0].x + v * p2s[1].x + w * p2s[2].x;
|
||||
p2Out.y = u * p2s[0].y + v * p2s[1].y + w * p2s[2].y;
|
||||
return 3;
|
||||
};
|
||||
b2Distance.InPoinsts = function(w, points, pointCount)
|
||||
{
|
||||
for (var i = 0; i < pointCount; ++i)
|
||||
{
|
||||
if (w.x == points[i].x && w.y == points[i].y)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
b2Distance.Distance = function(p1Out, p2Out, shape1, shape2)
|
||||
{
|
||||
//b2Vec2 p1s[3], p2s[3];
|
||||
var p1s = new Array(3);
|
||||
var p2s = new Array(3);
|
||||
//b2Vec2 points[3];
|
||||
var points = new Array(3);
|
||||
//int32 pointCount = 0;
|
||||
var pointCount = 0;
|
||||
|
||||
//*p1Out = shape1->m_position;
|
||||
p1Out.SetV(shape1.m_position);
|
||||
//*p2Out = shape2->m_position;
|
||||
p2Out.SetV(shape2.m_position);
|
||||
|
||||
var vSqr = 0.0;
|
||||
var maxIterations = 20;
|
||||
for (var iter = 0; iter < maxIterations; ++iter)
|
||||
{
|
||||
//b2Vec2 v = *p2Out - *p1Out;
|
||||
var vX = p2Out.x - p1Out.x;
|
||||
var vY = p2Out.y - p1Out.y;
|
||||
//b2Vec2 w1 = shape1->Support(v);
|
||||
var w1 = shape1.Support(vX, vY);
|
||||
//b2Vec2 w2 = shape2->Support(-v);
|
||||
var w2 = shape2.Support(-vX, -vY);
|
||||
//float32 vSqr = b2Dot(v, v);
|
||||
vSqr = (vX*vX + vY*vY);
|
||||
//b2Vec2 w = w2 - w1;
|
||||
var wX = w2.x - w1.x;
|
||||
var wY = w2.y - w1.y;
|
||||
//float32 vw = b2Dot(v, w);
|
||||
var vw = (vX*wX + vY*wY);
|
||||
//if (vSqr - b2Dot(v, w) <= 0.01f * vSqr)
|
||||
if (vSqr - b2Dot(vX * wX + vY * wY) <= 0.01 * vSqr)
|
||||
{
|
||||
if (pointCount == 0)
|
||||
{
|
||||
//*p1Out = w1;
|
||||
p1Out.SetV(w1);
|
||||
//*p2Out = w2;
|
||||
p2Out.SetV(w2);
|
||||
}
|
||||
b2Distance.g_GJK_Iterations = iter;
|
||||
return Math.sqrt(vSqr);
|
||||
}
|
||||
|
||||
switch (pointCount)
|
||||
{
|
||||
case 0:
|
||||
//p1s[0] = w1;
|
||||
p1s[0].SetV(w1);
|
||||
//p2s[0] = w2;
|
||||
p2s[0].SetV(w2);
|
||||
points[0] = w;
|
||||
//*p1Out = p1s[0];
|
||||
p1Out.SetV(p1s[0]);
|
||||
//*p2Out = p2s[0];
|
||||
p2Out.SetV(p2s[0]);
|
||||
++pointCount;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
//p1s[1] = w1;
|
||||
p1s[1].SetV(w1);
|
||||
//p2s[1] = w2;
|
||||
p2s[1].SetV(w2);
|
||||
//points[1] = w;
|
||||
points[1].x = wX;
|
||||
points[1].y = wY;
|
||||
pointCount = b2Distance.ProcessTwo(p1Out, p2Out, p1s, p2s, points);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//p1s[2] = w1;
|
||||
p1s[2].SetV(w1);
|
||||
//p2s[2] = w2;
|
||||
p2s[2].SetV(w2);
|
||||
//points[2] = w;
|
||||
points[2].x = wX;
|
||||
points[2].y = wY;
|
||||
pointCount = b2Distance.ProcessThree(p1Out, p2Out, p1s, p2s, points);
|
||||
break;
|
||||
}
|
||||
|
||||
// If we have three points, then the origin is in the corresponding triangle.
|
||||
if (pointCount == 3)
|
||||
{
|
||||
b2Distance.g_GJK_Iterations = iter;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//float32 maxSqr = -FLT_MAX;
|
||||
var maxSqr = -Number.MAX_VALUE;
|
||||
for (var i = 0; i < pointCount; ++i)
|
||||
{
|
||||
//maxSqr = b2Math.b2Max(maxSqr, b2Dot(points[i], points[i]));
|
||||
maxSqr = b2Math.b2Max(maxSqr, (points[i].x*points[i].x + points[i].y*points[i].y));
|
||||
}
|
||||
|
||||
if (pointCount == 3 || vSqr <= 100.0 * Number.MIN_VALUE * maxSqr)
|
||||
{
|
||||
b2Distance.g_GJK_Iterations = iter;
|
||||
return Math.sqrt(vSqr);
|
||||
}
|
||||
}
|
||||
|
||||
b2Distance.g_GJK_Iterations = maxIterations;
|
||||
return Math.sqrt(vSqr);
|
||||
};
|
||||
b2Distance.g_GJK_Iterations = 0;
|
34
lib/box2d-js/js/box2d/collision/b2Manifold.js
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// A manifold for two touching convex shapes.
|
||||
var b2Manifold = Class.create();
|
||||
b2Manifold.prototype =
|
||||
{
|
||||
initialize: function(){
|
||||
this.points = new Array(b2Settings.b2_maxManifoldPoints);
|
||||
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++){
|
||||
this.points[i] = new b2ContactPoint();
|
||||
}
|
||||
this.normal = new b2Vec2();
|
||||
},
|
||||
points: null,
|
||||
normal: null,
|
||||
pointCount: 0};
|
34
lib/box2d-js/js/box2d/collision/b2OBB.js
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// A manifold for two touching convex shapes.
|
||||
var b2OBB = Class.create();
|
||||
b2OBB.prototype =
|
||||
{
|
||||
R: new b2Mat22(),
|
||||
center: new b2Vec2(),
|
||||
extents: new b2Vec2(),
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.R = new b2Mat22();
|
||||
this.center = new b2Vec2();
|
||||
this.extents = new b2Vec2();
|
||||
//
|
||||
}};
|
60
lib/box2d-js/js/box2d/collision/b2Pair.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
// The pair manager is used by the broad-phase to quickly add/remove/find pairs
|
||||
// of overlapping proxies. It is based closely on code provided by Pierre Terdiman.
|
||||
// http:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2Pair = Class.create();
|
||||
b2Pair.prototype =
|
||||
{
|
||||
|
||||
|
||||
SetBuffered: function() { this.status |= b2Pair.e_pairBuffered; },
|
||||
ClearBuffered: function() { this.status &= ~b2Pair.e_pairBuffered; },
|
||||
IsBuffered: function(){ return (this.status & b2Pair.e_pairBuffered) == b2Pair.e_pairBuffered; },
|
||||
|
||||
SetRemoved: function() { this.status |= b2Pair.e_pairRemoved; },
|
||||
ClearRemoved: function() { this.status &= ~b2Pair.e_pairRemoved; },
|
||||
IsRemoved: function(){ return (this.status & b2Pair.e_pairRemoved) == b2Pair.e_pairRemoved; },
|
||||
|
||||
SetFinal: function() { this.status |= b2Pair.e_pairFinal; },
|
||||
IsFinal: function(){ return (this.status & b2Pair.e_pairFinal) == b2Pair.e_pairFinal; },
|
||||
|
||||
userData: null,
|
||||
proxyId1: 0,
|
||||
proxyId2: 0,
|
||||
next: 0,
|
||||
status: 0,
|
||||
|
||||
// STATIC
|
||||
|
||||
// enum
|
||||
|
||||
initialize: function() {}};
|
||||
b2Pair.b2_nullPair = b2Settings.USHRT_MAX;
|
||||
b2Pair.b2_nullProxy = b2Settings.USHRT_MAX;
|
||||
b2Pair.b2_tableCapacity = b2Settings.b2_maxPairs;
|
||||
b2Pair.b2_tableMask = b2Pair.b2_tableCapacity - 1;
|
||||
b2Pair.e_pairBuffered = 0x0001;
|
||||
b2Pair.e_pairRemoved = 0x0002;
|
||||
b2Pair.e_pairFinal = 0x0004;
|
34
lib/box2d-js/js/box2d/collision/b2PairCallback.js
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2PairCallback = Class.create();
|
||||
b2PairCallback.prototype =
|
||||
{
|
||||
//virtual ~b2PairCallback() {}
|
||||
|
||||
// This returns the new pair user data.
|
||||
PairAdded: function(proxyUserData1, proxyUserData2){return null},
|
||||
|
||||
// This should free the pair's user data. In extreme circumstances, it is possible
|
||||
// this will be called with null pairUserData because the pair never existed.
|
||||
PairRemoved: function(proxyUserData1, proxyUserData2, pairUserData){},
|
||||
initialize: function() {}};
|
||||
|
||||
|
386
lib/box2d-js/js/box2d/collision/b2PairManager.js
Normal file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
// The pair manager is used by the broad-phase to quickly add/remove/find pairs
|
||||
// of overlapping proxies. It is based closely on code provided by Pierre Terdiman.
|
||||
// http:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2PairManager = Class.create();
|
||||
b2PairManager.prototype =
|
||||
{
|
||||
//public:
|
||||
initialize: function(){
|
||||
var i = 0;
|
||||
//b2Settings.b2Assert(b2Math.b2IsPowerOfTwo(b2Pair.b2_tableCapacity) == true);
|
||||
//b2Settings.b2Assert(b2Pair.b2_tableCapacity >= b2Settings.b2_maxPairs);
|
||||
this.m_hashTable = new Array(b2Pair.b2_tableCapacity);
|
||||
for (i = 0; i < b2Pair.b2_tableCapacity; ++i)
|
||||
{
|
||||
this.m_hashTable[i] = b2Pair.b2_nullPair;
|
||||
}
|
||||
this.m_pairs = new Array(b2Settings.b2_maxPairs);
|
||||
for (i = 0; i < b2Settings.b2_maxPairs; ++i)
|
||||
{
|
||||
this.m_pairs[i] = new b2Pair();
|
||||
}
|
||||
this.m_pairBuffer = new Array(b2Settings.b2_maxPairs);
|
||||
for (i = 0; i < b2Settings.b2_maxPairs; ++i)
|
||||
{
|
||||
this.m_pairBuffer[i] = new b2BufferedPair();
|
||||
}
|
||||
|
||||
for (i = 0; i < b2Settings.b2_maxPairs; ++i)
|
||||
{
|
||||
this.m_pairs[i].proxyId1 = b2Pair.b2_nullProxy;
|
||||
this.m_pairs[i].proxyId2 = b2Pair.b2_nullProxy;
|
||||
this.m_pairs[i].userData = null;
|
||||
this.m_pairs[i].status = 0;
|
||||
this.m_pairs[i].next = (i + 1);
|
||||
}
|
||||
this.m_pairs[b2Settings.b2_maxPairs-1].next = b2Pair.b2_nullPair;
|
||||
this.m_pairCount = 0;
|
||||
},
|
||||
//~b2PairManager();
|
||||
|
||||
Initialize: function(broadPhase, callback){
|
||||
this.m_broadPhase = broadPhase;
|
||||
this.m_callback = callback;
|
||||
},
|
||||
|
||||
/*
|
||||
As proxies are created and moved, many pairs are created and destroyed. Even worse, the same
|
||||
pair may be added and removed multiple times in a single time step of the physics engine. To reduce
|
||||
traffic in the pair manager, we try to avoid destroying pairs in the pair manager until the
|
||||
end of the physics step. This is done by buffering all the this.RemovePair requests. this.AddPair
|
||||
requests are processed immediately because we need the hash table entry for quick lookup.
|
||||
|
||||
All user user callbacks are delayed until the buffered pairs are confirmed in this.Commit.
|
||||
This is very important because the user callbacks may be very expensive and client logic
|
||||
may be harmed if pairs are added and removed within the same time step.
|
||||
|
||||
Buffer a pair for addition.
|
||||
We may add a pair that is not in the pair manager or pair buffer.
|
||||
We may add a pair that is already in the pair manager and pair buffer.
|
||||
If the added pair is not a new pair, then it must be in the pair buffer (because this.RemovePair was called).
|
||||
*/
|
||||
AddBufferedPair: function(proxyId1, proxyId2){
|
||||
//b2Settings.b2Assert(id1 != b2_nullProxy && id2 != b2_nullProxy);
|
||||
//b2Settings.b2Assert(this.m_pairBufferCount < b2_maxPairs);
|
||||
|
||||
var pair = this.AddPair(proxyId1, proxyId2);
|
||||
|
||||
// If this pair is not in the pair buffer ...
|
||||
if (pair.IsBuffered() == false)
|
||||
{
|
||||
// This must be a newly added pair.
|
||||
//b2Settings.b2Assert(pair.IsFinal() == false);
|
||||
|
||||
// Add it to the pair buffer.
|
||||
pair.SetBuffered();
|
||||
this.m_pairBuffer[this.m_pairBufferCount].proxyId1 = pair.proxyId1;
|
||||
this.m_pairBuffer[this.m_pairBufferCount].proxyId2 = pair.proxyId2;
|
||||
++this.m_pairBufferCount;
|
||||
|
||||
//b2Settings.b2Assert(this.m_pairBufferCount <= this.m_pairCount);
|
||||
}
|
||||
|
||||
// Confirm this pair for the subsequent call to this.Commit.
|
||||
pair.ClearRemoved();
|
||||
|
||||
if (b2BroadPhase.s_validate)
|
||||
{
|
||||
this.ValidateBuffer();
|
||||
}
|
||||
},
|
||||
|
||||
// Buffer a pair for removal.
|
||||
RemoveBufferedPair: function(proxyId1, proxyId2){
|
||||
//b2Settings.b2Assert(id1 != b2_nullProxy && id2 != b2_nullProxy);
|
||||
//b2Settings.b2Assert(this.m_pairBufferCount < b2_maxPairs);
|
||||
|
||||
var pair = this.Find(proxyId1, proxyId2);
|
||||
|
||||
if (pair == null)
|
||||
{
|
||||
// The pair never existed. This is legal (due to collision filtering).
|
||||
return;
|
||||
}
|
||||
|
||||
// If this pair is not in the pair buffer ...
|
||||
if (pair.IsBuffered() == false)
|
||||
{
|
||||
// This must be an old pair.
|
||||
//b2Settings.b2Assert(pair.IsFinal() == true);
|
||||
|
||||
pair.SetBuffered();
|
||||
this.m_pairBuffer[this.m_pairBufferCount].proxyId1 = pair.proxyId1;
|
||||
this.m_pairBuffer[this.m_pairBufferCount].proxyId2 = pair.proxyId2;
|
||||
++this.m_pairBufferCount;
|
||||
|
||||
//b2Settings.b2Assert(this.m_pairBufferCount <= this.m_pairCount);
|
||||
}
|
||||
|
||||
pair.SetRemoved();
|
||||
|
||||
if (b2BroadPhase.s_validate)
|
||||
{
|
||||
this.ValidateBuffer();
|
||||
}
|
||||
},
|
||||
|
||||
Commit: function(){
|
||||
var i = 0;
|
||||
|
||||
var removeCount = 0;
|
||||
|
||||
var proxies = this.m_broadPhase.m_proxyPool;
|
||||
|
||||
for (i = 0; i < this.m_pairBufferCount; ++i)
|
||||
{
|
||||
var pair = this.Find(this.m_pairBuffer[i].proxyId1, this.m_pairBuffer[i].proxyId2);
|
||||
//b2Settings.b2Assert(pair.IsBuffered());
|
||||
pair.ClearBuffered();
|
||||
|
||||
//b2Settings.b2Assert(pair.proxyId1 < b2Settings.b2_maxProxies && pair.proxyId2 < b2Settings.b2_maxProxies);
|
||||
|
||||
var proxy1 = proxies[ pair.proxyId1 ];
|
||||
var proxy2 = proxies[ pair.proxyId2 ];
|
||||
|
||||
//b2Settings.b2Assert(proxy1.IsValid());
|
||||
//b2Settings.b2Assert(proxy2.IsValid());
|
||||
|
||||
if (pair.IsRemoved())
|
||||
{
|
||||
// It is possible a pair was added then removed before a commit. Therefore,
|
||||
// we should be careful not to tell the user the pair was removed when the
|
||||
// the user didn't receive a matching add.
|
||||
if (pair.IsFinal() == true)
|
||||
{
|
||||
this.m_callback.PairRemoved(proxy1.userData, proxy2.userData, pair.userData);
|
||||
}
|
||||
|
||||
// Store the ids so we can actually remove the pair below.
|
||||
this.m_pairBuffer[removeCount].proxyId1 = pair.proxyId1;
|
||||
this.m_pairBuffer[removeCount].proxyId2 = pair.proxyId2;
|
||||
++removeCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_broadPhase.TestOverlap(proxy1, proxy2) == true);
|
||||
|
||||
if (pair.IsFinal() == false)
|
||||
{
|
||||
pair.userData = this.m_callback.PairAdded(proxy1.userData, proxy2.userData);
|
||||
pair.SetFinal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < removeCount; ++i)
|
||||
{
|
||||
this.RemovePair(this.m_pairBuffer[i].proxyId1, this.m_pairBuffer[i].proxyId2);
|
||||
}
|
||||
|
||||
this.m_pairBufferCount = 0;
|
||||
|
||||
if (b2BroadPhase.s_validate)
|
||||
{
|
||||
this.ValidateTable();
|
||||
}
|
||||
},
|
||||
|
||||
//private:
|
||||
|
||||
// Add a pair and return the new pair. If the pair already exists,
|
||||
// no new pair is created and the old one is returned.
|
||||
AddPair: function(proxyId1, proxyId2){
|
||||
|
||||
if (proxyId1 > proxyId2){
|
||||
var temp = proxyId1;
|
||||
proxyId1 = proxyId2;
|
||||
proxyId2 = temp;
|
||||
//b2Math.b2Swap(p1, p2);
|
||||
}
|
||||
|
||||
var hash = b2PairManager.Hash(proxyId1, proxyId2) & b2Pair.b2_tableMask;
|
||||
|
||||
//var pairIndex = this.FindHash(proxyId1, proxyId2, hash);
|
||||
var pair = pair = this.FindHash(proxyId1, proxyId2, hash);
|
||||
|
||||
if (pair != null)
|
||||
{
|
||||
return pair;
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(this.m_pairCount < b2Settings.b2_maxPairs && this.m_freePair != b2_nullPair);
|
||||
|
||||
var pIndex = this.m_freePair;
|
||||
pair = this.m_pairs[pIndex];
|
||||
this.m_freePair = pair.next;
|
||||
|
||||
pair.proxyId1 = proxyId1;
|
||||
pair.proxyId2 = proxyId2;
|
||||
pair.status = 0;
|
||||
pair.userData = null;
|
||||
pair.next = this.m_hashTable[hash];
|
||||
|
||||
this.m_hashTable[hash] = pIndex;
|
||||
|
||||
++this.m_pairCount;
|
||||
|
||||
return pair;
|
||||
},
|
||||
|
||||
// Remove a pair, return the pair's userData.
|
||||
RemovePair: function(proxyId1, proxyId2){
|
||||
|
||||
//b2Settings.b2Assert(this.m_pairCount > 0);
|
||||
|
||||
if (proxyId1 > proxyId2){
|
||||
var temp = proxyId1;
|
||||
proxyId1 = proxyId2;
|
||||
proxyId2 = temp;
|
||||
//b2Math.b2Swap(proxyId1, proxyId2);
|
||||
}
|
||||
|
||||
var hash = b2PairManager.Hash(proxyId1, proxyId2) & b2Pair.b2_tableMask;
|
||||
|
||||
var node = this.m_hashTable[hash];
|
||||
var pNode = null;
|
||||
|
||||
while (node != b2Pair.b2_nullPair)
|
||||
{
|
||||
if (b2PairManager.Equals(this.m_pairs[node], proxyId1, proxyId2))
|
||||
{
|
||||
var index = node;
|
||||
|
||||
//*node = this.m_pairs[*node].next;
|
||||
if (pNode){
|
||||
pNode.next = this.m_pairs[node].next;
|
||||
}
|
||||
else{
|
||||
this.m_hashTable[hash] = this.m_pairs[node].next;
|
||||
}
|
||||
|
||||
var pair = this.m_pairs[ index ];
|
||||
var userData = pair.userData;
|
||||
|
||||
// Scrub
|
||||
pair.next = this.m_freePair;
|
||||
pair.proxyId1 = b2Pair.b2_nullProxy;
|
||||
pair.proxyId2 = b2Pair.b2_nullProxy;
|
||||
pair.userData = null;
|
||||
pair.status = 0;
|
||||
|
||||
this.m_freePair = index;
|
||||
--this.m_pairCount;
|
||||
return userData;
|
||||
}
|
||||
else
|
||||
{
|
||||
//node = &this.m_pairs[*node].next;
|
||||
pNode = this.m_pairs[node];
|
||||
node = pNode.next;
|
||||
}
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(false);
|
||||
return null;
|
||||
},
|
||||
|
||||
Find: function(proxyId1, proxyId2){
|
||||
|
||||
if (proxyId1 > proxyId2){
|
||||
var temp = proxyId1;
|
||||
proxyId1 = proxyId2;
|
||||
proxyId2 = temp;
|
||||
//b2Math.b2Swap(proxyId1, proxyId2);
|
||||
}
|
||||
|
||||
var hash = b2PairManager.Hash(proxyId1, proxyId2) & b2Pair.b2_tableMask;
|
||||
|
||||
return this.FindHash(proxyId1, proxyId2, hash);
|
||||
},
|
||||
FindHash: function(proxyId1, proxyId2, hash){
|
||||
var index = this.m_hashTable[hash];
|
||||
|
||||
while( index != b2Pair.b2_nullPair && b2PairManager.Equals(this.m_pairs[index], proxyId1, proxyId2) == false)
|
||||
{
|
||||
index = this.m_pairs[index].next;
|
||||
}
|
||||
|
||||
if ( index == b2Pair.b2_nullPair )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(index < b2_maxPairs);
|
||||
|
||||
return this.m_pairs[ index ];
|
||||
},
|
||||
|
||||
ValidateBuffer: function(){
|
||||
// DEBUG
|
||||
},
|
||||
|
||||
ValidateTable: function(){
|
||||
// DEBUG
|
||||
},
|
||||
|
||||
//public:
|
||||
m_broadPhase: null,
|
||||
m_callback: null,
|
||||
m_pairs: null,
|
||||
m_freePair: 0,
|
||||
m_pairCount: 0,
|
||||
|
||||
m_pairBuffer: null,
|
||||
m_pairBufferCount: 0,
|
||||
|
||||
m_hashTable: null
|
||||
|
||||
|
||||
// static
|
||||
// Thomas Wang's hash, see: http:
|
||||
|
||||
|
||||
|
||||
};
|
||||
b2PairManager.Hash = function(proxyId1, proxyId2)
|
||||
{
|
||||
var key = ((proxyId2 << 16) & 0xffff0000) | proxyId1;
|
||||
key = ~key + ((key << 15) & 0xFFFF8000);
|
||||
key = key ^ ((key >> 12) & 0x000fffff);
|
||||
key = key + ((key << 2) & 0xFFFFFFFC);
|
||||
key = key ^ ((key >> 4) & 0x0fffffff);
|
||||
key = key * 2057;
|
||||
key = key ^ ((key >> 16) & 0x0000ffff);
|
||||
return key;
|
||||
};
|
||||
b2PairManager.Equals = function(pair, proxyId1, proxyId2)
|
||||
{
|
||||
return (pair.proxyId1 == proxyId1 && pair.proxyId2 == proxyId2);
|
||||
};
|
||||
b2PairManager.EqualsPair = function(pair1, pair2)
|
||||
{
|
||||
return pair1.proxyId1 == pair2.proxyId1 && pair1.proxyId2 == pair2.proxyId2;
|
||||
};
|
40
lib/box2d-js/js/box2d/collision/b2Proxy.js
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2Proxy = Class.create();
|
||||
b2Proxy.prototype = {
|
||||
GetNext: function(){ return this.lowerBounds[0]; },
|
||||
SetNext: function(next) { this.lowerBounds[0] = next /*& 0x0000ffff*/; },
|
||||
|
||||
IsValid: function(){ return this.overlapCount != b2BroadPhase.b2_invalid; },
|
||||
|
||||
lowerBounds: [/*uint*/(0), /*uint*/(0)],
|
||||
upperBounds: [/*uint*/(0), /*uint*/(0)],
|
||||
overlapCount: 0,
|
||||
timeStamp: 0,
|
||||
|
||||
userData: null,
|
||||
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.lowerBounds = [/*uint*/(0), /*uint*/(0)];
|
||||
this.upperBounds = [/*uint*/(0), /*uint*/(0)];
|
||||
//
|
||||
}}
|
49
lib/box2d-js/js/box2d/collision/shapes/b2BoxDef.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2BoxDef = Class.create();
|
||||
Object.extend(b2BoxDef.prototype, b2ShapeDef.prototype);
|
||||
Object.extend(b2BoxDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2ShapeDef
|
||||
this.type = b2Shape.e_unknownShape;
|
||||
this.userData = null;
|
||||
this.localPosition = new b2Vec2(0.0, 0.0);
|
||||
this.localRotation = 0.0;
|
||||
this.friction = 0.2;
|
||||
this.restitution = 0.0;
|
||||
this.density = 0.0;
|
||||
this.categoryBits = 0x0001;
|
||||
this.maskBits = 0xFFFF;
|
||||
this.groupIndex = 0;
|
||||
//
|
||||
|
||||
this.type = b2Shape.e_boxShape;
|
||||
this.extents = new b2Vec2(1.0, 1.0);
|
||||
},
|
||||
|
||||
extents: null});
|
||||
|
49
lib/box2d-js/js/box2d/collision/shapes/b2CircleDef.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2CircleDef = Class.create();
|
||||
Object.extend(b2CircleDef.prototype, b2ShapeDef.prototype);
|
||||
Object.extend(b2CircleDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2ShapeDef
|
||||
this.type = b2Shape.e_unknownShape;
|
||||
this.userData = null;
|
||||
this.localPosition = new b2Vec2(0.0, 0.0);
|
||||
this.localRotation = 0.0;
|
||||
this.friction = 0.2;
|
||||
this.restitution = 0.0;
|
||||
this.density = 0.0;
|
||||
this.categoryBits = 0x0001;
|
||||
this.maskBits = 0xFFFF;
|
||||
this.groupIndex = 0;
|
||||
//
|
||||
|
||||
this.type = b2Shape.e_circleShape;
|
||||
this.radius = 1.0;
|
||||
},
|
||||
|
||||
radius: null});
|
||||
|
198
lib/box2d-js/js/box2d/collision/shapes/b2CircleShape.js
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2CircleShape = Class.create();
|
||||
Object.extend(b2CircleShape.prototype, b2Shape.prototype);
|
||||
Object.extend(b2CircleShape.prototype,
|
||||
{
|
||||
TestPoint: function(p){
|
||||
//var d = b2Math.SubtractVV(p, this.m_position);
|
||||
var d = new b2Vec2();
|
||||
d.SetV(p);
|
||||
d.Subtract(this.m_position);
|
||||
return b2Math.b2Dot(d, d) <= this.m_radius * this.m_radius;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(def, body, localCenter){
|
||||
// initialize instance variables for references
|
||||
this.m_R = new b2Mat22();
|
||||
this.m_position = new b2Vec2();
|
||||
//
|
||||
|
||||
// The constructor for b2Shape
|
||||
this.m_userData = def.userData;
|
||||
|
||||
this.m_friction = def.friction;
|
||||
this.m_restitution = def.restitution;
|
||||
this.m_body = body;
|
||||
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
|
||||
this.m_maxRadius = 0.0;
|
||||
|
||||
this.m_categoryBits = def.categoryBits;
|
||||
this.m_maskBits = def.maskBits;
|
||||
this.m_groupIndex = def.groupIndex;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_localPosition = new b2Vec2();
|
||||
//
|
||||
|
||||
//super(def, body);
|
||||
|
||||
//b2Settings.b2Assert(def.type == b2Shape.e_circleShape);
|
||||
var circle = def;
|
||||
|
||||
//this.m_localPosition = def.localPosition - localCenter;
|
||||
this.m_localPosition.Set(def.localPosition.x - localCenter.x, def.localPosition.y - localCenter.y);
|
||||
this.m_type = b2Shape.e_circleShape;
|
||||
this.m_radius = circle.radius;
|
||||
|
||||
this.m_R.SetM(this.m_body.m_R);
|
||||
//b2Vec2 r = b2Mul(this.m_body->this.m_R, this.m_localPosition);
|
||||
var rX = this.m_R.col1.x * this.m_localPosition.x + this.m_R.col2.x * this.m_localPosition.y;
|
||||
var rY = this.m_R.col1.y * this.m_localPosition.x + this.m_R.col2.y * this.m_localPosition.y;
|
||||
//this.m_position = this.m_body->this.m_position + r;
|
||||
this.m_position.x = this.m_body.m_position.x + rX;
|
||||
this.m_position.y = this.m_body.m_position.y + rY;
|
||||
//this.m_maxRadius = r.Length() + this.m_radius;
|
||||
this.m_maxRadius = Math.sqrt(rX*rX+rY*rY) + this.m_radius;
|
||||
|
||||
var aabb = new b2AABB();
|
||||
aabb.minVertex.Set(this.m_position.x - this.m_radius, this.m_position.y - this.m_radius);
|
||||
aabb.maxVertex.Set(this.m_position.x + this.m_radius, this.m_position.y + this.m_radius);
|
||||
|
||||
var broadPhase = this.m_body.m_world.m_broadPhase;
|
||||
if (broadPhase.InRange(aabb))
|
||||
{
|
||||
this.m_proxyId = broadPhase.CreateProxy(aabb, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
}
|
||||
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
this.m_body.Freeze();
|
||||
}
|
||||
},
|
||||
|
||||
Synchronize: function(position1, R1, position2, R2){
|
||||
this.m_R.SetM(R2);
|
||||
//this.m_position = position2 + b2Mul(R2, this.m_localPosition);
|
||||
this.m_position.x = (R2.col1.x * this.m_localPosition.x + R2.col2.x * this.m_localPosition.y) + position2.x;
|
||||
this.m_position.y = (R2.col1.y * this.m_localPosition.x + R2.col2.y * this.m_localPosition.y) + position2.y;
|
||||
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute an AABB that covers the swept shape (may miss some rotation effect).
|
||||
//b2Vec2 p1 = position1 + b2Mul(R1, this.m_localPosition);
|
||||
var p1X = position1.x + (R1.col1.x * this.m_localPosition.x + R1.col2.x * this.m_localPosition.y);
|
||||
var p1Y = position1.y + (R1.col1.y * this.m_localPosition.x + R1.col2.y * this.m_localPosition.y);
|
||||
//b2Vec2 lower = b2Min(p1, this.m_position);
|
||||
var lowerX = Math.min(p1X, this.m_position.x);
|
||||
var lowerY = Math.min(p1Y, this.m_position.y);
|
||||
//b2Vec2 upper = b2Max(p1, this.m_position);
|
||||
var upperX = Math.max(p1X, this.m_position.x);
|
||||
var upperY = Math.max(p1Y, this.m_position.y);
|
||||
|
||||
var aabb = new b2AABB();
|
||||
aabb.minVertex.Set(lowerX - this.m_radius, lowerY - this.m_radius);
|
||||
aabb.maxVertex.Set(upperX + this.m_radius, upperY + this.m_radius);
|
||||
|
||||
var broadPhase = this.m_body.m_world.m_broadPhase;
|
||||
if (broadPhase.InRange(aabb))
|
||||
{
|
||||
broadPhase.MoveProxy(this.m_proxyId, aabb);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_body.Freeze();
|
||||
}
|
||||
},
|
||||
|
||||
QuickSync: function(position, R){
|
||||
this.m_R.SetM(R);
|
||||
//this.m_position = position + b2Mul(R, this.m_localPosition);
|
||||
this.m_position.x = (R.col1.x * this.m_localPosition.x + R.col2.x * this.m_localPosition.y) + position.x;
|
||||
this.m_position.y = (R.col1.y * this.m_localPosition.x + R.col2.y * this.m_localPosition.y) + position.y;
|
||||
},
|
||||
|
||||
|
||||
ResetProxy: function(broadPhase)
|
||||
{
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var proxy = broadPhase.GetProxy(this.m_proxyId);
|
||||
|
||||
broadPhase.DestroyProxy(this.m_proxyId);
|
||||
proxy = null;
|
||||
|
||||
var aabb = new b2AABB();
|
||||
aabb.minVertex.Set(this.m_position.x - this.m_radius, this.m_position.y - this.m_radius);
|
||||
aabb.maxVertex.Set(this.m_position.x + this.m_radius, this.m_position.y + this.m_radius);
|
||||
|
||||
if (broadPhase.InRange(aabb))
|
||||
{
|
||||
this.m_proxyId = broadPhase.CreateProxy(aabb, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
}
|
||||
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
this.m_body.Freeze();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Support: function(dX, dY, out)
|
||||
{
|
||||
//b2Vec2 u = d;
|
||||
//u.Normalize();
|
||||
var len = Math.sqrt(dX*dX + dY*dY);
|
||||
dX /= len;
|
||||
dY /= len;
|
||||
//return this.m_position + this.m_radius * u;
|
||||
out.Set( this.m_position.x + this.m_radius*dX,
|
||||
this.m_position.y + this.m_radius*dY);
|
||||
},
|
||||
|
||||
|
||||
// Local position in parent body
|
||||
m_localPosition: new b2Vec2(),
|
||||
m_radius: null});
|
||||
|
36
lib/box2d-js/js/box2d/collision/shapes/b2MassData.js
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2MassData = Class.create();
|
||||
b2MassData.prototype =
|
||||
{
|
||||
mass: 0.0,
|
||||
center: new b2Vec2(0,0),
|
||||
I: 0.0,
|
||||
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.center = new b2Vec2(0,0);
|
||||
//
|
||||
}}
|
58
lib/box2d-js/js/box2d/collision/shapes/b2PolyDef.js
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2PolyDef = Class.create();
|
||||
Object.extend(b2PolyDef.prototype, b2ShapeDef.prototype);
|
||||
Object.extend(b2PolyDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2ShapeDef
|
||||
this.type = b2Shape.e_unknownShape;
|
||||
this.userData = null;
|
||||
this.localPosition = new b2Vec2(0.0, 0.0);
|
||||
this.localRotation = 0.0;
|
||||
this.friction = 0.2;
|
||||
this.restitution = 0.0;
|
||||
this.density = 0.0;
|
||||
this.categoryBits = 0x0001;
|
||||
this.maskBits = 0xFFFF;
|
||||
this.groupIndex = 0;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.vertices = new Array(b2Settings.b2_maxPolyVertices);
|
||||
//
|
||||
|
||||
this.type = b2Shape.e_polyShape;
|
||||
this.vertexCount = 0;
|
||||
|
||||
for (var i = 0; i < b2Settings.b2_maxPolyVertices; i++){
|
||||
this.vertices[i] = new b2Vec2();
|
||||
}
|
||||
},
|
||||
|
||||
vertices: new Array(b2Settings.b2_maxPolyVertices),
|
||||
vertexCount: 0});
|
||||
|
492
lib/box2d-js/js/box2d/collision/shapes/b2PolyShape.js
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// A convex polygon. The position of the polygon (m_position) is the
|
||||
// position of the centroid. The vertices of the incoming polygon are pre-rotated
|
||||
// according to the local rotation. The vertices are also shifted to be centered
|
||||
// on the centroid. Since the local rotation is absorbed into the vertex
|
||||
// coordinates, the polygon rotation is equal to the body rotation. However,
|
||||
// the polygon position is centered on the polygon centroid. This simplifies
|
||||
// some collision algorithms.
|
||||
|
||||
var b2PolyShape = Class.create();
|
||||
Object.extend(b2PolyShape.prototype, b2Shape.prototype);
|
||||
Object.extend(b2PolyShape.prototype,
|
||||
{
|
||||
TestPoint: function(p){
|
||||
|
||||
//var pLocal = b2Math.b2MulTMV(this.m_R, b2Math.SubtractVV(p, this.m_position));
|
||||
var pLocal = new b2Vec2();
|
||||
pLocal.SetV(p);
|
||||
pLocal.Subtract(this.m_position);
|
||||
pLocal.MulTM(this.m_R);
|
||||
|
||||
for (var i = 0; i < this.m_vertexCount; ++i)
|
||||
{
|
||||
//var dot = b2Math.b2Dot(this.m_normals[i], b2Math.SubtractVV(pLocal, this.m_vertices[i]));
|
||||
var tVec = new b2Vec2();
|
||||
tVec.SetV(pLocal);
|
||||
tVec.Subtract(this.m_vertices[i]);
|
||||
|
||||
var dot = b2Math.b2Dot(this.m_normals[i], tVec);
|
||||
if (dot > 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
// Temp vec for b2Shape.PolyCentroid
|
||||
|
||||
initialize: function(def, body, newOrigin){
|
||||
// initialize instance variables for references
|
||||
this.m_R = new b2Mat22();
|
||||
this.m_position = new b2Vec2();
|
||||
//
|
||||
|
||||
// The constructor for b2Shape
|
||||
this.m_userData = def.userData;
|
||||
|
||||
this.m_friction = def.friction;
|
||||
this.m_restitution = def.restitution;
|
||||
this.m_body = body;
|
||||
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
|
||||
this.m_maxRadius = 0.0;
|
||||
|
||||
this.m_categoryBits = def.categoryBits;
|
||||
this.m_maskBits = def.maskBits;
|
||||
this.m_groupIndex = def.groupIndex;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.syncAABB = new b2AABB();
|
||||
this.syncMat = new b2Mat22();
|
||||
this.m_localCentroid = new b2Vec2();
|
||||
this.m_localOBB = new b2OBB();
|
||||
//
|
||||
|
||||
|
||||
//super(def, body);
|
||||
|
||||
var i = 0;
|
||||
|
||||
|
||||
var hX;
|
||||
var hY;
|
||||
|
||||
var tVec;
|
||||
|
||||
var aabb = new b2AABB();
|
||||
|
||||
// Vertices
|
||||
this.m_vertices = new Array(b2Settings.b2_maxPolyVertices);
|
||||
this.m_coreVertices = new Array(b2Settings.b2_maxPolyVertices);
|
||||
//for (i = 0; i < b2Settings.b2_maxPolyVertices; i++)
|
||||
// this.m_vertices[i] = new b2Vec2();
|
||||
|
||||
// Normals
|
||||
this.m_normals = new Array(b2Settings.b2_maxPolyVertices);
|
||||
//for (i = 0; i < b2Settings.b2_maxPolyVertices; i++)
|
||||
// this.m_normals[i] = new b2Vec2();
|
||||
|
||||
//b2Settings.b2Assert(def.type == b2Shape.e_boxShape || def.type == b2Shape.e_polyShape);
|
||||
this.m_type = b2Shape.e_polyShape;
|
||||
|
||||
var localR = new b2Mat22(def.localRotation);
|
||||
|
||||
// Get the vertices transformed into the body frame.
|
||||
if (def.type == b2Shape.e_boxShape)
|
||||
{
|
||||
//this.m_localCentroid = def.localPosition - newOrigin;
|
||||
this.m_localCentroid.x = def.localPosition.x - newOrigin.x;
|
||||
this.m_localCentroid.y = def.localPosition.y - newOrigin.y;
|
||||
|
||||
var box = def;
|
||||
this.m_vertexCount = 4;
|
||||
hX = box.extents.x;
|
||||
hY = box.extents.y;
|
||||
|
||||
//hc.x = b2Max(0.0f, h.x - 2.0f * b2_linearSlop);
|
||||
var hcX = Math.max(0.0, hX - 2.0 * b2Settings.b2_linearSlop);
|
||||
//hc.y = b2Max(0.0f, h.y - 2.0f * b2_linearSlop);
|
||||
var hcY = Math.max(0.0, hY - 2.0 * b2Settings.b2_linearSlop);
|
||||
|
||||
//this.m_vertices[0] = b2Mul(localR, b2Vec2(h.x, h.y));
|
||||
tVec = this.m_vertices[0] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * hX + localR.col2.x * hY;
|
||||
tVec.y = localR.col1.y * hX + localR.col2.y * hY;
|
||||
//this.m_vertices[1] = b2Mul(localR, b2Vec2(-h.x, h.y));
|
||||
tVec = this.m_vertices[1] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * -hX + localR.col2.x * hY;
|
||||
tVec.y = localR.col1.y * -hX + localR.col2.y * hY;
|
||||
//this.m_vertices[2] = b2Mul(localR, b2Vec2(-h.x, -h.y));
|
||||
tVec = this.m_vertices[2] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * -hX + localR.col2.x * -hY;
|
||||
tVec.y = localR.col1.y * -hX + localR.col2.y * -hY;
|
||||
//this.m_vertices[3] = b2Mul(localR, b2Vec2(h.x, -h.y));
|
||||
tVec = this.m_vertices[3] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * hX + localR.col2.x * -hY;
|
||||
tVec.y = localR.col1.y * hX + localR.col2.y * -hY;
|
||||
|
||||
//this.m_coreVertices[0] = b2Mul(localR, b2Vec2(hc.x, hc.y));
|
||||
tVec = this.m_coreVertices[0] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * hcX + localR.col2.x * hcY;
|
||||
tVec.y = localR.col1.y * hcX + localR.col2.y * hcY;
|
||||
//this.m_coreVertices[1] = b2Mul(localR, b2Vec2(-hc.x, hc.y));
|
||||
tVec = this.m_coreVertices[1] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * -hcX + localR.col2.x * hcY;
|
||||
tVec.y = localR.col1.y * -hcX + localR.col2.y * hcY;
|
||||
//this.m_coreVertices[2] = b2Mul(localR, b2Vec2(-hc.x, -hc.y));
|
||||
tVec = this.m_coreVertices[2] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * -hcX + localR.col2.x * -hcY;
|
||||
tVec.y = localR.col1.y * -hcX + localR.col2.y * -hcY;
|
||||
//this.m_coreVertices[3] = b2Mul(localR, b2Vec2(hc.x, -hc.y));
|
||||
tVec = this.m_coreVertices[3] = new b2Vec2();
|
||||
tVec.x = localR.col1.x * hcX + localR.col2.x * -hcY;
|
||||
tVec.y = localR.col1.y * hcX + localR.col2.y * -hcY;
|
||||
}
|
||||
else
|
||||
{
|
||||
var poly = def;
|
||||
|
||||
this.m_vertexCount = poly.vertexCount;
|
||||
//b2Settings.b2Assert(3 <= this.m_vertexCount && this.m_vertexCount <= b2Settings.b2_maxPolyVertices);
|
||||
//b2Vec2 centroid = b2Shape.PolyCentroid(poly->vertices, poly->vertexCount);
|
||||
b2Shape.PolyCentroid(poly.vertices, poly.vertexCount, b2PolyShape.tempVec);
|
||||
var centroidX = b2PolyShape.tempVec.x;
|
||||
var centroidY = b2PolyShape.tempVec.y;
|
||||
//this.m_localCentroid = def->localPosition + b2Mul(localR, centroid) - newOrigin;
|
||||
this.m_localCentroid.x = def.localPosition.x + (localR.col1.x * centroidX + localR.col2.x * centroidY) - newOrigin.x;
|
||||
this.m_localCentroid.y = def.localPosition.y + (localR.col1.y * centroidX + localR.col2.y * centroidY) - newOrigin.y;
|
||||
|
||||
for (i = 0; i < this.m_vertexCount; ++i)
|
||||
{
|
||||
this.m_vertices[i] = new b2Vec2();
|
||||
this.m_coreVertices[i] = new b2Vec2();
|
||||
|
||||
//this.m_vertices[i] = b2Mul(localR, poly->vertices[i] - centroid);
|
||||
hX = poly.vertices[i].x - centroidX;
|
||||
hY = poly.vertices[i].y - centroidY;
|
||||
this.m_vertices[i].x = localR.col1.x * hX + localR.col2.x * hY;
|
||||
this.m_vertices[i].y = localR.col1.y * hX + localR.col2.y * hY;
|
||||
|
||||
//b2Vec2 u = this.m_vertices[i];
|
||||
var uX = this.m_vertices[i].x;
|
||||
var uY = this.m_vertices[i].y;
|
||||
//float32 length = u.Length();
|
||||
var length = Math.sqrt(uX*uX + uY*uY);
|
||||
if (length > Number.MIN_VALUE)
|
||||
{
|
||||
uX *= 1.0 / length;
|
||||
uY *= 1.0 / length;
|
||||
}
|
||||
|
||||
//this.m_coreVertices[i] = this.m_vertices[i] - 2.0f * b2_linearSlop * u;
|
||||
this.m_coreVertices[i].x = this.m_vertices[i].x - 2.0 * b2Settings.b2_linearSlop * uX;
|
||||
this.m_coreVertices[i].y = this.m_vertices[i].y - 2.0 * b2Settings.b2_linearSlop * uY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Compute bounding box. TODO_ERIN optimize OBB
|
||||
//var minVertex = new b2Vec2(Number.MAX_VALUE, Number.MAX_VALUE);
|
||||
var minVertexX = Number.MAX_VALUE;
|
||||
var minVertexY = Number.MAX_VALUE;
|
||||
var maxVertexX = -Number.MAX_VALUE;
|
||||
var maxVertexY = -Number.MAX_VALUE;
|
||||
this.m_maxRadius = 0.0;
|
||||
for (i = 0; i < this.m_vertexCount; ++i)
|
||||
{
|
||||
var v = this.m_vertices[i];
|
||||
//minVertex = b2Math.b2MinV(minVertex, this.m_vertices[i]);
|
||||
minVertexX = Math.min(minVertexX, v.x);
|
||||
minVertexY = Math.min(minVertexY, v.y);
|
||||
//maxVertex = b2Math.b2MaxV(maxVertex, this.m_vertices[i]);
|
||||
maxVertexX = Math.max(maxVertexX, v.x);
|
||||
maxVertexY = Math.max(maxVertexY, v.y);
|
||||
//this.m_maxRadius = b2Max(this.m_maxRadius, v.Length());
|
||||
this.m_maxRadius = Math.max(this.m_maxRadius, v.Length());
|
||||
}
|
||||
|
||||
this.m_localOBB.R.SetIdentity();
|
||||
//this.m_localOBB.center = 0.5 * (minVertex + maxVertex);
|
||||
this.m_localOBB.center.Set((minVertexX + maxVertexX) * 0.5, (minVertexY + maxVertexY) * 0.5);
|
||||
//this.m_localOBB.extents = 0.5 * (maxVertex - minVertex);
|
||||
this.m_localOBB.extents.Set((maxVertexX - minVertexX) * 0.5, (maxVertexY - minVertexY) * 0.5);
|
||||
|
||||
// Compute the edge normals and next index map.
|
||||
var i1 = 0;
|
||||
var i2 = 0;
|
||||
for (i = 0; i < this.m_vertexCount; ++i)
|
||||
{
|
||||
this.m_normals[i] = new b2Vec2();
|
||||
i1 = i;
|
||||
i2 = i + 1 < this.m_vertexCount ? i + 1 : 0;
|
||||
//b2Vec2 edge = this.m_vertices[i2] - this.m_vertices[i1];
|
||||
//var edgeX = this.m_vertices[i2].x - this.m_vertices[i1].x;
|
||||
//var edgeY = this.m_vertices[i2].y - this.m_vertices[i1].y;
|
||||
//this.m_normals[i] = b2Cross(edge, 1.0f);
|
||||
this.m_normals[i].x = this.m_vertices[i2].y - this.m_vertices[i1].y;
|
||||
this.m_normals[i].y = -(this.m_vertices[i2].x - this.m_vertices[i1].x);
|
||||
this.m_normals[i].Normalize();
|
||||
}
|
||||
|
||||
// Ensure the polygon in convex. TODO_ERIN compute convex hull.
|
||||
for (i = 0; i < this.m_vertexCount; ++i)
|
||||
{
|
||||
i1 = i;
|
||||
i2 = i + 1 < this.m_vertexCount ? i + 1 : 0;
|
||||
|
||||
//b2Settings.b2Assert(b2Math.b2CrossVV(this.m_normals[i1], this.m_normals[i2]) > Number.MIN_VALUE);
|
||||
}
|
||||
|
||||
this.m_R.SetM(this.m_body.m_R);
|
||||
//this.m_position.SetV( this.m_body.m_position + b2Mul(this.m_body->this.m_R, this.m_localCentroid) );
|
||||
this.m_position.x = this.m_body.m_position.x + (this.m_R.col1.x * this.m_localCentroid.x + this.m_R.col2.x * this.m_localCentroid.y);
|
||||
this.m_position.y = this.m_body.m_position.y + (this.m_R.col1.y * this.m_localCentroid.x + this.m_R.col2.y * this.m_localCentroid.y);
|
||||
|
||||
//var R = b2Math.b2MulMM(this.m_R, this.m_localOBB.R);
|
||||
//R.col1 = b2MulMV(this.m_R, this.m_localOBB.R.col1);
|
||||
b2PolyShape.tAbsR.col1.x = this.m_R.col1.x * this.m_localOBB.R.col1.x + this.m_R.col2.x * this.m_localOBB.R.col1.y;
|
||||
b2PolyShape.tAbsR.col1.y = this.m_R.col1.y * this.m_localOBB.R.col1.x + this.m_R.col2.y * this.m_localOBB.R.col1.y;
|
||||
//R.col2 = b2MulMV(this.m_R, this.m_localOBB.R.col2)
|
||||
b2PolyShape.tAbsR.col2.x = this.m_R.col1.x * this.m_localOBB.R.col2.x + this.m_R.col2.x * this.m_localOBB.R.col2.y;
|
||||
b2PolyShape.tAbsR.col2.y = this.m_R.col1.y * this.m_localOBB.R.col2.x + this.m_R.col2.y * this.m_localOBB.R.col2.y;
|
||||
//var absR = b2Math.b2AbsM(R);
|
||||
b2PolyShape.tAbsR.Abs()
|
||||
|
||||
//h = b2Math.b2MulMV(b2PolyShape.tAbsR, this.m_localOBB.extents);
|
||||
hX = b2PolyShape.tAbsR.col1.x * this.m_localOBB.extents.x + b2PolyShape.tAbsR.col2.x * this.m_localOBB.extents.y;
|
||||
hY = b2PolyShape.tAbsR.col1.y * this.m_localOBB.extents.x + b2PolyShape.tAbsR.col2.y * this.m_localOBB.extents.y;
|
||||
|
||||
//var position = this.m_position + b2Mul(this.m_R, this.m_localOBB.center);
|
||||
var positionX = this.m_position.x + (this.m_R.col1.x * this.m_localOBB.center.x + this.m_R.col2.x * this.m_localOBB.center.y);
|
||||
var positionY = this.m_position.y + (this.m_R.col1.y * this.m_localOBB.center.x + this.m_R.col2.y * this.m_localOBB.center.y);
|
||||
|
||||
//aabb.minVertex = b2Math.SubtractVV(this.m_position, h);
|
||||
aabb.minVertex.x = positionX - hX;
|
||||
aabb.minVertex.y = positionY - hY;
|
||||
//aabb.maxVertex = b2Math.AddVV(this.m_position, h);
|
||||
aabb.maxVertex.x = positionX + hX;
|
||||
aabb.maxVertex.y = positionY + hY;
|
||||
|
||||
var broadPhase = this.m_body.m_world.m_broadPhase;
|
||||
if (broadPhase.InRange(aabb))
|
||||
{
|
||||
this.m_proxyId = broadPhase.CreateProxy(aabb, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
}
|
||||
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
this.m_body.Freeze();
|
||||
}
|
||||
},
|
||||
|
||||
// Temp AABB for Synch function
|
||||
syncAABB: new b2AABB(),
|
||||
syncMat: new b2Mat22(),
|
||||
Synchronize: function(position1, R1, position2, R2){
|
||||
// The body transform is copied for convenience.
|
||||
this.m_R.SetM(R2);
|
||||
//this.m_position = this.m_body->this.m_position + b2Mul(this.m_body->this.m_R, this.m_localCentroid)
|
||||
this.m_position.x = this.m_body.m_position.x + (R2.col1.x * this.m_localCentroid.x + R2.col2.x * this.m_localCentroid.y);
|
||||
this.m_position.y = this.m_body.m_position.y + (R2.col1.y * this.m_localCentroid.x + R2.col2.y * this.m_localCentroid.y);
|
||||
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//b2AABB aabb1, aabb2;
|
||||
var hX;
|
||||
var hY;
|
||||
|
||||
//b2Mat22 obbR = b2Mul(R1, this.m_localOBB.R);
|
||||
var v1 = R1.col1;
|
||||
var v2 = R1.col2;
|
||||
var v3 = this.m_localOBB.R.col1;
|
||||
var v4 = this.m_localOBB.R.col2;
|
||||
//this.syncMat.col1 = b2MulMV(R1, this.m_localOBB.R.col1);
|
||||
this.syncMat.col1.x = v1.x * v3.x + v2.x * v3.y;
|
||||
this.syncMat.col1.y = v1.y * v3.x + v2.y * v3.y;
|
||||
//this.syncMat.col2 = b2MulMV(R1, this.m_localOBB.R.col2);
|
||||
this.syncMat.col2.x = v1.x * v4.x + v2.x * v4.y;
|
||||
this.syncMat.col2.y = v1.y * v4.x + v2.y * v4.y;
|
||||
//b2Mat22 absR = b2Abs(obbR);
|
||||
this.syncMat.Abs();
|
||||
//b2Vec2 center = position1 + b2Mul(R1, this.m_localCentroid + this.m_localOBB.center);
|
||||
hX = this.m_localCentroid.x + this.m_localOBB.center.x;
|
||||
hY = this.m_localCentroid.y + this.m_localOBB.center.y;
|
||||
var centerX = position1.x + (R1.col1.x * hX + R1.col2.x * hY);
|
||||
var centerY = position1.y + (R1.col1.y * hX + R1.col2.y * hY);
|
||||
//b2Vec2 h = b2Mul(this.syncMat, this.m_localOBB.extents);
|
||||
hX = this.syncMat.col1.x * this.m_localOBB.extents.x + this.syncMat.col2.x * this.m_localOBB.extents.y;
|
||||
hY = this.syncMat.col1.y * this.m_localOBB.extents.x + this.syncMat.col2.y * this.m_localOBB.extents.y;
|
||||
//aabb1.minVertex = center - h;
|
||||
this.syncAABB.minVertex.x = centerX - hX;
|
||||
this.syncAABB.minVertex.y = centerY - hY;
|
||||
//aabb1.maxVertex = center + h;
|
||||
this.syncAABB.maxVertex.x = centerX + hX;
|
||||
this.syncAABB.maxVertex.y = centerY + hY;
|
||||
|
||||
//b2Mat22 obbR = b2Mul(R2, this.m_localOBB.R);
|
||||
v1 = R2.col1;
|
||||
v2 = R2.col2;
|
||||
v3 = this.m_localOBB.R.col1;
|
||||
v4 = this.m_localOBB.R.col2;
|
||||
//this.syncMat.col1 = b2MulMV(R1, this.m_localOBB.R.col1);
|
||||
this.syncMat.col1.x = v1.x * v3.x + v2.x * v3.y;
|
||||
this.syncMat.col1.y = v1.y * v3.x + v2.y * v3.y;
|
||||
//this.syncMat.col2 = b2MulMV(R1, this.m_localOBB.R.col2);
|
||||
this.syncMat.col2.x = v1.x * v4.x + v2.x * v4.y;
|
||||
this.syncMat.col2.y = v1.y * v4.x + v2.y * v4.y;
|
||||
//b2Mat22 absR = b2Abs(obbR);
|
||||
this.syncMat.Abs();
|
||||
//b2Vec2 center = position2 + b2Mul(R2, this.m_localCentroid + this.m_localOBB.center);
|
||||
hX = this.m_localCentroid.x + this.m_localOBB.center.x;
|
||||
hY = this.m_localCentroid.y + this.m_localOBB.center.y;
|
||||
centerX = position2.x + (R2.col1.x * hX + R2.col2.x * hY);
|
||||
centerY = position2.y + (R2.col1.y * hX + R2.col2.y * hY);
|
||||
//b2Vec2 h = b2Mul(absR, this.m_localOBB.extents);
|
||||
hX = this.syncMat.col1.x * this.m_localOBB.extents.x + this.syncMat.col2.x * this.m_localOBB.extents.y;
|
||||
hY = this.syncMat.col1.y * this.m_localOBB.extents.x + this.syncMat.col2.y * this.m_localOBB.extents.y;
|
||||
//aabb2.minVertex = center - h;
|
||||
//aabb2.maxVertex = center + h;
|
||||
|
||||
//aabb.minVertex = b2Min(aabb1.minVertex, aabb2.minVertex);
|
||||
this.syncAABB.minVertex.x = Math.min(this.syncAABB.minVertex.x, centerX - hX);
|
||||
this.syncAABB.minVertex.y = Math.min(this.syncAABB.minVertex.y, centerY - hY);
|
||||
//aabb.maxVertex = b2Max(aabb1.maxVertex, aabb2.maxVertex);
|
||||
this.syncAABB.maxVertex.x = Math.max(this.syncAABB.maxVertex.x, centerX + hX);
|
||||
this.syncAABB.maxVertex.y = Math.max(this.syncAABB.maxVertex.y, centerY + hY);
|
||||
|
||||
var broadPhase = this.m_body.m_world.m_broadPhase;
|
||||
if (broadPhase.InRange(this.syncAABB))
|
||||
{
|
||||
broadPhase.MoveProxy(this.m_proxyId, this.syncAABB);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_body.Freeze();
|
||||
}
|
||||
},
|
||||
|
||||
QuickSync: function(position, R){
|
||||
//this.m_R = R;
|
||||
this.m_R.SetM(R);
|
||||
//this.m_position = position + b2Mul(R, this.m_localCentroid);
|
||||
this.m_position.x = position.x + (R.col1.x * this.m_localCentroid.x + R.col2.x * this.m_localCentroid.y);
|
||||
this.m_position.y = position.y + (R.col1.y * this.m_localCentroid.x + R.col2.y * this.m_localCentroid.y);
|
||||
},
|
||||
|
||||
ResetProxy: function(broadPhase){
|
||||
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var proxy = broadPhase.GetProxy(this.m_proxyId);
|
||||
|
||||
broadPhase.DestroyProxy(this.m_proxyId);
|
||||
proxy = null;
|
||||
|
||||
var R = b2Math.b2MulMM(this.m_R, this.m_localOBB.R);
|
||||
var absR = b2Math.b2AbsM(R);
|
||||
var h = b2Math.b2MulMV(absR, this.m_localOBB.extents);
|
||||
//var position = this.m_position + b2Mul(this.m_R, this.m_localOBB.center);
|
||||
var position = b2Math.b2MulMV(this.m_R, this.m_localOBB.center);
|
||||
position.Add(this.m_position);
|
||||
|
||||
var aabb = new b2AABB();
|
||||
//aabb.minVertex = position - h;
|
||||
aabb.minVertex.SetV(position);
|
||||
aabb.minVertex.Subtract(h);
|
||||
//aabb.maxVertex = position + h;
|
||||
aabb.maxVertex.SetV(position);
|
||||
aabb.maxVertex.Add(h);
|
||||
|
||||
if (broadPhase.InRange(aabb))
|
||||
{
|
||||
this.m_proxyId = broadPhase.CreateProxy(aabb, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
}
|
||||
|
||||
if (this.m_proxyId == b2Pair.b2_nullProxy)
|
||||
{
|
||||
this.m_body.Freeze();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Support: function(dX, dY, out)
|
||||
{
|
||||
//b2Vec2 dLocal = b2MulT(this.m_R, d);
|
||||
var dLocalX = (dX*this.m_R.col1.x + dY*this.m_R.col1.y);
|
||||
var dLocalY = (dX*this.m_R.col2.x + dY*this.m_R.col2.y);
|
||||
|
||||
var bestIndex = 0;
|
||||
//float32 bestValue = b2Dot(this.m_vertices[0], dLocal);
|
||||
var bestValue = (this.m_coreVertices[0].x * dLocalX + this.m_coreVertices[0].y * dLocalY);
|
||||
for (var i = 1; i < this.m_vertexCount; ++i)
|
||||
{
|
||||
//float32 value = b2Dot(this.m_vertices[i], dLocal);
|
||||
var value = (this.m_coreVertices[i].x * dLocalX + this.m_coreVertices[i].y * dLocalY);
|
||||
if (value > bestValue)
|
||||
{
|
||||
bestIndex = i;
|
||||
bestValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
//return this.m_position + b2Mul(this.m_R, this.m_vertices[bestIndex]);
|
||||
out.Set( this.m_position.x + (this.m_R.col1.x * this.m_coreVertices[bestIndex].x + this.m_R.col2.x * this.m_coreVertices[bestIndex].y),
|
||||
this.m_position.y + (this.m_R.col1.y * this.m_coreVertices[bestIndex].x + this.m_R.col2.y * this.m_coreVertices[bestIndex].y));
|
||||
|
||||
},
|
||||
|
||||
|
||||
// Local position of the shape centroid in parent body frame.
|
||||
m_localCentroid: new b2Vec2(),
|
||||
|
||||
// Local position oriented bounding box. The OBB center is relative to
|
||||
// shape centroid.
|
||||
m_localOBB: new b2OBB(),
|
||||
m_vertices: null,
|
||||
m_coreVertices: null,
|
||||
m_vertexCount: 0,
|
||||
m_normals: null});
|
||||
|
||||
b2PolyShape.tempVec = new b2Vec2();
|
||||
b2PolyShape.tAbsR = new b2Mat22();
|
339
lib/box2d-js/js/box2d/collision/shapes/b2Shape.js
Normal file
@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Shapes are created automatically when a body is created.
|
||||
// Client code does not normally interact with shapes.
|
||||
var b2Shape = Class.create();
|
||||
b2Shape.prototype =
|
||||
{
|
||||
TestPoint: function(p){return false},
|
||||
|
||||
GetUserData: function(){return this.m_userData;},
|
||||
|
||||
GetType: function(){
|
||||
return this.m_type;
|
||||
},
|
||||
|
||||
// Get the parent body of this shape.
|
||||
GetBody: function(){
|
||||
return this.m_body;
|
||||
},
|
||||
|
||||
GetPosition: function(){
|
||||
return this.m_position;
|
||||
},
|
||||
GetRotationMatrix: function(){
|
||||
return this.m_R;
|
||||
},
|
||||
|
||||
// Remove and then add proxy from the broad-phase.
|
||||
// This is used to refresh the collision filters.
|
||||
ResetProxy: function(broadPhase){},
|
||||
|
||||
// Get the next shape in the parent body's shape list.
|
||||
GetNext: function(){
|
||||
return this.m_next;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
|
||||
|
||||
|
||||
initialize: function(def, body){
|
||||
// initialize instance variables for references
|
||||
this.m_R = new b2Mat22();
|
||||
this.m_position = new b2Vec2();
|
||||
//
|
||||
|
||||
this.m_userData = def.userData;
|
||||
|
||||
this.m_friction = def.friction;
|
||||
this.m_restitution = def.restitution;
|
||||
this.m_body = body;
|
||||
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
|
||||
this.m_maxRadius = 0.0;
|
||||
|
||||
this.m_categoryBits = def.categoryBits;
|
||||
this.m_maskBits = def.maskBits;
|
||||
this.m_groupIndex = def.groupIndex;
|
||||
},
|
||||
|
||||
// Internal use only. Do not call.
|
||||
//b2Shape::~b2Shape()
|
||||
//{
|
||||
// this.m_body->m_world->m_broadPhase->this.DestroyProxy(this.m_proxyId);
|
||||
//}
|
||||
|
||||
|
||||
DestroyProxy: function()
|
||||
{
|
||||
if (this.m_proxyId != b2Pair.b2_nullProxy)
|
||||
{
|
||||
this.m_body.m_world.m_broadPhase.DestroyProxy(this.m_proxyId);
|
||||
this.m_proxyId = b2Pair.b2_nullProxy;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Internal use only. Do not call.
|
||||
Synchronize: function(position1, R1, position2, R2){},
|
||||
QuickSync: function(position, R){},
|
||||
Support: function(dX, dY, out){},
|
||||
GetMaxRadius: function(){
|
||||
return this.m_maxRadius;
|
||||
},
|
||||
|
||||
m_next: null,
|
||||
|
||||
m_R: new b2Mat22(),
|
||||
m_position: new b2Vec2(),
|
||||
|
||||
m_type: 0,
|
||||
|
||||
m_userData: null,
|
||||
|
||||
m_body: null,
|
||||
|
||||
m_friction: null,
|
||||
m_restitution: null,
|
||||
|
||||
m_maxRadius: null,
|
||||
|
||||
m_proxyId: 0,
|
||||
m_categoryBits: 0,
|
||||
m_maskBits: 0,
|
||||
m_groupIndex: 0
|
||||
|
||||
|
||||
|
||||
// b2ShapeType
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
b2Shape.Create = function(def, body, center){
|
||||
switch (def.type)
|
||||
{
|
||||
case b2Shape.e_circleShape:
|
||||
{
|
||||
//void* mem = body->m_world->m_blockAllocator.Allocate(sizeof(b2CircleShape));
|
||||
return new b2CircleShape(def, body, center);
|
||||
}
|
||||
|
||||
case b2Shape.e_boxShape:
|
||||
case b2Shape.e_polyShape:
|
||||
{
|
||||
//void* mem = body->m_world->m_blockAllocator.Allocate(sizeof(b2PolyShape));
|
||||
return new b2PolyShape(def, body, center);
|
||||
}
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(false);
|
||||
return null;
|
||||
};
|
||||
b2Shape.Destroy = function(shape)
|
||||
{
|
||||
/*b2BlockAllocator& allocator = shape->m_body->m_world->m_blockAllocator;
|
||||
|
||||
switch (shape.m_type)
|
||||
{
|
||||
case b2Shape.e_circleShape:
|
||||
shape->~b2Shape();
|
||||
allocator.Free(shape, sizeof(b2CircleShape));
|
||||
break;
|
||||
|
||||
case b2Shape.e_polyShape:
|
||||
shape->~b2Shape();
|
||||
allocator.Free(shape, sizeof(b2PolyShape));
|
||||
break;
|
||||
|
||||
default:
|
||||
b2Assert(false);
|
||||
}
|
||||
|
||||
shape = NULL;*/
|
||||
|
||||
// FROM DESTRUCTOR
|
||||
if (shape.m_proxyId != b2Pair.b2_nullProxy)
|
||||
shape.m_body.m_world.m_broadPhase.DestroyProxy(shape.m_proxyId);
|
||||
};
|
||||
b2Shape.e_unknownShape = -1;
|
||||
b2Shape.e_circleShape = 0;
|
||||
b2Shape.e_boxShape = 1;
|
||||
b2Shape.e_polyShape = 2;
|
||||
b2Shape.e_meshShape = 3;
|
||||
b2Shape.e_shapeTypeCount = 4;
|
||||
b2Shape.PolyMass = function(massData, vs, count, rho)
|
||||
{
|
||||
//b2Settings.b2Assert(count >= 3);
|
||||
|
||||
//var center = new b2Vec2(0.0, 0.0);
|
||||
var center = new b2Vec2();
|
||||
center.SetZero();
|
||||
|
||||
var area = 0.0;
|
||||
var I = 0.0;
|
||||
|
||||
// pRef is the reference point for forming triangles.
|
||||
// It's location doesn't change the result (except for rounding error).
|
||||
var pRef = new b2Vec2(0.0, 0.0);
|
||||
|
||||
var inv3 = 1.0 / 3.0;
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
// Triangle vertices.
|
||||
var p1 = pRef;
|
||||
var p2 = vs[i];
|
||||
var p3 = i + 1 < count ? vs[i+1] : vs[0];
|
||||
|
||||
var e1 = b2Math.SubtractVV(p2, p1);
|
||||
var e2 = b2Math.SubtractVV(p3, p1);
|
||||
|
||||
var D = b2Math.b2CrossVV(e1, e2);
|
||||
|
||||
var triangleArea = 0.5 * D;
|
||||
area += triangleArea;
|
||||
|
||||
// Area weighted centroid
|
||||
// center += triangleArea * inv3 * (p1 + p2 + p3);
|
||||
var tVec = new b2Vec2();
|
||||
tVec.SetV(p1);
|
||||
tVec.Add(p2);
|
||||
tVec.Add(p3);
|
||||
tVec.Multiply(inv3*triangleArea);
|
||||
center.Add(tVec);
|
||||
|
||||
var px = p1.x;
|
||||
var py = p1.y;
|
||||
var ex1 = e1.x;
|
||||
var ey1 = e1.y;
|
||||
var ex2 = e2.x;
|
||||
var ey2 = e2.y;
|
||||
|
||||
var intx2 = inv3 * (0.25 * (ex1*ex1 + ex2*ex1 + ex2*ex2) + (px*ex1 + px*ex2)) + 0.5*px*px;
|
||||
var inty2 = inv3 * (0.25 * (ey1*ey1 + ey2*ey1 + ey2*ey2) + (py*ey1 + py*ey2)) + 0.5*py*py;
|
||||
|
||||
I += D * (intx2 + inty2);
|
||||
}
|
||||
|
||||
// Total mass
|
||||
massData.mass = rho * area;
|
||||
|
||||
// Center of mass
|
||||
//b2Settings.b2Assert(area > Number.MIN_VALUE);
|
||||
center.Multiply( 1.0 / area );
|
||||
massData.center = center;
|
||||
|
||||
// Inertia tensor relative to the center.
|
||||
I = rho * (I - area * b2Math.b2Dot(center, center));
|
||||
massData.I = I;
|
||||
};
|
||||
b2Shape.PolyCentroid = function(vs, count, out)
|
||||
{
|
||||
//b2Settings.b2Assert(count >= 3);
|
||||
|
||||
//b2Vec2 c; c.Set(0.0f, 0.0f);
|
||||
var cX = 0.0;
|
||||
var cY = 0.0;
|
||||
//float32 area = 0.0f;
|
||||
var area = 0.0;
|
||||
|
||||
// pRef is the reference point for forming triangles.
|
||||
// It's location doesn't change the result (except for rounding error).
|
||||
//b2Vec2 pRef(0.0f, 0.0f);
|
||||
var pRefX = 0.0;
|
||||
var pRefY = 0.0;
|
||||
/*
|
||||
// This code would put the reference point inside the polygon.
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
//pRef += vs[i];
|
||||
pRef.x += vs[i].x;
|
||||
pRef.y += vs[i].y;
|
||||
}
|
||||
pRef.x *= 1.0 / count;
|
||||
pRef.y *= 1.0 / count;
|
||||
*/
|
||||
|
||||
//const float32 inv3 = 1.0f / 3.0f;
|
||||
var inv3 = 1.0 / 3.0;
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
// Triangle vertices.
|
||||
//b2Vec2 p1 = pRef;
|
||||
var p1X = pRefX;
|
||||
var p1Y = pRefY;
|
||||
//b2Vec2 p2 = vs[i];
|
||||
var p2X = vs[i].x;
|
||||
var p2Y = vs[i].y;
|
||||
//b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];
|
||||
var p3X = i + 1 < count ? vs[i+1].x : vs[0].x;
|
||||
var p3Y = i + 1 < count ? vs[i+1].y : vs[0].y;
|
||||
|
||||
//b2Vec2 e1 = p2 - p1;
|
||||
var e1X = p2X - p1X;
|
||||
var e1Y = p2Y - p1Y;
|
||||
//b2Vec2 e2 = p3 - p1;
|
||||
var e2X = p3X - p1X;
|
||||
var e2Y = p3Y - p1Y;
|
||||
|
||||
//float32 D = b2Cross(e1, e2);
|
||||
var D = (e1X * e2Y - e1Y * e2X);
|
||||
|
||||
//float32 triangleArea = 0.5f * D;
|
||||
var triangleArea = 0.5 * D;
|
||||
area += triangleArea;
|
||||
|
||||
// Area weighted centroid
|
||||
//c += triangleArea * inv3 * (p1 + p2 + p3);
|
||||
cX += triangleArea * inv3 * (p1X + p2X + p3X);
|
||||
cY += triangleArea * inv3 * (p1Y + p2Y + p3Y);
|
||||
}
|
||||
|
||||
// Centroid
|
||||
//b2Settings.b2Assert(area > Number.MIN_VALUE);
|
||||
cX *= 1.0 / area;
|
||||
cY *= 1.0 / area;
|
||||
|
||||
// Replace return with 'out' vector
|
||||
//return c;
|
||||
out.Set(cX, cY);
|
||||
};
|
109
lib/box2d-js/js/box2d/collision/shapes/b2ShapeDef.js
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2ShapeDef = Class.create();
|
||||
b2ShapeDef.prototype =
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
this.type = b2Shape.e_unknownShape;
|
||||
this.userData = null;
|
||||
this.localPosition = new b2Vec2(0.0, 0.0);
|
||||
this.localRotation = 0.0;
|
||||
this.friction = 0.2;
|
||||
this.restitution = 0.0;
|
||||
this.density = 0.0;
|
||||
this.categoryBits = 0x0001;
|
||||
this.maskBits = 0xFFFF;
|
||||
this.groupIndex = 0;
|
||||
},
|
||||
|
||||
//virtual ~b2ShapeDef() {}
|
||||
|
||||
ComputeMass: function(massData)
|
||||
{
|
||||
|
||||
massData.center = new b2Vec2(0.0, 0.0)
|
||||
|
||||
if (this.density == 0.0)
|
||||
{
|
||||
massData.mass = 0.0;
|
||||
massData.center.Set(0.0, 0.0);
|
||||
massData.I = 0.0;
|
||||
};
|
||||
|
||||
switch (this.type)
|
||||
{
|
||||
case b2Shape.e_circleShape:
|
||||
{
|
||||
var circle = this;
|
||||
massData.mass = this.density * b2Settings.b2_pi * circle.radius * circle.radius;
|
||||
massData.center.Set(0.0, 0.0);
|
||||
massData.I = 0.5 * (massData.mass) * circle.radius * circle.radius;
|
||||
}
|
||||
break;
|
||||
|
||||
case b2Shape.e_boxShape:
|
||||
{
|
||||
var box = this;
|
||||
massData.mass = 4.0 * this.density * box.extents.x * box.extents.y;
|
||||
massData.center.Set(0.0, 0.0);
|
||||
massData.I = massData.mass / 3.0 * b2Math.b2Dot(box.extents, box.extents);
|
||||
}
|
||||
break;
|
||||
|
||||
case b2Shape.e_polyShape:
|
||||
{
|
||||
var poly = this;
|
||||
b2Shape.PolyMass(massData, poly.vertices, poly.vertexCount, this.density);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
massData.mass = 0.0;
|
||||
massData.center.Set(0.0, 0.0);
|
||||
massData.I = 0.0;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
type: 0,
|
||||
userData: null,
|
||||
localPosition: null,
|
||||
localRotation: null,
|
||||
friction: null,
|
||||
restitution: null,
|
||||
density: null,
|
||||
|
||||
// The collision category bits. Normally you would just set one bit.
|
||||
categoryBits: 0,
|
||||
|
||||
// The collision mask bits. This states the categories that this
|
||||
// shape would accept for collision.
|
||||
maskBits: 0,
|
||||
|
||||
// Collision groups allow a certain group of objects to never collide (negative)
|
||||
// or always collide (positive). Zero means no collision group. Non-zero group
|
||||
// filtering always wins against the mask bits.
|
||||
groupIndex: 0};
|
72
lib/box2d-js/js/box2d/common/b2Settings.js
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2Settings = Class.create();
|
||||
b2Settings.prototype = {
|
||||
|
||||
|
||||
|
||||
// Define your unit system here. The default system is
|
||||
// meters-kilograms-seconds. For the tuning to work well,
|
||||
// your dynamic objects should be bigger than a pebble and smaller
|
||||
// than a house.
|
||||
//static public const b2Settings.b2_lengthUnitsPerMeter = 1.0;
|
||||
|
||||
// Use this for pixels:
|
||||
|
||||
// Global tuning constants based on MKS units.
|
||||
|
||||
// Collision
|
||||
|
||||
// Dynamics
|
||||
|
||||
// Sleep
|
||||
|
||||
// assert
|
||||
|
||||
initialize: function() {}}
|
||||
b2Settings.USHRT_MAX = 0x0000ffff;
|
||||
b2Settings.b2_pi = Math.PI;
|
||||
b2Settings.b2_massUnitsPerKilogram = 1.0;
|
||||
b2Settings.b2_timeUnitsPerSecond = 1.0;
|
||||
b2Settings.b2_lengthUnitsPerMeter = 30.0;
|
||||
b2Settings.b2_maxManifoldPoints = 2;
|
||||
b2Settings.b2_maxShapesPerBody = 64;
|
||||
b2Settings.b2_maxPolyVertices = 8;
|
||||
b2Settings.b2_maxProxies = 1024;
|
||||
b2Settings.b2_maxPairs = 8 * b2Settings.b2_maxProxies;
|
||||
b2Settings.b2_linearSlop = 0.005 * b2Settings.b2_lengthUnitsPerMeter;
|
||||
b2Settings.b2_angularSlop = 2.0 / 180.0 * b2Settings.b2_pi;
|
||||
b2Settings.b2_velocityThreshold = 1.0 * b2Settings.b2_lengthUnitsPerMeter / b2Settings.b2_timeUnitsPerSecond;
|
||||
b2Settings.b2_maxLinearCorrection = 0.2 * b2Settings.b2_lengthUnitsPerMeter;
|
||||
b2Settings.b2_maxAngularCorrection = 8.0 / 180.0 * b2Settings.b2_pi;
|
||||
b2Settings.b2_contactBaumgarte = 0.2;
|
||||
b2Settings.b2_timeToSleep = 0.5 * b2Settings.b2_timeUnitsPerSecond;
|
||||
b2Settings.b2_linearSleepTolerance = 0.01 * b2Settings.b2_lengthUnitsPerMeter / b2Settings.b2_timeUnitsPerSecond;
|
||||
b2Settings.b2_angularSleepTolerance = 2.0 / 180.0 / b2Settings.b2_timeUnitsPerSecond;
|
||||
b2Settings.b2Assert = function(a)
|
||||
{
|
||||
if (!a){
|
||||
var nullVec;
|
||||
nullVec.x++;
|
||||
}
|
||||
};
|
130
lib/box2d-js/js/box2d/common/math/b2Mat22.js
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2Mat22 = Class.create();
|
||||
b2Mat22.prototype =
|
||||
{
|
||||
initialize: function(angle, c1, c2)
|
||||
{
|
||||
if (angle==null) angle = 0;
|
||||
// initialize instance variables for references
|
||||
this.col1 = new b2Vec2();
|
||||
this.col2 = new b2Vec2();
|
||||
//
|
||||
|
||||
if (c1!=null && c2!=null){
|
||||
this.col1.SetV(c1);
|
||||
this.col2.SetV(c2);
|
||||
}
|
||||
else{
|
||||
var c = Math.cos(angle);
|
||||
var s = Math.sin(angle);
|
||||
this.col1.x = c; this.col2.x = -s;
|
||||
this.col1.y = s; this.col2.y = c;
|
||||
}
|
||||
},
|
||||
|
||||
Set: function(angle)
|
||||
{
|
||||
var c = Math.cos(angle);
|
||||
var s = Math.sin(angle);
|
||||
this.col1.x = c; this.col2.x = -s;
|
||||
this.col1.y = s; this.col2.y = c;
|
||||
},
|
||||
|
||||
SetVV: function(c1, c2)
|
||||
{
|
||||
this.col1.SetV(c1);
|
||||
this.col2.SetV(c2);
|
||||
},
|
||||
|
||||
Copy: function(){
|
||||
return new b2Mat22(0, this.col1, this.col2);
|
||||
},
|
||||
|
||||
SetM: function(m)
|
||||
{
|
||||
this.col1.SetV(m.col1);
|
||||
this.col2.SetV(m.col2);
|
||||
},
|
||||
|
||||
AddM: function(m)
|
||||
{
|
||||
this.col1.x += m.col1.x;
|
||||
this.col1.y += m.col1.y;
|
||||
this.col2.x += m.col2.x;
|
||||
this.col2.y += m.col2.y;
|
||||
},
|
||||
|
||||
SetIdentity: function()
|
||||
{
|
||||
this.col1.x = 1.0; this.col2.x = 0.0;
|
||||
this.col1.y = 0.0; this.col2.y = 1.0;
|
||||
},
|
||||
|
||||
SetZero: function()
|
||||
{
|
||||
this.col1.x = 0.0; this.col2.x = 0.0;
|
||||
this.col1.y = 0.0; this.col2.y = 0.0;
|
||||
},
|
||||
|
||||
Invert: function(out)
|
||||
{
|
||||
var a = this.col1.x;
|
||||
var b = this.col2.x;
|
||||
var c = this.col1.y;
|
||||
var d = this.col2.y;
|
||||
//var B = new b2Mat22();
|
||||
var det = a * d - b * c;
|
||||
//b2Settings.b2Assert(det != 0.0);
|
||||
det = 1.0 / det;
|
||||
out.col1.x = det * d; out.col2.x = -det * b;
|
||||
out.col1.y = -det * c; out.col2.y = det * a;
|
||||
return out;
|
||||
},
|
||||
|
||||
// this.Solve A * x = b
|
||||
Solve: function(out, bX, bY)
|
||||
{
|
||||
//float32 a11 = this.col1.x, a12 = this.col2.x, a21 = this.col1.y, a22 = this.col2.y;
|
||||
var a11 = this.col1.x;
|
||||
var a12 = this.col2.x;
|
||||
var a21 = this.col1.y;
|
||||
var a22 = this.col2.y;
|
||||
//float32 det = a11 * a22 - a12 * a21;
|
||||
var det = a11 * a22 - a12 * a21;
|
||||
//b2Settings.b2Assert(det != 0.0);
|
||||
det = 1.0 / det;
|
||||
out.x = det * (a22 * bX - a12 * bY);
|
||||
out.y = det * (a11 * bY - a21 * bX);
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
Abs: function()
|
||||
{
|
||||
this.col1.Abs();
|
||||
this.col2.Abs();
|
||||
},
|
||||
|
||||
col1: new b2Vec2(),
|
||||
col2: new b2Vec2()};
|
218
lib/box2d-js/js/box2d/common/math/b2Math.js
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2Math = Class.create();
|
||||
b2Math.prototype = {
|
||||
|
||||
|
||||
/*static public function b2InvSqrt(x)
|
||||
{
|
||||
float32 xhalf = 0.5f * x;
|
||||
int32 i = *(int32*)&x;
|
||||
i = 0x5f3759df - (i >> 1);
|
||||
x = *(float32*)&i;
|
||||
x = x * (1.5f - xhalf * x * x);
|
||||
return x;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// A * B
|
||||
|
||||
// A^T * B
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// b2Math.b2Random number in range [-1,1]
|
||||
|
||||
/*inline float32 b2Math.b2Random(float32 lo, float32 hi)
|
||||
{
|
||||
float32 r = (float32)rand();
|
||||
r /= RAND_MAX;
|
||||
r = (hi - lo) * r + lo;
|
||||
return r;
|
||||
}*/
|
||||
|
||||
// "Next Largest Power of 2
|
||||
// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
|
||||
// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
|
||||
// the same most significant 1, but all 1's below it. Adding 1 to that value yields the next
|
||||
// largest power of 2. For a 32-bit value:"
|
||||
|
||||
|
||||
|
||||
// Temp vector functions to reduce calls to 'new'
|
||||
/*static public var tempVec = new b2Vec2();
|
||||
|
||||
|
||||
static public var tempAABB = new b2AABB(); */
|
||||
|
||||
|
||||
|
||||
initialize: function() {}}
|
||||
b2Math.b2IsValid = function(x)
|
||||
{
|
||||
return isFinite(x);
|
||||
};
|
||||
b2Math.b2Dot = function(a, b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y;
|
||||
};
|
||||
b2Math.b2CrossVV = function(a, b)
|
||||
{
|
||||
return a.x * b.y - a.y * b.x;
|
||||
};
|
||||
b2Math.b2CrossVF = function(a, s)
|
||||
{
|
||||
var v = new b2Vec2(s * a.y, -s * a.x);
|
||||
return v;
|
||||
};
|
||||
b2Math.b2CrossFV = function(s, a)
|
||||
{
|
||||
var v = new b2Vec2(-s * a.y, s * a.x);
|
||||
return v;
|
||||
};
|
||||
b2Math.b2MulMV = function(A, v)
|
||||
{
|
||||
var u = new b2Vec2(A.col1.x * v.x + A.col2.x * v.y, A.col1.y * v.x + A.col2.y * v.y);
|
||||
return u;
|
||||
};
|
||||
b2Math.b2MulTMV = function(A, v)
|
||||
{
|
||||
var u = new b2Vec2(b2Math.b2Dot(v, A.col1), b2Math.b2Dot(v, A.col2));
|
||||
return u;
|
||||
};
|
||||
b2Math.AddVV = function(a, b)
|
||||
{
|
||||
var v = new b2Vec2(a.x + b.x, a.y + b.y);
|
||||
return v;
|
||||
};
|
||||
b2Math.SubtractVV = function(a, b)
|
||||
{
|
||||
var v = new b2Vec2(a.x - b.x, a.y - b.y);
|
||||
return v;
|
||||
};
|
||||
b2Math.MulFV = function(s, a)
|
||||
{
|
||||
var v = new b2Vec2(s * a.x, s * a.y);
|
||||
return v;
|
||||
};
|
||||
b2Math.AddMM = function(A, B)
|
||||
{
|
||||
var C = new b2Mat22(0, b2Math.AddVV(A.col1, B.col1), b2Math.AddVV(A.col2, B.col2));
|
||||
return C;
|
||||
};
|
||||
b2Math.b2MulMM = function(A, B)
|
||||
{
|
||||
var C = new b2Mat22(0, b2Math.b2MulMV(A, B.col1), b2Math.b2MulMV(A, B.col2));
|
||||
return C;
|
||||
};
|
||||
b2Math.b2MulTMM = function(A, B)
|
||||
{
|
||||
var c1 = new b2Vec2(b2Math.b2Dot(A.col1, B.col1), b2Math.b2Dot(A.col2, B.col1));
|
||||
var c2 = new b2Vec2(b2Math.b2Dot(A.col1, B.col2), b2Math.b2Dot(A.col2, B.col2));
|
||||
var C = new b2Mat22(0, c1, c2);
|
||||
return C;
|
||||
};
|
||||
b2Math.b2Abs = function(a)
|
||||
{
|
||||
return a > 0.0 ? a : -a;
|
||||
};
|
||||
b2Math.b2AbsV = function(a)
|
||||
{
|
||||
var b = new b2Vec2(b2Math.b2Abs(a.x), b2Math.b2Abs(a.y));
|
||||
return b;
|
||||
};
|
||||
b2Math.b2AbsM = function(A)
|
||||
{
|
||||
var B = new b2Mat22(0, b2Math.b2AbsV(A.col1), b2Math.b2AbsV(A.col2));
|
||||
return B;
|
||||
};
|
||||
b2Math.b2Min = function(a, b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
};
|
||||
b2Math.b2MinV = function(a, b)
|
||||
{
|
||||
var c = new b2Vec2(b2Math.b2Min(a.x, b.x), b2Math.b2Min(a.y, b.y));
|
||||
return c;
|
||||
};
|
||||
b2Math.b2Max = function(a, b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
};
|
||||
b2Math.b2MaxV = function(a, b)
|
||||
{
|
||||
var c = new b2Vec2(b2Math.b2Max(a.x, b.x), b2Math.b2Max(a.y, b.y));
|
||||
return c;
|
||||
};
|
||||
b2Math.b2Clamp = function(a, low, high)
|
||||
{
|
||||
return b2Math.b2Max(low, b2Math.b2Min(a, high));
|
||||
};
|
||||
b2Math.b2ClampV = function(a, low, high)
|
||||
{
|
||||
return b2Math.b2MaxV(low, b2Math.b2MinV(a, high));
|
||||
};
|
||||
b2Math.b2Swap = function(a, b)
|
||||
{
|
||||
var tmp = a[0];
|
||||
a[0] = b[0];
|
||||
b[0] = tmp;
|
||||
};
|
||||
b2Math.b2Random = function()
|
||||
{
|
||||
return Math.random() * 2 - 1;
|
||||
};
|
||||
b2Math.b2NextPowerOfTwo = function(x)
|
||||
{
|
||||
x |= (x >> 1) & 0x7FFFFFFF;
|
||||
x |= (x >> 2) & 0x3FFFFFFF;
|
||||
x |= (x >> 4) & 0x0FFFFFFF;
|
||||
x |= (x >> 8) & 0x00FFFFFF;
|
||||
x |= (x >> 16)& 0x0000FFFF;
|
||||
return x + 1;
|
||||
};
|
||||
b2Math.b2IsPowerOfTwo = function(x)
|
||||
{
|
||||
var result = x > 0 && (x & (x - 1)) == 0;
|
||||
return result;
|
||||
};
|
||||
b2Math.tempVec2 = new b2Vec2();
|
||||
b2Math.tempVec3 = new b2Vec2();
|
||||
b2Math.tempVec4 = new b2Vec2();
|
||||
b2Math.tempVec5 = new b2Vec2();
|
||||
b2Math.tempMat = new b2Mat22();
|
131
lib/box2d-js/js/box2d/common/math/b2Vec2.js
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// b2Vec2 has no constructor so that it
|
||||
// can be placed in a union.
|
||||
var b2Vec2 = Class.create();
|
||||
b2Vec2.prototype =
|
||||
{
|
||||
initialize: function(x_, y_) {this.x=x_; this.y=y_;},
|
||||
|
||||
SetZero: function() { this.x = 0.0; this.y = 0.0; },
|
||||
Set: function(x_, y_) {this.x=x_; this.y=y_;},
|
||||
SetV: function(v) {this.x=v.x; this.y=v.y;},
|
||||
|
||||
Negative: function(){ return new b2Vec2(-this.x, -this.y); },
|
||||
|
||||
|
||||
Copy: function(){
|
||||
return new b2Vec2(this.x,this.y);
|
||||
},
|
||||
|
||||
Add: function(v)
|
||||
{
|
||||
this.x += v.x; this.y += v.y;
|
||||
},
|
||||
|
||||
Subtract: function(v)
|
||||
{
|
||||
this.x -= v.x; this.y -= v.y;
|
||||
},
|
||||
|
||||
Multiply: function(a)
|
||||
{
|
||||
this.x *= a; this.y *= a;
|
||||
},
|
||||
|
||||
MulM: function(A)
|
||||
{
|
||||
var tX = this.x;
|
||||
this.x = A.col1.x * tX + A.col2.x * this.y;
|
||||
this.y = A.col1.y * tX + A.col2.y * this.y;
|
||||
},
|
||||
|
||||
MulTM: function(A)
|
||||
{
|
||||
var tX = b2Math.b2Dot(this, A.col1);
|
||||
this.y = b2Math.b2Dot(this, A.col2);
|
||||
this.x = tX;
|
||||
},
|
||||
|
||||
CrossVF: function(s)
|
||||
{
|
||||
var tX = this.x;
|
||||
this.x = s * this.y;
|
||||
this.y = -s * tX;
|
||||
},
|
||||
|
||||
CrossFV: function(s)
|
||||
{
|
||||
var tX = this.x;
|
||||
this.x = -s * this.y;
|
||||
this.y = s * tX;
|
||||
},
|
||||
|
||||
MinV: function(b)
|
||||
{
|
||||
this.x = this.x < b.x ? this.x : b.x;
|
||||
this.y = this.y < b.y ? this.y : b.y;
|
||||
},
|
||||
|
||||
MaxV: function(b)
|
||||
{
|
||||
this.x = this.x > b.x ? this.x : b.x;
|
||||
this.y = this.y > b.y ? this.y : b.y;
|
||||
},
|
||||
|
||||
Abs: function()
|
||||
{
|
||||
this.x = Math.abs(this.x);
|
||||
this.y = Math.abs(this.y);
|
||||
},
|
||||
|
||||
Length: function()
|
||||
{
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
||||
},
|
||||
|
||||
Normalize: function()
|
||||
{
|
||||
var length = this.Length();
|
||||
if (length < Number.MIN_VALUE)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
var invLength = 1.0 / length;
|
||||
this.x *= invLength;
|
||||
this.y *= invLength;
|
||||
|
||||
return length;
|
||||
},
|
||||
|
||||
IsValid: function()
|
||||
{
|
||||
return b2Math.b2IsValid(this.x) && b2Math.b2IsValid(this.y);
|
||||
},
|
||||
|
||||
x: null,
|
||||
y: null};
|
||||
b2Vec2.Make = function(x_, y_)
|
||||
{
|
||||
return new b2Vec2(x_, y_);
|
||||
};
|
469
lib/box2d-js/js/box2d/dynamics/b2Body.js
Normal file
@ -0,0 +1,469 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// A rigid body. Internal computation are done in terms
|
||||
// of the center of mass position. The center of mass may
|
||||
// be offset from the body's origin.
|
||||
var b2Body = Class.create();
|
||||
b2Body.prototype =
|
||||
{
|
||||
// Set the position of the body's origin and rotation (radians).
|
||||
// This breaks any contacts and wakes the other bodies.
|
||||
SetOriginPosition: function(position, rotation){
|
||||
if (this.IsFrozen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.m_rotation = rotation;
|
||||
this.m_R.Set(this.m_rotation);
|
||||
this.m_position = b2Math.AddVV(position , b2Math.b2MulMV(this.m_R, this.m_center));
|
||||
|
||||
this.m_position0.SetV(this.m_position);
|
||||
this.m_rotation0 = this.m_rotation;
|
||||
|
||||
for (var s = this.m_shapeList; s != null; s = s.m_next)
|
||||
{
|
||||
s.Synchronize(this.m_position, this.m_R, this.m_position, this.m_R);
|
||||
}
|
||||
|
||||
this.m_world.m_broadPhase.Commit();
|
||||
},
|
||||
|
||||
// Get the position of the body's origin. The body's origin does not
|
||||
// necessarily coincide with the center of mass. It depends on how the
|
||||
// shapes are created.
|
||||
GetOriginPosition: function(){
|
||||
return b2Math.SubtractVV(this.m_position, b2Math.b2MulMV(this.m_R, this.m_center));
|
||||
},
|
||||
|
||||
// Set the position of the body's center of mass and rotation (radians).
|
||||
// This breaks any contacts and wakes the other bodies.
|
||||
SetCenterPosition: function(position, rotation){
|
||||
if (this.IsFrozen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.m_rotation = rotation;
|
||||
this.m_R.Set(this.m_rotation);
|
||||
this.m_position.SetV( position );
|
||||
|
||||
this.m_position0.SetV(this.m_position);
|
||||
this.m_rotation0 = this.m_rotation;
|
||||
|
||||
for (var s = this.m_shapeList; s != null; s = s.m_next)
|
||||
{
|
||||
s.Synchronize(this.m_position, this.m_R, this.m_position, this.m_R);
|
||||
}
|
||||
|
||||
this.m_world.m_broadPhase.Commit();
|
||||
},
|
||||
|
||||
// Get the position of the body's center of mass. The body's center of mass
|
||||
// does not necessarily coincide with the body's origin. It depends on how the
|
||||
// shapes are created.
|
||||
GetCenterPosition: function(){
|
||||
return this.m_position;
|
||||
},
|
||||
|
||||
// Get the rotation in radians.
|
||||
GetRotation: function(){
|
||||
return this.m_rotation;
|
||||
},
|
||||
|
||||
GetRotationMatrix: function(){
|
||||
return this.m_R;
|
||||
},
|
||||
|
||||
// Set/Get the linear velocity of the center of mass.
|
||||
SetLinearVelocity: function(v){
|
||||
this.m_linearVelocity.SetV(v);
|
||||
},
|
||||
GetLinearVelocity: function(){
|
||||
return this.m_linearVelocity;
|
||||
},
|
||||
|
||||
// Set/Get the angular velocity.
|
||||
SetAngularVelocity: function(w){
|
||||
this.m_angularVelocity = w;
|
||||
},
|
||||
GetAngularVelocity: function(){
|
||||
return this.m_angularVelocity;
|
||||
},
|
||||
|
||||
// Apply a force at a world point. Additive.
|
||||
ApplyForce: function(force, point)
|
||||
{
|
||||
if (this.IsSleeping() == false)
|
||||
{
|
||||
this.m_force.Add( force );
|
||||
this.m_torque += b2Math.b2CrossVV(b2Math.SubtractVV(point, this.m_position), force);
|
||||
}
|
||||
},
|
||||
|
||||
// Apply a torque. Additive.
|
||||
ApplyTorque: function(torque)
|
||||
{
|
||||
if (this.IsSleeping() == false)
|
||||
{
|
||||
this.m_torque += torque;
|
||||
}
|
||||
},
|
||||
|
||||
// Apply an impulse at a point. This immediately modifies the velocity.
|
||||
ApplyImpulse: function(impulse, point)
|
||||
{
|
||||
if (this.IsSleeping() == false)
|
||||
{
|
||||
this.m_linearVelocity.Add( b2Math.MulFV(this.m_invMass, impulse) );
|
||||
this.m_angularVelocity += ( this.m_invI * b2Math.b2CrossVV( b2Math.SubtractVV(point, this.m_position), impulse) );
|
||||
}
|
||||
},
|
||||
|
||||
GetMass: function(){
|
||||
return this.m_mass;
|
||||
},
|
||||
|
||||
GetInertia: function(){
|
||||
return this.m_I;
|
||||
},
|
||||
|
||||
// Get the world coordinates of a point give the local coordinates
|
||||
// relative to the body's center of mass.
|
||||
GetWorldPoint: function(localPoint){
|
||||
return b2Math.AddVV(this.m_position , b2Math.b2MulMV(this.m_R, localPoint));
|
||||
},
|
||||
|
||||
// Get the world coordinates of a vector given the local coordinates.
|
||||
GetWorldVector: function(localVector){
|
||||
return b2Math.b2MulMV(this.m_R, localVector);
|
||||
},
|
||||
|
||||
// Returns a local point relative to the center of mass given a world point.
|
||||
GetLocalPoint: function(worldPoint){
|
||||
return b2Math.b2MulTMV(this.m_R, b2Math.SubtractVV(worldPoint, this.m_position));
|
||||
},
|
||||
|
||||
// Returns a local vector given a world vector.
|
||||
GetLocalVector: function(worldVector){
|
||||
return b2Math.b2MulTMV(this.m_R, worldVector);
|
||||
},
|
||||
|
||||
// Is this body static (immovable)?
|
||||
IsStatic: function(){
|
||||
return (this.m_flags & b2Body.e_staticFlag) == b2Body.e_staticFlag;
|
||||
},
|
||||
|
||||
IsFrozen: function()
|
||||
{
|
||||
return (this.m_flags & b2Body.e_frozenFlag) == b2Body.e_frozenFlag;
|
||||
},
|
||||
|
||||
// Is this body sleeping (not simulating).
|
||||
IsSleeping: function(){
|
||||
return (this.m_flags & b2Body.e_sleepFlag) == b2Body.e_sleepFlag;
|
||||
},
|
||||
|
||||
// You can disable sleeping on this particular body.
|
||||
AllowSleeping: function(flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
this.m_flags |= b2Body.e_allowSleepFlag;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_flags &= ~b2Body.e_allowSleepFlag;
|
||||
this.WakeUp();
|
||||
}
|
||||
},
|
||||
|
||||
// Wake up this body so it will begin simulating.
|
||||
WakeUp: function(){
|
||||
this.m_flags &= ~b2Body.e_sleepFlag;
|
||||
this.m_sleepTime = 0.0;
|
||||
},
|
||||
|
||||
// Get the list of all shapes attached to this body.
|
||||
GetShapeList: function(){
|
||||
return this.m_shapeList;
|
||||
},
|
||||
|
||||
GetContactList: function()
|
||||
{
|
||||
return this.m_contactList;
|
||||
},
|
||||
|
||||
GetJointList: function()
|
||||
{
|
||||
return this.m_jointList;
|
||||
},
|
||||
|
||||
// Get the next body in the world's body list.
|
||||
GetNext: function(){
|
||||
return this.m_next;
|
||||
},
|
||||
|
||||
GetUserData: function(){
|
||||
return this.m_userData;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(bd, world){
|
||||
// initialize instance variables for references
|
||||
this.sMat0 = new b2Mat22();
|
||||
this.m_position = new b2Vec2();
|
||||
this.m_R = new b2Mat22(0);
|
||||
this.m_position0 = new b2Vec2();
|
||||
//
|
||||
|
||||
var i = 0;
|
||||
var sd;
|
||||
var massData;
|
||||
|
||||
this.m_flags = 0;
|
||||
this.m_position.SetV( bd.position );
|
||||
this.m_rotation = bd.rotation;
|
||||
this.m_R.Set(this.m_rotation);
|
||||
this.m_position0.SetV(this.m_position);
|
||||
this.m_rotation0 = this.m_rotation;
|
||||
this.m_world = world;
|
||||
|
||||
this.m_linearDamping = b2Math.b2Clamp(1.0 - bd.linearDamping, 0.0, 1.0);
|
||||
this.m_angularDamping = b2Math.b2Clamp(1.0 - bd.angularDamping, 0.0, 1.0);
|
||||
|
||||
this.m_force = new b2Vec2(0.0, 0.0);
|
||||
this.m_torque = 0.0;
|
||||
|
||||
this.m_mass = 0.0;
|
||||
|
||||
var massDatas = new Array(b2Settings.b2_maxShapesPerBody);
|
||||
for (i = 0; i < b2Settings.b2_maxShapesPerBody; i++){
|
||||
massDatas[i] = new b2MassData();
|
||||
}
|
||||
|
||||
// Compute the shape mass properties, the bodies total mass and COM.
|
||||
this.m_shapeCount = 0;
|
||||
this.m_center = new b2Vec2(0.0, 0.0);
|
||||
for (i = 0; i < b2Settings.b2_maxShapesPerBody; ++i)
|
||||
{
|
||||
sd = bd.shapes[i];
|
||||
if (sd == null) break;
|
||||
massData = massDatas[ i ];
|
||||
sd.ComputeMass(massData);
|
||||
this.m_mass += massData.mass;
|
||||
//this.m_center += massData->mass * (sd->localPosition + massData->center);
|
||||
this.m_center.x += massData.mass * (sd.localPosition.x + massData.center.x);
|
||||
this.m_center.y += massData.mass * (sd.localPosition.y + massData.center.y);
|
||||
++this.m_shapeCount;
|
||||
}
|
||||
|
||||
// Compute center of mass, and shift the origin to the COM.
|
||||
if (this.m_mass > 0.0)
|
||||
{
|
||||
this.m_center.Multiply( 1.0 / this.m_mass );
|
||||
this.m_position.Add( b2Math.b2MulMV(this.m_R, this.m_center) );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_flags |= b2Body.e_staticFlag;
|
||||
}
|
||||
|
||||
// Compute the moment of inertia.
|
||||
this.m_I = 0.0;
|
||||
for (i = 0; i < this.m_shapeCount; ++i)
|
||||
{
|
||||
sd = bd.shapes[i];
|
||||
massData = massDatas[ i ];
|
||||
this.m_I += massData.I;
|
||||
var r = b2Math.SubtractVV( b2Math.AddVV(sd.localPosition, massData.center), this.m_center );
|
||||
this.m_I += massData.mass * b2Math.b2Dot(r, r);
|
||||
}
|
||||
|
||||
if (this.m_mass > 0.0)
|
||||
{
|
||||
this.m_invMass = 1.0 / this.m_mass;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_invMass = 0.0;
|
||||
}
|
||||
|
||||
if (this.m_I > 0.0 && bd.preventRotation == false)
|
||||
{
|
||||
this.m_invI = 1.0 / this.m_I;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_I = 0.0;
|
||||
this.m_invI = 0.0;
|
||||
}
|
||||
|
||||
// Compute the center of mass velocity.
|
||||
this.m_linearVelocity = b2Math.AddVV(bd.linearVelocity, b2Math.b2CrossFV(bd.angularVelocity, this.m_center));
|
||||
this.m_angularVelocity = bd.angularVelocity;
|
||||
|
||||
this.m_jointList = null;
|
||||
this.m_contactList = null;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
|
||||
// Create the shapes.
|
||||
this.m_shapeList = null;
|
||||
for (i = 0; i < this.m_shapeCount; ++i)
|
||||
{
|
||||
sd = bd.shapes[i];
|
||||
var shape = b2Shape.Create(sd, this, this.m_center);
|
||||
shape.m_next = this.m_shapeList;
|
||||
this.m_shapeList = shape;
|
||||
}
|
||||
|
||||
this.m_sleepTime = 0.0;
|
||||
if (bd.allowSleep)
|
||||
{
|
||||
this.m_flags |= b2Body.e_allowSleepFlag;
|
||||
}
|
||||
if (bd.isSleeping)
|
||||
{
|
||||
this.m_flags |= b2Body.e_sleepFlag;
|
||||
}
|
||||
|
||||
if ((this.m_flags & b2Body.e_sleepFlag) || this.m_invMass == 0.0)
|
||||
{
|
||||
this.m_linearVelocity.Set(0.0, 0.0);
|
||||
this.m_angularVelocity = 0.0;
|
||||
}
|
||||
|
||||
this.m_userData = bd.userData;
|
||||
},
|
||||
// does not support destructors
|
||||
/*~b2Body(){
|
||||
b2Shape* s = this.m_shapeList;
|
||||
while (s)
|
||||
{
|
||||
b2Shape* s0 = s;
|
||||
s = s->this.m_next;
|
||||
|
||||
b2Shape::this.Destroy(s0);
|
||||
}
|
||||
}*/
|
||||
|
||||
Destroy: function(){
|
||||
var s = this.m_shapeList;
|
||||
while (s)
|
||||
{
|
||||
var s0 = s;
|
||||
s = s.m_next;
|
||||
|
||||
b2Shape.Destroy(s0);
|
||||
}
|
||||
},
|
||||
|
||||
// Temp mat
|
||||
sMat0: new b2Mat22(),
|
||||
SynchronizeShapes: function(){
|
||||
//b2Mat22 R0(this.m_rotation0);
|
||||
this.sMat0.Set(this.m_rotation0);
|
||||
for (var s = this.m_shapeList; s != null; s = s.m_next)
|
||||
{
|
||||
s.Synchronize(this.m_position0, this.sMat0, this.m_position, this.m_R);
|
||||
}
|
||||
},
|
||||
|
||||
QuickSyncShapes: function(){
|
||||
for (var s = this.m_shapeList; s != null; s = s.m_next)
|
||||
{
|
||||
s.QuickSync(this.m_position, this.m_R);
|
||||
}
|
||||
},
|
||||
|
||||
// This is used to prevent connected bodies from colliding.
|
||||
// It may lie, depending on the collideConnected flag.
|
||||
IsConnected: function(other){
|
||||
for (var jn = this.m_jointList; jn != null; jn = jn.next)
|
||||
{
|
||||
if (jn.other == other)
|
||||
return jn.joint.m_collideConnected == false;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
Freeze: function(){
|
||||
this.m_flags |= b2Body.e_frozenFlag;
|
||||
this.m_linearVelocity.SetZero();
|
||||
this.m_angularVelocity = 0.0;
|
||||
|
||||
for (var s = this.m_shapeList; s != null; s = s.m_next)
|
||||
{
|
||||
s.DestroyProxy();
|
||||
}
|
||||
},
|
||||
|
||||
m_flags: 0,
|
||||
|
||||
m_position: new b2Vec2(),
|
||||
m_rotation: null,
|
||||
m_R: new b2Mat22(0),
|
||||
|
||||
// Conservative advancement data.
|
||||
m_position0: new b2Vec2(),
|
||||
m_rotation0: null,
|
||||
|
||||
m_linearVelocity: null,
|
||||
m_angularVelocity: null,
|
||||
|
||||
m_force: null,
|
||||
m_torque: null,
|
||||
|
||||
m_center: null,
|
||||
|
||||
m_world: null,
|
||||
m_prev: null,
|
||||
m_next: null,
|
||||
|
||||
m_shapeList: null,
|
||||
m_shapeCount: 0,
|
||||
|
||||
m_jointList: null,
|
||||
m_contactList: null,
|
||||
|
||||
m_mass: null,
|
||||
m_invMass: null,
|
||||
m_I: null,
|
||||
m_invI: null,
|
||||
|
||||
m_linearDamping: null,
|
||||
m_angularDamping: null,
|
||||
|
||||
m_sleepTime: null,
|
||||
|
||||
m_userData: null};
|
||||
b2Body.e_staticFlag = 0x0001;
|
||||
b2Body.e_frozenFlag = 0x0002;
|
||||
b2Body.e_islandFlag = 0x0004;
|
||||
b2Body.e_sleepFlag = 0x0008;
|
||||
b2Body.e_allowSleepFlag = 0x0010;
|
||||
b2Body.e_destroyFlag = 0x0020;
|
69
lib/box2d-js/js/box2d/dynamics/b2BodyDef.js
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2BodyDef = Class.create();
|
||||
b2BodyDef.prototype =
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// initialize instance variables for references
|
||||
this.shapes = new Array();
|
||||
//
|
||||
|
||||
this.userData = null;
|
||||
for (var i = 0; i < b2Settings.b2_maxShapesPerBody; i++){
|
||||
this.shapes[i] = null;
|
||||
}
|
||||
this.position = new b2Vec2(0.0, 0.0);
|
||||
this.rotation = 0.0;
|
||||
this.linearVelocity = new b2Vec2(0.0, 0.0);
|
||||
this.angularVelocity = 0.0;
|
||||
this.linearDamping = 0.0;
|
||||
this.angularDamping = 0.0;
|
||||
this.allowSleep = true;
|
||||
this.isSleeping = false;
|
||||
this.preventRotation = false;
|
||||
},
|
||||
|
||||
userData: null,
|
||||
shapes: new Array(),
|
||||
position: null,
|
||||
rotation: null,
|
||||
linearVelocity: null,
|
||||
angularVelocity: null,
|
||||
linearDamping: null,
|
||||
angularDamping: null,
|
||||
allowSleep: null,
|
||||
isSleeping: null,
|
||||
preventRotation: null,
|
||||
|
||||
AddShape: function(shape)
|
||||
{
|
||||
for (var i = 0; i < b2Settings.b2_maxShapesPerBody; ++i)
|
||||
{
|
||||
if (this.shapes[i] == null)
|
||||
{
|
||||
this.shapes[i] = shape;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}};
|
42
lib/box2d-js/js/box2d/dynamics/b2CollisionFilter.js
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2CollisionFilter = Class.create();
|
||||
b2CollisionFilter.prototype =
|
||||
{
|
||||
|
||||
// Return true if contact calculations should be performed between these two shapes.
|
||||
ShouldCollide: function(shape1, shape2){
|
||||
if (shape1.m_groupIndex == shape2.m_groupIndex && shape1.m_groupIndex != 0)
|
||||
{
|
||||
return shape1.m_groupIndex > 0;
|
||||
}
|
||||
|
||||
var collide = (shape1.m_maskBits & shape2.m_categoryBits) != 0 && (shape1.m_categoryBits & shape2.m_maskBits) != 0;
|
||||
return collide;
|
||||
},
|
||||
|
||||
|
||||
initialize: function() {}};
|
||||
b2CollisionFilter.b2_defaultFilter = new b2CollisionFilter;
|
337
lib/box2d-js/js/box2d/dynamics/b2ContactManager.js
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2ContactManager = Class.create();
|
||||
Object.extend(b2ContactManager.prototype, b2PairCallback.prototype);
|
||||
Object.extend(b2ContactManager.prototype,
|
||||
{
|
||||
initialize: function(){
|
||||
// The constructor for b2PairCallback
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_nullContact = new b2NullContact();
|
||||
//
|
||||
|
||||
this.m_world = null;
|
||||
this.m_destroyImmediate = false;
|
||||
},
|
||||
|
||||
// This is a callback from the broadphase when two AABB proxies begin
|
||||
// to overlap. We create a b2Contact to manage the narrow phase.
|
||||
PairAdded: function(proxyUserData1, proxyUserData2){
|
||||
var shape1 = proxyUserData1;
|
||||
var shape2 = proxyUserData2;
|
||||
|
||||
var body1 = shape1.m_body;
|
||||
var body2 = shape2.m_body;
|
||||
|
||||
if (body1.IsStatic() && body2.IsStatic())
|
||||
{
|
||||
return this.m_nullContact;
|
||||
}
|
||||
|
||||
if (shape1.m_body == shape2.m_body)
|
||||
{
|
||||
return this.m_nullContact;
|
||||
}
|
||||
|
||||
if (body2.IsConnected(body1))
|
||||
{
|
||||
return this.m_nullContact;
|
||||
}
|
||||
|
||||
if (this.m_world.m_filter != null && this.m_world.m_filter.ShouldCollide(shape1, shape2) == false)
|
||||
{
|
||||
return this.m_nullContact;
|
||||
}
|
||||
|
||||
// Ensure that body2 is dynamic (body1 is static or dynamic).
|
||||
if (body2.m_invMass == 0.0)
|
||||
{
|
||||
var tempShape = shape1;
|
||||
shape1 = shape2;
|
||||
shape2 = tempShape;
|
||||
//b2Math.b2Swap(shape1, shape2);
|
||||
var tempBody = body1;
|
||||
body1 = body2;
|
||||
body2 = tempBody;
|
||||
//b2Math.b2Swap(body1, body2);
|
||||
}
|
||||
|
||||
// Call the factory.
|
||||
var contact = b2Contact.Create(shape1, shape2, this.m_world.m_blockAllocator);
|
||||
|
||||
if (contact == null)
|
||||
{
|
||||
return this.m_nullContact;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert into the world.
|
||||
contact.m_prev = null;
|
||||
contact.m_next = this.m_world.m_contactList;
|
||||
if (this.m_world.m_contactList != null)
|
||||
{
|
||||
this.m_world.m_contactList.m_prev = contact;
|
||||
}
|
||||
this.m_world.m_contactList = contact;
|
||||
this.m_world.m_contactCount++;
|
||||
}
|
||||
|
||||
return contact;
|
||||
},
|
||||
|
||||
// This is a callback from the broadphase when two AABB proxies cease
|
||||
// to overlap. We destroy the b2Contact.
|
||||
PairRemoved: function(proxyUserData1, proxyUserData2, pairUserData){
|
||||
|
||||
if (pairUserData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var c = pairUserData;
|
||||
if (c != this.m_nullContact)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_world.m_contactCount > 0);
|
||||
if (this.m_destroyImmediate == true)
|
||||
{
|
||||
this.DestroyContact(c);
|
||||
c = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
c.m_flags |= b2Contact.e_destroyFlag;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
DestroyContact: function(c)
|
||||
{
|
||||
|
||||
//b2Settings.b2Assert(this.m_world.m_contactCount > 0);
|
||||
|
||||
// Remove from the world.
|
||||
if (c.m_prev)
|
||||
{
|
||||
c.m_prev.m_next = c.m_next;
|
||||
}
|
||||
|
||||
if (c.m_next)
|
||||
{
|
||||
c.m_next.m_prev = c.m_prev;
|
||||
}
|
||||
|
||||
if (c == this.m_world.m_contactList)
|
||||
{
|
||||
this.m_world.m_contactList = c.m_next;
|
||||
}
|
||||
|
||||
// If there are contact points, then disconnect from the island graph.
|
||||
if (c.GetManifoldCount() > 0)
|
||||
{
|
||||
var body1 = c.m_shape1.m_body;
|
||||
var body2 = c.m_shape2.m_body;
|
||||
var node1 = c.m_node1;
|
||||
var node2 = c.m_node2;
|
||||
|
||||
// Wake up touching bodies.
|
||||
body1.WakeUp();
|
||||
body2.WakeUp();
|
||||
|
||||
// Remove from body 1
|
||||
if (node1.prev)
|
||||
{
|
||||
node1.prev.next = node1.next;
|
||||
}
|
||||
|
||||
if (node1.next)
|
||||
{
|
||||
node1.next.prev = node1.prev;
|
||||
}
|
||||
|
||||
if (node1 == body1.m_contactList)
|
||||
{
|
||||
body1.m_contactList = node1.next;
|
||||
}
|
||||
|
||||
node1.prev = null;
|
||||
node1.next = null;
|
||||
|
||||
// Remove from body 2
|
||||
if (node2.prev)
|
||||
{
|
||||
node2.prev.next = node2.next;
|
||||
}
|
||||
|
||||
if (node2.next)
|
||||
{
|
||||
node2.next.prev = node2.prev;
|
||||
}
|
||||
|
||||
if (node2 == body2.m_contactList)
|
||||
{
|
||||
body2.m_contactList = node2.next;
|
||||
}
|
||||
|
||||
node2.prev = null;
|
||||
node2.next = null;
|
||||
}
|
||||
|
||||
// Call the factory.
|
||||
b2Contact.Destroy(c, this.m_world.m_blockAllocator);
|
||||
--this.m_world.m_contactCount;
|
||||
},
|
||||
|
||||
|
||||
// Destroy any contacts marked for deferred destruction.
|
||||
CleanContactList: function()
|
||||
{
|
||||
var c = this.m_world.m_contactList;
|
||||
while (c != null)
|
||||
{
|
||||
var c0 = c;
|
||||
c = c.m_next;
|
||||
|
||||
if (c0.m_flags & b2Contact.e_destroyFlag)
|
||||
{
|
||||
this.DestroyContact(c0);
|
||||
c0 = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// This is the top level collision call for the time step. Here
|
||||
// all the narrow phase collision is processed for the world
|
||||
// contact list.
|
||||
Collide: function()
|
||||
{
|
||||
var body1;
|
||||
var body2;
|
||||
var node1;
|
||||
var node2;
|
||||
|
||||
for (var c = this.m_world.m_contactList; c != null; c = c.m_next)
|
||||
{
|
||||
if (c.m_shape1.m_body.IsSleeping() &&
|
||||
c.m_shape2.m_body.IsSleeping())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var oldCount = c.GetManifoldCount();
|
||||
c.Evaluate();
|
||||
|
||||
var newCount = c.GetManifoldCount();
|
||||
|
||||
if (oldCount == 0 && newCount > 0)
|
||||
{
|
||||
//b2Settings.b2Assert(c.GetManifolds().pointCount > 0);
|
||||
|
||||
// Connect to island graph.
|
||||
body1 = c.m_shape1.m_body;
|
||||
body2 = c.m_shape2.m_body;
|
||||
node1 = c.m_node1;
|
||||
node2 = c.m_node2;
|
||||
|
||||
// Connect to body 1
|
||||
node1.contact = c;
|
||||
node1.other = body2;
|
||||
|
||||
node1.prev = null;
|
||||
node1.next = body1.m_contactList;
|
||||
if (node1.next != null)
|
||||
{
|
||||
node1.next.prev = c.m_node1;
|
||||
}
|
||||
body1.m_contactList = c.m_node1;
|
||||
|
||||
// Connect to body 2
|
||||
node2.contact = c;
|
||||
node2.other = body1;
|
||||
|
||||
node2.prev = null;
|
||||
node2.next = body2.m_contactList;
|
||||
if (node2.next != null)
|
||||
{
|
||||
node2.next.prev = node2;
|
||||
}
|
||||
body2.m_contactList = node2;
|
||||
}
|
||||
else if (oldCount > 0 && newCount == 0)
|
||||
{
|
||||
// Disconnect from island graph.
|
||||
body1 = c.m_shape1.m_body;
|
||||
body2 = c.m_shape2.m_body;
|
||||
node1 = c.m_node1;
|
||||
node2 = c.m_node2;
|
||||
|
||||
// Remove from body 1
|
||||
if (node1.prev)
|
||||
{
|
||||
node1.prev.next = node1.next;
|
||||
}
|
||||
|
||||
if (node1.next)
|
||||
{
|
||||
node1.next.prev = node1.prev;
|
||||
}
|
||||
|
||||
if (node1 == body1.m_contactList)
|
||||
{
|
||||
body1.m_contactList = node1.next;
|
||||
}
|
||||
|
||||
node1.prev = null;
|
||||
node1.next = null;
|
||||
|
||||
// Remove from body 2
|
||||
if (node2.prev)
|
||||
{
|
||||
node2.prev.next = node2.next;
|
||||
}
|
||||
|
||||
if (node2.next)
|
||||
{
|
||||
node2.next.prev = node2.prev;
|
||||
}
|
||||
|
||||
if (node2 == body2.m_contactList)
|
||||
{
|
||||
body2.m_contactList = node2.next;
|
||||
}
|
||||
|
||||
node2.prev = null;
|
||||
node2.next = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
m_world: null,
|
||||
|
||||
// This lets us provide broadphase proxy pair user data for
|
||||
// contacts that shouldn't exist.
|
||||
m_nullContact: new b2NullContact(),
|
||||
m_destroyImmediate: null});
|
||||
|
331
lib/box2d-js/js/box2d/dynamics/b2Island.js
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Position Correction Notes
|
||||
=========================
|
||||
I tried the several algorithms for position correction of the 2D revolute joint.
|
||||
I looked at these systems:
|
||||
- simple pendulum (1m diameter sphere on massless 5m stick) with initial angular velocity of 100 rad/s.
|
||||
- suspension bridge with 30 1m long planks of length 1m.
|
||||
- multi-link chain with 30 1m long links.
|
||||
|
||||
Here are the algorithms:
|
||||
|
||||
Baumgarte - A fraction of the position error is added to the velocity error. There is no
|
||||
separate position solver.
|
||||
|
||||
Pseudo Velocities - After the velocity solver and position integration,
|
||||
the position error, Jacobian, and effective mass are recomputed. Then
|
||||
the velocity constraints are solved with pseudo velocities and a fraction
|
||||
of the position error is added to the pseudo velocity error. The pseudo
|
||||
velocities are initialized to zero and there is no warm-starting. After
|
||||
the position solver, the pseudo velocities are added to the positions.
|
||||
This is also called the First Order World method or the Position LCP method.
|
||||
|
||||
Modified Nonlinear Gauss-Seidel (NGS) - Like Pseudo Velocities except the
|
||||
position error is re-computed for each constraint and the positions are updated
|
||||
after the constraint is solved. The radius vectors (aka Jacobians) are
|
||||
re-computed too (otherwise the algorithm has horrible instability). The pseudo
|
||||
velocity states are not needed because they are effectively zero at the beginning
|
||||
of each iteration. Since we have the current position error, we allow the
|
||||
iterations to terminate early if the error becomes smaller than b2_linearSlop.
|
||||
|
||||
Full NGS or just NGS - Like Modified NGS except the effective mass are re-computed
|
||||
each time a constraint is solved.
|
||||
|
||||
Here are the results:
|
||||
Baumgarte - this is the cheapest algorithm but it has some stability problems,
|
||||
especially with the bridge. The chain links separate easily close to the root
|
||||
and they jitter struggle to pull together. This is one of the most common
|
||||
methods in the field. The big drawback is that the position correction artificially
|
||||
affects the momentum, thus leading to instabilities and false bounce. I used a
|
||||
bias factor of 0.2. A larger bias factor makes the bridge less stable, a smaller
|
||||
factor makes joints and contacts more spongy.
|
||||
|
||||
Pseudo Velocities - the is more stable than the Baumgarte method. The bridge is
|
||||
stable. However, joints still separate with large angular velocities. Drag the
|
||||
simple pendulum in a circle quickly and the joint will separate. The chain separates
|
||||
easily and does not recover. I used a bias factor of 0.2. A larger value lead to
|
||||
the bridge collapsing when a heavy cube drops on it.
|
||||
|
||||
Modified NGS - this algorithm is better in some ways than Baumgarte and Pseudo
|
||||
Velocities, but in other ways it is worse. The bridge and chain are much more
|
||||
stable, but the simple pendulum goes unstable at high angular velocities.
|
||||
|
||||
Full NGS - stable in all tests. The joints display good stiffness. The bridge
|
||||
still sags, but this is better than infinite forces.
|
||||
|
||||
Recommendations
|
||||
Pseudo Velocities are not really worthwhile because the bridge and chain cannot
|
||||
recover from joint separation. In other cases the benefit over Baumgarte is small.
|
||||
|
||||
Modified NGS is not a robust method for the revolute joint due to the violent
|
||||
instability seen in the simple pendulum. Perhaps it is viable with other constraint
|
||||
types, especially scalar constraints where the effective mass is a scalar.
|
||||
|
||||
This leaves Baumgarte and Full NGS. Baumgarte has small, but manageable instabilities
|
||||
and is very fast. I don't think we can escape Baumgarte, especially in highly
|
||||
demanding cases where high constraint fidelity is not needed.
|
||||
|
||||
Full NGS is robust and easy on the eyes. I recommend this option for
|
||||
higher fidelity simulation and certainly for suspension bridges and long chains.
|
||||
Full NGS might be a good choice for ragdolls, especially motorized ragdolls where
|
||||
joint separation can be problematic. The number of NGS iterations can be reduced
|
||||
for better performance without harming robustness much.
|
||||
|
||||
Each joint in a can be handled differently in the position solver. So I recommend
|
||||
a system where the user can select the algorithm on a per joint basis. I would
|
||||
probably default to the slower Full NGS and let the user select the faster
|
||||
Baumgarte method in performance critical scenarios.
|
||||
*/
|
||||
|
||||
|
||||
var b2Island = Class.create();
|
||||
b2Island.prototype =
|
||||
{
|
||||
initialize: function(bodyCapacity, contactCapacity, jointCapacity, allocator)
|
||||
{
|
||||
var i = 0;
|
||||
|
||||
this.m_bodyCapacity = bodyCapacity;
|
||||
this.m_contactCapacity = contactCapacity;
|
||||
this.m_jointCapacity = jointCapacity;
|
||||
this.m_bodyCount = 0;
|
||||
this.m_contactCount = 0;
|
||||
this.m_jointCount = 0;
|
||||
|
||||
|
||||
//this.m_bodies = (b2Body**)allocator->Allocate(bodyCapacity * sizeof(b2Body*));
|
||||
this.m_bodies = new Array(bodyCapacity);
|
||||
for (i = 0; i < bodyCapacity; i++)
|
||||
this.m_bodies[i] = null;
|
||||
|
||||
//this.m_contacts = (b2Contact**)allocator->Allocate(contactCapacity * sizeof(b2Contact*));
|
||||
this.m_contacts = new Array(contactCapacity);
|
||||
for (i = 0; i < contactCapacity; i++)
|
||||
this.m_contacts[i] = null;
|
||||
|
||||
//this.m_joints = (b2Joint**)allocator->Allocate(jointCapacity * sizeof(b2Joint*));
|
||||
this.m_joints = new Array(jointCapacity);
|
||||
for (i = 0; i < jointCapacity; i++)
|
||||
this.m_joints[i] = null;
|
||||
|
||||
this.m_allocator = allocator;
|
||||
},
|
||||
//~b2Island();
|
||||
|
||||
Clear: function()
|
||||
{
|
||||
this.m_bodyCount = 0;
|
||||
this.m_contactCount = 0;
|
||||
this.m_jointCount = 0;
|
||||
},
|
||||
|
||||
Solve: function(step, gravity)
|
||||
{
|
||||
var i = 0;
|
||||
var b;
|
||||
|
||||
for (i = 0; i < this.m_bodyCount; ++i)
|
||||
{
|
||||
b = this.m_bodies[i];
|
||||
|
||||
if (b.m_invMass == 0.0)
|
||||
continue;
|
||||
|
||||
b.m_linearVelocity.Add( b2Math.MulFV (step.dt, b2Math.AddVV(gravity, b2Math.MulFV( b.m_invMass, b.m_force ) ) ) );
|
||||
b.m_angularVelocity += step.dt * b.m_invI * b.m_torque;
|
||||
|
||||
//b.m_linearVelocity *= b.m_linearDamping;
|
||||
b.m_linearVelocity.Multiply(b.m_linearDamping);
|
||||
b.m_angularVelocity *= b.m_angularDamping;
|
||||
|
||||
// Store positions for conservative advancement.
|
||||
b.m_position0.SetV(b.m_position);
|
||||
b.m_rotation0 = b.m_rotation;
|
||||
}
|
||||
|
||||
var contactSolver = new b2ContactSolver(this.m_contacts, this.m_contactCount, this.m_allocator);
|
||||
|
||||
// Pre-solve
|
||||
contactSolver.PreSolve();
|
||||
|
||||
for (i = 0; i < this.m_jointCount; ++i)
|
||||
{
|
||||
this.m_joints[i].PrepareVelocitySolver();
|
||||
}
|
||||
|
||||
// this.Solve velocity constraints.
|
||||
for (i = 0; i < step.iterations; ++i)
|
||||
{
|
||||
contactSolver.SolveVelocityConstraints();
|
||||
|
||||
for (var j = 0; j < this.m_jointCount; ++j)
|
||||
{
|
||||
this.m_joints[j].SolveVelocityConstraints(step);
|
||||
}
|
||||
}
|
||||
|
||||
// Integrate positions.
|
||||
for (i = 0; i < this.m_bodyCount; ++i)
|
||||
{
|
||||
b = this.m_bodies[i];
|
||||
|
||||
if (b.m_invMass == 0.0)
|
||||
continue;
|
||||
|
||||
//b.m_position.Add( b2Math.MulFV (step.dt, b.m_linearVelocity) );
|
||||
b.m_position.x += step.dt * b.m_linearVelocity.x;
|
||||
b.m_position.y += step.dt * b.m_linearVelocity.y;
|
||||
b.m_rotation += step.dt * b.m_angularVelocity;
|
||||
|
||||
b.m_R.Set(b.m_rotation);
|
||||
}
|
||||
|
||||
for (i = 0; i < this.m_jointCount; ++i)
|
||||
{
|
||||
this.m_joints[i].PreparePositionSolver();
|
||||
}
|
||||
|
||||
// this.Solve position constraints.
|
||||
if (b2World.s_enablePositionCorrection)
|
||||
{
|
||||
for (b2Island.m_positionIterationCount = 0; b2Island.m_positionIterationCount < step.iterations; ++b2Island.m_positionIterationCount)
|
||||
{
|
||||
var contactsOkay = contactSolver.SolvePositionConstraints(b2Settings.b2_contactBaumgarte);
|
||||
|
||||
var jointsOkay = true;
|
||||
for (i = 0; i < this.m_jointCount; ++i)
|
||||
{
|
||||
var jointOkay = this.m_joints[i].SolvePositionConstraints();
|
||||
jointsOkay = jointsOkay && jointOkay;
|
||||
}
|
||||
|
||||
if (contactsOkay && jointsOkay)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Post-solve.
|
||||
contactSolver.PostSolve();
|
||||
|
||||
// Synchronize shapes and reset forces.
|
||||
for (i = 0; i < this.m_bodyCount; ++i)
|
||||
{
|
||||
b = this.m_bodies[i];
|
||||
|
||||
if (b.m_invMass == 0.0)
|
||||
continue;
|
||||
|
||||
b.m_R.Set(b.m_rotation);
|
||||
|
||||
b.SynchronizeShapes();
|
||||
b.m_force.Set(0.0, 0.0);
|
||||
b.m_torque = 0.0;
|
||||
}
|
||||
},
|
||||
|
||||
UpdateSleep: function(dt)
|
||||
{
|
||||
var i = 0;
|
||||
var b;
|
||||
|
||||
var minSleepTime = Number.MAX_VALUE;
|
||||
|
||||
var linTolSqr = b2Settings.b2_linearSleepTolerance * b2Settings.b2_linearSleepTolerance;
|
||||
var angTolSqr = b2Settings.b2_angularSleepTolerance * b2Settings.b2_angularSleepTolerance;
|
||||
|
||||
for (i = 0; i < this.m_bodyCount; ++i)
|
||||
{
|
||||
b = this.m_bodies[i];
|
||||
if (b.m_invMass == 0.0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((b.m_flags & b2Body.e_allowSleepFlag) == 0)
|
||||
{
|
||||
b.m_sleepTime = 0.0;
|
||||
minSleepTime = 0.0;
|
||||
}
|
||||
|
||||
if ((b.m_flags & b2Body.e_allowSleepFlag) == 0 ||
|
||||
b.m_angularVelocity * b.m_angularVelocity > angTolSqr ||
|
||||
b2Math.b2Dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr)
|
||||
{
|
||||
b.m_sleepTime = 0.0;
|
||||
minSleepTime = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
b.m_sleepTime += dt;
|
||||
minSleepTime = b2Math.b2Min(minSleepTime, b.m_sleepTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (minSleepTime >= b2Settings.b2_timeToSleep)
|
||||
{
|
||||
for (i = 0; i < this.m_bodyCount; ++i)
|
||||
{
|
||||
b = this.m_bodies[i];
|
||||
b.m_flags |= b2Body.e_sleepFlag;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
AddBody: function(body)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_bodyCount < this.m_bodyCapacity);
|
||||
this.m_bodies[this.m_bodyCount++] = body;
|
||||
},
|
||||
|
||||
AddContact: function(contact)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_contactCount < this.m_contactCapacity);
|
||||
this.m_contacts[this.m_contactCount++] = contact;
|
||||
},
|
||||
|
||||
AddJoint: function(joint)
|
||||
{
|
||||
//b2Settings.b2Assert(this.m_jointCount < this.m_jointCapacity);
|
||||
this.m_joints[this.m_jointCount++] = joint;
|
||||
},
|
||||
|
||||
m_allocator: null,
|
||||
|
||||
m_bodies: null,
|
||||
m_contacts: null,
|
||||
m_joints: null,
|
||||
|
||||
m_bodyCount: 0,
|
||||
m_jointCount: 0,
|
||||
m_contactCount: 0,
|
||||
|
||||
m_bodyCapacity: 0,
|
||||
m_contactCapacity: 0,
|
||||
m_jointCapacity: 0,
|
||||
|
||||
m_positionError: null};
|
||||
b2Island.m_positionIterationCount = 0;
|
27
lib/box2d-js/js/box2d/dynamics/b2TimeStep.js
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2TimeStep = Class.create();
|
||||
b2TimeStep.prototype =
|
||||
{
|
||||
dt: null,
|
||||
inv_dt: null,
|
||||
iterations: 0,
|
||||
initialize: function() {}};
|
522
lib/box2d-js/js/box2d/dynamics/b2World.js
Normal file
@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
var b2World = Class.create();
|
||||
b2World.prototype =
|
||||
{
|
||||
initialize: function(worldAABB, gravity, doSleep){
|
||||
// initialize instance variables for references
|
||||
this.step = new b2TimeStep();
|
||||
this.m_contactManager = new b2ContactManager();
|
||||
//
|
||||
|
||||
|
||||
this.m_listener = null;
|
||||
this.m_filter = b2CollisionFilter.b2_defaultFilter;
|
||||
|
||||
this.m_bodyList = null;
|
||||
this.m_contactList = null;
|
||||
this.m_jointList = null;
|
||||
|
||||
this.m_bodyCount = 0;
|
||||
this.m_contactCount = 0;
|
||||
this.m_jointCount = 0;
|
||||
|
||||
this.m_bodyDestroyList = null;
|
||||
|
||||
this.m_allowSleep = doSleep;
|
||||
|
||||
this.m_gravity = gravity;
|
||||
|
||||
this.m_contactManager.m_world = this;
|
||||
this.m_broadPhase = new b2BroadPhase(worldAABB, this.m_contactManager);
|
||||
|
||||
var bd = new b2BodyDef();
|
||||
this.m_groundBody = this.CreateBody(bd);
|
||||
},
|
||||
//~b2World(){
|
||||
// this.DestroyBody(this.m_groundBody);
|
||||
// delete this.m_broadPhase;
|
||||
//}
|
||||
|
||||
// Set a callback to notify you when a joint is implicitly destroyed
|
||||
// when an attached body is destroyed.
|
||||
SetListener: function(listener){
|
||||
this.m_listener = listener;
|
||||
},
|
||||
|
||||
// Register a collision filter to provide specific control over collision.
|
||||
// Otherwise the default filter is used (b2CollisionFilter).
|
||||
SetFilter: function(filter){
|
||||
this.m_filter = filter;
|
||||
},
|
||||
|
||||
// Create and destroy rigid bodies. Destruction is deferred until the
|
||||
// the next call to this.Step. This is done so that bodies may be destroyed
|
||||
// while you iterate through the contact list.
|
||||
CreateBody: function(def){
|
||||
//void* mem = this.m_blockAllocator.Allocate(sizeof(b2Body));
|
||||
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;
|
||||
},
|
||||
// Body destruction is deferred to make contact processing more robust.
|
||||
DestroyBody: function(b)
|
||||
{
|
||||
|
||||
if (b.m_flags & b2Body.e_destroyFlag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove from normal body list.
|
||||
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_flags |= b2Body.e_destroyFlag;
|
||||
//b2Settings.b2Assert(this.m_bodyCount > 0);
|
||||
--this.m_bodyCount;
|
||||
|
||||
//b->~b2Body();
|
||||
//b.Destroy();
|
||||
// Add to the deferred destruction list.
|
||||
b.m_prev = null;
|
||||
b.m_next = this.m_bodyDestroyList;
|
||||
this.m_bodyDestroyList = b;
|
||||
},
|
||||
|
||||
CleanBodyList: function()
|
||||
{
|
||||
this.m_contactManager.m_destroyImmediate = true;
|
||||
|
||||
var b = this.m_bodyDestroyList;
|
||||
while (b)
|
||||
{
|
||||
//b2Settings.b2Assert((b.m_flags & b2Body.e_destroyFlag) != 0);
|
||||
|
||||
// Preserve the next pointer.
|
||||
var b0 = b;
|
||||
b = b.m_next;
|
||||
|
||||
// Delete the attached joints
|
||||
var jn = b0.m_jointList;
|
||||
while (jn)
|
||||
{
|
||||
var jn0 = jn;
|
||||
jn = jn.next;
|
||||
|
||||
if (this.m_listener)
|
||||
{
|
||||
this.m_listener.NotifyJointDestroyed(jn0.joint);
|
||||
}
|
||||
|
||||
this.DestroyJoint(jn0.joint);
|
||||
}
|
||||
|
||||
b0.Destroy();
|
||||
//this.m_blockAllocator.Free(b0, sizeof(b2Body));
|
||||
}
|
||||
|
||||
// Reset the list.
|
||||
this.m_bodyDestroyList = null;
|
||||
|
||||
this.m_contactManager.m_destroyImmediate = false;
|
||||
},
|
||||
|
||||
CreateJoint: function(def){
|
||||
var j = b2Joint.Create(def, this.m_blockAllocator);
|
||||
|
||||
// Connect to the world list.
|
||||
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;
|
||||
|
||||
// Connect to the bodies
|
||||
j.m_node1.joint = j;
|
||||
j.m_node1.other = j.m_body2;
|
||||
j.m_node1.prev = null;
|
||||
j.m_node1.next = j.m_body1.m_jointList;
|
||||
if (j.m_body1.m_jointList) j.m_body1.m_jointList.prev = j.m_node1;
|
||||
j.m_body1.m_jointList = j.m_node1;
|
||||
|
||||
j.m_node2.joint = j;
|
||||
j.m_node2.other = j.m_body1;
|
||||
j.m_node2.prev = null;
|
||||
j.m_node2.next = j.m_body2.m_jointList;
|
||||
if (j.m_body2.m_jointList) j.m_body2.m_jointList.prev = j.m_node2;
|
||||
j.m_body2.m_jointList = j.m_node2;
|
||||
|
||||
// If the joint prevents collisions, then reset collision filtering.
|
||||
if (def.collideConnected == false)
|
||||
{
|
||||
// Reset the proxies on the body with the minimum number of shapes.
|
||||
var b = def.body1.m_shapeCount < def.body2.m_shapeCount ? def.body1 : def.body2;
|
||||
for (var s = b.m_shapeList; s; s = s.m_next)
|
||||
{
|
||||
s.ResetProxy(this.m_broadPhase);
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
},
|
||||
DestroyJoint: function(j)
|
||||
{
|
||||
|
||||
var collideConnected = j.m_collideConnected;
|
||||
|
||||
// Remove from the world.
|
||||
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;
|
||||
}
|
||||
|
||||
// Disconnect from island graph.
|
||||
var body1 = j.m_body1;
|
||||
var body2 = j.m_body2;
|
||||
|
||||
// Wake up touching bodies.
|
||||
body1.WakeUp();
|
||||
body2.WakeUp();
|
||||
|
||||
// Remove from body 1
|
||||
if (j.m_node1.prev)
|
||||
{
|
||||
j.m_node1.prev.next = j.m_node1.next;
|
||||
}
|
||||
|
||||
if (j.m_node1.next)
|
||||
{
|
||||
j.m_node1.next.prev = j.m_node1.prev;
|
||||
}
|
||||
|
||||
if (j.m_node1 == body1.m_jointList)
|
||||
{
|
||||
body1.m_jointList = j.m_node1.next;
|
||||
}
|
||||
|
||||
j.m_node1.prev = null;
|
||||
j.m_node1.next = null;
|
||||
|
||||
// Remove from body 2
|
||||
if (j.m_node2.prev)
|
||||
{
|
||||
j.m_node2.prev.next = j.m_node2.next;
|
||||
}
|
||||
|
||||
if (j.m_node2.next)
|
||||
{
|
||||
j.m_node2.next.prev = j.m_node2.prev;
|
||||
}
|
||||
|
||||
if (j.m_node2 == body2.m_jointList)
|
||||
{
|
||||
body2.m_jointList = j.m_node2.next;
|
||||
}
|
||||
|
||||
j.m_node2.prev = null;
|
||||
j.m_node2.next = null;
|
||||
|
||||
b2Joint.Destroy(j, this.m_blockAllocator);
|
||||
|
||||
//b2Settings.b2Assert(this.m_jointCount > 0);
|
||||
--this.m_jointCount;
|
||||
|
||||
// If the joint prevents collisions, then reset collision filtering.
|
||||
if (collideConnected == false)
|
||||
{
|
||||
// Reset the proxies on the body with the minimum number of shapes.
|
||||
var b = body1.m_shapeCount < body2.m_shapeCount ? body1 : body2;
|
||||
for (var s = b.m_shapeList; s; s = s.m_next)
|
||||
{
|
||||
s.ResetProxy(this.m_broadPhase);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// The world provides a single ground body with no collision shapes. You
|
||||
// can use this to simplify the creation of joints.
|
||||
GetGroundBody: function(){
|
||||
return this.m_groundBody;
|
||||
},
|
||||
|
||||
|
||||
step: new b2TimeStep(),
|
||||
// this.Step
|
||||
Step: function(dt, iterations){
|
||||
|
||||
var b;
|
||||
var other;
|
||||
|
||||
|
||||
this.step.dt = dt;
|
||||
this.step.iterations = iterations;
|
||||
if (dt > 0.0)
|
||||
{
|
||||
this.step.inv_dt = 1.0 / dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.step.inv_dt = 0.0;
|
||||
}
|
||||
|
||||
this.m_positionIterationCount = 0;
|
||||
|
||||
// Handle deferred contact destruction.
|
||||
this.m_contactManager.CleanContactList();
|
||||
|
||||
// Handle deferred body destruction.
|
||||
this.CleanBodyList();
|
||||
|
||||
// Update contacts.
|
||||
this.m_contactManager.Collide();
|
||||
|
||||
// Size the island for the worst case.
|
||||
var island = new b2Island(this.m_bodyCount, this.m_contactCount, this.m_jointCount, this.m_stackAllocator);
|
||||
|
||||
// Clear all the island flags.
|
||||
for (b = this.m_bodyList; b != null; b = b.m_next)
|
||||
{
|
||||
b.m_flags &= ~b2Body.e_islandFlag;
|
||||
}
|
||||
for (var c = this.m_contactList; c != null; c = c.m_next)
|
||||
{
|
||||
c.m_flags &= ~b2Contact.e_islandFlag;
|
||||
}
|
||||
for (var j = this.m_jointList; j != null; j = j.m_next)
|
||||
{
|
||||
j.m_islandFlag = false;
|
||||
}
|
||||
|
||||
// Build and simulate all awake islands.
|
||||
var stackSize = this.m_bodyCount;
|
||||
//var stack = (b2Body**)this.m_stackAllocator.Allocate(stackSize * sizeof(b2Body*));
|
||||
var stack = new Array(this.m_bodyCount);
|
||||
for (var k = 0; k < this.m_bodyCount; k++)
|
||||
stack[k] = null;
|
||||
|
||||
for (var seed = this.m_bodyList; seed != null; seed = seed.m_next)
|
||||
{
|
||||
if (seed.m_flags & (b2Body.e_staticFlag | b2Body.e_islandFlag | b2Body.e_sleepFlag | b2Body.e_frozenFlag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reset island and stack.
|
||||
island.Clear();
|
||||
var stackCount = 0;
|
||||
stack[stackCount++] = seed;
|
||||
seed.m_flags |= b2Body.e_islandFlag;;
|
||||
|
||||
// Perform a depth first search (DFS) on the constraint graph.
|
||||
while (stackCount > 0)
|
||||
{
|
||||
// Grab the next body off the stack and add it to the island.
|
||||
b = stack[--stackCount];
|
||||
island.AddBody(b);
|
||||
|
||||
// Make sure the body is awake.
|
||||
b.m_flags &= ~b2Body.e_sleepFlag;
|
||||
|
||||
// To keep islands, we don't
|
||||
// propagate islands across static bodies.
|
||||
if (b.m_flags & b2Body.e_staticFlag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Search all contacts connected to this body.
|
||||
for (var cn = b.m_contactList; cn != null; cn = cn.next)
|
||||
{
|
||||
if (cn.contact.m_flags & b2Contact.e_islandFlag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
island.AddContact(cn.contact);
|
||||
cn.contact.m_flags |= b2Contact.e_islandFlag;
|
||||
|
||||
other = cn.other;
|
||||
if (other.m_flags & b2Body.e_islandFlag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(stackCount < stackSize);
|
||||
stack[stackCount++] = other;
|
||||
other.m_flags |= b2Body.e_islandFlag;
|
||||
}
|
||||
|
||||
// Search all joints connect to this body.
|
||||
for (var jn = b.m_jointList; jn != null; jn = jn.next)
|
||||
{
|
||||
if (jn.joint.m_islandFlag == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
island.AddJoint(jn.joint);
|
||||
jn.joint.m_islandFlag = true;
|
||||
|
||||
other = jn.other;
|
||||
if (other.m_flags & b2Body.e_islandFlag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(stackCount < stackSize);
|
||||
stack[stackCount++] = other;
|
||||
other.m_flags |= b2Body.e_islandFlag;
|
||||
}
|
||||
}
|
||||
|
||||
island.Solve(this.step, this.m_gravity);
|
||||
|
||||
this.m_positionIterationCount = b2Math.b2Max(this.m_positionIterationCount, b2Island.m_positionIterationCount);
|
||||
|
||||
if (this.m_allowSleep)
|
||||
{
|
||||
island.UpdateSleep(dt);
|
||||
}
|
||||
|
||||
// Post solve cleanup.
|
||||
for (var i = 0; i < island.m_bodyCount; ++i)
|
||||
{
|
||||
// Allow static bodies to participate in other islands.
|
||||
b = island.m_bodies[i];
|
||||
if (b.m_flags & b2Body.e_staticFlag)
|
||||
{
|
||||
b.m_flags &= ~b2Body.e_islandFlag;
|
||||
}
|
||||
|
||||
// Handle newly frozen bodies.
|
||||
if (b.IsFrozen() && this.m_listener)
|
||||
{
|
||||
var response = this.m_listener.NotifyBoundaryViolated(b);
|
||||
if (response == b2WorldListener.b2_destroyBody)
|
||||
{
|
||||
this.DestroyBody(b);
|
||||
b = null;
|
||||
island.m_bodies[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.m_broadPhase.Commit();
|
||||
|
||||
//this.m_stackAllocator.Free(stack);
|
||||
},
|
||||
|
||||
// this.Query the world for all shapes that potentially overlap the
|
||||
// provided AABB. You provide a shape pointer buffer of specified
|
||||
// size. The number of shapes found is returned.
|
||||
Query: function(aabb, shapes, maxCount){
|
||||
|
||||
//void** results = (void**)this.m_stackAllocator.Allocate(maxCount * sizeof(void*));
|
||||
var results = new Array();
|
||||
var count = this.m_broadPhase.QueryAABB(aabb, results, maxCount);
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
shapes[i] = results[i];
|
||||
}
|
||||
|
||||
//this.m_stackAllocator.Free(results);
|
||||
return count;
|
||||
},
|
||||
|
||||
// You can use these to iterate over all the bodies, joints, and contacts.
|
||||
GetBodyList: function(){
|
||||
return this.m_bodyList;
|
||||
},
|
||||
GetJointList: function(){
|
||||
return this.m_jointList;
|
||||
},
|
||||
GetContactList: function(){
|
||||
return this.m_contactList;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
m_blockAllocator: null,
|
||||
m_stackAllocator: null,
|
||||
|
||||
m_broadPhase: null,
|
||||
m_contactManager: new b2ContactManager(),
|
||||
|
||||
m_bodyList: null,
|
||||
m_contactList: null,
|
||||
m_jointList: null,
|
||||
|
||||
m_bodyCount: 0,
|
||||
m_contactCount: 0,
|
||||
m_jointCount: 0,
|
||||
|
||||
// These bodies will be destroyed at the next time this.step.
|
||||
m_bodyDestroyList: null,
|
||||
|
||||
m_gravity: null,
|
||||
m_allowSleep: null,
|
||||
|
||||
m_groundBody: null,
|
||||
|
||||
m_listener: null,
|
||||
m_filter: null,
|
||||
|
||||
m_positionIterationCount: 0};
|
||||
b2World.s_enablePositionCorrection = 1;
|
||||
b2World.s_enableWarmStarting = 1;
|
52
lib/box2d-js/js/box2d/dynamics/b2WorldListener.js
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2WorldListener = Class.create();
|
||||
b2WorldListener.prototype =
|
||||
{
|
||||
|
||||
// If a body is destroyed, then any joints attached to it are also destroyed.
|
||||
// This prevents memory leaks, but you may unexpectedly be left with an
|
||||
// orphaned joint pointer.
|
||||
// Box2D will notify you when a joint is implicitly destroyed.
|
||||
// It is NOT called if you directly destroy a joint.
|
||||
// Implement this abstract class and provide it to b2World via
|
||||
// b2World::SetListener().
|
||||
// DO NOT modify the Box2D world inside this callback.
|
||||
NotifyJointDestroyed: function(joint){},
|
||||
|
||||
// This is called when a body's shape passes outside of the world boundary. If you
|
||||
// override this and pass back e_destroyBody, you must nullify your copies of the
|
||||
// body pointer.
|
||||
NotifyBoundaryViolated: function(body)
|
||||
{
|
||||
//NOT_USED(body);
|
||||
return b2WorldListener.b2_freezeBody;
|
||||
},
|
||||
|
||||
|
||||
|
||||
initialize: function() {}};
|
||||
b2WorldListener.b2_freezeBody = 0;
|
||||
b2WorldListener.b2_destroyBody = 1;
|
102
lib/box2d-js/js/box2d/dynamics/contacts/b2CircleContact.js
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
var b2CircleContact = Class.create();
|
||||
Object.extend(b2CircleContact.prototype, b2Contact.prototype);
|
||||
Object.extend(b2CircleContact.prototype,
|
||||
{
|
||||
|
||||
initialize: function(s1, s2) {
|
||||
// The constructor for b2Contact
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2ContactNode();
|
||||
this.m_node2 = new b2ContactNode();
|
||||
//
|
||||
this.m_flags = 0;
|
||||
|
||||
if (!s1 || !s2){
|
||||
this.m_shape1 = null;
|
||||
this.m_shape2 = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.m_shape1 = s1;
|
||||
this.m_shape2 = s2;
|
||||
|
||||
this.m_manifoldCount = 0;
|
||||
|
||||
this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction);
|
||||
this.m_restitution = b2Math.b2Max(this.m_shape1.m_restitution, this.m_shape2.m_restitution);
|
||||
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
|
||||
this.m_node1.contact = null;
|
||||
this.m_node1.prev = null;
|
||||
this.m_node1.next = null;
|
||||
this.m_node1.other = null;
|
||||
|
||||
this.m_node2.contact = null;
|
||||
this.m_node2.prev = null;
|
||||
this.m_node2.next = null;
|
||||
this.m_node2.other = null;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_manifold = [new b2Manifold()];
|
||||
//
|
||||
|
||||
//super(shape1, shape2);
|
||||
|
||||
//b2Settings.b2Assert(this.m_shape1.m_type == b2Shape.e_circleShape);
|
||||
//b2Settings.b2Assert(this.m_shape2.m_type == b2Shape.e_circleShape);
|
||||
this.m_manifold[0].pointCount = 0;
|
||||
this.m_manifold[0].points[0].normalImpulse = 0.0;
|
||||
this.m_manifold[0].points[0].tangentImpulse = 0.0;
|
||||
},
|
||||
//~b2CircleContact() {}
|
||||
|
||||
Evaluate: function(){
|
||||
b2Collision.b2CollideCircle(this.m_manifold[0], this.m_shape1, this.m_shape2, false);
|
||||
|
||||
if (this.m_manifold[0].pointCount > 0)
|
||||
{
|
||||
this.m_manifoldCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_manifoldCount = 0;
|
||||
}
|
||||
},
|
||||
|
||||
GetManifolds: function()
|
||||
{
|
||||
return this.m_manifold;
|
||||
},
|
||||
|
||||
m_manifold: [new b2Manifold()]});
|
||||
|
||||
b2CircleContact.Create = function(shape1, shape2, allocator){
|
||||
return new b2CircleContact(shape1, shape2);
|
||||
};
|
||||
b2CircleContact.Destroy = function(contact, allocator){
|
||||
//
|
||||
};
|
228
lib/box2d-js/js/box2d/dynamics/contacts/b2Conservative.js
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2Conservative = Class.create();
|
||||
b2Conservative.prototype = {
|
||||
|
||||
// Temp vars
|
||||
|
||||
|
||||
|
||||
initialize: function() {}}
|
||||
b2Conservative.R1 = new b2Mat22();
|
||||
b2Conservative.R2 = new b2Mat22();
|
||||
b2Conservative.x1 = new b2Vec2();
|
||||
b2Conservative.x2 = new b2Vec2();
|
||||
b2Conservative.Conservative = function(shape1, shape2){
|
||||
var body1 = shape1.GetBody();
|
||||
var body2 = shape2.GetBody();
|
||||
|
||||
//b2Vec2 v1 = body1->m_position - body1->m_position0;
|
||||
var v1X = body1.m_position.x - body1.m_position0.x;
|
||||
var v1Y = body1.m_position.y - body1.m_position0.y;
|
||||
//float32 omega1 = body1->m_rotation - body1->m_rotation0;
|
||||
var omega1 = body1.m_rotation - body1.m_rotation0;
|
||||
//b2Vec2 v2 = body2->m_position - body2->m_position0;
|
||||
var v2X = body2.m_position.x - body2.m_position0.x;
|
||||
var v2Y = body2.m_position.y - body2.m_position0.y;
|
||||
//float32 omega2 = body2->m_rotation - body2->m_rotation0;
|
||||
var omega2 = body2.m_rotation - body2.m_rotation0;
|
||||
|
||||
//float32 r1 = shape1->GetMaxRadius();
|
||||
var r1 = shape1.GetMaxRadius();
|
||||
//float32 r2 = shape2->GetMaxRadius();
|
||||
var r2 = shape2.GetMaxRadius();
|
||||
|
||||
//b2Vec2 p1Start = body1->m_position0;
|
||||
var p1StartX = body1.m_position0.x;
|
||||
var p1StartY = body1.m_position0.y;
|
||||
//float32 a1Start = body1->m_rotation0;
|
||||
var a1Start = body1.m_rotation0;
|
||||
|
||||
//b2Vec2 p2Start = body2->m_position0;
|
||||
var p2StartX = body2.m_position0.x;
|
||||
var p2StartY = body2.m_position0.y;
|
||||
//float32 a2Start = body2->m_rotation0;
|
||||
var a2Start = body2.m_rotation0;
|
||||
|
||||
//b2Vec2 p1 = p1Start;
|
||||
var p1X = p1StartX;
|
||||
var p1Y = p1StartY;
|
||||
//float32 a1 = a1Start;
|
||||
var a1 = a1Start;
|
||||
//b2Vec2 p2 = p2Start;
|
||||
var p2X = p2StartX;
|
||||
var p2Y = p2StartY;
|
||||
//float32 a2 = a2Start;
|
||||
var a2 = a2Start;
|
||||
|
||||
//b2Mat22 b2Conservative.R1(a1), b2Conservative.R2(a2);
|
||||
b2Conservative.R1.Set(a1);
|
||||
b2Conservative.R2.Set(a2);
|
||||
|
||||
//shape1->QuickSync(p1, b2Conservative.R1);
|
||||
shape1.QuickSync(p1, b2Conservative.R1);
|
||||
//shape2->QuickSync(p2, b2Conservative.R2);
|
||||
shape2.QuickSync(p2, b2Conservative.R2);
|
||||
|
||||
//float32 s1 = 0.0f;
|
||||
var s1 = 0.0;
|
||||
//const int32 maxIterations = 10;
|
||||
var maxIterations = 10;
|
||||
//b2Vec2 d;
|
||||
var dX;
|
||||
var dY;
|
||||
//float32 invRelativeVelocity = 0.0f;
|
||||
var invRelativeVelocity = 0.0;
|
||||
//bool hit = true;
|
||||
var hit = true;
|
||||
//b2Vec2 b2Conservative.x1, b2Conservative.x2; moved to static var
|
||||
for (var iter = 0; iter < maxIterations; ++iter)
|
||||
{
|
||||
// Get the accurate distance between shapes.
|
||||
//float32 distance = b2Distance.Distance(&b2Conservative.x1, &b2Conservative.x2, shape1, shape2);
|
||||
var distance = b2Distance.Distance(b2Conservative.x1, b2Conservative.x2, shape1, shape2);
|
||||
if (distance < b2Settings.b2_linearSlop)
|
||||
{
|
||||
if (iter == 0)
|
||||
{
|
||||
hit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
hit = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (iter == 0)
|
||||
{
|
||||
//b2Vec2 d = b2Conservative.x2 - b2Conservative.x1;
|
||||
dX = b2Conservative.x2.x - b2Conservative.x1.x;
|
||||
dY = b2Conservative.x2.y - b2Conservative.x1.y;
|
||||
//d.Normalize();
|
||||
var dLen = Math.sqrt(dX*dX + dY*dY);
|
||||
//float32 relativeVelocity = b2Dot(d, v1 - v2) + b2Abs(omega1) * r1 + b2Abs(omega2) * r2;
|
||||
var relativeVelocity = (dX*(v1X-v2X) + dY*(v1Y - v2Y)) + Math.abs(omega1) * r1 + Math.abs(omega2) * r2;
|
||||
if (Math.abs(relativeVelocity) < Number.MIN_VALUE)
|
||||
{
|
||||
hit = false;
|
||||
break;
|
||||
}
|
||||
|
||||
invRelativeVelocity = 1.0 / relativeVelocity;
|
||||
}
|
||||
|
||||
// Get the conservative movement.
|
||||
//float32 ds = distance * invRelativeVelocity;
|
||||
var ds = distance * invRelativeVelocity;
|
||||
//float32 s2 = s1 + ds;
|
||||
var s2 = s1 + ds;
|
||||
|
||||
if (s2 < 0.0 || 1.0 < s2)
|
||||
{
|
||||
hit = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s2 < (1.0 + 100.0 * Number.MIN_VALUE) * s1)
|
||||
{
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
s1 = s2;
|
||||
|
||||
// Move forward conservatively.
|
||||
//p1 = p1Start + s1 * v1;
|
||||
p1X = p1StartX + s1 * v1.x;
|
||||
p1Y = p1StartY + s1 * v1.y;
|
||||
//a1 = a1Start + s1 * omega1;
|
||||
a1 = a1Start + s1 * omega1;
|
||||
//p2 = p2Start + s1 * v2;
|
||||
p2X = p2StartX + s1 * v2.x;
|
||||
p2Y = p2StartY + s1 * v2.y;
|
||||
//a2 = a2Start + s1 * omega2;
|
||||
a2 = a2Start + s1 * omega2;
|
||||
|
||||
b2Conservative.R1.Set(a1);
|
||||
b2Conservative.R2.Set(a2);
|
||||
shape1.QuickSync(p1, b2Conservative.R1);
|
||||
shape2.QuickSync(p2, b2Conservative.R2);
|
||||
}
|
||||
|
||||
if (hit)
|
||||
{
|
||||
// Hit, move bodies to safe position and re-sync shapes.
|
||||
//b2Vec2 d = b2Conservative.x2 - b2Conservative.x1;
|
||||
dX = b2Conservative.x2.x - b2Conservative.x1.x;
|
||||
dY = b2Conservative.x2.y - b2Conservative.x1.y;
|
||||
//float32 length = d.Length();
|
||||
var length = Math.sqrt(dX*dX + dY*dY);
|
||||
if (length > FLT_EPSILON)
|
||||
{
|
||||
d *= b2_linearSlop / length;
|
||||
}
|
||||
|
||||
if (body1.IsStatic())
|
||||
{
|
||||
//body1.m_position = p1;
|
||||
body1.m_position.x = p1X;
|
||||
body1.m_position.y = p1Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
//body1.m_position = p1 - d;
|
||||
body1.m_position.x = p1X - dX;
|
||||
body1.m_position.y = p1Y - dY;
|
||||
}
|
||||
body1.m_rotation = a1;
|
||||
body1.m_R.Set(a1);
|
||||
body1.QuickSyncShapes();
|
||||
|
||||
if (body2.IsStatic())
|
||||
{
|
||||
//body2->m_position = p2;
|
||||
body2.m_position.x = p2X;
|
||||
body2.m_position.y = p2Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
//body2->m_position = p2 + d;
|
||||
body2.m_position.x = p2X + dX;
|
||||
body2.m_position.y = p2Y + dY;
|
||||
}
|
||||
//body2.m_position = p2 + d;
|
||||
body2.m_position.x = p2X + dX;
|
||||
body2.m_position.y = p2Y + dY;
|
||||
body2.m_rotation = a2;
|
||||
body2.m_R.Set(a2);
|
||||
body2.QuickSyncShapes();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// No hit, restore shapes.
|
||||
shape1.QuickSync(body1.m_position, body1.m_R);
|
||||
shape2.QuickSync(body2.m_position, body2.m_R);
|
||||
return false;
|
||||
};
|
201
lib/box2d-js/js/box2d/dynamics/contacts/b2Contact.js
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//typedef b2Contact* b2ContactCreateFcn(b2Shape* shape1, b2Shape* shape2, b2BlockAllocator* allocator);
|
||||
//typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);
|
||||
|
||||
|
||||
|
||||
var b2Contact = Class.create();
|
||||
b2Contact.prototype =
|
||||
{
|
||||
GetManifolds: function(){return null},
|
||||
GetManifoldCount: function()
|
||||
{
|
||||
return this.m_manifoldCount;
|
||||
},
|
||||
|
||||
GetNext: function(){
|
||||
return this.m_next;
|
||||
},
|
||||
|
||||
GetShape1: function(){
|
||||
return this.m_shape1;
|
||||
},
|
||||
|
||||
GetShape2: function(){
|
||||
return this.m_shape2;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
// this.m_flags
|
||||
// enum
|
||||
|
||||
|
||||
initialize: function(s1, s2)
|
||||
{
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2ContactNode();
|
||||
this.m_node2 = new b2ContactNode();
|
||||
//
|
||||
|
||||
this.m_flags = 0;
|
||||
|
||||
if (!s1 || !s2){
|
||||
this.m_shape1 = null;
|
||||
this.m_shape2 = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.m_shape1 = s1;
|
||||
this.m_shape2 = s2;
|
||||
|
||||
this.m_manifoldCount = 0;
|
||||
|
||||
this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction);
|
||||
this.m_restitution = b2Math.b2Max(this.m_shape1.m_restitution, this.m_shape2.m_restitution);
|
||||
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
|
||||
this.m_node1.contact = null;
|
||||
this.m_node1.prev = null;
|
||||
this.m_node1.next = null;
|
||||
this.m_node1.other = null;
|
||||
|
||||
this.m_node2.contact = null;
|
||||
this.m_node2.prev = null;
|
||||
this.m_node2.next = null;
|
||||
this.m_node2.other = null;
|
||||
},
|
||||
|
||||
//virtual ~b2Contact() {}
|
||||
|
||||
Evaluate: function(){},
|
||||
|
||||
m_flags: 0,
|
||||
|
||||
// World pool and list pointers.
|
||||
m_prev: null,
|
||||
m_next: null,
|
||||
|
||||
// Nodes for connecting bodies.
|
||||
m_node1: new b2ContactNode(),
|
||||
m_node2: new b2ContactNode(),
|
||||
|
||||
m_shape1: null,
|
||||
m_shape2: null,
|
||||
|
||||
m_manifoldCount: 0,
|
||||
|
||||
// Combined friction
|
||||
m_friction: null,
|
||||
m_restitution: null};
|
||||
b2Contact.e_islandFlag = 0x0001;
|
||||
b2Contact.e_destroyFlag = 0x0002;
|
||||
b2Contact.AddType = function(createFcn, destroyFcn, type1, type2)
|
||||
{
|
||||
//b2Settings.b2Assert(b2Shape.e_unknownShape < type1 && type1 < b2Shape.e_shapeTypeCount);
|
||||
//b2Settings.b2Assert(b2Shape.e_unknownShape < type2 && type2 < b2Shape.e_shapeTypeCount);
|
||||
|
||||
b2Contact.s_registers[type1][type2].createFcn = createFcn;
|
||||
b2Contact.s_registers[type1][type2].destroyFcn = destroyFcn;
|
||||
b2Contact.s_registers[type1][type2].primary = true;
|
||||
|
||||
if (type1 != type2)
|
||||
{
|
||||
b2Contact.s_registers[type2][type1].createFcn = createFcn;
|
||||
b2Contact.s_registers[type2][type1].destroyFcn = destroyFcn;
|
||||
b2Contact.s_registers[type2][type1].primary = false;
|
||||
}
|
||||
};
|
||||
b2Contact.InitializeRegisters = function(){
|
||||
b2Contact.s_registers = new Array(b2Shape.e_shapeTypeCount);
|
||||
for (var i = 0; i < b2Shape.e_shapeTypeCount; i++){
|
||||
b2Contact.s_registers[i] = new Array(b2Shape.e_shapeTypeCount);
|
||||
for (var j = 0; j < b2Shape.e_shapeTypeCount; j++){
|
||||
b2Contact.s_registers[i][j] = new b2ContactRegister();
|
||||
}
|
||||
}
|
||||
|
||||
b2Contact.AddType(b2CircleContact.Create, b2CircleContact.Destroy, b2Shape.e_circleShape, b2Shape.e_circleShape);
|
||||
b2Contact.AddType(b2PolyAndCircleContact.Create, b2PolyAndCircleContact.Destroy, b2Shape.e_polyShape, b2Shape.e_circleShape);
|
||||
b2Contact.AddType(b2PolyContact.Create, b2PolyContact.Destroy, b2Shape.e_polyShape, b2Shape.e_polyShape);
|
||||
|
||||
};
|
||||
b2Contact.Create = function(shape1, shape2, allocator){
|
||||
if (b2Contact.s_initialized == false)
|
||||
{
|
||||
b2Contact.InitializeRegisters();
|
||||
b2Contact.s_initialized = true;
|
||||
}
|
||||
|
||||
var type1 = shape1.m_type;
|
||||
var type2 = shape2.m_type;
|
||||
|
||||
//b2Settings.b2Assert(b2Shape.e_unknownShape < type1 && type1 < b2Shape.e_shapeTypeCount);
|
||||
//b2Settings.b2Assert(b2Shape.e_unknownShape < type2 && type2 < b2Shape.e_shapeTypeCount);
|
||||
|
||||
var createFcn = b2Contact.s_registers[type1][type2].createFcn;
|
||||
if (createFcn)
|
||||
{
|
||||
if (b2Contact.s_registers[type1][type2].primary)
|
||||
{
|
||||
return createFcn(shape1, shape2, allocator);
|
||||
}
|
||||
else
|
||||
{
|
||||
var c = createFcn(shape2, shape1, allocator);
|
||||
for (var i = 0; i < c.GetManifoldCount(); ++i)
|
||||
{
|
||||
var m = c.GetManifolds()[ i ];
|
||||
m.normal = m.normal.Negative();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
};
|
||||
b2Contact.Destroy = function(contact, allocator){
|
||||
//b2Settings.b2Assert(b2Contact.s_initialized == true);
|
||||
|
||||
if (contact.GetManifoldCount() > 0)
|
||||
{
|
||||
contact.m_shape1.m_body.WakeUp();
|
||||
contact.m_shape2.m_body.WakeUp();
|
||||
}
|
||||
|
||||
var type1 = contact.m_shape1.m_type;
|
||||
var type2 = contact.m_shape2.m_type;
|
||||
|
||||
//b2Settings.b2Assert(b2Shape.e_unknownShape < type1 && type1 < b2Shape.e_shapeTypeCount);
|
||||
//b2Settings.b2Assert(b2Shape.e_unknownShape < type2 && type2 < b2Shape.e_shapeTypeCount);
|
||||
|
||||
var destroyFcn = b2Contact.s_registers[type1][type2].destroyFcn;
|
||||
destroyFcn(contact, allocator);
|
||||
};
|
||||
b2Contact.s_registers = null;
|
||||
b2Contact.s_initialized = false;
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2ContactConstraint = Class.create();
|
||||
b2ContactConstraint.prototype =
|
||||
{
|
||||
initialize: function(){
|
||||
// initialize instance variables for references
|
||||
this.normal = new b2Vec2();
|
||||
//
|
||||
|
||||
this.points = new Array(b2Settings.b2_maxManifoldPoints);
|
||||
for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++){
|
||||
this.points[i] = new b2ContactConstraintPoint();
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
points: null,
|
||||
normal: new b2Vec2(),
|
||||
manifold: null,
|
||||
body1: null,
|
||||
body2: null,
|
||||
friction: null,
|
||||
restitution: null,
|
||||
pointCount: 0};
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2ContactConstraintPoint = Class.create();
|
||||
b2ContactConstraintPoint.prototype =
|
||||
{
|
||||
localAnchor1: new b2Vec2(),
|
||||
localAnchor2: new b2Vec2(),
|
||||
normalImpulse: null,
|
||||
tangentImpulse: null,
|
||||
positionImpulse: null,
|
||||
normalMass: null,
|
||||
tangentMass: null,
|
||||
separation: null,
|
||||
velocityBias: null,
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.localAnchor1 = new b2Vec2();
|
||||
this.localAnchor2 = new b2Vec2();
|
||||
//
|
||||
}};
|
33
lib/box2d-js/js/box2d/dynamics/contacts/b2ContactNode.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2ContactNode = Class.create();
|
||||
b2ContactNode.prototype =
|
||||
{
|
||||
other: null,
|
||||
contact: null,
|
||||
prev: null,
|
||||
next: null,
|
||||
initialize: function() {}};
|
||||
|
||||
|
||||
|
30
lib/box2d-js/js/box2d/dynamics/contacts/b2ContactRegister.js
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var b2ContactRegister = Class.create();
|
||||
b2ContactRegister.prototype =
|
||||
{
|
||||
createFcn: null,
|
||||
destroyFcn: null,
|
||||
primary: null,
|
||||
initialize: function() {}};
|
||||
|
||||
|
||||
|
537
lib/box2d-js/js/box2d/dynamics/contacts/b2ContactSolver.js
Normal file
@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2ContactSolver = Class.create();
|
||||
b2ContactSolver.prototype =
|
||||
{
|
||||
initialize: function(contacts, contactCount, allocator){
|
||||
// initialize instance variables for references
|
||||
this.m_constraints = new Array();
|
||||
//
|
||||
|
||||
this.m_allocator = allocator;
|
||||
|
||||
var i = 0;
|
||||
var tVec;
|
||||
var tMat;
|
||||
|
||||
this.m_constraintCount = 0;
|
||||
for (i = 0; i < contactCount; ++i)
|
||||
{
|
||||
this.m_constraintCount += contacts[i].GetManifoldCount();
|
||||
}
|
||||
|
||||
// fill array
|
||||
for (i = 0; i < this.m_constraintCount; i++){
|
||||
this.m_constraints[i] = new b2ContactConstraint();
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
for (i = 0; i < contactCount; ++i)
|
||||
{
|
||||
var contact = contacts[i];
|
||||
var b1 = contact.m_shape1.m_body;
|
||||
var b2 = contact.m_shape2.m_body;
|
||||
var manifoldCount = contact.GetManifoldCount();
|
||||
var manifolds = contact.GetManifolds();
|
||||
var friction = contact.m_friction;
|
||||
var restitution = contact.m_restitution;
|
||||
|
||||
//var v1 = b1.m_linearVelocity.Copy();
|
||||
var v1X = b1.m_linearVelocity.x;
|
||||
var v1Y = b1.m_linearVelocity.y;
|
||||
//var v2 = b2.m_linearVelocity.Copy();
|
||||
var v2X = b2.m_linearVelocity.x;
|
||||
var v2Y = b2.m_linearVelocity.y;
|
||||
var w1 = b1.m_angularVelocity;
|
||||
var w2 = b2.m_angularVelocity;
|
||||
|
||||
for (var j = 0; j < manifoldCount; ++j)
|
||||
{
|
||||
var manifold = manifolds[ j ];
|
||||
|
||||
//b2Settings.b2Assert(manifold.pointCount > 0);
|
||||
|
||||
//var normal = manifold.normal.Copy();
|
||||
var normalX = manifold.normal.x;
|
||||
var normalY = manifold.normal.y;
|
||||
|
||||
//b2Settings.b2Assert(count < this.m_constraintCount);
|
||||
var c = this.m_constraints[ count ];
|
||||
c.body1 = b1;
|
||||
c.body2 = b2;
|
||||
c.manifold = manifold;
|
||||
//c.normal = normal;
|
||||
c.normal.x = normalX;
|
||||
c.normal.y = normalY;
|
||||
c.pointCount = manifold.pointCount;
|
||||
c.friction = friction;
|
||||
c.restitution = restitution;
|
||||
|
||||
for (var k = 0; k < c.pointCount; ++k)
|
||||
{
|
||||
var cp = manifold.points[ k ];
|
||||
var ccp = c.points[ k ];
|
||||
|
||||
ccp.normalImpulse = cp.normalImpulse;
|
||||
ccp.tangentImpulse = cp.tangentImpulse;
|
||||
ccp.separation = cp.separation;
|
||||
|
||||
//var r1 = b2Math.SubtractVV( cp.position, b1.m_position );
|
||||
var r1X = cp.position.x - b1.m_position.x;
|
||||
var r1Y = cp.position.y - b1.m_position.y;
|
||||
//var r2 = b2Math.SubtractVV( cp.position, b2.m_position );
|
||||
var r2X = cp.position.x - b2.m_position.x;
|
||||
var r2Y = cp.position.y - b2.m_position.y;
|
||||
|
||||
//ccp.localAnchor1 = b2Math.b2MulTMV(b1.m_R, r1);
|
||||
tVec = ccp.localAnchor1;
|
||||
tMat = b1.m_R;
|
||||
tVec.x = r1X * tMat.col1.x + r1Y * tMat.col1.y;
|
||||
tVec.y = r1X * tMat.col2.x + r1Y * tMat.col2.y;
|
||||
|
||||
//ccp.localAnchor2 = b2Math.b2MulTMV(b2.m_R, r2);
|
||||
tVec = ccp.localAnchor2;
|
||||
tMat = b2.m_R;
|
||||
tVec.x = r2X * tMat.col1.x + r2Y * tMat.col1.y;
|
||||
tVec.y = r2X * tMat.col2.x + r2Y * tMat.col2.y;
|
||||
|
||||
var r1Sqr = r1X * r1X + r1Y * r1Y;
|
||||
var r2Sqr = r2X * r2X + r2Y * r2Y;
|
||||
|
||||
//var rn1 = b2Math.b2Dot(r1, normal);
|
||||
var rn1 = r1X*normalX + r1Y*normalY;
|
||||
//var rn2 = b2Math.b2Dot(r2, normal);
|
||||
var rn2 = r2X*normalX + r2Y*normalY;
|
||||
var kNormal = b1.m_invMass + b2.m_invMass;
|
||||
kNormal += b1.m_invI * (r1Sqr - rn1 * rn1) + b2.m_invI * (r2Sqr - rn2 * rn2);
|
||||
//b2Settings.b2Assert(kNormal > Number.MIN_VALUE);
|
||||
ccp.normalMass = 1.0 / kNormal;
|
||||
|
||||
//var tangent = b2Math.b2CrossVF(normal, 1.0);
|
||||
var tangentX = normalY
|
||||
var tangentY = -normalX;
|
||||
|
||||
//var rt1 = b2Math.b2Dot(r1, tangent);
|
||||
var rt1 = r1X*tangentX + r1Y*tangentY;
|
||||
//var rt2 = b2Math.b2Dot(r2, tangent);
|
||||
var rt2 = r2X*tangentX + r2Y*tangentY;
|
||||
var kTangent = b1.m_invMass + b2.m_invMass;
|
||||
kTangent += b1.m_invI * (r1Sqr - rt1 * rt1) + b2.m_invI * (r2Sqr - rt2 * rt2);
|
||||
//b2Settings.b2Assert(kTangent > Number.MIN_VALUE);
|
||||
ccp.tangentMass = 1.0 / kTangent;
|
||||
|
||||
// Setup a velocity bias for restitution.
|
||||
ccp.velocityBias = 0.0;
|
||||
if (ccp.separation > 0.0)
|
||||
{
|
||||
ccp.velocityBias = -60.0 * ccp.separation;
|
||||
}
|
||||
//var vRel = b2Math.b2Dot(c.normal, b2Math.SubtractVV( b2Math.SubtractVV( b2Math.AddVV( v2, b2Math.b2CrossFV(w2, r2)), v1 ), b2Math.b2CrossFV(w1, r1)));
|
||||
var tX = v2X + (-w2*r2Y) - v1X - (-w1*r1Y);
|
||||
var tY = v2Y + (w2*r2X) - v1Y - (w1*r1X);
|
||||
//var vRel = b2Dot(c.normal, tX/Y);
|
||||
var vRel = c.normal.x*tX + c.normal.y*tY;
|
||||
if (vRel < -b2Settings.b2_velocityThreshold)
|
||||
{
|
||||
ccp.velocityBias += -c.restitution * vRel;
|
||||
}
|
||||
}
|
||||
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
//b2Settings.b2Assert(count == this.m_constraintCount);
|
||||
},
|
||||
//~b2ContactSolver();
|
||||
|
||||
PreSolve: function(){
|
||||
var tVec;
|
||||
var tVec2;
|
||||
var tMat;
|
||||
|
||||
// Warm start.
|
||||
for (var i = 0; i < this.m_constraintCount; ++i)
|
||||
{
|
||||
var c = this.m_constraints[ i ];
|
||||
|
||||
var b1 = c.body1;
|
||||
var b2 = c.body2;
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invI1 = b1.m_invI;
|
||||
var invMass2 = b2.m_invMass;
|
||||
var invI2 = b2.m_invI;
|
||||
//var normal = new b2Vec2(c.normal.x, c.normal.y);
|
||||
var normalX = c.normal.x;
|
||||
var normalY = c.normal.y;
|
||||
//var tangent = b2Math.b2CrossVF(normal, 1.0);
|
||||
var tangentX = normalY;
|
||||
var tangentY = -normalX;
|
||||
|
||||
var j = 0;
|
||||
var tCount = 0;
|
||||
if (b2World.s_enableWarmStarting)
|
||||
{
|
||||
tCount = c.pointCount;
|
||||
for (j = 0; j < tCount; ++j)
|
||||
{
|
||||
var ccp = c.points[ j ];
|
||||
//var P = b2Math.AddVV( b2Math.MulFV(ccp.normalImpulse, normal), b2Math.MulFV(ccp.tangentImpulse, tangent));
|
||||
var PX = ccp.normalImpulse*normalX + ccp.tangentImpulse*tangentX;
|
||||
var PY = ccp.normalImpulse*normalY + ccp.tangentImpulse*tangentY;
|
||||
|
||||
//var r1 = b2Math.b2MulMV(b1.m_R, ccp.localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
tVec = ccp.localAnchor1;
|
||||
var r1X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
|
||||
var r1Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
|
||||
|
||||
//var r2 = b2Math.b2MulMV(b2.m_R, ccp.localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
tVec = ccp.localAnchor2;
|
||||
var r2X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
|
||||
var r2Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
|
||||
|
||||
//b1.m_angularVelocity -= invI1 * b2Math.b2CrossVV(r1, P);
|
||||
b1.m_angularVelocity -= invI1 * (r1X * PY - r1Y * PX);
|
||||
//b1.m_linearVelocity.Subtract( b2Math.MulFV(invMass1, P) );
|
||||
b1.m_linearVelocity.x -= invMass1 * PX;
|
||||
b1.m_linearVelocity.y -= invMass1 * PY;
|
||||
//b2.m_angularVelocity += invI2 * b2Math.b2CrossVV(r2, P);
|
||||
b2.m_angularVelocity += invI2 * (r2X * PY - r2Y * PX);
|
||||
//b2.m_linearVelocity.Add( b2Math.MulFV(invMass2, P) );
|
||||
b2.m_linearVelocity.x += invMass2 * PX;
|
||||
b2.m_linearVelocity.y += invMass2 * PY;
|
||||
|
||||
ccp.positionImpulse = 0.0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
tCount = c.pointCount;
|
||||
for (j = 0; j < tCount; ++j)
|
||||
{
|
||||
var ccp2 = c.points[ j ];
|
||||
ccp2.normalImpulse = 0.0;
|
||||
ccp2.tangentImpulse = 0.0;
|
||||
|
||||
ccp2.positionImpulse = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
SolveVelocityConstraints: function(){
|
||||
var j = 0;
|
||||
var ccp;
|
||||
var r1X;
|
||||
var r1Y;
|
||||
var r2X;
|
||||
var r2Y;
|
||||
var dvX;
|
||||
var dvY;
|
||||
var lambda;
|
||||
var newImpulse;
|
||||
var PX;
|
||||
var PY;
|
||||
|
||||
var tMat;
|
||||
var tVec;
|
||||
|
||||
for (var i = 0; i < this.m_constraintCount; ++i)
|
||||
{
|
||||
var c = this.m_constraints[ i ];
|
||||
var b1 = c.body1;
|
||||
var b2 = c.body2;
|
||||
var b1_angularVelocity = b1.m_angularVelocity;
|
||||
var b1_linearVelocity = b1.m_linearVelocity;
|
||||
var b2_angularVelocity = b2.m_angularVelocity;
|
||||
var b2_linearVelocity = b2.m_linearVelocity;
|
||||
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invI1 = b1.m_invI;
|
||||
var invMass2 = b2.m_invMass;
|
||||
var invI2 = b2.m_invI;
|
||||
//var normal = new b2Vec2(c.normal.x, c.normal.y);
|
||||
var normalX = c.normal.x;
|
||||
var normalY = c.normal.y;
|
||||
//var tangent = b2Math.b2CrossVF(normal, 1.0);
|
||||
var tangentX = normalY;
|
||||
var tangentY = -normalX;
|
||||
|
||||
// Solver normal constraints
|
||||
var tCount = c.pointCount;
|
||||
for (j = 0; j < tCount; ++j)
|
||||
{
|
||||
ccp = c.points[ j ];
|
||||
|
||||
//r1 = b2Math.b2MulMV(b1.m_R, ccp.localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
tVec = ccp.localAnchor1;
|
||||
r1X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y
|
||||
r1Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y
|
||||
//r2 = b2Math.b2MulMV(b2.m_R, ccp.localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
tVec = ccp.localAnchor2;
|
||||
r2X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y
|
||||
r2Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y
|
||||
|
||||
// Relative velocity at contact
|
||||
//var dv = b2Math.SubtractVV( b2Math.AddVV( b2.m_linearVelocity, b2Math.b2CrossFV(b2.m_angularVelocity, r2)), b2Math.SubtractVV(b1.m_linearVelocity, b2Math.b2CrossFV(b1.m_angularVelocity, r1)));
|
||||
//dv = b2Math.SubtractVV(b2Math.SubtractVV( b2Math.AddVV( b2.m_linearVelocity, b2Math.b2CrossFV(b2.m_angularVelocity, r2)), b1.m_linearVelocity), b2Math.b2CrossFV(b1.m_angularVelocity, r1));
|
||||
dvX = b2_linearVelocity.x + (-b2_angularVelocity * r2Y) - b1_linearVelocity.x - (-b1_angularVelocity * r1Y);
|
||||
dvY = b2_linearVelocity.y + (b2_angularVelocity * r2X) - b1_linearVelocity.y - (b1_angularVelocity * r1X);
|
||||
|
||||
// Compute normal impulse
|
||||
//var vn = b2Math.b2Dot(dv, normal);
|
||||
var vn = dvX * normalX + dvY * normalY;
|
||||
lambda = -ccp.normalMass * (vn - ccp.velocityBias);
|
||||
|
||||
// b2Clamp the accumulated impulse
|
||||
newImpulse = b2Math.b2Max(ccp.normalImpulse + lambda, 0.0);
|
||||
lambda = newImpulse - ccp.normalImpulse;
|
||||
|
||||
// Apply contact impulse
|
||||
//P = b2Math.MulFV(lambda, normal);
|
||||
PX = lambda * normalX;
|
||||
PY = lambda * normalY;
|
||||
|
||||
//b1.m_linearVelocity.Subtract( b2Math.MulFV( invMass1, P ) );
|
||||
b1_linearVelocity.x -= invMass1 * PX;
|
||||
b1_linearVelocity.y -= invMass1 * PY;
|
||||
b1_angularVelocity -= invI1 * (r1X * PY - r1Y * PX);
|
||||
|
||||
//b2.m_linearVelocity.Add( b2Math.MulFV( invMass2, P ) );
|
||||
b2_linearVelocity.x += invMass2 * PX;
|
||||
b2_linearVelocity.y += invMass2 * PY;
|
||||
b2_angularVelocity += invI2 * (r2X * PY - r2Y * PX);
|
||||
|
||||
ccp.normalImpulse = newImpulse;
|
||||
|
||||
|
||||
|
||||
// MOVED FROM BELOW
|
||||
// Relative velocity at contact
|
||||
//var dv = b2.m_linearVelocity + b2Cross(b2.m_angularVelocity, r2) - b1.m_linearVelocity - b2Cross(b1.m_angularVelocity, r1);
|
||||
//dv = b2Math.SubtractVV(b2Math.SubtractVV(b2Math.AddVV(b2.m_linearVelocity, b2Math.b2CrossFV(b2.m_angularVelocity, r2)), b1.m_linearVelocity), b2Math.b2CrossFV(b1.m_angularVelocity, r1));
|
||||
dvX = b2_linearVelocity.x + (-b2_angularVelocity * r2Y) - b1_linearVelocity.x - (-b1_angularVelocity * r1Y);
|
||||
dvY = b2_linearVelocity.y + (b2_angularVelocity * r2X) - b1_linearVelocity.y - (b1_angularVelocity * r1X);
|
||||
|
||||
// Compute tangent impulse
|
||||
var vt = dvX*tangentX + dvY*tangentY;
|
||||
lambda = ccp.tangentMass * (-vt);
|
||||
|
||||
// b2Clamp the accumulated impulse
|
||||
var maxFriction = c.friction * ccp.normalImpulse;
|
||||
newImpulse = b2Math.b2Clamp(ccp.tangentImpulse + lambda, -maxFriction, maxFriction);
|
||||
lambda = newImpulse - ccp.tangentImpulse;
|
||||
|
||||
// Apply contact impulse
|
||||
//P = b2Math.MulFV(lambda, tangent);
|
||||
PX = lambda * tangentX;
|
||||
PY = lambda * tangentY;
|
||||
|
||||
//b1.m_linearVelocity.Subtract( b2Math.MulFV( invMass1, P ) );
|
||||
b1_linearVelocity.x -= invMass1 * PX;
|
||||
b1_linearVelocity.y -= invMass1 * PY;
|
||||
b1_angularVelocity -= invI1 * (r1X * PY - r1Y * PX);
|
||||
|
||||
//b2.m_linearVelocity.Add( b2Math.MulFV( invMass2, P ) );
|
||||
b2_linearVelocity.x += invMass2 * PX;
|
||||
b2_linearVelocity.y += invMass2 * PY;
|
||||
b2_angularVelocity += invI2 * (r2X * PY - r2Y * PX);
|
||||
|
||||
ccp.tangentImpulse = newImpulse;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Solver tangent constraints
|
||||
// MOVED ABOVE FOR EFFICIENCY
|
||||
/*for (j = 0; j < tCount; ++j)
|
||||
{
|
||||
ccp = c.points[ j ];
|
||||
|
||||
//r1 = b2Math.b2MulMV(b1.m_R, ccp.localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
tVec = ccp.localAnchor1;
|
||||
r1X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y
|
||||
r1Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y
|
||||
//r2 = b2Math.b2MulMV(b2.m_R, ccp.localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
tVec = ccp.localAnchor2;
|
||||
r2X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y
|
||||
r2Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y
|
||||
|
||||
// Relative velocity at contact
|
||||
//var dv = b2.m_linearVelocity + b2Cross(b2.m_angularVelocity, r2) - b1.m_linearVelocity - b2Cross(b1.m_angularVelocity, r1);
|
||||
//dv = b2Math.SubtractVV(b2Math.SubtractVV(b2Math.AddVV(b2.m_linearVelocity, b2Math.b2CrossFV(b2.m_angularVelocity, r2)), b1.m_linearVelocity), b2Math.b2CrossFV(b1.m_angularVelocity, r1));
|
||||
dvX = b2_linearVelocity.x + (-b2_angularVelocity * r2Y) - b1_linearVelocity.x - (-b1_angularVelocity * r1Y);
|
||||
dvY = b2_linearVelocity.y + (b2_angularVelocity * r2X) - b1_linearVelocity.y - (b1_angularVelocity * r1X);
|
||||
|
||||
// Compute tangent impulse
|
||||
var vt = dvX*tangentX + dvY*tangentY;
|
||||
lambda = ccp.tangentMass * (-vt);
|
||||
|
||||
// b2Clamp the accumulated impulse
|
||||
var maxFriction = c.friction * ccp.normalImpulse;
|
||||
newImpulse = b2Math.b2Clamp(ccp.tangentImpulse + lambda, -maxFriction, maxFriction);
|
||||
lambda = newImpulse - ccp.tangentImpulse;
|
||||
|
||||
// Apply contact impulse
|
||||
//P = b2Math.MulFV(lambda, tangent);
|
||||
PX = lambda * tangentX;
|
||||
PY = lambda * tangentY;
|
||||
|
||||
//b1.m_linearVelocity.Subtract( b2Math.MulFV( invMass1, P ) );
|
||||
b1_linearVelocity.x -= invMass1 * PX;
|
||||
b1_linearVelocity.y -= invMass1 * PY;
|
||||
b1_angularVelocity -= invI1 * (r1X * PY - r1Y * PX);
|
||||
|
||||
//b2.m_linearVelocity.Add( b2Math.MulFV( invMass2, P ) );
|
||||
b2_linearVelocity.x += invMass2 * PX;
|
||||
b2_linearVelocity.y += invMass2 * PY;
|
||||
b2_angularVelocity += invI2 * (r2X * PY - r2Y * PX);
|
||||
|
||||
ccp.tangentImpulse = newImpulse;
|
||||
}*/
|
||||
|
||||
// Update angular velocity
|
||||
b1.m_angularVelocity = b1_angularVelocity;
|
||||
b2.m_angularVelocity = b2_angularVelocity;
|
||||
}
|
||||
},
|
||||
SolvePositionConstraints: function(beta){
|
||||
var minSeparation = 0.0;
|
||||
|
||||
var tMat;
|
||||
var tVec;
|
||||
|
||||
for (var i = 0; i < this.m_constraintCount; ++i)
|
||||
{
|
||||
var c = this.m_constraints[ i ];
|
||||
var b1 = c.body1;
|
||||
var b2 = c.body2;
|
||||
var b1_position = b1.m_position;
|
||||
var b1_rotation = b1.m_rotation;
|
||||
var b2_position = b2.m_position;
|
||||
var b2_rotation = b2.m_rotation;
|
||||
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invI1 = b1.m_invI;
|
||||
var invMass2 = b2.m_invMass;
|
||||
var invI2 = b2.m_invI;
|
||||
//var normal = new b2Vec2(c.normal.x, c.normal.y);
|
||||
var normalX = c.normal.x;
|
||||
var normalY = c.normal.y;
|
||||
//var tangent = b2Math.b2CrossVF(normal, 1.0);
|
||||
var tangentX = normalY;
|
||||
var tangentY = -normalX;
|
||||
|
||||
// Solver normal constraints
|
||||
var tCount = c.pointCount;
|
||||
for (var j = 0; j < tCount; ++j)
|
||||
{
|
||||
var ccp = c.points[ j ];
|
||||
|
||||
//r1 = b2Math.b2MulMV(b1.m_R, ccp.localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
tVec = ccp.localAnchor1;
|
||||
var r1X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y
|
||||
var r1Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y
|
||||
//r2 = b2Math.b2MulMV(b2.m_R, ccp.localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
tVec = ccp.localAnchor2;
|
||||
var r2X = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y
|
||||
var r2Y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y
|
||||
|
||||
//var p1 = b2Math.AddVV(b1.m_position, r1);
|
||||
var p1X = b1_position.x + r1X;
|
||||
var p1Y = b1_position.y + r1Y;
|
||||
|
||||
//var p2 = b2Math.AddVV(b2.m_position, r2);
|
||||
var p2X = b2_position.x + r2X;
|
||||
var p2Y = b2_position.y + r2Y;
|
||||
|
||||
//var dp = b2Math.SubtractVV(p2, p1);
|
||||
var dpX = p2X - p1X;
|
||||
var dpY = p2Y - p1Y;
|
||||
|
||||
// Approximate the current separation.
|
||||
//var separation = b2Math.b2Dot(dp, normal) + ccp.separation;
|
||||
var separation = (dpX*normalX + dpY*normalY) + ccp.separation;
|
||||
|
||||
// Track max constraint error.
|
||||
minSeparation = b2Math.b2Min(minSeparation, separation);
|
||||
|
||||
// Prevent large corrections and allow slop.
|
||||
var C = beta * b2Math.b2Clamp(separation + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
||||
|
||||
// Compute normal impulse
|
||||
var dImpulse = -ccp.normalMass * C;
|
||||
|
||||
// b2Clamp the accumulated impulse
|
||||
var impulse0 = ccp.positionImpulse;
|
||||
ccp.positionImpulse = b2Math.b2Max(impulse0 + dImpulse, 0.0);
|
||||
dImpulse = ccp.positionImpulse - impulse0;
|
||||
|
||||
//var impulse = b2Math.MulFV( dImpulse, normal );
|
||||
var impulseX = dImpulse * normalX;
|
||||
var impulseY = dImpulse * normalY;
|
||||
|
||||
//b1.m_position.Subtract( b2Math.MulFV( invMass1, impulse ) );
|
||||
b1_position.x -= invMass1 * impulseX;
|
||||
b1_position.y -= invMass1 * impulseY;
|
||||
b1_rotation -= invI1 * (r1X * impulseY - r1Y * impulseX);
|
||||
b1.m_R.Set(b1_rotation);
|
||||
|
||||
//b2.m_position.Add( b2Math.MulFV( invMass2, impulse ) );
|
||||
b2_position.x += invMass2 * impulseX;
|
||||
b2_position.y += invMass2 * impulseY;
|
||||
b2_rotation += invI2 * (r2X * impulseY - r2Y * impulseX);
|
||||
b2.m_R.Set(b2_rotation);
|
||||
}
|
||||
// Update body rotations
|
||||
b1.m_rotation = b1_rotation;
|
||||
b2.m_rotation = b2_rotation;
|
||||
}
|
||||
|
||||
return minSeparation >= -b2Settings.b2_linearSlop;
|
||||
},
|
||||
PostSolve: function(){
|
||||
for (var i = 0; i < this.m_constraintCount; ++i)
|
||||
{
|
||||
var c = this.m_constraints[ i ];
|
||||
var m = c.manifold;
|
||||
|
||||
for (var j = 0; j < c.pointCount; ++j)
|
||||
{
|
||||
var mPoint = m.points[j];
|
||||
var cPoint = c.points[j];
|
||||
mPoint.normalImpulse = cPoint.normalImpulse;
|
||||
mPoint.tangentImpulse = cPoint.tangentImpulse;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
m_allocator: null,
|
||||
m_constraints: new Array(),
|
||||
m_constraintCount: 0};
|
65
lib/box2d-js/js/box2d/dynamics/contacts/b2NullContact.js
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2NullContact = Class.create();
|
||||
Object.extend(b2NullContact.prototype, b2Contact.prototype);
|
||||
Object.extend(b2NullContact.prototype,
|
||||
{
|
||||
initialize: function(s1, s2) {
|
||||
// The constructor for b2Contact
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2ContactNode();
|
||||
this.m_node2 = new b2ContactNode();
|
||||
//
|
||||
this.m_flags = 0;
|
||||
|
||||
if (!s1 || !s2){
|
||||
this.m_shape1 = null;
|
||||
this.m_shape2 = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.m_shape1 = s1;
|
||||
this.m_shape2 = s2;
|
||||
|
||||
this.m_manifoldCount = 0;
|
||||
|
||||
this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction);
|
||||
this.m_restitution = b2Math.b2Max(this.m_shape1.m_restitution, this.m_shape2.m_restitution);
|
||||
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
|
||||
this.m_node1.contact = null;
|
||||
this.m_node1.prev = null;
|
||||
this.m_node1.next = null;
|
||||
this.m_node1.other = null;
|
||||
|
||||
this.m_node2.contact = null;
|
||||
this.m_node2.prev = null;
|
||||
this.m_node2.next = null;
|
||||
this.m_node2.other = null;
|
||||
//
|
||||
},
|
||||
Evaluate: function() {},
|
||||
GetManifolds: function(){ return null; }});
|
||||
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2PolyAndCircleContact = Class.create();
|
||||
Object.extend(b2PolyAndCircleContact.prototype, b2Contact.prototype);
|
||||
Object.extend(b2PolyAndCircleContact.prototype, {
|
||||
|
||||
|
||||
initialize: function(s1, s2) {
|
||||
// The constructor for b2Contact
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2ContactNode();
|
||||
this.m_node2 = new b2ContactNode();
|
||||
//
|
||||
this.m_flags = 0;
|
||||
|
||||
if (!s1 || !s2){
|
||||
this.m_shape1 = null;
|
||||
this.m_shape2 = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.m_shape1 = s1;
|
||||
this.m_shape2 = s2;
|
||||
|
||||
this.m_manifoldCount = 0;
|
||||
|
||||
this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction);
|
||||
this.m_restitution = b2Math.b2Max(this.m_shape1.m_restitution, this.m_shape2.m_restitution);
|
||||
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
|
||||
this.m_node1.contact = null;
|
||||
this.m_node1.prev = null;
|
||||
this.m_node1.next = null;
|
||||
this.m_node1.other = null;
|
||||
|
||||
this.m_node2.contact = null;
|
||||
this.m_node2.prev = null;
|
||||
this.m_node2.next = null;
|
||||
this.m_node2.other = null;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_manifold = [new b2Manifold()];
|
||||
//
|
||||
|
||||
//super(shape1, shape2);
|
||||
|
||||
b2Settings.b2Assert(this.m_shape1.m_type == b2Shape.e_polyShape);
|
||||
b2Settings.b2Assert(this.m_shape2.m_type == b2Shape.e_circleShape);
|
||||
this.m_manifold[0].pointCount = 0;
|
||||
this.m_manifold[0].points[0].normalImpulse = 0.0;
|
||||
this.m_manifold[0].points[0].tangentImpulse = 0.0;
|
||||
},
|
||||
//~b2PolyAndCircleContact() {}
|
||||
|
||||
Evaluate: function(){
|
||||
b2Collision.b2CollidePolyAndCircle(this.m_manifold[0], this.m_shape1, this.m_shape2, false);
|
||||
|
||||
if (this.m_manifold[0].pointCount > 0)
|
||||
{
|
||||
this.m_manifoldCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_manifoldCount = 0;
|
||||
}
|
||||
},
|
||||
|
||||
GetManifolds: function()
|
||||
{
|
||||
return this.m_manifold;
|
||||
},
|
||||
|
||||
m_manifold: [new b2Manifold()]})
|
||||
|
||||
b2PolyAndCircleContact.Create = function(shape1, shape2, allocator){
|
||||
return new b2PolyAndCircleContact(shape1, shape2);
|
||||
};
|
||||
b2PolyAndCircleContact.Destroy = function(contact, allocator){
|
||||
//
|
||||
};
|
163
lib/box2d-js/js/box2d/dynamics/contacts/b2PolyContact.js
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2PolyContact = Class.create();
|
||||
Object.extend(b2PolyContact.prototype, b2Contact.prototype);
|
||||
Object.extend(b2PolyContact.prototype,
|
||||
{
|
||||
|
||||
initialize: function(s1, s2) {
|
||||
// The constructor for b2Contact
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2ContactNode();
|
||||
this.m_node2 = new b2ContactNode();
|
||||
//
|
||||
this.m_flags = 0;
|
||||
|
||||
if (!s1 || !s2){
|
||||
this.m_shape1 = null;
|
||||
this.m_shape2 = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.m_shape1 = s1;
|
||||
this.m_shape2 = s2;
|
||||
|
||||
this.m_manifoldCount = 0;
|
||||
|
||||
this.m_friction = Math.sqrt(this.m_shape1.m_friction * this.m_shape2.m_friction);
|
||||
this.m_restitution = b2Math.b2Max(this.m_shape1.m_restitution, this.m_shape2.m_restitution);
|
||||
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
|
||||
this.m_node1.contact = null;
|
||||
this.m_node1.prev = null;
|
||||
this.m_node1.next = null;
|
||||
this.m_node1.other = null;
|
||||
|
||||
this.m_node2.contact = null;
|
||||
this.m_node2.prev = null;
|
||||
this.m_node2.next = null;
|
||||
this.m_node2.other = null;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m0 = new b2Manifold();
|
||||
this.m_manifold = [new b2Manifold()];
|
||||
//
|
||||
|
||||
//super(shape1, shape2);
|
||||
//b2Settings.b2Assert(this.m_shape1.m_type == b2Shape.e_polyShape);
|
||||
//b2Settings.b2Assert(this.m_shape2.m_type == b2Shape.e_polyShape);
|
||||
this.m_manifold[0].pointCount = 0;
|
||||
},
|
||||
//~b2PolyContact() {}
|
||||
|
||||
// store temp manifold to reduce calls to new
|
||||
m0: new b2Manifold(),
|
||||
|
||||
Evaluate: function(){
|
||||
var tMani = this.m_manifold[0];
|
||||
// replace memcpy
|
||||
// memcpy(&this.m0, &this.m_manifold, sizeof(b2Manifold));
|
||||
//this.m0.points = new Array(tMani.pointCount);
|
||||
var tPoints = this.m0.points;
|
||||
|
||||
for (var k = 0; k < tMani.pointCount; k++){
|
||||
var tPoint = tPoints[k];
|
||||
var tPoint0 = tMani.points[k];
|
||||
//tPoint.separation = tPoint0.separation;
|
||||
tPoint.normalImpulse = tPoint0.normalImpulse;
|
||||
tPoint.tangentImpulse = tPoint0.tangentImpulse;
|
||||
//tPoint.position.SetV( tPoint0.position );
|
||||
|
||||
tPoint.id = tPoint0.id.Copy();
|
||||
|
||||
/*this.m0.points[k].id.features = new Features();
|
||||
this.m0.points[k].id.features.referenceFace = this.m_manifold[0].points[k].id.features.referenceFace;
|
||||
this.m0.points[k].id.features.incidentEdge = this.m_manifold[0].points[k].id.features.incidentEdge;
|
||||
this.m0.points[k].id.features.incidentVertex = this.m_manifold[0].points[k].id.features.incidentVertex;
|
||||
this.m0.points[k].id.features.flip = this.m_manifold[0].points[k].id.features.flip;*/
|
||||
}
|
||||
//this.m0.normal.SetV( tMani.normal );
|
||||
this.m0.pointCount = tMani.pointCount;
|
||||
|
||||
b2Collision.b2CollidePoly(tMani, this.m_shape1, this.m_shape2, false);
|
||||
|
||||
// Match contact ids to facilitate warm starting.
|
||||
if (tMani.pointCount > 0)
|
||||
{
|
||||
var match = [false, false];
|
||||
|
||||
// Match old contact ids to new contact ids and copy the
|
||||
// stored impulses to warm start the solver.
|
||||
for (var i = 0; i < tMani.pointCount; ++i)
|
||||
{
|
||||
var cp = tMani.points[ i ];
|
||||
|
||||
cp.normalImpulse = 0.0;
|
||||
cp.tangentImpulse = 0.0;
|
||||
var idKey = cp.id.key;
|
||||
|
||||
for (var j = 0; j < this.m0.pointCount; ++j)
|
||||
{
|
||||
|
||||
if (match[j] == true)
|
||||
continue;
|
||||
|
||||
var cp0 = this.m0.points[j];
|
||||
var id0 = cp0.id;
|
||||
|
||||
if (id0.key == idKey)
|
||||
{
|
||||
match[j] = true;
|
||||
cp.normalImpulse = cp0.normalImpulse;
|
||||
cp.tangentImpulse = cp0.tangentImpulse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.m_manifoldCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_manifoldCount = 0;
|
||||
}
|
||||
},
|
||||
|
||||
GetManifolds: function()
|
||||
{
|
||||
return this.m_manifold;
|
||||
},
|
||||
|
||||
m_manifold: [new b2Manifold()]});
|
||||
|
||||
b2PolyContact.Create = function(shape1, shape2, allocator){
|
||||
//void* mem = allocator->Allocate(sizeof(b2PolyContact));
|
||||
return new b2PolyContact(shape1, shape2);
|
||||
};
|
||||
b2PolyContact.Destroy = function(contact, allocator){
|
||||
//((b2PolyContact*)contact)->~b2PolyContact();
|
||||
//allocator->Free(contact, sizeof(b2PolyContact));
|
||||
};
|
264
lib/box2d-js/js/box2d/dynamics/joints/b2DistanceJoint.js
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// C = norm(p2 - p1) - L
|
||||
// u = (p2 - p1) / norm(p2 - p1)
|
||||
// Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1))
|
||||
// J = [-u -cross(r1, u) u cross(r2, u)]
|
||||
// K = J * invM * JT
|
||||
// = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2
|
||||
|
||||
var b2DistanceJoint = Class.create();
|
||||
Object.extend(b2DistanceJoint.prototype, b2Joint.prototype);
|
||||
Object.extend(b2DistanceJoint.prototype,
|
||||
{
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(def){
|
||||
// The constructor for b2Joint
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2JointNode();
|
||||
this.m_node2 = new b2JointNode();
|
||||
//
|
||||
this.m_type = def.type;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
this.m_body1 = def.body1;
|
||||
this.m_body2 = def.body2;
|
||||
this.m_collideConnected = def.collideConnected;
|
||||
this.m_islandFlag = false;
|
||||
this.m_userData = def.userData;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_localAnchor1 = new b2Vec2();
|
||||
this.m_localAnchor2 = new b2Vec2();
|
||||
this.m_u = new b2Vec2();
|
||||
//
|
||||
|
||||
//super(def);
|
||||
|
||||
var tMat;
|
||||
var tX;
|
||||
var tY;
|
||||
//this.m_localAnchor1 = b2MulT(this.m_body1->m_R, def->anchorPoint1 - this.m_body1->m_position);
|
||||
tMat = this.m_body1.m_R;
|
||||
tX = def.anchorPoint1.x - this.m_body1.m_position.x;
|
||||
tY = def.anchorPoint1.y - this.m_body1.m_position.y;
|
||||
this.m_localAnchor1.x = tX*tMat.col1.x + tY*tMat.col1.y;
|
||||
this.m_localAnchor1.y = tX*tMat.col2.x + tY*tMat.col2.y;
|
||||
//this.m_localAnchor2 = b2MulT(this.m_body2->m_R, def->anchorPoint2 - this.m_body2->m_position);
|
||||
tMat = this.m_body2.m_R;
|
||||
tX = def.anchorPoint2.x - this.m_body2.m_position.x;
|
||||
tY = def.anchorPoint2.y - this.m_body2.m_position.y;
|
||||
this.m_localAnchor2.x = tX*tMat.col1.x + tY*tMat.col1.y;
|
||||
this.m_localAnchor2.y = tX*tMat.col2.x + tY*tMat.col2.y;
|
||||
|
||||
//b2Vec2 d = def->anchorPoint2 - def->anchorPoint1;
|
||||
tX = def.anchorPoint2.x - def.anchorPoint1.x;
|
||||
tY = def.anchorPoint2.y - def.anchorPoint1.y;
|
||||
//this.m_length = d.Length();
|
||||
this.m_length = Math.sqrt(tX*tX + tY*tY);
|
||||
this.m_impulse = 0.0;
|
||||
},
|
||||
|
||||
PrepareVelocitySolver: function(){
|
||||
|
||||
var tMat;
|
||||
|
||||
// Compute the effective mass matrix.
|
||||
//b2Vec2 r1 = b2Mul(this.m_body1->m_R, this.m_localAnchor1);
|
||||
tMat = this.m_body1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(this.m_body2->m_R, this.m_localAnchor2);
|
||||
tMat = this.m_body2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//this.m_u = this.m_body2->m_position + r2 - this.m_body1->m_position - r1;
|
||||
this.m_u.x = this.m_body2.m_position.x + r2X - this.m_body1.m_position.x - r1X;
|
||||
this.m_u.y = this.m_body2.m_position.y + r2Y - this.m_body1.m_position.y - r1Y;
|
||||
|
||||
// Handle singularity.
|
||||
//float32 length = this.m_u.Length();
|
||||
var length = Math.sqrt(this.m_u.x*this.m_u.x + this.m_u.y*this.m_u.y);
|
||||
if (length > b2Settings.b2_linearSlop)
|
||||
{
|
||||
//this.m_u *= 1.0 / length;
|
||||
this.m_u.Multiply( 1.0 / length );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_u.SetZero();
|
||||
}
|
||||
|
||||
//float32 cr1u = b2Cross(r1, this.m_u);
|
||||
var cr1u = (r1X * this.m_u.y - r1Y * this.m_u.x);
|
||||
//float32 cr2u = b2Cross(r2, this.m_u);
|
||||
var cr2u = (r2X * this.m_u.y - r2Y * this.m_u.x);
|
||||
//this.m_mass = this.m_body1->m_invMass + this.m_body1->m_invI * cr1u * cr1u + this.m_body2->m_invMass + this.m_body2->m_invI * cr2u * cr2u;
|
||||
this.m_mass = this.m_body1.m_invMass + this.m_body1.m_invI * cr1u * cr1u + this.m_body2.m_invMass + this.m_body2.m_invI * cr2u * cr2u;
|
||||
//b2Settings.b2Assert(this.m_mass > Number.MIN_VALUE);
|
||||
this.m_mass = 1.0 / this.m_mass;
|
||||
|
||||
if (b2World.s_enableWarmStarting)
|
||||
{
|
||||
//b2Vec2 P = this.m_impulse * this.m_u;
|
||||
var PX = this.m_impulse * this.m_u.x;
|
||||
var PY = this.m_impulse * this.m_u.y;
|
||||
//this.m_body1.m_linearVelocity -= this.m_body1.m_invMass * P;
|
||||
this.m_body1.m_linearVelocity.x -= this.m_body1.m_invMass * PX;
|
||||
this.m_body1.m_linearVelocity.y -= this.m_body1.m_invMass * PY;
|
||||
//this.m_body1.m_angularVelocity -= this.m_body1.m_invI * b2Cross(r1, P);
|
||||
this.m_body1.m_angularVelocity -= this.m_body1.m_invI * (r1X * PY - r1Y * PX);
|
||||
//this.m_body2.m_linearVelocity += this.m_body2.m_invMass * P;
|
||||
this.m_body2.m_linearVelocity.x += this.m_body2.m_invMass * PX;
|
||||
this.m_body2.m_linearVelocity.y += this.m_body2.m_invMass * PY;
|
||||
//this.m_body2.m_angularVelocity += this.m_body2.m_invI * b2Cross(r2, P);
|
||||
this.m_body2.m_angularVelocity += this.m_body2.m_invI * (r2X * PY - r2Y * PX);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_impulse = 0.0;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
|
||||
SolveVelocityConstraints: function(step){
|
||||
|
||||
var tMat;
|
||||
|
||||
//b2Vec2 r1 = b2Mul(this.m_body1->m_R, this.m_localAnchor1);
|
||||
tMat = this.m_body1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(this.m_body2->m_R, this.m_localAnchor2);
|
||||
tMat = this.m_body2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
// Cdot = dot(u, v + cross(w, r))
|
||||
//b2Vec2 v1 = this.m_body1->m_linearVelocity + b2Cross(this.m_body1->m_angularVelocity, r1);
|
||||
var v1X = this.m_body1.m_linearVelocity.x + (-this.m_body1.m_angularVelocity * r1Y);
|
||||
var v1Y = this.m_body1.m_linearVelocity.y + (this.m_body1.m_angularVelocity * r1X);
|
||||
//b2Vec2 v2 = this.m_body2->m_linearVelocity + b2Cross(this.m_body2->m_angularVelocity, r2);
|
||||
var v2X = this.m_body2.m_linearVelocity.x + (-this.m_body2.m_angularVelocity * r2Y);
|
||||
var v2Y = this.m_body2.m_linearVelocity.y + (this.m_body2.m_angularVelocity * r2X);
|
||||
//float32 Cdot = b2Dot(this.m_u, v2 - v1);
|
||||
var Cdot = (this.m_u.x * (v2X - v1X) + this.m_u.y * (v2Y - v1Y));
|
||||
//float32 impulse = -this.m_mass * Cdot;
|
||||
var impulse = -this.m_mass * Cdot;
|
||||
this.m_impulse += impulse;
|
||||
|
||||
//b2Vec2 P = impulse * this.m_u;
|
||||
var PX = impulse * this.m_u.x;
|
||||
var PY = impulse * this.m_u.y;
|
||||
//this.m_body1->m_linearVelocity -= this.m_body1->m_invMass * P;
|
||||
this.m_body1.m_linearVelocity.x -= this.m_body1.m_invMass * PX;
|
||||
this.m_body1.m_linearVelocity.y -= this.m_body1.m_invMass * PY;
|
||||
//this.m_body1->m_angularVelocity -= this.m_body1->m_invI * b2Cross(r1, P);
|
||||
this.m_body1.m_angularVelocity -= this.m_body1.m_invI * (r1X * PY - r1Y * PX);
|
||||
//this.m_body2->m_linearVelocity += this.m_body2->m_invMass * P;
|
||||
this.m_body2.m_linearVelocity.x += this.m_body2.m_invMass * PX;
|
||||
this.m_body2.m_linearVelocity.y += this.m_body2.m_invMass * PY;
|
||||
//this.m_body2->m_angularVelocity += this.m_body2->m_invI * b2Cross(r2, P);
|
||||
this.m_body2.m_angularVelocity += this.m_body2.m_invI * (r2X * PY - r2Y * PX);
|
||||
},
|
||||
|
||||
SolvePositionConstraints: function(){
|
||||
|
||||
var tMat;
|
||||
|
||||
//b2Vec2 r1 = b2Mul(this.m_body1->m_R, this.m_localAnchor1);
|
||||
tMat = this.m_body1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(this.m_body2->m_R, this.m_localAnchor2);
|
||||
tMat = this.m_body2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//b2Vec2 d = this.m_body2->m_position + r2 - this.m_body1->m_position - r1;
|
||||
var dX = this.m_body2.m_position.x + r2X - this.m_body1.m_position.x - r1X;
|
||||
var dY = this.m_body2.m_position.y + r2Y - this.m_body1.m_position.y - r1Y;
|
||||
|
||||
//float32 length = d.Normalize();
|
||||
var length = Math.sqrt(dX*dX + dY*dY);
|
||||
dX /= length;
|
||||
dY /= length;
|
||||
//float32 C = length - this.m_length;
|
||||
var C = length - this.m_length;
|
||||
C = b2Math.b2Clamp(C, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
|
||||
|
||||
var impulse = -this.m_mass * C;
|
||||
//this.m_u = d;
|
||||
this.m_u.Set(dX, dY);
|
||||
//b2Vec2 P = impulse * this.m_u;
|
||||
var PX = impulse * this.m_u.x;
|
||||
var PY = impulse * this.m_u.y;
|
||||
|
||||
//this.m_body1->m_position -= this.m_body1->m_invMass * P;
|
||||
this.m_body1.m_position.x -= this.m_body1.m_invMass * PX;
|
||||
this.m_body1.m_position.y -= this.m_body1.m_invMass * PY;
|
||||
//this.m_body1->m_rotation -= this.m_body1->m_invI * b2Cross(r1, P);
|
||||
this.m_body1.m_rotation -= this.m_body1.m_invI * (r1X * PY - r1Y * PX);
|
||||
//this.m_body2->m_position += this.m_body2->m_invMass * P;
|
||||
this.m_body2.m_position.x += this.m_body2.m_invMass * PX;
|
||||
this.m_body2.m_position.y += this.m_body2.m_invMass * PY;
|
||||
//this.m_body2->m_rotation -= this.m_body2->m_invI * b2Cross(r2, P);
|
||||
this.m_body2.m_rotation += this.m_body2.m_invI * (r2X * PY - r2Y * PX);
|
||||
|
||||
this.m_body1.m_R.Set(this.m_body1.m_rotation);
|
||||
this.m_body2.m_R.Set(this.m_body2.m_rotation);
|
||||
|
||||
return b2Math.b2Abs(C) < b2Settings.b2_linearSlop;
|
||||
|
||||
},
|
||||
|
||||
GetAnchor1: function(){
|
||||
return b2Math.AddVV(this.m_body1.m_position , b2Math.b2MulMV(this.m_body1.m_R, this.m_localAnchor1));
|
||||
},
|
||||
GetAnchor2: function(){
|
||||
return b2Math.AddVV(this.m_body2.m_position , b2Math.b2MulMV(this.m_body2.m_R, this.m_localAnchor2));
|
||||
},
|
||||
|
||||
GetReactionForce: function(invTimeStep)
|
||||
{
|
||||
//var F = (this.m_impulse * invTimeStep) * this.m_u;
|
||||
var F = new b2Vec2();
|
||||
F.SetV(this.m_u);
|
||||
F.Multiply(this.m_impulse * invTimeStep);
|
||||
return F;
|
||||
},
|
||||
|
||||
GetReactionTorque: function(invTimeStep)
|
||||
{
|
||||
//NOT_USED(invTimeStep);
|
||||
return 0.0;
|
||||
},
|
||||
|
||||
m_localAnchor1: new b2Vec2(),
|
||||
m_localAnchor2: new b2Vec2(),
|
||||
m_u: new b2Vec2(),
|
||||
m_impulse: null,
|
||||
m_mass: null,
|
||||
m_length: null});
|
||||
|
49
lib/box2d-js/js/box2d/dynamics/joints/b2DistanceJointDef.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2DistanceJointDef = Class.create();
|
||||
Object.extend(b2DistanceJointDef.prototype, b2JointDef.prototype);
|
||||
Object.extend(b2DistanceJointDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2JointDef
|
||||
this.type = b2Joint.e_unknownJoint;
|
||||
this.userData = null;
|
||||
this.body1 = null;
|
||||
this.body2 = null;
|
||||
this.collideConnected = false;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.anchorPoint1 = new b2Vec2();
|
||||
this.anchorPoint2 = new b2Vec2();
|
||||
//
|
||||
|
||||
this.type = b2Joint.e_distanceJoint;
|
||||
//this.anchorPoint1.Set(0.0, 0.0);
|
||||
//this.anchorPoint2.Set(0.0, 0.0);
|
||||
},
|
||||
|
||||
anchorPoint1: new b2Vec2(),
|
||||
anchorPoint2: new b2Vec2()});
|
||||
|
307
lib/box2d-js/js/box2d/dynamics/joints/b2GearJoint.js
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2GearJoint = Class.create();
|
||||
Object.extend(b2GearJoint.prototype, b2Joint.prototype);
|
||||
Object.extend(b2GearJoint.prototype,
|
||||
{
|
||||
GetAnchor1: function(){
|
||||
//return this.m_body1.m_position + b2MulMV(this.m_body1.m_R, this.m_localAnchor1);
|
||||
var tMat = this.m_body1.m_R;
|
||||
return new b2Vec2( this.m_body1.m_position.x + (tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y),
|
||||
this.m_body1.m_position.y + (tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y));
|
||||
},
|
||||
GetAnchor2: function(){
|
||||
//return this.m_body2->m_position + b2Mul(this.m_body2->m_R, this.m_localAnchor2);
|
||||
var tMat = this.m_body2.m_R;
|
||||
return new b2Vec2( this.m_body2.m_position.x + (tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y),
|
||||
this.m_body2.m_position.y + (tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y));
|
||||
},
|
||||
|
||||
GetReactionForce: function(invTimeStep){
|
||||
//b2Vec2 F(0.0f, 0.0f);
|
||||
return new b2Vec2();
|
||||
},
|
||||
GetReactionTorque: function(invTimeStep){
|
||||
return 0.0;
|
||||
},
|
||||
|
||||
GetRatio: function(){
|
||||
return this.m_ratio;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(def){
|
||||
// The constructor for b2Joint
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2JointNode();
|
||||
this.m_node2 = new b2JointNode();
|
||||
//
|
||||
this.m_type = def.type;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
this.m_body1 = def.body1;
|
||||
this.m_body2 = def.body2;
|
||||
this.m_collideConnected = def.collideConnected;
|
||||
this.m_islandFlag = false;
|
||||
this.m_userData = def.userData;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_groundAnchor1 = new b2Vec2();
|
||||
this.m_groundAnchor2 = new b2Vec2();
|
||||
this.m_localAnchor1 = new b2Vec2();
|
||||
this.m_localAnchor2 = new b2Vec2();
|
||||
this.m_J = new b2Jacobian();
|
||||
//
|
||||
|
||||
// parent constructor
|
||||
//super(def);
|
||||
|
||||
//b2Settings.b2Assert(def.joint1.m_type == b2Joint.e_revoluteJoint || def.joint1.m_type == b2Joint.e_prismaticJoint);
|
||||
//b2Settings.b2Assert(def.joint2.m_type == b2Joint.e_revoluteJoint || def.joint2.m_type == b2Joint.e_prismaticJoint);
|
||||
//b2Settings.b2Assert(def.joint1.m_body1.IsStatic());
|
||||
//b2Settings.b2Assert(def.joint2.m_body1.IsStatic());
|
||||
|
||||
this.m_revolute1 = null;
|
||||
this.m_prismatic1 = null;
|
||||
this.m_revolute2 = null;
|
||||
this.m_prismatic2 = null;
|
||||
|
||||
var coordinate1;
|
||||
var coordinate2;
|
||||
|
||||
this.m_ground1 = def.joint1.m_body1;
|
||||
this.m_body1 = def.joint1.m_body2;
|
||||
if (def.joint1.m_type == b2Joint.e_revoluteJoint)
|
||||
{
|
||||
this.m_revolute1 = def.joint1;
|
||||
this.m_groundAnchor1.SetV( this.m_revolute1.m_localAnchor1 );
|
||||
this.m_localAnchor1.SetV( this.m_revolute1.m_localAnchor2 );
|
||||
coordinate1 = this.m_revolute1.GetJointAngle();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_prismatic1 = def.joint1;
|
||||
this.m_groundAnchor1.SetV( this.m_prismatic1.m_localAnchor1 );
|
||||
this.m_localAnchor1.SetV( this.m_prismatic1.m_localAnchor2 );
|
||||
coordinate1 = this.m_prismatic1.GetJointTranslation();
|
||||
}
|
||||
|
||||
this.m_ground2 = def.joint2.m_body1;
|
||||
this.m_body2 = def.joint2.m_body2;
|
||||
if (def.joint2.m_type == b2Joint.e_revoluteJoint)
|
||||
{
|
||||
this.m_revolute2 = def.joint2;
|
||||
this.m_groundAnchor2.SetV( this.m_revolute2.m_localAnchor1 );
|
||||
this.m_localAnchor2.SetV( this.m_revolute2.m_localAnchor2 );
|
||||
coordinate2 = this.m_revolute2.GetJointAngle();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_prismatic2 = def.joint2;
|
||||
this.m_groundAnchor2.SetV( this.m_prismatic2.m_localAnchor1 );
|
||||
this.m_localAnchor2.SetV( this.m_prismatic2.m_localAnchor2 );
|
||||
coordinate2 = this.m_prismatic2.GetJointTranslation();
|
||||
}
|
||||
|
||||
this.m_ratio = def.ratio;
|
||||
|
||||
this.m_constant = coordinate1 + this.m_ratio * coordinate2;
|
||||
|
||||
this.m_impulse = 0.0;
|
||||
|
||||
},
|
||||
|
||||
PrepareVelocitySolver: function(){
|
||||
var g1 = this.m_ground1;
|
||||
var g2 = this.m_ground2;
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
// temp vars
|
||||
var ugX;
|
||||
var ugY;
|
||||
var rX;
|
||||
var rY;
|
||||
var tMat;
|
||||
var tVec;
|
||||
var crug;
|
||||
|
||||
var K = 0.0;
|
||||
this.m_J.SetZero();
|
||||
|
||||
if (this.m_revolute1)
|
||||
{
|
||||
this.m_J.angular1 = -1.0;
|
||||
K += b1.m_invI;
|
||||
}
|
||||
else
|
||||
{
|
||||
//b2Vec2 ug = b2MulMV(g1->m_R, this.m_prismatic1->m_localXAxis1);
|
||||
tMat = g1.m_R;
|
||||
tVec = this.m_prismatic1.m_localXAxis1;
|
||||
ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
|
||||
ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
|
||||
//b2Vec2 r = b2MulMV(b1->m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
rX = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
rY = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
|
||||
//var crug = b2Cross(r, ug);
|
||||
crug = rX * ugY - rY * ugX;
|
||||
//this.m_J.linear1 = -ug;
|
||||
this.m_J.linear1.Set(-ugX, -ugY);
|
||||
this.m_J.angular1 = -crug;
|
||||
K += b1.m_invMass + b1.m_invI * crug * crug;
|
||||
}
|
||||
|
||||
if (this.m_revolute2)
|
||||
{
|
||||
this.m_J.angular2 = -this.m_ratio;
|
||||
K += this.m_ratio * this.m_ratio * b2.m_invI;
|
||||
}
|
||||
else
|
||||
{
|
||||
//b2Vec2 ug = b2Mul(g2->m_R, this.m_prismatic2->m_localXAxis1);
|
||||
tMat = g2.m_R;
|
||||
tVec = this.m_prismatic2.m_localXAxis1;
|
||||
ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
|
||||
ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
|
||||
//b2Vec2 r = b2Mul(b2->m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
rX = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
rY = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//float32 crug = b2Cross(r, ug);
|
||||
crug = rX * ugY - rY * ugX;
|
||||
//this.m_J.linear2 = -this.m_ratio * ug;
|
||||
this.m_J.linear2.Set(-this.m_ratio*ugX, -this.m_ratio*ugY);
|
||||
this.m_J.angular2 = -this.m_ratio * crug;
|
||||
K += this.m_ratio * this.m_ratio * (b2.m_invMass + b2.m_invI * crug * crug);
|
||||
}
|
||||
|
||||
// Compute effective mass.
|
||||
//b2Settings.b2Assert(K > 0.0);
|
||||
this.m_mass = 1.0 / K;
|
||||
|
||||
// Warm starting.
|
||||
//b1.m_linearVelocity += b1.m_invMass * this.m_impulse * this.m_J.linear1;
|
||||
b1.m_linearVelocity.x += b1.m_invMass * this.m_impulse * this.m_J.linear1.x;
|
||||
b1.m_linearVelocity.y += b1.m_invMass * this.m_impulse * this.m_J.linear1.y;
|
||||
b1.m_angularVelocity += b1.m_invI * this.m_impulse * this.m_J.angular1;
|
||||
//b2.m_linearVelocity += b2.m_invMass * this.m_impulse * this.m_J.linear2;
|
||||
b2.m_linearVelocity.x += b2.m_invMass * this.m_impulse * this.m_J.linear2.x;
|
||||
b2.m_linearVelocity.y += b2.m_invMass * this.m_impulse * this.m_J.linear2.y;
|
||||
b2.m_angularVelocity += b2.m_invI * this.m_impulse * this.m_J.angular2;
|
||||
},
|
||||
|
||||
|
||||
SolveVelocityConstraints: function(step){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var Cdot = this.m_J.Compute( b1.m_linearVelocity, b1.m_angularVelocity,
|
||||
b2.m_linearVelocity, b2.m_angularVelocity);
|
||||
|
||||
var impulse = -this.m_mass * Cdot;
|
||||
this.m_impulse += impulse;
|
||||
|
||||
b1.m_linearVelocity.x += b1.m_invMass * impulse * this.m_J.linear1.x;
|
||||
b1.m_linearVelocity.y += b1.m_invMass * impulse * this.m_J.linear1.y;
|
||||
b1.m_angularVelocity += b1.m_invI * impulse * this.m_J.angular1;
|
||||
b2.m_linearVelocity.x += b2.m_invMass * impulse * this.m_J.linear2.x;
|
||||
b2.m_linearVelocity.y += b2.m_invMass * impulse * this.m_J.linear2.y;
|
||||
b2.m_angularVelocity += b2.m_invI * impulse * this.m_J.angular2;
|
||||
},
|
||||
|
||||
SolvePositionConstraints: function(){
|
||||
var linearError = 0.0;
|
||||
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var coordinate1;
|
||||
var coordinate2;
|
||||
if (this.m_revolute1)
|
||||
{
|
||||
coordinate1 = this.m_revolute1.GetJointAngle();
|
||||
}
|
||||
else
|
||||
{
|
||||
coordinate1 = this.m_prismatic1.GetJointTranslation();
|
||||
}
|
||||
|
||||
if (this.m_revolute2)
|
||||
{
|
||||
coordinate2 = this.m_revolute2.GetJointAngle();
|
||||
}
|
||||
else
|
||||
{
|
||||
coordinate2 = this.m_prismatic2.GetJointTranslation();
|
||||
}
|
||||
|
||||
var C = this.m_constant - (coordinate1 + this.m_ratio * coordinate2);
|
||||
|
||||
var impulse = -this.m_mass * C;
|
||||
|
||||
b1.m_position.x += b1.m_invMass * impulse * this.m_J.linear1.x;
|
||||
b1.m_position.y += b1.m_invMass * impulse * this.m_J.linear1.y;
|
||||
b1.m_rotation += b1.m_invI * impulse * this.m_J.angular1;
|
||||
b2.m_position.x += b2.m_invMass * impulse * this.m_J.linear2.x;
|
||||
b2.m_position.y += b2.m_invMass * impulse * this.m_J.linear2.y;
|
||||
b2.m_rotation += b2.m_invI * impulse * this.m_J.angular2;
|
||||
b1.m_R.Set(b1.m_rotation);
|
||||
b2.m_R.Set(b2.m_rotation);
|
||||
|
||||
return linearError < b2Settings.b2_linearSlop;
|
||||
},
|
||||
|
||||
m_ground1: null,
|
||||
m_ground2: null,
|
||||
|
||||
// One of these is NULL.
|
||||
m_revolute1: null,
|
||||
m_prismatic1: null,
|
||||
|
||||
// One of these is NULL.
|
||||
m_revolute2: null,
|
||||
m_prismatic2: null,
|
||||
|
||||
m_groundAnchor1: new b2Vec2(),
|
||||
m_groundAnchor2: new b2Vec2(),
|
||||
|
||||
m_localAnchor1: new b2Vec2(),
|
||||
m_localAnchor2: new b2Vec2(),
|
||||
|
||||
m_J: new b2Jacobian(),
|
||||
|
||||
m_constant: null,
|
||||
m_ratio: null,
|
||||
|
||||
// Effective mass
|
||||
m_mass: null,
|
||||
|
||||
// Impulse for accumulation/warm starting.
|
||||
m_impulse: null});
|
||||
|
50
lib/box2d-js/js/box2d/dynamics/joints/b2GearJointDef.js
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// A gear joint is used to connect two joints together. Either joint
|
||||
// can be a revolute or prismatic joint. You specify a gear ratio
|
||||
// to bind the motions together:
|
||||
// coordinate1 + ratio * coordinate2 = constant
|
||||
// The ratio can be negative or positive. If one joint is a revolute joint
|
||||
// and the other joint is a prismatic joint, then the ratio will have units
|
||||
// of length or units of 1/length.
|
||||
//
|
||||
// RESTRICITON: The revolute and prismatic joints must be attached to
|
||||
// a fixed body (which must be body1 on those joints).
|
||||
|
||||
var b2GearJointDef = Class.create();
|
||||
Object.extend(b2GearJointDef.prototype, b2JointDef.prototype);
|
||||
Object.extend(b2GearJointDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
this.type = b2Joint.e_gearJoint;
|
||||
this.joint1 = null;
|
||||
this.joint2 = null;
|
||||
this.ratio = 1.0;
|
||||
},
|
||||
|
||||
joint1: null,
|
||||
joint2: null,
|
||||
ratio: null});
|
||||
|
49
lib/box2d-js/js/box2d/dynamics/joints/b2Jacobian.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2Jacobian = Class.create();
|
||||
b2Jacobian.prototype =
|
||||
{
|
||||
linear1: new b2Vec2(),
|
||||
angular1: null,
|
||||
linear2: new b2Vec2(),
|
||||
angular2: null,
|
||||
|
||||
SetZero: function(){
|
||||
this.linear1.SetZero(); this.angular1 = 0.0;
|
||||
this.linear2.SetZero(); this.angular2 = 0.0;
|
||||
},
|
||||
Set: function(x1, a1, x2, a2){
|
||||
this.linear1.SetV(x1); this.angular1 = a1;
|
||||
this.linear2.SetV(x2); this.angular2 = a2;
|
||||
},
|
||||
Compute: function(x1, a1, x2, a2){
|
||||
|
||||
//return b2Math.b2Dot(this.linear1, x1) + this.angular1 * a1 + b2Math.b2Dot(this.linear2, x2) + this.angular2 * a2;
|
||||
return (this.linear1.x*x1.x + this.linear1.y*x1.y) + this.angular1 * a1 + (this.linear2.x*x2.x + this.linear2.y*x2.y) + this.angular2 * a2;
|
||||
},
|
||||
initialize: function() {
|
||||
// initialize instance variables for references
|
||||
this.linear1 = new b2Vec2();
|
||||
this.linear2 = new b2Vec2();
|
||||
//
|
||||
}};
|
200
lib/box2d-js/js/box2d/dynamics/joints/b2Joint.js
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2Joint = Class.create();
|
||||
b2Joint.prototype =
|
||||
{
|
||||
GetType: function(){
|
||||
return this.m_type;
|
||||
},
|
||||
|
||||
GetAnchor1: function(){return null},
|
||||
GetAnchor2: function(){return null},
|
||||
|
||||
GetReactionForce: function(invTimeStep){return null},
|
||||
GetReactionTorque: function(invTimeStep){return 0.0},
|
||||
|
||||
GetBody1: function()
|
||||
{
|
||||
return this.m_body1;
|
||||
},
|
||||
|
||||
GetBody2: function()
|
||||
{
|
||||
return this.m_body2;
|
||||
},
|
||||
|
||||
GetNext: function(){
|
||||
return this.m_next;
|
||||
},
|
||||
|
||||
GetUserData: function(){
|
||||
return this.m_userData;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
|
||||
|
||||
initialize: function(def){
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2JointNode();
|
||||
this.m_node2 = new b2JointNode();
|
||||
//
|
||||
|
||||
this.m_type = def.type;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
this.m_body1 = def.body1;
|
||||
this.m_body2 = def.body2;
|
||||
this.m_collideConnected = def.collideConnected;
|
||||
this.m_islandFlag = false;
|
||||
this.m_userData = def.userData;
|
||||
},
|
||||
//virtual ~b2Joint() {}
|
||||
|
||||
PrepareVelocitySolver: function(){},
|
||||
SolveVelocityConstraints: function(step){},
|
||||
|
||||
// This returns true if the position errors are within tolerance.
|
||||
PreparePositionSolver: function(){},
|
||||
SolvePositionConstraints: function(){return false},
|
||||
|
||||
m_type: 0,
|
||||
m_prev: null,
|
||||
m_next: null,
|
||||
m_node1: new b2JointNode(),
|
||||
m_node2: new b2JointNode(),
|
||||
m_body1: null,
|
||||
m_body2: null,
|
||||
|
||||
m_islandFlag: null,
|
||||
m_collideConnected: null,
|
||||
|
||||
m_userData: null
|
||||
|
||||
|
||||
// ENUMS
|
||||
|
||||
// enum b2JointType
|
||||
|
||||
// enum b2LimitState
|
||||
|
||||
};
|
||||
b2Joint.Create = function(def, allocator){
|
||||
var joint = null;
|
||||
|
||||
switch (def.type)
|
||||
{
|
||||
case b2Joint.e_distanceJoint:
|
||||
{
|
||||
//void* mem = allocator->Allocate(sizeof(b2DistanceJoint));
|
||||
joint = new b2DistanceJoint(def);
|
||||
}
|
||||
break;
|
||||
|
||||
case b2Joint.e_mouseJoint:
|
||||
{
|
||||
//void* mem = allocator->Allocate(sizeof(b2MouseJoint));
|
||||
joint = new b2MouseJoint(def);
|
||||
}
|
||||
break;
|
||||
|
||||
case b2Joint.e_prismaticJoint:
|
||||
{
|
||||
//void* mem = allocator->Allocate(sizeof(b2PrismaticJoint));
|
||||
joint = new b2PrismaticJoint(def);
|
||||
}
|
||||
break;
|
||||
|
||||
case b2Joint.e_revoluteJoint:
|
||||
{
|
||||
//void* mem = allocator->Allocate(sizeof(b2RevoluteJoint));
|
||||
joint = new b2RevoluteJoint(def);
|
||||
}
|
||||
break;
|
||||
|
||||
case b2Joint.e_pulleyJoint:
|
||||
{
|
||||
//void* mem = allocator->Allocate(sizeof(b2PulleyJoint));
|
||||
joint = new b2PulleyJoint(def);
|
||||
}
|
||||
break;
|
||||
|
||||
case b2Joint.e_gearJoint:
|
||||
{
|
||||
//void* mem = allocator->Allocate(sizeof(b2GearJoint));
|
||||
joint = new b2GearJoint(def);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//b2Settings.b2Assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return joint;
|
||||
};
|
||||
b2Joint.Destroy = function(joint, allocator){
|
||||
/*joint->~b2Joint();
|
||||
switch (joint.m_type)
|
||||
{
|
||||
case b2Joint.e_distanceJoint:
|
||||
allocator->Free(joint, sizeof(b2DistanceJoint));
|
||||
break;
|
||||
|
||||
case b2Joint.e_mouseJoint:
|
||||
allocator->Free(joint, sizeof(b2MouseJoint));
|
||||
break;
|
||||
|
||||
case b2Joint.e_prismaticJoint:
|
||||
allocator->Free(joint, sizeof(b2PrismaticJoint));
|
||||
break;
|
||||
|
||||
case b2Joint.e_revoluteJoint:
|
||||
allocator->Free(joint, sizeof(b2RevoluteJoint));
|
||||
break;
|
||||
|
||||
case b2Joint.e_pulleyJoint:
|
||||
allocator->Free(joint, sizeof(b2PulleyJoint));
|
||||
break;
|
||||
|
||||
case b2Joint.e_gearJoint:
|
||||
allocator->Free(joint, sizeof(b2GearJoint));
|
||||
break;
|
||||
|
||||
default:
|
||||
b2Assert(false);
|
||||
break;
|
||||
}*/
|
||||
};
|
||||
b2Joint.e_unknownJoint = 0;
|
||||
b2Joint.e_revoluteJoint = 1;
|
||||
b2Joint.e_prismaticJoint = 2;
|
||||
b2Joint.e_distanceJoint = 3;
|
||||
b2Joint.e_pulleyJoint = 4;
|
||||
b2Joint.e_mouseJoint = 5;
|
||||
b2Joint.e_gearJoint = 6;
|
||||
b2Joint.e_inactiveLimit = 0;
|
||||
b2Joint.e_atLowerLimit = 1;
|
||||
b2Joint.e_atUpperLimit = 2;
|
||||
b2Joint.e_equalLimits = 3;
|
40
lib/box2d-js/js/box2d/dynamics/joints/b2JointDef.js
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2JointDef = Class.create();
|
||||
b2JointDef.prototype =
|
||||
{
|
||||
|
||||
initialize: function()
|
||||
{
|
||||
this.type = b2Joint.e_unknownJoint;
|
||||
this.userData = null;
|
||||
this.body1 = null;
|
||||
this.body2 = null;
|
||||
this.collideConnected = false;
|
||||
},
|
||||
|
||||
type: 0,
|
||||
userData: null,
|
||||
body1: null,
|
||||
body2: null,
|
||||
collideConnected: null}
|
33
lib/box2d-js/js/box2d/dynamics/joints/b2JointNode.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2JointNode = Class.create();
|
||||
b2JointNode.prototype =
|
||||
{
|
||||
|
||||
other: null,
|
||||
joint: null,
|
||||
prev: null,
|
||||
next: null,
|
||||
|
||||
|
||||
initialize: function() {}}
|
234
lib/box2d-js/js/box2d/dynamics/joints/b2MouseJoint.js
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// p = attached point, m = mouse point
|
||||
// C = p - m
|
||||
// Cdot = v
|
||||
// = v + cross(w, r)
|
||||
// J = [I r_skew]
|
||||
// Identity used:
|
||||
// w k % (rx i + ry j) = w * (-ry i + rx j)
|
||||
|
||||
var b2MouseJoint = Class.create();
|
||||
Object.extend(b2MouseJoint.prototype, b2Joint.prototype);
|
||||
Object.extend(b2MouseJoint.prototype,
|
||||
{
|
||||
GetAnchor1: function(){
|
||||
return this.m_target;
|
||||
},
|
||||
GetAnchor2: function(){
|
||||
var tVec = b2Math.b2MulMV(this.m_body2.m_R, this.m_localAnchor);
|
||||
tVec.Add(this.m_body2.m_position);
|
||||
return tVec;
|
||||
},
|
||||
|
||||
GetReactionForce: function(invTimeStep)
|
||||
{
|
||||
//b2Vec2 F = invTimeStep * this.m_impulse;
|
||||
var F = new b2Vec2();
|
||||
F.SetV(this.m_impulse);
|
||||
F.Multiply(invTimeStep);
|
||||
return F;
|
||||
},
|
||||
|
||||
GetReactionTorque: function(invTimeStep)
|
||||
{
|
||||
//NOT_USED(invTimeStep);
|
||||
return 0.0;
|
||||
},
|
||||
|
||||
SetTarget: function(target){
|
||||
this.m_body2.WakeUp();
|
||||
this.m_target = target;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(def){
|
||||
// The constructor for b2Joint
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2JointNode();
|
||||
this.m_node2 = new b2JointNode();
|
||||
//
|
||||
this.m_type = def.type;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
this.m_body1 = def.body1;
|
||||
this.m_body2 = def.body2;
|
||||
this.m_collideConnected = def.collideConnected;
|
||||
this.m_islandFlag = false;
|
||||
this.m_userData = def.userData;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.K = new b2Mat22();
|
||||
this.K1 = new b2Mat22();
|
||||
this.K2 = new b2Mat22();
|
||||
this.m_localAnchor = new b2Vec2();
|
||||
this.m_target = new b2Vec2();
|
||||
this.m_impulse = new b2Vec2();
|
||||
this.m_ptpMass = new b2Mat22();
|
||||
this.m_C = new b2Vec2();
|
||||
//
|
||||
|
||||
//super(def);
|
||||
|
||||
this.m_target.SetV(def.target);
|
||||
//this.m_localAnchor = b2Math.b2MulTMV(this.m_body2.m_R, b2Math.SubtractVV( this.m_target, this.m_body2.m_position ) );
|
||||
var tX = this.m_target.x - this.m_body2.m_position.x;
|
||||
var tY = this.m_target.y - this.m_body2.m_position.y;
|
||||
this.m_localAnchor.x = (tX * this.m_body2.m_R.col1.x + tY * this.m_body2.m_R.col1.y);
|
||||
this.m_localAnchor.y = (tX * this.m_body2.m_R.col2.x + tY * this.m_body2.m_R.col2.y);
|
||||
|
||||
this.m_maxForce = def.maxForce;
|
||||
this.m_impulse.SetZero();
|
||||
|
||||
var mass = this.m_body2.m_mass;
|
||||
|
||||
// Frequency
|
||||
var omega = 2.0 * b2Settings.b2_pi * def.frequencyHz;
|
||||
|
||||
// Damping coefficient
|
||||
var d = 2.0 * mass * def.dampingRatio * omega;
|
||||
|
||||
// Spring stiffness
|
||||
var k = mass * omega * omega;
|
||||
|
||||
// magic formulas
|
||||
this.m_gamma = 1.0 / (d + def.timeStep * k);
|
||||
this.m_beta = def.timeStep * k / (d + def.timeStep * k);
|
||||
},
|
||||
|
||||
// Presolve vars
|
||||
K: new b2Mat22(),
|
||||
K1: new b2Mat22(),
|
||||
K2: new b2Mat22(),
|
||||
PrepareVelocitySolver: function(){
|
||||
var b = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
// Compute the effective mass matrix.
|
||||
//b2Vec2 r = b2Mul(b.m_R, this.m_localAnchor);
|
||||
tMat = b.m_R;
|
||||
var rX = tMat.col1.x * this.m_localAnchor.x + tMat.col2.x * this.m_localAnchor.y;
|
||||
var rY = tMat.col1.y * this.m_localAnchor.x + tMat.col2.y * this.m_localAnchor.y;
|
||||
|
||||
// this.K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
|
||||
// = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
|
||||
// [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
|
||||
var invMass = b.m_invMass;
|
||||
var invI = b.m_invI;
|
||||
|
||||
//b2Mat22 this.K1;
|
||||
this.K1.col1.x = invMass; this.K1.col2.x = 0.0;
|
||||
this.K1.col1.y = 0.0; this.K1.col2.y = invMass;
|
||||
|
||||
//b2Mat22 this.K2;
|
||||
this.K2.col1.x = invI * rY * rY; this.K2.col2.x = -invI * rX * rY;
|
||||
this.K2.col1.y = -invI * rX * rY; this.K2.col2.y = invI * rX * rX;
|
||||
|
||||
//b2Mat22 this.K = this.K1 + this.K2;
|
||||
this.K.SetM(this.K1);
|
||||
this.K.AddM(this.K2);
|
||||
this.K.col1.x += this.m_gamma;
|
||||
this.K.col2.y += this.m_gamma;
|
||||
|
||||
//this.m_ptpMass = this.K.Invert();
|
||||
this.K.Invert(this.m_ptpMass);
|
||||
|
||||
//this.m_C = b.m_position + r - this.m_target;
|
||||
this.m_C.x = b.m_position.x + rX - this.m_target.x;
|
||||
this.m_C.y = b.m_position.y + rY - this.m_target.y;
|
||||
|
||||
// Cheat with some damping
|
||||
b.m_angularVelocity *= 0.98;
|
||||
|
||||
// Warm starting.
|
||||
//b2Vec2 P = this.m_impulse;
|
||||
var PX = this.m_impulse.x;
|
||||
var PY = this.m_impulse.y;
|
||||
//b.m_linearVelocity += invMass * P;
|
||||
b.m_linearVelocity.x += invMass * PX;
|
||||
b.m_linearVelocity.y += invMass * PY;
|
||||
//b.m_angularVelocity += invI * b2Cross(r, P);
|
||||
b.m_angularVelocity += invI * (rX * PY - rY * PX);
|
||||
},
|
||||
|
||||
|
||||
SolveVelocityConstraints: function(step){
|
||||
var body = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
// Compute the effective mass matrix.
|
||||
//b2Vec2 r = b2Mul(body.m_R, this.m_localAnchor);
|
||||
tMat = body.m_R;
|
||||
var rX = tMat.col1.x * this.m_localAnchor.x + tMat.col2.x * this.m_localAnchor.y;
|
||||
var rY = tMat.col1.y * this.m_localAnchor.x + tMat.col2.y * this.m_localAnchor.y;
|
||||
|
||||
// Cdot = v + cross(w, r)
|
||||
//b2Vec2 Cdot = body->m_linearVelocity + b2Cross(body->m_angularVelocity, r);
|
||||
var CdotX = body.m_linearVelocity.x + (-body.m_angularVelocity * rY);
|
||||
var CdotY = body.m_linearVelocity.y + (body.m_angularVelocity * rX);
|
||||
//b2Vec2 impulse = -b2Mul(this.m_ptpMass, Cdot + (this.m_beta * step->inv_dt) * this.m_C + this.m_gamma * this.m_impulse);
|
||||
tMat = this.m_ptpMass;
|
||||
var tX = CdotX + (this.m_beta * step.inv_dt) * this.m_C.x + this.m_gamma * this.m_impulse.x;
|
||||
var tY = CdotY + (this.m_beta * step.inv_dt) * this.m_C.y + this.m_gamma * this.m_impulse.y;
|
||||
var impulseX = -(tMat.col1.x * tX + tMat.col2.x * tY);
|
||||
var impulseY = -(tMat.col1.y * tX + tMat.col2.y * tY);
|
||||
|
||||
var oldImpulseX = this.m_impulse.x;
|
||||
var oldImpulseY = this.m_impulse.y;
|
||||
//this.m_impulse += impulse;
|
||||
this.m_impulse.x += impulseX;
|
||||
this.m_impulse.y += impulseY;
|
||||
var length = this.m_impulse.Length();
|
||||
if (length > step.dt * this.m_maxForce)
|
||||
{
|
||||
//this.m_impulse *= step.dt * this.m_maxForce / length;
|
||||
this.m_impulse.Multiply(step.dt * this.m_maxForce / length);
|
||||
}
|
||||
//impulse = this.m_impulse - oldImpulse;
|
||||
impulseX = this.m_impulse.x - oldImpulseX;
|
||||
impulseY = this.m_impulse.y - oldImpulseY;
|
||||
|
||||
//body.m_linearVelocity += body->m_invMass * impulse;
|
||||
body.m_linearVelocity.x += body.m_invMass * impulseX;
|
||||
body.m_linearVelocity.y += body.m_invMass * impulseY;
|
||||
//body.m_angularVelocity += body->m_invI * b2Cross(r, impulse);
|
||||
body.m_angularVelocity += body.m_invI * (rX * impulseY - rY * impulseX);
|
||||
},
|
||||
SolvePositionConstraints: function(){
|
||||
return true;
|
||||
},
|
||||
|
||||
m_localAnchor: new b2Vec2(),
|
||||
m_target: new b2Vec2(),
|
||||
m_impulse: new b2Vec2(),
|
||||
|
||||
m_ptpMass: new b2Mat22(),
|
||||
m_C: new b2Vec2(),
|
||||
m_maxForce: null,
|
||||
m_beta: null,
|
||||
m_gamma: null});
|
||||
|
53
lib/box2d-js/js/box2d/dynamics/joints/b2MouseJointDef.js
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2MouseJointDef = Class.create();
|
||||
Object.extend(b2MouseJointDef.prototype, b2JointDef.prototype);
|
||||
Object.extend(b2MouseJointDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2JointDef
|
||||
this.type = b2Joint.e_unknownJoint;
|
||||
this.userData = null;
|
||||
this.body1 = null;
|
||||
this.body2 = null;
|
||||
this.collideConnected = false;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.target = new b2Vec2();
|
||||
//
|
||||
|
||||
this.type = b2Joint.e_mouseJoint;
|
||||
this.maxForce = 0.0;
|
||||
this.frequencyHz = 5.0;
|
||||
this.dampingRatio = 0.7;
|
||||
this.timeStep = 1.0 / 60.0;
|
||||
},
|
||||
|
||||
target: new b2Vec2(),
|
||||
maxForce: null,
|
||||
frequencyHz: null,
|
||||
dampingRatio: null,
|
||||
timeStep: null});
|
||||
|
676
lib/box2d-js/js/box2d/dynamics/joints/b2PrismaticJoint.js
Normal file
@ -0,0 +1,676 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Linear constraint (point-to-line)
|
||||
// d = p2 - p1 = x2 + r2 - x1 - r1
|
||||
// C = dot(ay1, d)
|
||||
// Cdot = dot(d, cross(w1, ay1)) + dot(ay1, v2 + cross(w2, r2) - v1 - cross(w1, r1))
|
||||
// = -dot(ay1, v1) - dot(cross(d + r1, ay1), w1) + dot(ay1, v2) + dot(cross(r2, ay1), v2)
|
||||
// J = [-ay1 -cross(d+r1,ay1) ay1 cross(r2,ay1)]
|
||||
//
|
||||
// Angular constraint
|
||||
// C = a2 - a1 + a_initial
|
||||
// Cdot = w2 - w1
|
||||
// J = [0 0 -1 0 0 1]
|
||||
|
||||
// Motor/Limit linear constraint
|
||||
// C = dot(ax1, d)
|
||||
// Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2)
|
||||
// J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]
|
||||
|
||||
|
||||
var b2PrismaticJoint = Class.create();
|
||||
Object.extend(b2PrismaticJoint.prototype, b2Joint.prototype);
|
||||
Object.extend(b2PrismaticJoint.prototype,
|
||||
{
|
||||
GetAnchor1: function(){
|
||||
var b1 = this.m_body1;
|
||||
//return b2Math.AddVV(b1.m_position, b2Math.b2MulMV(b1.m_R, this.m_localAnchor1));
|
||||
var tVec = new b2Vec2();
|
||||
tVec.SetV(this.m_localAnchor1);
|
||||
tVec.MulM(b1.m_R);
|
||||
tVec.Add(b1.m_position);
|
||||
return tVec;
|
||||
},
|
||||
GetAnchor2: function(){
|
||||
var b2 = this.m_body2;
|
||||
//return b2Math.AddVV(b2.m_position, b2Math.b2MulMV(b2.m_R, this.m_localAnchor2));
|
||||
var tVec = new b2Vec2();
|
||||
tVec.SetV(this.m_localAnchor2);
|
||||
tVec.MulM(b2.m_R);
|
||||
tVec.Add(b2.m_position);
|
||||
return tVec;
|
||||
},
|
||||
GetJointTranslation: function(){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
//var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//var p1 = b2Math.AddVV(b1.m_position , r1);
|
||||
var p1X = b1.m_position.x + r1X;
|
||||
var p1Y = b1.m_position.y + r1Y;
|
||||
//var p2 = b2Math.AddVV(b2.m_position , r2);
|
||||
var p2X = b2.m_position.x + r2X;
|
||||
var p2Y = b2.m_position.y + r2Y;
|
||||
//var d = b2Math.SubtractVV(p2, p1);
|
||||
var dX = p2X - p1X;
|
||||
var dY = p2Y - p1Y;
|
||||
//var ax1 = b2Math.b2MulMV(b1.m_R, this.m_localXAxis1);
|
||||
tMat = b1.m_R;
|
||||
var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
|
||||
var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
|
||||
|
||||
//var translation = b2Math.b2Dot(ax1, d);
|
||||
var translation = ax1X*dX + ax1Y*dY;
|
||||
return translation;
|
||||
},
|
||||
GetJointSpeed: function(){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
//var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//var p1 = b2Math.AddVV(b1.m_position , r1);
|
||||
var p1X = b1.m_position.x + r1X;
|
||||
var p1Y = b1.m_position.y + r1Y;
|
||||
//var p2 = b2Math.AddVV(b2.m_position , r2);
|
||||
var p2X = b2.m_position.x + r2X;
|
||||
var p2Y = b2.m_position.y + r2Y;
|
||||
//var d = b2Math.SubtractVV(p2, p1);
|
||||
var dX = p2X - p1X;
|
||||
var dY = p2Y - p1Y;
|
||||
//var ax1 = b2Math.b2MulMV(b1.m_R, this.m_localXAxis1);
|
||||
tMat = b1.m_R;
|
||||
var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
|
||||
var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
|
||||
|
||||
var v1 = b1.m_linearVelocity;
|
||||
var v2 = b2.m_linearVelocity;
|
||||
var w1 = b1.m_angularVelocity;
|
||||
var w2 = b2.m_angularVelocity;
|
||||
|
||||
//var speed = b2Math.b2Dot(d, b2Math.b2CrossFV(w1, ax1)) + b2Math.b2Dot(ax1, b2Math.SubtractVV( b2Math.SubtractVV( b2Math.AddVV( v2 , b2Math.b2CrossFV(w2, r2)) , v1) , b2Math.b2CrossFV(w1, r1)));
|
||||
//var b2D = (dX*(-w1 * ax1Y) + dY*(w1 * ax1X));
|
||||
//var b2D2 = (ax1X * ((( v2.x + (-w2 * r2Y)) - v1.x) - (-w1 * r1Y)) + ax1Y * ((( v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
|
||||
var speed = (dX*(-w1 * ax1Y) + dY*(w1 * ax1X)) + (ax1X * ((( v2.x + (-w2 * r2Y)) - v1.x) - (-w1 * r1Y)) + ax1Y * ((( v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
|
||||
|
||||
return speed;
|
||||
},
|
||||
GetMotorForce: function(invTimeStep){
|
||||
return invTimeStep * this.m_motorImpulse;
|
||||
},
|
||||
|
||||
SetMotorSpeed: function(speed)
|
||||
{
|
||||
this.m_motorSpeed = speed;
|
||||
},
|
||||
|
||||
SetMotorForce: function(force)
|
||||
{
|
||||
this.m_maxMotorForce = force;
|
||||
},
|
||||
|
||||
GetReactionForce: function(invTimeStep)
|
||||
{
|
||||
var tImp = invTimeStep * this.m_limitImpulse;
|
||||
var tMat;
|
||||
|
||||
//var ax1 = b2Math.b2MulMV(this.m_body1.m_R, this.m_localXAxis1);
|
||||
tMat = this.m_body1.m_R;
|
||||
var ax1X = tImp * (tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y);
|
||||
var ax1Y = tImp * (tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y);
|
||||
//var ay1 = b2Math.b2MulMV(this.m_body1.m_R, this.m_localYAxis1);
|
||||
var ay1X = tImp * (tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y);
|
||||
var ay1Y = tImp * (tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y);
|
||||
|
||||
//return (invTimeStep * this.m_limitImpulse) * ax1 + (invTimeStep * this.m_linearImpulse) * ay1;
|
||||
|
||||
return new b2Vec2(ax1X+ay1X, ax1Y+ay1Y);
|
||||
},
|
||||
|
||||
GetReactionTorque: function(invTimeStep)
|
||||
{
|
||||
return invTimeStep * this.m_angularImpulse;
|
||||
},
|
||||
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(def){
|
||||
// The constructor for b2Joint
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2JointNode();
|
||||
this.m_node2 = new b2JointNode();
|
||||
//
|
||||
this.m_type = def.type;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
this.m_body1 = def.body1;
|
||||
this.m_body2 = def.body2;
|
||||
this.m_collideConnected = def.collideConnected;
|
||||
this.m_islandFlag = false;
|
||||
this.m_userData = def.userData;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_localAnchor1 = new b2Vec2();
|
||||
this.m_localAnchor2 = new b2Vec2();
|
||||
this.m_localXAxis1 = new b2Vec2();
|
||||
this.m_localYAxis1 = new b2Vec2();
|
||||
this.m_linearJacobian = new b2Jacobian();
|
||||
this.m_motorJacobian = new b2Jacobian();
|
||||
//
|
||||
|
||||
//super(def);
|
||||
|
||||
var tMat;
|
||||
var tX;
|
||||
var tY;
|
||||
|
||||
//this.m_localAnchor1 = b2Math.b2MulTMV(this.m_body1.m_R, b2Math.SubtractVV(def.anchorPoint , this.m_body1.m_position));
|
||||
tMat = this.m_body1.m_R;
|
||||
tX = (def.anchorPoint.x - this.m_body1.m_position.x);
|
||||
tY = (def.anchorPoint.y - this.m_body1.m_position.y);
|
||||
this.m_localAnchor1.Set((tX*tMat.col1.x + tY*tMat.col1.y), (tX*tMat.col2.x + tY*tMat.col2.y));
|
||||
|
||||
//this.m_localAnchor2 = b2Math.b2MulTMV(this.m_body2.m_R, b2Math.SubtractVV(def.anchorPoint , this.m_body2.m_position));
|
||||
tMat = this.m_body2.m_R;
|
||||
tX = (def.anchorPoint.x - this.m_body2.m_position.x);
|
||||
tY = (def.anchorPoint.y - this.m_body2.m_position.y);
|
||||
this.m_localAnchor2.Set((tX*tMat.col1.x + tY*tMat.col1.y), (tX*tMat.col2.x + tY*tMat.col2.y));
|
||||
|
||||
//this.m_localXAxis1 = b2Math.b2MulTMV(this.m_body1.m_R, def.axis);
|
||||
tMat = this.m_body1.m_R;
|
||||
tX = def.axis.x;
|
||||
tY = def.axis.y;
|
||||
this.m_localXAxis1.Set((tX*tMat.col1.x + tY*tMat.col1.y), (tX*tMat.col2.x + tY*tMat.col2.y));
|
||||
|
||||
//this.m_localYAxis1 = b2Math.b2CrossFV(1.0, this.m_localXAxis1);
|
||||
this.m_localYAxis1.x = -this.m_localXAxis1.y;
|
||||
this.m_localYAxis1.y = this.m_localXAxis1.x;
|
||||
|
||||
this.m_initialAngle = this.m_body2.m_rotation - this.m_body1.m_rotation;
|
||||
|
||||
this.m_linearJacobian.SetZero();
|
||||
this.m_linearMass = 0.0;
|
||||
this.m_linearImpulse = 0.0;
|
||||
|
||||
this.m_angularMass = 0.0;
|
||||
this.m_angularImpulse = 0.0;
|
||||
|
||||
this.m_motorJacobian.SetZero();
|
||||
this.m_motorMass = 0.0;
|
||||
this.m_motorImpulse = 0.0;
|
||||
this.m_limitImpulse = 0.0;
|
||||
this.m_limitPositionImpulse = 0.0;
|
||||
|
||||
this.m_lowerTranslation = def.lowerTranslation;
|
||||
this.m_upperTranslation = def.upperTranslation;
|
||||
this.m_maxMotorForce = def.motorForce;
|
||||
this.m_motorSpeed = def.motorSpeed;
|
||||
this.m_enableLimit = def.enableLimit;
|
||||
this.m_enableMotor = def.enableMotor;
|
||||
},
|
||||
|
||||
PrepareVelocitySolver: function(){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
// Compute the effective masses.
|
||||
//b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
//float32 invMass1 = b1->m_invMass, invMass2 = b2->m_invMass;
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invMass2 = b2.m_invMass;
|
||||
//float32 invI1 = b1->m_invI, invI2 = b2->m_invI;
|
||||
var invI1 = b1.m_invI;
|
||||
var invI2 = b2.m_invI;
|
||||
|
||||
// Compute point to line constraint effective mass.
|
||||
// J = [-ay1 -cross(d+r1,ay1) ay1 cross(r2,ay1)]
|
||||
//b2Vec2 ay1 = b2Mul(b1->m_R, this.m_localYAxis1);
|
||||
tMat = b1.m_R;
|
||||
var ay1X = tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y;
|
||||
var ay1Y = tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y;
|
||||
//b2Vec2 e = b2->m_position + r2 - b1->m_position;
|
||||
var eX = b2.m_position.x + r2X - b1.m_position.x;
|
||||
var eY = b2.m_position.y + r2Y - b1.m_position.y;
|
||||
|
||||
//this.m_linearJacobian.Set(-ay1, -b2Math.b2Cross(e, ay1), ay1, b2Math.b2Cross(r2, ay1));
|
||||
this.m_linearJacobian.linear1.x = -ay1X;
|
||||
this.m_linearJacobian.linear1.y = -ay1Y;
|
||||
this.m_linearJacobian.linear2.x = ay1X;
|
||||
this.m_linearJacobian.linear2.y = ay1Y;
|
||||
this.m_linearJacobian.angular1 = -(eX * ay1Y - eY * ay1X);
|
||||
this.m_linearJacobian.angular2 = r2X * ay1Y - r2Y * ay1X;
|
||||
|
||||
this.m_linearMass = invMass1 + invI1 * this.m_linearJacobian.angular1 * this.m_linearJacobian.angular1 +
|
||||
invMass2 + invI2 * this.m_linearJacobian.angular2 * this.m_linearJacobian.angular2;
|
||||
//b2Settings.b2Assert(this.m_linearMass > Number.MIN_VALUE);
|
||||
this.m_linearMass = 1.0 / this.m_linearMass;
|
||||
|
||||
// Compute angular constraint effective mass.
|
||||
this.m_angularMass = 1.0 / (invI1 + invI2);
|
||||
|
||||
// Compute motor and limit terms.
|
||||
if (this.m_enableLimit || this.m_enableMotor)
|
||||
{
|
||||
// The motor and limit share a Jacobian and effective mass.
|
||||
//b2Vec2 ax1 = b2Mul(b1->m_R, this.m_localXAxis1);
|
||||
tMat = b1.m_R;
|
||||
var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
|
||||
var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
|
||||
//this.m_motorJacobian.Set(-ax1, -b2Cross(e, ax1), ax1, b2Cross(r2, ax1));
|
||||
this.m_motorJacobian.linear1.x = -ax1X; this.m_motorJacobian.linear1.y = -ax1Y;
|
||||
this.m_motorJacobian.linear2.x = ax1X; this.m_motorJacobian.linear2.y = ax1Y;
|
||||
this.m_motorJacobian.angular1 = -(eX * ax1Y - eY * ax1X);
|
||||
this.m_motorJacobian.angular2 = r2X * ax1Y - r2Y * ax1X;
|
||||
|
||||
this.m_motorMass = invMass1 + invI1 * this.m_motorJacobian.angular1 * this.m_motorJacobian.angular1 +
|
||||
invMass2 + invI2 * this.m_motorJacobian.angular2 * this.m_motorJacobian.angular2;
|
||||
//b2Settings.b2Assert(this.m_motorMass > Number.MIN_VALUE);
|
||||
this.m_motorMass = 1.0 / this.m_motorMass;
|
||||
|
||||
if (this.m_enableLimit)
|
||||
{
|
||||
//b2Vec2 d = e - r1;
|
||||
var dX = eX - r1X;
|
||||
var dY = eY - r1Y;
|
||||
//float32 jointTranslation = b2Dot(ax1, d);
|
||||
var jointTranslation = ax1X * dX + ax1Y * dY;
|
||||
if (b2Math.b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * b2Settings.b2_linearSlop)
|
||||
{
|
||||
this.m_limitState = b2Joint.e_equalLimits;
|
||||
}
|
||||
else if (jointTranslation <= this.m_lowerTranslation)
|
||||
{
|
||||
if (this.m_limitState != b2Joint.e_atLowerLimit)
|
||||
{
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
this.m_limitState = b2Joint.e_atLowerLimit;
|
||||
}
|
||||
else if (jointTranslation >= this.m_upperTranslation)
|
||||
{
|
||||
if (this.m_limitState != b2Joint.e_atUpperLimit)
|
||||
{
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
this.m_limitState = b2Joint.e_atUpperLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_limitState = b2Joint.e_inactiveLimit;
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.m_enableMotor == false)
|
||||
{
|
||||
this.m_motorImpulse = 0.0;
|
||||
}
|
||||
|
||||
if (this.m_enableLimit == false)
|
||||
{
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
|
||||
if (b2World.s_enableWarmStarting)
|
||||
{
|
||||
//b2Vec2 P1 = this.m_linearImpulse * this.m_linearJacobian.linear1 + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear1;
|
||||
var P1X = this.m_linearImpulse * this.m_linearJacobian.linear1.x + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear1.x;
|
||||
var P1Y = this.m_linearImpulse * this.m_linearJacobian.linear1.y + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear1.y;
|
||||
//b2Vec2 P2 = this.m_linearImpulse * this.m_linearJacobian.linear2 + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear2;
|
||||
var P2X = this.m_linearImpulse * this.m_linearJacobian.linear2.x + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear2.x;
|
||||
var P2Y = this.m_linearImpulse * this.m_linearJacobian.linear2.y + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear2.y;
|
||||
//float32 L1 = this.m_linearImpulse * this.m_linearJacobian.angular1 - this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular1;
|
||||
var L1 = this.m_linearImpulse * this.m_linearJacobian.angular1 - this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular1;
|
||||
//float32 L2 = this.m_linearImpulse * this.m_linearJacobian.angular2 + this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular2;
|
||||
var L2 = this.m_linearImpulse * this.m_linearJacobian.angular2 + this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular2;
|
||||
|
||||
//b1->m_linearVelocity += invMass1 * P1;
|
||||
b1.m_linearVelocity.x += invMass1 * P1X;
|
||||
b1.m_linearVelocity.y += invMass1 * P1Y;
|
||||
//b1->m_angularVelocity += invI1 * L1;
|
||||
b1.m_angularVelocity += invI1 * L1;
|
||||
|
||||
//b2->m_linearVelocity += invMass2 * P2;
|
||||
b2.m_linearVelocity.x += invMass2 * P2X;
|
||||
b2.m_linearVelocity.y += invMass2 * P2Y;
|
||||
//b2->m_angularVelocity += invI2 * L2;
|
||||
b2.m_angularVelocity += invI2 * L2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_linearImpulse = 0.0;
|
||||
this.m_angularImpulse = 0.0;
|
||||
this.m_limitImpulse = 0.0;
|
||||
this.m_motorImpulse = 0.0;
|
||||
}
|
||||
|
||||
this.m_limitPositionImpulse = 0.0;
|
||||
|
||||
},
|
||||
|
||||
SolveVelocityConstraints: function(step){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invMass2 = b2.m_invMass;
|
||||
var invI1 = b1.m_invI;
|
||||
var invI2 = b2.m_invI;
|
||||
|
||||
var oldLimitImpulse;
|
||||
|
||||
// Solve linear constraint.
|
||||
var linearCdot = this.m_linearJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity);
|
||||
var linearImpulse = -this.m_linearMass * linearCdot;
|
||||
this.m_linearImpulse += linearImpulse;
|
||||
|
||||
//b1->m_linearVelocity += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1;
|
||||
b1.m_linearVelocity.x += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.x;
|
||||
b1.m_linearVelocity.y += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.y;
|
||||
//b1->m_angularVelocity += invI1 * linearImpulse * this.m_linearJacobian.angular1;
|
||||
b1.m_angularVelocity += invI1 * linearImpulse * this.m_linearJacobian.angular1;
|
||||
|
||||
//b2->m_linearVelocity += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2;
|
||||
b2.m_linearVelocity.x += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.x;
|
||||
b2.m_linearVelocity.y += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.y;
|
||||
//b2.m_angularVelocity += invI2 * linearImpulse * this.m_linearJacobian.angular2;
|
||||
b2.m_angularVelocity += invI2 * linearImpulse * this.m_linearJacobian.angular2;
|
||||
|
||||
// Solve angular constraint.
|
||||
var angularCdot = b2.m_angularVelocity - b1.m_angularVelocity;
|
||||
var angularImpulse = -this.m_angularMass * angularCdot;
|
||||
this.m_angularImpulse += angularImpulse;
|
||||
|
||||
b1.m_angularVelocity -= invI1 * angularImpulse;
|
||||
b2.m_angularVelocity += invI2 * angularImpulse;
|
||||
|
||||
// Solve linear motor constraint.
|
||||
if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits)
|
||||
{
|
||||
var motorCdot = this.m_motorJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity) - this.m_motorSpeed;
|
||||
var motorImpulse = -this.m_motorMass * motorCdot;
|
||||
var oldMotorImpulse = this.m_motorImpulse;
|
||||
this.m_motorImpulse = b2Math.b2Clamp(this.m_motorImpulse + motorImpulse, -step.dt * this.m_maxMotorForce, step.dt * this.m_maxMotorForce);
|
||||
motorImpulse = this.m_motorImpulse - oldMotorImpulse;
|
||||
|
||||
//b1.m_linearVelocity += (invMass1 * motorImpulse) * this.m_motorJacobian.linear1;
|
||||
b1.m_linearVelocity.x += (invMass1 * motorImpulse) * this.m_motorJacobian.linear1.x;
|
||||
b1.m_linearVelocity.y += (invMass1 * motorImpulse) * this.m_motorJacobian.linear1.y;
|
||||
//b1.m_angularVelocity += invI1 * motorImpulse * this.m_motorJacobian.angular1;
|
||||
b1.m_angularVelocity += invI1 * motorImpulse * this.m_motorJacobian.angular1;
|
||||
|
||||
//b2->m_linearVelocity += (invMass2 * motorImpulse) * this.m_motorJacobian.linear2;
|
||||
b2.m_linearVelocity.x += (invMass2 * motorImpulse) * this.m_motorJacobian.linear2.x;
|
||||
b2.m_linearVelocity.y += (invMass2 * motorImpulse) * this.m_motorJacobian.linear2.y;
|
||||
//b2->m_angularVelocity += invI2 * motorImpulse * this.m_motorJacobian.angular2;
|
||||
b2.m_angularVelocity += invI2 * motorImpulse * this.m_motorJacobian.angular2;
|
||||
}
|
||||
|
||||
// Solve linear limit constraint.
|
||||
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
||||
{
|
||||
var limitCdot = this.m_motorJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity);
|
||||
var limitImpulse = -this.m_motorMass * limitCdot;
|
||||
|
||||
if (this.m_limitState == b2Joint.e_equalLimits)
|
||||
{
|
||||
this.m_limitImpulse += limitImpulse;
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
||||
{
|
||||
oldLimitImpulse = this.m_limitImpulse;
|
||||
this.m_limitImpulse = b2Math.b2Max(this.m_limitImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitImpulse - oldLimitImpulse;
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
oldLimitImpulse = this.m_limitImpulse;
|
||||
this.m_limitImpulse = b2Math.b2Min(this.m_limitImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitImpulse - oldLimitImpulse;
|
||||
}
|
||||
|
||||
//b1->m_linearVelocity += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1;
|
||||
b1.m_linearVelocity.x += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.x;
|
||||
b1.m_linearVelocity.y += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.y;
|
||||
//b1->m_angularVelocity += invI1 * limitImpulse * this.m_motorJacobian.angular1;
|
||||
b1.m_angularVelocity += invI1 * limitImpulse * this.m_motorJacobian.angular1;
|
||||
|
||||
//b2->m_linearVelocity += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2;
|
||||
b2.m_linearVelocity.x += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.x;
|
||||
b2.m_linearVelocity.y += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.y;
|
||||
//b2->m_angularVelocity += invI2 * limitImpulse * this.m_motorJacobian.angular2;
|
||||
b2.m_angularVelocity += invI2 * limitImpulse * this.m_motorJacobian.angular2;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
SolvePositionConstraints: function(){
|
||||
|
||||
var limitC;
|
||||
var oldLimitImpulse;
|
||||
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invMass2 = b2.m_invMass;
|
||||
var invI1 = b1.m_invI;
|
||||
var invI2 = b2.m_invI;
|
||||
|
||||
var tMat;
|
||||
|
||||
//b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//b2Vec2 p1 = b1->m_position + r1;
|
||||
var p1X = b1.m_position.x + r1X;
|
||||
var p1Y = b1.m_position.y + r1Y;
|
||||
//b2Vec2 p2 = b2->m_position + r2;
|
||||
var p2X = b2.m_position.x + r2X;
|
||||
var p2Y = b2.m_position.y + r2Y;
|
||||
//b2Vec2 d = p2 - p1;
|
||||
var dX = p2X - p1X;
|
||||
var dY = p2Y - p1Y;
|
||||
//b2Vec2 ay1 = b2Mul(b1->m_R, this.m_localYAxis1);
|
||||
tMat = b1.m_R;
|
||||
var ay1X = tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y;
|
||||
var ay1Y = tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y;
|
||||
|
||||
// Solve linear (point-to-line) constraint.
|
||||
//float32 linearC = b2Dot(ay1, d);
|
||||
var linearC = ay1X*dX + ay1Y*dY;
|
||||
// Prevent overly large corrections.
|
||||
linearC = b2Math.b2Clamp(linearC, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
|
||||
var linearImpulse = -this.m_linearMass * linearC;
|
||||
|
||||
//b1->m_position += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1;
|
||||
b1.m_position.x += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.x;
|
||||
b1.m_position.y += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.y;
|
||||
//b1->m_rotation += invI1 * linearImpulse * this.m_linearJacobian.angular1;
|
||||
b1.m_rotation += invI1 * linearImpulse * this.m_linearJacobian.angular1;
|
||||
//b1->m_R.Set(b1->m_rotation);
|
||||
//b2->m_position += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2;
|
||||
b2.m_position.x += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.x;
|
||||
b2.m_position.y += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.y;
|
||||
b2.m_rotation += invI2 * linearImpulse * this.m_linearJacobian.angular2;
|
||||
//b2->m_R.Set(b2->m_rotation);
|
||||
|
||||
var positionError = b2Math.b2Abs(linearC);
|
||||
|
||||
// Solve angular constraint.
|
||||
var angularC = b2.m_rotation - b1.m_rotation - this.m_initialAngle;
|
||||
// Prevent overly large corrections.
|
||||
angularC = b2Math.b2Clamp(angularC, -b2Settings.b2_maxAngularCorrection, b2Settings.b2_maxAngularCorrection);
|
||||
var angularImpulse = -this.m_angularMass * angularC;
|
||||
|
||||
b1.m_rotation -= b1.m_invI * angularImpulse;
|
||||
b1.m_R.Set(b1.m_rotation);
|
||||
b2.m_rotation += b2.m_invI * angularImpulse;
|
||||
b2.m_R.Set(b2.m_rotation);
|
||||
|
||||
var angularError = b2Math.b2Abs(angularC);
|
||||
|
||||
// Solve linear limit constraint.
|
||||
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
||||
{
|
||||
|
||||
//b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//b2Vec2 p1 = b1->m_position + r1;
|
||||
p1X = b1.m_position.x + r1X;
|
||||
p1Y = b1.m_position.y + r1Y;
|
||||
//b2Vec2 p2 = b2->m_position + r2;
|
||||
p2X = b2.m_position.x + r2X;
|
||||
p2Y = b2.m_position.y + r2Y;
|
||||
//b2Vec2 d = p2 - p1;
|
||||
dX = p2X - p1X;
|
||||
dY = p2Y - p1Y;
|
||||
//b2Vec2 ax1 = b2Mul(b1->m_R, this.m_localXAxis1);
|
||||
tMat = b1.m_R;
|
||||
var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
|
||||
var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
|
||||
|
||||
//float32 translation = b2Dot(ax1, d);
|
||||
var translation = (ax1X*dX + ax1Y*dY);
|
||||
var limitImpulse = 0.0;
|
||||
|
||||
if (this.m_limitState == b2Joint.e_equalLimits)
|
||||
{
|
||||
// Prevent large angular corrections
|
||||
limitC = b2Math.b2Clamp(translation, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
|
||||
limitImpulse = -this.m_motorMass * limitC;
|
||||
positionError = b2Math.b2Max(positionError, b2Math.b2Abs(angularC));
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
||||
{
|
||||
limitC = translation - this.m_lowerTranslation;
|
||||
positionError = b2Math.b2Max(positionError, -limitC);
|
||||
|
||||
// Prevent large linear corrections and allow some slop.
|
||||
limitC = b2Math.b2Clamp(limitC + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
||||
limitImpulse = -this.m_motorMass * limitC;
|
||||
oldLimitImpulse = this.m_limitPositionImpulse;
|
||||
this.m_limitPositionImpulse = b2Math.b2Max(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
limitC = translation - this.m_upperTranslation;
|
||||
positionError = b2Math.b2Max(positionError, limitC);
|
||||
|
||||
// Prevent large linear corrections and allow some slop.
|
||||
limitC = b2Math.b2Clamp(limitC - b2Settings.b2_linearSlop, 0.0, b2Settings.b2_maxLinearCorrection);
|
||||
limitImpulse = -this.m_motorMass * limitC;
|
||||
oldLimitImpulse = this.m_limitPositionImpulse;
|
||||
this.m_limitPositionImpulse = b2Math.b2Min(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
||||
}
|
||||
|
||||
//b1->m_position += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1;
|
||||
b1.m_position.x += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.x;
|
||||
b1.m_position.y += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.y;
|
||||
//b1->m_rotation += invI1 * limitImpulse * this.m_motorJacobian.angular1;
|
||||
b1.m_rotation += invI1 * limitImpulse * this.m_motorJacobian.angular1;
|
||||
b1.m_R.Set(b1.m_rotation);
|
||||
//b2->m_position += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2;
|
||||
b2.m_position.x += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.x;
|
||||
b2.m_position.y += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.y;
|
||||
//b2->m_rotation += invI2 * limitImpulse * this.m_motorJacobian.angular2;
|
||||
b2.m_rotation += invI2 * limitImpulse * this.m_motorJacobian.angular2;
|
||||
b2.m_R.Set(b2.m_rotation);
|
||||
}
|
||||
|
||||
return positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
|
||||
|
||||
},
|
||||
|
||||
m_localAnchor1: new b2Vec2(),
|
||||
m_localAnchor2: new b2Vec2(),
|
||||
m_localXAxis1: new b2Vec2(),
|
||||
m_localYAxis1: new b2Vec2(),
|
||||
m_initialAngle: null,
|
||||
|
||||
m_linearJacobian: new b2Jacobian(),
|
||||
m_linearMass: null,
|
||||
m_linearImpulse: null,
|
||||
|
||||
m_angularMass: null,
|
||||
m_angularImpulse: null,
|
||||
|
||||
m_motorJacobian: new b2Jacobian(),
|
||||
m_motorMass: null,
|
||||
m_motorImpulse: null,
|
||||
m_limitImpulse: null,
|
||||
m_limitPositionImpulse: null,
|
||||
|
||||
m_lowerTranslation: null,
|
||||
m_upperTranslation: null,
|
||||
m_maxMotorForce: null,
|
||||
m_motorSpeed: null,
|
||||
|
||||
m_enableLimit: null,
|
||||
m_enableMotor: null,
|
||||
m_limitState: 0});
|
||||
|
56
lib/box2d-js/js/box2d/dynamics/joints/b2PrismaticJointDef.js
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2PrismaticJointDef = Class.create();
|
||||
Object.extend(b2PrismaticJointDef.prototype, b2JointDef.prototype);
|
||||
Object.extend(b2PrismaticJointDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2JointDef
|
||||
this.type = b2Joint.e_unknownJoint;
|
||||
this.userData = null;
|
||||
this.body1 = null;
|
||||
this.body2 = null;
|
||||
this.collideConnected = false;
|
||||
//
|
||||
|
||||
this.type = b2Joint.e_prismaticJoint;
|
||||
this.anchorPoint = new b2Vec2(0.0, 0.0);
|
||||
this.axis = new b2Vec2(0.0, 0.0);
|
||||
this.lowerTranslation = 0.0;
|
||||
this.upperTranslation = 0.0;
|
||||
this.motorForce = 0.0;
|
||||
this.motorSpeed = 0.0;
|
||||
this.enableLimit = false;
|
||||
this.enableMotor = false;
|
||||
},
|
||||
|
||||
anchorPoint: null,
|
||||
axis: null,
|
||||
lowerTranslation: null,
|
||||
upperTranslation: null,
|
||||
motorForce: null,
|
||||
motorSpeed: null,
|
||||
enableLimit: null,
|
||||
enableMotor: null});
|
||||
|
618
lib/box2d-js/js/box2d/dynamics/joints/b2PulleyJoint.js
Normal file
@ -0,0 +1,618 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2PulleyJoint = Class.create();
|
||||
Object.extend(b2PulleyJoint.prototype, b2Joint.prototype);
|
||||
Object.extend(b2PulleyJoint.prototype,
|
||||
{
|
||||
GetAnchor1: function(){
|
||||
//return this.m_body1->m_position + b2Mul(this.m_body1->m_R, this.m_localAnchor1);
|
||||
var tMat = this.m_body1.m_R;
|
||||
return new b2Vec2( this.m_body1.m_position.x + (tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y),
|
||||
this.m_body1.m_position.y + (tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y));
|
||||
},
|
||||
GetAnchor2: function(){
|
||||
//return this.m_body2->m_position + b2Mul(this.m_body2->m_R, this.m_localAnchor2);
|
||||
var tMat = this.m_body2.m_R;
|
||||
return new b2Vec2( this.m_body2.m_position.x + (tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y),
|
||||
this.m_body2.m_position.y + (tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y));
|
||||
},
|
||||
|
||||
GetGroundPoint1: function(){
|
||||
//return this.m_ground->m_position + this.m_groundAnchor1;
|
||||
return new b2Vec2(this.m_ground.m_position.x + this.m_groundAnchor1.x, this.m_ground.m_position.y + this.m_groundAnchor1.y);
|
||||
},
|
||||
GetGroundPoint2: function(){
|
||||
return new b2Vec2(this.m_ground.m_position.x + this.m_groundAnchor2.x, this.m_ground.m_position.y + this.m_groundAnchor2.y);
|
||||
},
|
||||
|
||||
GetReactionForce: function(invTimeStep){
|
||||
//b2Vec2 F(0.0f, 0.0f);
|
||||
return new b2Vec2();
|
||||
},
|
||||
GetReactionTorque: function(invTimeStep){
|
||||
return 0.0;
|
||||
},
|
||||
|
||||
GetLength1: function(){
|
||||
var tMat;
|
||||
//b2Vec2 p = this.m_body1->m_position + b2Mul(this.m_body1->m_R, this.m_localAnchor1);
|
||||
tMat = this.m_body1.m_R;
|
||||
var pX = this.m_body1.m_position.x + (tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y);
|
||||
var pY = this.m_body1.m_position.y + (tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y);
|
||||
//b2Vec2 s = this.m_ground->m_position + this.m_groundAnchor1;
|
||||
//b2Vec2 d = p - s;
|
||||
var dX = pX - (this.m_ground.m_position.x + this.m_groundAnchor1.x);
|
||||
var dY = pY - (this.m_ground.m_position.y + this.m_groundAnchor1.y);
|
||||
return Math.sqrt(dX*dX + dY*dY);
|
||||
},
|
||||
GetLength2: function(){
|
||||
var tMat;
|
||||
//b2Vec2 p = this.m_body2->m_position + b2Mul(this.m_body2->m_R, this.m_localAnchor2);
|
||||
tMat = this.m_body2.m_R;
|
||||
var pX = this.m_body2.m_position.x + (tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y);
|
||||
var pY = this.m_body2.m_position.y + (tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y);
|
||||
//b2Vec2 s = this.m_ground->m_position + this.m_groundAnchor2;
|
||||
//b2Vec2 d = p - s;
|
||||
var dX = pX - (this.m_ground.m_position.x + this.m_groundAnchor2.x);
|
||||
var dY = pY - (this.m_ground.m_position.y + this.m_groundAnchor2.y);
|
||||
return Math.sqrt(dX*dX + dY*dY);
|
||||
},
|
||||
|
||||
GetRatio: function(){
|
||||
return this.m_ratio;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(def){
|
||||
// The constructor for b2Joint
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2JointNode();
|
||||
this.m_node2 = new b2JointNode();
|
||||
//
|
||||
this.m_type = def.type;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
this.m_body1 = def.body1;
|
||||
this.m_body2 = def.body2;
|
||||
this.m_collideConnected = def.collideConnected;
|
||||
this.m_islandFlag = false;
|
||||
this.m_userData = def.userData;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.m_groundAnchor1 = new b2Vec2();
|
||||
this.m_groundAnchor2 = new b2Vec2();
|
||||
this.m_localAnchor1 = new b2Vec2();
|
||||
this.m_localAnchor2 = new b2Vec2();
|
||||
this.m_u1 = new b2Vec2();
|
||||
this.m_u2 = new b2Vec2();
|
||||
//
|
||||
|
||||
|
||||
// parent
|
||||
//super(def);
|
||||
|
||||
var tMat;
|
||||
var tX;
|
||||
var tY;
|
||||
|
||||
this.m_ground = this.m_body1.m_world.m_groundBody;
|
||||
//this.m_groundAnchor1 = def.groundPoint1 - this.m_ground.m_position;
|
||||
this.m_groundAnchor1.x = def.groundPoint1.x - this.m_ground.m_position.x;
|
||||
this.m_groundAnchor1.y = def.groundPoint1.y - this.m_ground.m_position.y;
|
||||
//this.m_groundAnchor2 = def.groundPoint2 - this.m_ground.m_position;
|
||||
this.m_groundAnchor2.x = def.groundPoint2.x - this.m_ground.m_position.x;
|
||||
this.m_groundAnchor2.y = def.groundPoint2.y - this.m_ground.m_position.y;
|
||||
//this.m_localAnchor1 = b2MulT(this.m_body1.m_R, def.anchorPoint1 - this.m_body1.m_position);
|
||||
tMat = this.m_body1.m_R;
|
||||
tX = def.anchorPoint1.x - this.m_body1.m_position.x;
|
||||
tY = def.anchorPoint1.y - this.m_body1.m_position.y;
|
||||
this.m_localAnchor1.x = tX*tMat.col1.x + tY*tMat.col1.y;
|
||||
this.m_localAnchor1.y = tX*tMat.col2.x + tY*tMat.col2.y;
|
||||
//this.m_localAnchor2 = b2MulT(this.m_body2.m_R, def.anchorPoint2 - this.m_body2.m_position);
|
||||
tMat = this.m_body2.m_R;
|
||||
tX = def.anchorPoint2.x - this.m_body2.m_position.x;
|
||||
tY = def.anchorPoint2.y - this.m_body2.m_position.y;
|
||||
this.m_localAnchor2.x = tX*tMat.col1.x + tY*tMat.col1.y;
|
||||
this.m_localAnchor2.y = tX*tMat.col2.x + tY*tMat.col2.y;
|
||||
|
||||
this.m_ratio = def.ratio;
|
||||
|
||||
//var d1 = def.groundPoint1 - def.anchorPoint1;
|
||||
tX = def.groundPoint1.x - def.anchorPoint1.x;
|
||||
tY = def.groundPoint1.y - def.anchorPoint1.y;
|
||||
var d1Len = Math.sqrt(tX*tX + tY*tY);
|
||||
//var d2 = def.groundPoint2 - def.anchorPoint2;
|
||||
tX = def.groundPoint2.x - def.anchorPoint2.x;
|
||||
tY = def.groundPoint2.y - def.anchorPoint2.y;
|
||||
var d2Len = Math.sqrt(tX*tX + tY*tY);
|
||||
|
||||
var length1 = b2Math.b2Max(0.5 * b2PulleyJoint.b2_minPulleyLength, d1Len);
|
||||
var length2 = b2Math.b2Max(0.5 * b2PulleyJoint.b2_minPulleyLength, d2Len);
|
||||
|
||||
this.m_constant = length1 + this.m_ratio * length2;
|
||||
|
||||
this.m_maxLength1 = b2Math.b2Clamp(def.maxLength1, length1, this.m_constant - this.m_ratio * b2PulleyJoint.b2_minPulleyLength);
|
||||
this.m_maxLength2 = b2Math.b2Clamp(def.maxLength2, length2, (this.m_constant - b2PulleyJoint.b2_minPulleyLength) / this.m_ratio);
|
||||
|
||||
this.m_pulleyImpulse = 0.0;
|
||||
this.m_limitImpulse1 = 0.0;
|
||||
this.m_limitImpulse2 = 0.0;
|
||||
|
||||
},
|
||||
|
||||
PrepareVelocitySolver: function(){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
//b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
//b2Vec2 p1 = b1->m_position + r1;
|
||||
var p1X = b1.m_position.x + r1X;
|
||||
var p1Y = b1.m_position.y + r1Y;
|
||||
//b2Vec2 p2 = b2->m_position + r2;
|
||||
var p2X = b2.m_position.x + r2X;
|
||||
var p2Y = b2.m_position.y + r2Y;
|
||||
|
||||
//b2Vec2 s1 = this.m_ground->m_position + this.m_groundAnchor1;
|
||||
var s1X = this.m_ground.m_position.x + this.m_groundAnchor1.x;
|
||||
var s1Y = this.m_ground.m_position.y + this.m_groundAnchor1.y;
|
||||
//b2Vec2 s2 = this.m_ground->m_position + this.m_groundAnchor2;
|
||||
var s2X = this.m_ground.m_position.x + this.m_groundAnchor2.x;
|
||||
var s2Y = this.m_ground.m_position.y + this.m_groundAnchor2.y;
|
||||
|
||||
// Get the pulley axes.
|
||||
//this.m_u1 = p1 - s1;
|
||||
this.m_u1.Set(p1X - s1X, p1Y - s1Y);
|
||||
//this.m_u2 = p2 - s2;
|
||||
this.m_u2.Set(p2X - s2X, p2Y - s2Y);
|
||||
|
||||
var length1 = this.m_u1.Length();
|
||||
var length2 = this.m_u2.Length();
|
||||
|
||||
if (length1 > b2Settings.b2_linearSlop)
|
||||
{
|
||||
//this.m_u1 *= 1.0f / length1;
|
||||
this.m_u1.Multiply(1.0 / length1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_u1.SetZero();
|
||||
}
|
||||
|
||||
if (length2 > b2Settings.b2_linearSlop)
|
||||
{
|
||||
//this.m_u2 *= 1.0f / length2;
|
||||
this.m_u2.Multiply(1.0 / length2);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_u2.SetZero();
|
||||
}
|
||||
|
||||
if (length1 < this.m_maxLength1)
|
||||
{
|
||||
this.m_limitState1 = b2Joint.e_inactiveLimit;
|
||||
this.m_limitImpulse1 = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_limitState1 = b2Joint.e_atUpperLimit;
|
||||
this.m_limitPositionImpulse1 = 0.0;
|
||||
}
|
||||
|
||||
if (length2 < this.m_maxLength2)
|
||||
{
|
||||
this.m_limitState2 = b2Joint.e_inactiveLimit;
|
||||
this.m_limitImpulse2 = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_limitState2 = b2Joint.e_atUpperLimit;
|
||||
this.m_limitPositionImpulse2 = 0.0;
|
||||
}
|
||||
|
||||
// Compute effective mass.
|
||||
//var cr1u1 = b2Cross(r1, this.m_u1);
|
||||
var cr1u1 = r1X * this.m_u1.y - r1Y * this.m_u1.x;
|
||||
//var cr2u2 = b2Cross(r2, this.m_u2);
|
||||
var cr2u2 = r2X * this.m_u2.y - r2Y * this.m_u2.x;
|
||||
|
||||
this.m_limitMass1 = b1.m_invMass + b1.m_invI * cr1u1 * cr1u1;
|
||||
this.m_limitMass2 = b2.m_invMass + b2.m_invI * cr2u2 * cr2u2;
|
||||
this.m_pulleyMass = this.m_limitMass1 + this.m_ratio * this.m_ratio * this.m_limitMass2;
|
||||
//b2Settings.b2Assert(this.m_limitMass1 > Number.MIN_VALUE);
|
||||
//b2Settings.b2Assert(this.m_limitMass2 > Number.MIN_VALUE);
|
||||
//b2Settings.b2Assert(this.m_pulleyMass > Number.MIN_VALUE);
|
||||
this.m_limitMass1 = 1.0 / this.m_limitMass1;
|
||||
this.m_limitMass2 = 1.0 / this.m_limitMass2;
|
||||
this.m_pulleyMass = 1.0 / this.m_pulleyMass;
|
||||
|
||||
// Warm starting.
|
||||
//b2Vec2 P1 = (-this.m_pulleyImpulse - this.m_limitImpulse1) * this.m_u1;
|
||||
var P1X = (-this.m_pulleyImpulse - this.m_limitImpulse1) * this.m_u1.x;
|
||||
var P1Y = (-this.m_pulleyImpulse - this.m_limitImpulse1) * this.m_u1.y;
|
||||
//b2Vec2 P2 = (-this.m_ratio * this.m_pulleyImpulse - this.m_limitImpulse2) * this.m_u2;
|
||||
var P2X = (-this.m_ratio * this.m_pulleyImpulse - this.m_limitImpulse2) * this.m_u2.x;
|
||||
var P2Y = (-this.m_ratio * this.m_pulleyImpulse - this.m_limitImpulse2) * this.m_u2.y;
|
||||
//b1.m_linearVelocity += b1.m_invMass * P1;
|
||||
b1.m_linearVelocity.x += b1.m_invMass * P1X;
|
||||
b1.m_linearVelocity.y += b1.m_invMass * P1Y;
|
||||
//b1.m_angularVelocity += b1.m_invI * b2Cross(r1, P1);
|
||||
b1.m_angularVelocity += b1.m_invI * (r1X * P1Y - r1Y * P1X);
|
||||
//b2.m_linearVelocity += b2.m_invMass * P2;
|
||||
b2.m_linearVelocity.x += b2.m_invMass * P2X;
|
||||
b2.m_linearVelocity.y += b2.m_invMass * P2Y;
|
||||
//b2.m_angularVelocity += b2.m_invI * b2Cross(r2, P2);
|
||||
b2.m_angularVelocity += b2.m_invI * (r2X * P2Y - r2Y * P2X);
|
||||
},
|
||||
|
||||
SolveVelocityConstraints: function(step){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
//var r1 = b2Mul(b1.m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//var r2 = b2Mul(b2.m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
// temp vars
|
||||
var v1X;
|
||||
var v1Y;
|
||||
var v2X;
|
||||
var v2Y;
|
||||
var P1X;
|
||||
var P1Y;
|
||||
var P2X;
|
||||
var P2Y;
|
||||
var Cdot;
|
||||
var impulse;
|
||||
var oldLimitImpulse;
|
||||
|
||||
//{
|
||||
//b2Vec2 v1 = b1->m_linearVelocity + b2Cross(b1->m_angularVelocity, r1);
|
||||
v1X = b1.m_linearVelocity.x + (-b1.m_angularVelocity * r1Y);
|
||||
v1Y = b1.m_linearVelocity.y + (b1.m_angularVelocity * r1X);
|
||||
//b2Vec2 v2 = b2->m_linearVelocity + b2Cross(b2->m_angularVelocity, r2);
|
||||
v2X = b2.m_linearVelocity.x + (-b2.m_angularVelocity * r2Y);
|
||||
v2Y = b2.m_linearVelocity.y + (b2.m_angularVelocity * r2X);
|
||||
|
||||
//Cdot = -b2Dot(this.m_u1, v1) - this.m_ratio * b2Dot(this.m_u2, v2);
|
||||
Cdot = -(this.m_u1.x * v1X + this.m_u1.y * v1Y) - this.m_ratio * (this.m_u2.x * v2X + this.m_u2.y * v2Y);
|
||||
impulse = -this.m_pulleyMass * Cdot;
|
||||
this.m_pulleyImpulse += impulse;
|
||||
|
||||
//b2Vec2 P1 = -impulse * this.m_u1;
|
||||
P1X = -impulse * this.m_u1.x;
|
||||
P1Y = -impulse * this.m_u1.y;
|
||||
//b2Vec2 P2 = -this.m_ratio * impulse * this.m_u2;
|
||||
P2X = -this.m_ratio * impulse * this.m_u2.x;
|
||||
P2Y = -this.m_ratio * impulse * this.m_u2.y;
|
||||
//b1.m_linearVelocity += b1.m_invMass * P1;
|
||||
b1.m_linearVelocity.x += b1.m_invMass * P1X;
|
||||
b1.m_linearVelocity.y += b1.m_invMass * P1Y;
|
||||
//b1.m_angularVelocity += b1.m_invI * b2Cross(r1, P1);
|
||||
b1.m_angularVelocity += b1.m_invI * (r1X * P1Y - r1Y * P1X);
|
||||
//b2.m_linearVelocity += b2.m_invMass * P2;
|
||||
b2.m_linearVelocity.x += b2.m_invMass * P2X;
|
||||
b2.m_linearVelocity.y += b2.m_invMass * P2Y;
|
||||
//b2.m_angularVelocity += b2.m_invI * b2Cross(r2, P2);
|
||||
b2.m_angularVelocity += b2.m_invI * (r2X * P2Y - r2Y * P2X);
|
||||
//}
|
||||
|
||||
if (this.m_limitState1 == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
//b2Vec2 v1 = b1->m_linearVelocity + b2Cross(b1->m_angularVelocity, r1);
|
||||
v1X = b1.m_linearVelocity.x + (-b1.m_angularVelocity * r1Y);
|
||||
v1Y = b1.m_linearVelocity.y + (b1.m_angularVelocity * r1X);
|
||||
|
||||
//float32 Cdot = -b2Dot(this.m_u1, v1);
|
||||
Cdot = -(this.m_u1.x * v1X + this.m_u1.y * v1Y);
|
||||
impulse = -this.m_limitMass1 * Cdot;
|
||||
oldLimitImpulse = this.m_limitImpulse1;
|
||||
this.m_limitImpulse1 = b2Math.b2Max(0.0, this.m_limitImpulse1 + impulse);
|
||||
impulse = this.m_limitImpulse1 - oldLimitImpulse;
|
||||
//b2Vec2 P1 = -impulse * this.m_u1;
|
||||
P1X = -impulse * this.m_u1.x;
|
||||
P1Y = -impulse * this.m_u1.y;
|
||||
//b1.m_linearVelocity += b1->m_invMass * P1;
|
||||
b1.m_linearVelocity.x += b1.m_invMass * P1X;
|
||||
b1.m_linearVelocity.y += b1.m_invMass * P1Y;
|
||||
//b1.m_angularVelocity += b1->m_invI * b2Cross(r1, P1);
|
||||
b1.m_angularVelocity += b1.m_invI * (r1X * P1Y - r1Y * P1X);
|
||||
}
|
||||
|
||||
if (this.m_limitState2 == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
//b2Vec2 v2 = b2->m_linearVelocity + b2Cross(b2->m_angularVelocity, r2);
|
||||
v2X = b2.m_linearVelocity.x + (-b2.m_angularVelocity * r2Y);
|
||||
v2Y = b2.m_linearVelocity.y + (b2.m_angularVelocity * r2X);
|
||||
|
||||
//float32 Cdot = -b2Dot(this.m_u2, v2);
|
||||
Cdot = -(this.m_u2.x * v2X + this.m_u2.y * v2Y);
|
||||
impulse = -this.m_limitMass2 * Cdot;
|
||||
oldLimitImpulse = this.m_limitImpulse2;
|
||||
this.m_limitImpulse2 = b2Math.b2Max(0.0, this.m_limitImpulse2 + impulse);
|
||||
impulse = this.m_limitImpulse2 - oldLimitImpulse;
|
||||
//b2Vec2 P2 = -impulse * this.m_u2;
|
||||
P2X = -impulse * this.m_u2.x;
|
||||
P2Y = -impulse * this.m_u2.y;
|
||||
//b2->m_linearVelocity += b2->m_invMass * P2;
|
||||
b2.m_linearVelocity.x += b2.m_invMass * P2X;
|
||||
b2.m_linearVelocity.y += b2.m_invMass * P2Y;
|
||||
//b2->m_angularVelocity += b2->m_invI * b2Cross(r2, P2);
|
||||
b2.m_angularVelocity += b2.m_invI * (r2X * P2Y - r2Y * P2X);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
SolvePositionConstraints: function(){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
//b2Vec2 s1 = this.m_ground->m_position + this.m_groundAnchor1;
|
||||
var s1X = this.m_ground.m_position.x + this.m_groundAnchor1.x;
|
||||
var s1Y = this.m_ground.m_position.y + this.m_groundAnchor1.y;
|
||||
//b2Vec2 s2 = this.m_ground->m_position + this.m_groundAnchor2;
|
||||
var s2X = this.m_ground.m_position.x + this.m_groundAnchor2.x;
|
||||
var s2Y = this.m_ground.m_position.y + this.m_groundAnchor2.y;
|
||||
|
||||
// temp vars
|
||||
var r1X;
|
||||
var r1Y;
|
||||
var r2X;
|
||||
var r2Y;
|
||||
var p1X;
|
||||
var p1Y;
|
||||
var p2X;
|
||||
var p2Y;
|
||||
var length1;
|
||||
var length2;
|
||||
var C;
|
||||
var impulse;
|
||||
var oldLimitPositionImpulse;
|
||||
|
||||
var linearError = 0.0;
|
||||
|
||||
{
|
||||
//var r1 = b2Mul(b1.m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//var r2 = b2Mul(b2.m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
//b2Vec2 p1 = b1->m_position + r1;
|
||||
p1X = b1.m_position.x + r1X;
|
||||
p1Y = b1.m_position.y + r1Y;
|
||||
//b2Vec2 p2 = b2->m_position + r2;
|
||||
p2X = b2.m_position.x + r2X;
|
||||
p2Y = b2.m_position.y + r2Y;
|
||||
|
||||
// Get the pulley axes.
|
||||
//this.m_u1 = p1 - s1;
|
||||
this.m_u1.Set(p1X - s1X, p1Y - s1Y);
|
||||
//this.m_u2 = p2 - s2;
|
||||
this.m_u2.Set(p2X - s2X, p2Y - s2Y);
|
||||
|
||||
length1 = this.m_u1.Length();
|
||||
length2 = this.m_u2.Length();
|
||||
|
||||
if (length1 > b2Settings.b2_linearSlop)
|
||||
{
|
||||
//this.m_u1 *= 1.0f / length1;
|
||||
this.m_u1.Multiply( 1.0 / length1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_u1.SetZero();
|
||||
}
|
||||
|
||||
if (length2 > b2Settings.b2_linearSlop)
|
||||
{
|
||||
//this.m_u2 *= 1.0f / length2;
|
||||
this.m_u2.Multiply( 1.0 / length2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_u2.SetZero();
|
||||
}
|
||||
|
||||
C = this.m_constant - length1 - this.m_ratio * length2;
|
||||
linearError = b2Math.b2Max(linearError, Math.abs(C));
|
||||
C = b2Math.b2Clamp(C, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
|
||||
impulse = -this.m_pulleyMass * C;
|
||||
|
||||
p1X = -impulse * this.m_u1.x;
|
||||
p1Y = -impulse * this.m_u1.y;
|
||||
p2X = -this.m_ratio * impulse * this.m_u2.x;
|
||||
p2Y = -this.m_ratio * impulse * this.m_u2.y;
|
||||
|
||||
b1.m_position.x += b1.m_invMass * p1X;
|
||||
b1.m_position.y += b1.m_invMass * p1Y;
|
||||
b1.m_rotation += b1.m_invI * (r1X * p1Y - r1Y * p1X);
|
||||
b2.m_position.x += b2.m_invMass * p2X;
|
||||
b2.m_position.y += b2.m_invMass * p2Y;
|
||||
b2.m_rotation += b2.m_invI * (r2X * p2Y - r2Y * p2X);
|
||||
|
||||
b1.m_R.Set(b1.m_rotation);
|
||||
b2.m_R.Set(b2.m_rotation);
|
||||
}
|
||||
|
||||
if (this.m_limitState1 == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
//b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 p1 = b1->m_position + r1;
|
||||
p1X = b1.m_position.x + r1X;
|
||||
p1Y = b1.m_position.y + r1Y;
|
||||
|
||||
//this.m_u1 = p1 - s1;
|
||||
this.m_u1.Set(p1X - s1X, p1Y - s1Y);
|
||||
|
||||
length1 = this.m_u1.Length();
|
||||
|
||||
if (length1 > b2Settings.b2_linearSlop)
|
||||
{
|
||||
//this.m_u1 *= 1.0 / length1;
|
||||
this.m_u1.x *= 1.0 / length1;
|
||||
this.m_u1.y *= 1.0 / length1;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_u1.SetZero();
|
||||
}
|
||||
|
||||
C = this.m_maxLength1 - length1;
|
||||
linearError = b2Math.b2Max(linearError, -C);
|
||||
C = b2Math.b2Clamp(C + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
||||
impulse = -this.m_limitMass1 * C;
|
||||
oldLimitPositionImpulse = this.m_limitPositionImpulse1;
|
||||
this.m_limitPositionImpulse1 = b2Math.b2Max(0.0, this.m_limitPositionImpulse1 + impulse);
|
||||
impulse = this.m_limitPositionImpulse1 - oldLimitPositionImpulse;
|
||||
|
||||
//P1 = -impulse * this.m_u1;
|
||||
p1X = -impulse * this.m_u1.x;
|
||||
p1Y = -impulse * this.m_u1.y;
|
||||
|
||||
b1.m_position.x += b1.m_invMass * p1X;
|
||||
b1.m_position.y += b1.m_invMass * p1Y;
|
||||
//b1.m_rotation += b1.m_invI * b2Cross(r1, P1);
|
||||
b1.m_rotation += b1.m_invI * (r1X * p1Y - r1Y * p1X);
|
||||
b1.m_R.Set(b1.m_rotation);
|
||||
}
|
||||
|
||||
if (this.m_limitState2 == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
//b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
//b2Vec2 p2 = b2->m_position + r2;
|
||||
p2X = b2.m_position.x + r2X;
|
||||
p2Y = b2.m_position.y + r2Y;
|
||||
|
||||
//this.m_u2 = p2 - s2;
|
||||
this.m_u2.Set(p2X - s2X, p2Y - s2Y);
|
||||
|
||||
length2 = this.m_u2.Length();
|
||||
|
||||
if (length2 > b2Settings.b2_linearSlop)
|
||||
{
|
||||
//this.m_u2 *= 1.0 / length2;
|
||||
this.m_u2.x *= 1.0 / length2;
|
||||
this.m_u2.y *= 1.0 / length2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_u2.SetZero();
|
||||
}
|
||||
|
||||
C = this.m_maxLength2 - length2;
|
||||
linearError = b2Math.b2Max(linearError, -C);
|
||||
C = b2Math.b2Clamp(C + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
|
||||
impulse = -this.m_limitMass2 * C;
|
||||
oldLimitPositionImpulse = this.m_limitPositionImpulse2;
|
||||
this.m_limitPositionImpulse2 = b2Math.b2Max(0.0, this.m_limitPositionImpulse2 + impulse);
|
||||
impulse = this.m_limitPositionImpulse2 - oldLimitPositionImpulse;
|
||||
|
||||
//P2 = -impulse * this.m_u2;
|
||||
p2X = -impulse * this.m_u2.x;
|
||||
p2Y = -impulse * this.m_u2.y;
|
||||
|
||||
//b2.m_position += b2.m_invMass * P2;
|
||||
b2.m_position.x += b2.m_invMass * p2X;
|
||||
b2.m_position.y += b2.m_invMass * p2Y;
|
||||
//b2.m_rotation += b2.m_invI * b2Cross(r2, P2);
|
||||
b2.m_rotation += b2.m_invI * (r2X * p2Y - r2Y * p2X);
|
||||
b2.m_R.Set(b2.m_rotation);
|
||||
}
|
||||
|
||||
return linearError < b2Settings.b2_linearSlop;
|
||||
},
|
||||
|
||||
|
||||
|
||||
m_ground: null,
|
||||
m_groundAnchor1: new b2Vec2(),
|
||||
m_groundAnchor2: new b2Vec2(),
|
||||
m_localAnchor1: new b2Vec2(),
|
||||
m_localAnchor2: new b2Vec2(),
|
||||
|
||||
m_u1: new b2Vec2(),
|
||||
m_u2: new b2Vec2(),
|
||||
|
||||
m_constant: null,
|
||||
m_ratio: null,
|
||||
|
||||
m_maxLength1: null,
|
||||
m_maxLength2: null,
|
||||
|
||||
// Effective masses
|
||||
m_pulleyMass: null,
|
||||
m_limitMass1: null,
|
||||
m_limitMass2: null,
|
||||
|
||||
// Impulses for accumulation/warm starting.
|
||||
m_pulleyImpulse: null,
|
||||
m_limitImpulse1: null,
|
||||
m_limitImpulse2: null,
|
||||
|
||||
// Position impulses for accumulation.
|
||||
m_limitPositionImpulse1: null,
|
||||
m_limitPositionImpulse2: null,
|
||||
|
||||
m_limitState1: 0,
|
||||
m_limitState2: 0
|
||||
|
||||
// static
|
||||
});
|
||||
|
||||
|
||||
|
||||
b2PulleyJoint.b2_minPulleyLength = b2Settings.b2_lengthUnitsPerMeter;
|
70
lib/box2d-js/js/box2d/dynamics/joints/b2PulleyJointDef.js
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The pulley joint is connected to two bodies and two fixed ground points.
|
||||
// The pulley supports a ratio such that:
|
||||
// length1 + ratio * length2 = constant
|
||||
// Yes, the force transmitted is scaled by the ratio.
|
||||
// The pulley also enforces a maximum length limit on both sides. This is
|
||||
// useful to prevent one side of the pulley hitting the top.
|
||||
|
||||
var b2PulleyJointDef = Class.create();
|
||||
Object.extend(b2PulleyJointDef.prototype, b2JointDef.prototype);
|
||||
Object.extend(b2PulleyJointDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2JointDef
|
||||
this.type = b2Joint.e_unknownJoint;
|
||||
this.userData = null;
|
||||
this.body1 = null;
|
||||
this.body2 = null;
|
||||
this.collideConnected = false;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.groundPoint1 = new b2Vec2();
|
||||
this.groundPoint2 = new b2Vec2();
|
||||
this.anchorPoint1 = new b2Vec2();
|
||||
this.anchorPoint2 = new b2Vec2();
|
||||
//
|
||||
|
||||
this.type = b2Joint.e_pulleyJoint;
|
||||
this.groundPoint1.Set(-1.0, 1.0);
|
||||
this.groundPoint2.Set(1.0, 1.0);
|
||||
this.anchorPoint1.Set(-1.0, 0.0);
|
||||
this.anchorPoint2.Set(1.0, 0.0);
|
||||
this.maxLength1 = 0.5 * b2PulleyJoint.b2_minPulleyLength;
|
||||
this.maxLength2 = 0.5 * b2PulleyJoint.b2_minPulleyLength;
|
||||
this.ratio = 1.0;
|
||||
this.collideConnected = true;
|
||||
},
|
||||
|
||||
groundPoint1: new b2Vec2(),
|
||||
groundPoint2: new b2Vec2(),
|
||||
anchorPoint1: new b2Vec2(),
|
||||
anchorPoint2: new b2Vec2(),
|
||||
maxLength1: null,
|
||||
maxLength2: null,
|
||||
ratio: null});
|
||||
|
491
lib/box2d-js/js/box2d/dynamics/joints/b2RevoluteJoint.js
Normal file
@ -0,0 +1,491 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Point-to-point constraint
|
||||
// C = p2 - p1
|
||||
// Cdot = v2 - v1
|
||||
// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
|
||||
// J = [-I -r1_skew I r2_skew ]
|
||||
// Identity used:
|
||||
// w k % (rx i + ry j) = w * (-ry i + rx j)
|
||||
|
||||
// Motor constraint
|
||||
// Cdot = w2 - w1
|
||||
// J = [0 0 -1 0 0 1]
|
||||
// K = invI1 + invI2
|
||||
|
||||
var b2RevoluteJoint = Class.create();
|
||||
Object.extend(b2RevoluteJoint.prototype, b2Joint.prototype);
|
||||
Object.extend(b2RevoluteJoint.prototype,
|
||||
{
|
||||
GetAnchor1: function(){
|
||||
var tMat = this.m_body1.m_R;
|
||||
return new b2Vec2( this.m_body1.m_position.x + (tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y),
|
||||
this.m_body1.m_position.y + (tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y));
|
||||
},
|
||||
GetAnchor2: function(){
|
||||
var tMat = this.m_body2.m_R;
|
||||
return new b2Vec2( this.m_body2.m_position.x + (tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y),
|
||||
this.m_body2.m_position.y + (tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y));
|
||||
},
|
||||
GetJointAngle: function(){
|
||||
return this.m_body2.m_rotation - this.m_body1.m_rotation;
|
||||
},
|
||||
GetJointSpeed: function(){
|
||||
return this.m_body2.m_angularVelocity - this.m_body1.m_angularVelocity;
|
||||
},
|
||||
GetMotorTorque: function(invTimeStep){
|
||||
return invTimeStep * this.m_motorImpulse;
|
||||
},
|
||||
|
||||
SetMotorSpeed: function(speed)
|
||||
{
|
||||
this.m_motorSpeed = speed;
|
||||
},
|
||||
|
||||
SetMotorTorque: function(torque)
|
||||
{
|
||||
this.m_maxMotorTorque = torque;
|
||||
},
|
||||
|
||||
GetReactionForce: function(invTimeStep)
|
||||
{
|
||||
var tVec = this.m_ptpImpulse.Copy();
|
||||
tVec.Multiply(invTimeStep);
|
||||
//return invTimeStep * this.m_ptpImpulse;
|
||||
return tVec;
|
||||
},
|
||||
|
||||
GetReactionTorque: function(invTimeStep)
|
||||
{
|
||||
return invTimeStep * this.m_limitImpulse;
|
||||
},
|
||||
|
||||
//--------------- Internals Below -------------------
|
||||
|
||||
initialize: function(def){
|
||||
// The constructor for b2Joint
|
||||
// initialize instance variables for references
|
||||
this.m_node1 = new b2JointNode();
|
||||
this.m_node2 = new b2JointNode();
|
||||
//
|
||||
this.m_type = def.type;
|
||||
this.m_prev = null;
|
||||
this.m_next = null;
|
||||
this.m_body1 = def.body1;
|
||||
this.m_body2 = def.body2;
|
||||
this.m_collideConnected = def.collideConnected;
|
||||
this.m_islandFlag = false;
|
||||
this.m_userData = def.userData;
|
||||
//
|
||||
|
||||
// initialize instance variables for references
|
||||
this.K = new b2Mat22();
|
||||
this.K1 = new b2Mat22();
|
||||
this.K2 = new b2Mat22();
|
||||
this.K3 = new b2Mat22();
|
||||
this.m_localAnchor1 = new b2Vec2();
|
||||
this.m_localAnchor2 = new b2Vec2();
|
||||
this.m_ptpImpulse = new b2Vec2();
|
||||
this.m_ptpMass = new b2Mat22();
|
||||
//
|
||||
|
||||
//super(def);
|
||||
|
||||
var tMat;
|
||||
var tX;
|
||||
var tY;
|
||||
|
||||
//this.m_localAnchor1 = b2Math.b2MulTMV(this.m_body1.m_R, b2Math.SubtractVV( def.anchorPoint, this.m_body1.m_position));
|
||||
tMat = this.m_body1.m_R;
|
||||
tX = def.anchorPoint.x - this.m_body1.m_position.x;
|
||||
tY = def.anchorPoint.y - this.m_body1.m_position.y;
|
||||
this.m_localAnchor1.x = tX * tMat.col1.x + tY * tMat.col1.y;
|
||||
this.m_localAnchor1.y = tX * tMat.col2.x + tY * tMat.col2.y;
|
||||
//this.m_localAnchor2 = b2Math.b2MulTMV(this.m_body2.m_R, b2Math.SubtractVV( def.anchorPoint, this.m_body2.m_position));
|
||||
tMat = this.m_body2.m_R;
|
||||
tX = def.anchorPoint.x - this.m_body2.m_position.x;
|
||||
tY = def.anchorPoint.y - this.m_body2.m_position.y;
|
||||
this.m_localAnchor2.x = tX * tMat.col1.x + tY * tMat.col1.y;
|
||||
this.m_localAnchor2.y = tX * tMat.col2.x + tY * tMat.col2.y;
|
||||
|
||||
this.m_intialAngle = this.m_body2.m_rotation - this.m_body1.m_rotation;
|
||||
|
||||
this.m_ptpImpulse.Set(0.0, 0.0);
|
||||
this.m_motorImpulse = 0.0;
|
||||
this.m_limitImpulse = 0.0;
|
||||
this.m_limitPositionImpulse = 0.0;
|
||||
|
||||
this.m_lowerAngle = def.lowerAngle;
|
||||
this.m_upperAngle = def.upperAngle;
|
||||
this.m_maxMotorTorque = def.motorTorque;
|
||||
this.m_motorSpeed = def.motorSpeed;
|
||||
this.m_enableLimit = def.enableLimit;
|
||||
this.m_enableMotor = def.enableMotor;
|
||||
},
|
||||
|
||||
// internal vars
|
||||
K: new b2Mat22(),
|
||||
K1: new b2Mat22(),
|
||||
K2: new b2Mat22(),
|
||||
K3: new b2Mat22(),
|
||||
PrepareVelocitySolver: function(){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
// Compute the effective mass matrix.
|
||||
//b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
// this.K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
|
||||
// = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
|
||||
// [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invMass2 = b2.m_invMass;
|
||||
var invI1 = b1.m_invI;
|
||||
var invI2 = b2.m_invI;
|
||||
|
||||
//var this.K1 = new b2Mat22();
|
||||
this.K1.col1.x = invMass1 + invMass2; this.K1.col2.x = 0.0;
|
||||
this.K1.col1.y = 0.0; this.K1.col2.y = invMass1 + invMass2;
|
||||
|
||||
//var this.K2 = new b2Mat22();
|
||||
this.K2.col1.x = invI1 * r1Y * r1Y; this.K2.col2.x = -invI1 * r1X * r1Y;
|
||||
this.K2.col1.y = -invI1 * r1X * r1Y; this.K2.col2.y = invI1 * r1X * r1X;
|
||||
|
||||
//var this.K3 = new b2Mat22();
|
||||
this.K3.col1.x = invI2 * r2Y * r2Y; this.K3.col2.x = -invI2 * r2X * r2Y;
|
||||
this.K3.col1.y = -invI2 * r2X * r2Y; this.K3.col2.y = invI2 * r2X * r2X;
|
||||
|
||||
//var this.K = b2Math.AddMM(b2Math.AddMM(this.K1, this.K2), this.K3);
|
||||
this.K.SetM(this.K1);
|
||||
this.K.AddM(this.K2);
|
||||
this.K.AddM(this.K3);
|
||||
|
||||
//this.m_ptpMass = this.K.Invert();
|
||||
this.K.Invert(this.m_ptpMass);
|
||||
|
||||
this.m_motorMass = 1.0 / (invI1 + invI2);
|
||||
|
||||
if (this.m_enableMotor == false)
|
||||
{
|
||||
this.m_motorImpulse = 0.0;
|
||||
}
|
||||
|
||||
if (this.m_enableLimit)
|
||||
{
|
||||
var jointAngle = b2.m_rotation - b1.m_rotation - this.m_intialAngle;
|
||||
if (b2Math.b2Abs(this.m_upperAngle - this.m_lowerAngle) < 2.0 * b2Settings.b2_angularSlop)
|
||||
{
|
||||
this.m_limitState = b2Joint.e_equalLimits;
|
||||
}
|
||||
else if (jointAngle <= this.m_lowerAngle)
|
||||
{
|
||||
if (this.m_limitState != b2Joint.e_atLowerLimit)
|
||||
{
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
this.m_limitState = b2Joint.e_atLowerLimit;
|
||||
}
|
||||
else if (jointAngle >= this.m_upperAngle)
|
||||
{
|
||||
if (this.m_limitState != b2Joint.e_atUpperLimit)
|
||||
{
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
this.m_limitState = b2Joint.e_atUpperLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_limitState = b2Joint.e_inactiveLimit;
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
|
||||
// Warm starting.
|
||||
if (b2World.s_enableWarmStarting)
|
||||
{
|
||||
//b1.m_linearVelocity.Subtract( b2Math.MulFV( invMass1, this.m_ptpImpulse) );
|
||||
b1.m_linearVelocity.x -= invMass1 * this.m_ptpImpulse.x;
|
||||
b1.m_linearVelocity.y -= invMass1 * this.m_ptpImpulse.y;
|
||||
//b1.m_angularVelocity -= invI1 * (b2Math.b2CrossVV(r1, this.m_ptpImpulse) + this.m_motorImpulse + this.m_limitImpulse);
|
||||
b1.m_angularVelocity -= invI1 * ((r1X * this.m_ptpImpulse.y - r1Y * this.m_ptpImpulse.x) + this.m_motorImpulse + this.m_limitImpulse);
|
||||
|
||||
//b2.m_linearVelocity.Add( b2Math.MulFV( invMass2 , this.m_ptpImpulse ));
|
||||
b2.m_linearVelocity.x += invMass2 * this.m_ptpImpulse.x;
|
||||
b2.m_linearVelocity.y += invMass2 * this.m_ptpImpulse.y;
|
||||
//b2.m_angularVelocity += invI2 * (b2Math.b2CrossVV(r2, this.m_ptpImpulse) + this.m_motorImpulse + this.m_limitImpulse);
|
||||
b2.m_angularVelocity += invI2 * ((r2X * this.m_ptpImpulse.y - r2Y * this.m_ptpImpulse.x) + this.m_motorImpulse + this.m_limitImpulse);
|
||||
}
|
||||
else{
|
||||
this.m_ptpImpulse.SetZero();
|
||||
this.m_motorImpulse = 0.0;
|
||||
this.m_limitImpulse = 0.0;
|
||||
}
|
||||
|
||||
this.m_limitPositionImpulse = 0.0;
|
||||
},
|
||||
|
||||
|
||||
SolveVelocityConstraints: function(step){
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var tMat;
|
||||
|
||||
//var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
var oldLimitImpulse;
|
||||
|
||||
// Solve point-to-point constraint
|
||||
//b2Vec2 ptpCdot = b2.m_linearVelocity + b2Cross(b2.m_angularVelocity, r2) - b1.m_linearVelocity - b2Cross(b1.m_angularVelocity, r1);
|
||||
var ptpCdotX = b2.m_linearVelocity.x + (-b2.m_angularVelocity * r2Y) - b1.m_linearVelocity.x - (-b1.m_angularVelocity * r1Y);
|
||||
var ptpCdotY = b2.m_linearVelocity.y + (b2.m_angularVelocity * r2X) - b1.m_linearVelocity.y - (b1.m_angularVelocity * r1X);
|
||||
|
||||
//b2Vec2 ptpImpulse = -b2Mul(this.m_ptpMass, ptpCdot);
|
||||
var ptpImpulseX = -(this.m_ptpMass.col1.x * ptpCdotX + this.m_ptpMass.col2.x * ptpCdotY);
|
||||
var ptpImpulseY = -(this.m_ptpMass.col1.y * ptpCdotX + this.m_ptpMass.col2.y * ptpCdotY);
|
||||
this.m_ptpImpulse.x += ptpImpulseX;
|
||||
this.m_ptpImpulse.y += ptpImpulseY;
|
||||
|
||||
//b1->m_linearVelocity -= b1->m_invMass * ptpImpulse;
|
||||
b1.m_linearVelocity.x -= b1.m_invMass * ptpImpulseX;
|
||||
b1.m_linearVelocity.y -= b1.m_invMass * ptpImpulseY;
|
||||
//b1->m_angularVelocity -= b1->m_invI * b2Cross(r1, ptpImpulse);
|
||||
b1.m_angularVelocity -= b1.m_invI * (r1X * ptpImpulseY - r1Y * ptpImpulseX);
|
||||
|
||||
//b2->m_linearVelocity += b2->m_invMass * ptpImpulse;
|
||||
b2.m_linearVelocity.x += b2.m_invMass * ptpImpulseX;
|
||||
b2.m_linearVelocity.y += b2.m_invMass * ptpImpulseY;
|
||||
//b2->m_angularVelocity += b2->m_invI * b2Cross(r2, ptpImpulse);
|
||||
b2.m_angularVelocity += b2.m_invI * (r2X * ptpImpulseY - r2Y * ptpImpulseX);
|
||||
|
||||
if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits)
|
||||
{
|
||||
var motorCdot = b2.m_angularVelocity - b1.m_angularVelocity - this.m_motorSpeed;
|
||||
var motorImpulse = -this.m_motorMass * motorCdot;
|
||||
var oldMotorImpulse = this.m_motorImpulse;
|
||||
this.m_motorImpulse = b2Math.b2Clamp(this.m_motorImpulse + motorImpulse, -step.dt * this.m_maxMotorTorque, step.dt * this.m_maxMotorTorque);
|
||||
motorImpulse = this.m_motorImpulse - oldMotorImpulse;
|
||||
b1.m_angularVelocity -= b1.m_invI * motorImpulse;
|
||||
b2.m_angularVelocity += b2.m_invI * motorImpulse;
|
||||
}
|
||||
|
||||
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
||||
{
|
||||
var limitCdot = b2.m_angularVelocity - b1.m_angularVelocity;
|
||||
var limitImpulse = -this.m_motorMass * limitCdot;
|
||||
|
||||
if (this.m_limitState == b2Joint.e_equalLimits)
|
||||
{
|
||||
this.m_limitImpulse += limitImpulse;
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
||||
{
|
||||
oldLimitImpulse = this.m_limitImpulse;
|
||||
this.m_limitImpulse = b2Math.b2Max(this.m_limitImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitImpulse - oldLimitImpulse;
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
oldLimitImpulse = this.m_limitImpulse;
|
||||
this.m_limitImpulse = b2Math.b2Min(this.m_limitImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitImpulse - oldLimitImpulse;
|
||||
}
|
||||
|
||||
b1.m_angularVelocity -= b1.m_invI * limitImpulse;
|
||||
b2.m_angularVelocity += b2.m_invI * limitImpulse;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
SolvePositionConstraints: function(){
|
||||
|
||||
var oldLimitImpulse;
|
||||
var limitC;
|
||||
|
||||
var b1 = this.m_body1;
|
||||
var b2 = this.m_body2;
|
||||
|
||||
var positionError = 0.0;
|
||||
|
||||
var tMat;
|
||||
|
||||
// Solve point-to-point position error.
|
||||
//var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
|
||||
tMat = b1.m_R;
|
||||
var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
|
||||
var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
|
||||
//var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
|
||||
tMat = b2.m_R;
|
||||
var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
|
||||
var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
|
||||
|
||||
//b2Vec2 p1 = b1->m_position + r1;
|
||||
var p1X = b1.m_position.x + r1X;
|
||||
var p1Y = b1.m_position.y + r1Y;
|
||||
//b2Vec2 p2 = b2->m_position + r2;
|
||||
var p2X = b2.m_position.x + r2X;
|
||||
var p2Y = b2.m_position.y + r2Y;
|
||||
|
||||
//b2Vec2 ptpC = p2 - p1;
|
||||
var ptpCX = p2X - p1X;
|
||||
var ptpCY = p2Y - p1Y;
|
||||
|
||||
//float32 positionError = ptpC.Length();
|
||||
positionError = Math.sqrt(ptpCX*ptpCX + ptpCY*ptpCY);
|
||||
|
||||
// Prevent overly large corrections.
|
||||
//b2Vec2 dpMax(b2_maxLinearCorrection, b2_maxLinearCorrection);
|
||||
//ptpC = b2Clamp(ptpC, -dpMax, dpMax);
|
||||
|
||||
//float32 invMass1 = b1->m_invMass, invMass2 = b2->m_invMass;
|
||||
var invMass1 = b1.m_invMass;
|
||||
var invMass2 = b2.m_invMass;
|
||||
//float32 invI1 = b1->m_invI, invI2 = b2->m_invI;
|
||||
var invI1 = b1.m_invI;
|
||||
var invI2 = b2.m_invI;
|
||||
|
||||
//b2Mat22 this.K1;
|
||||
this.K1.col1.x = invMass1 + invMass2; this.K1.col2.x = 0.0;
|
||||
this.K1.col1.y = 0.0; this.K1.col2.y = invMass1 + invMass2;
|
||||
|
||||
//b2Mat22 this.K2;
|
||||
this.K2.col1.x = invI1 * r1Y * r1Y; this.K2.col2.x = -invI1 * r1X * r1Y;
|
||||
this.K2.col1.y = -invI1 * r1X * r1Y; this.K2.col2.y = invI1 * r1X * r1X;
|
||||
|
||||
//b2Mat22 this.K3;
|
||||
this.K3.col1.x = invI2 * r2Y * r2Y; this.K3.col2.x = -invI2 * r2X * r2Y;
|
||||
this.K3.col1.y = -invI2 * r2X * r2Y; this.K3.col2.y = invI2 * r2X * r2X;
|
||||
|
||||
//b2Mat22 this.K = this.K1 + this.K2 + this.K3;
|
||||
this.K.SetM(this.K1);
|
||||
this.K.AddM(this.K2);
|
||||
this.K.AddM(this.K3);
|
||||
//b2Vec2 impulse = this.K.Solve(-ptpC);
|
||||
this.K.Solve(b2RevoluteJoint.tImpulse, -ptpCX, -ptpCY);
|
||||
var impulseX = b2RevoluteJoint.tImpulse.x;
|
||||
var impulseY = b2RevoluteJoint.tImpulse.y;
|
||||
|
||||
//b1.m_position -= b1.m_invMass * impulse;
|
||||
b1.m_position.x -= b1.m_invMass * impulseX;
|
||||
b1.m_position.y -= b1.m_invMass * impulseY;
|
||||
//b1.m_rotation -= b1.m_invI * b2Cross(r1, impulse);
|
||||
b1.m_rotation -= b1.m_invI * (r1X * impulseY - r1Y * impulseX);
|
||||
b1.m_R.Set(b1.m_rotation);
|
||||
|
||||
//b2.m_position += b2.m_invMass * impulse;
|
||||
b2.m_position.x += b2.m_invMass * impulseX;
|
||||
b2.m_position.y += b2.m_invMass * impulseY;
|
||||
//b2.m_rotation += b2.m_invI * b2Cross(r2, impulse);
|
||||
b2.m_rotation += b2.m_invI * (r2X * impulseY - r2Y * impulseX);
|
||||
b2.m_R.Set(b2.m_rotation);
|
||||
|
||||
|
||||
// Handle limits.
|
||||
var angularError = 0.0;
|
||||
|
||||
if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
|
||||
{
|
||||
var angle = b2.m_rotation - b1.m_rotation - this.m_intialAngle;
|
||||
var limitImpulse = 0.0;
|
||||
|
||||
if (this.m_limitState == b2Joint.e_equalLimits)
|
||||
{
|
||||
// Prevent large angular corrections
|
||||
limitC = b2Math.b2Clamp(angle, -b2Settings.b2_maxAngularCorrection, b2Settings.b2_maxAngularCorrection);
|
||||
limitImpulse = -this.m_motorMass * limitC;
|
||||
angularError = b2Math.b2Abs(limitC);
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atLowerLimit)
|
||||
{
|
||||
limitC = angle - this.m_lowerAngle;
|
||||
angularError = b2Math.b2Max(0.0, -limitC);
|
||||
|
||||
// Prevent large angular corrections and allow some slop.
|
||||
limitC = b2Math.b2Clamp(limitC + b2Settings.b2_angularSlop, -b2Settings.b2_maxAngularCorrection, 0.0);
|
||||
limitImpulse = -this.m_motorMass * limitC;
|
||||
oldLimitImpulse = this.m_limitPositionImpulse;
|
||||
this.m_limitPositionImpulse = b2Math.b2Max(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
||||
}
|
||||
else if (this.m_limitState == b2Joint.e_atUpperLimit)
|
||||
{
|
||||
limitC = angle - this.m_upperAngle;
|
||||
angularError = b2Math.b2Max(0.0, limitC);
|
||||
|
||||
// Prevent large angular corrections and allow some slop.
|
||||
limitC = b2Math.b2Clamp(limitC - b2Settings.b2_angularSlop, 0.0, b2Settings.b2_maxAngularCorrection);
|
||||
limitImpulse = -this.m_motorMass * limitC;
|
||||
oldLimitImpulse = this.m_limitPositionImpulse;
|
||||
this.m_limitPositionImpulse = b2Math.b2Min(this.m_limitPositionImpulse + limitImpulse, 0.0);
|
||||
limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
|
||||
}
|
||||
|
||||
b1.m_rotation -= b1.m_invI * limitImpulse;
|
||||
b1.m_R.Set(b1.m_rotation);
|
||||
b2.m_rotation += b2.m_invI * limitImpulse;
|
||||
b2.m_R.Set(b2.m_rotation);
|
||||
}
|
||||
|
||||
return positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
|
||||
},
|
||||
|
||||
m_localAnchor1: new b2Vec2(),
|
||||
m_localAnchor2: new b2Vec2(),
|
||||
m_ptpImpulse: new b2Vec2(),
|
||||
m_motorImpulse: null,
|
||||
m_limitImpulse: null,
|
||||
m_limitPositionImpulse: null,
|
||||
|
||||
m_ptpMass: new b2Mat22(),
|
||||
m_motorMass: null,
|
||||
m_intialAngle: null,
|
||||
m_lowerAngle: null,
|
||||
m_upperAngle: null,
|
||||
m_maxMotorTorque: null,
|
||||
m_motorSpeed: null,
|
||||
|
||||
m_enableLimit: null,
|
||||
m_enableMotor: null,
|
||||
m_limitState: 0});
|
||||
|
||||
b2RevoluteJoint.tImpulse = new b2Vec2();
|
55
lib/box2d-js/js/box2d/dynamics/joints/b2RevoluteJointDef.js
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Erin Catto http:
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked, and must not be
|
||||
* misrepresented the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var b2RevoluteJointDef = Class.create();
|
||||
Object.extend(b2RevoluteJointDef.prototype, b2JointDef.prototype);
|
||||
Object.extend(b2RevoluteJointDef.prototype,
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
// The constructor for b2JointDef
|
||||
this.type = b2Joint.e_unknownJoint;
|
||||
this.userData = null;
|
||||
this.body1 = null;
|
||||
this.body2 = null;
|
||||
this.collideConnected = false;
|
||||
//
|
||||
|
||||
this.type = b2Joint.e_revoluteJoint;
|
||||
this.anchorPoint = new b2Vec2(0.0, 0.0);
|
||||
this.lowerAngle = 0.0;
|
||||
this.upperAngle = 0.0;
|
||||
this.motorTorque = 0.0;
|
||||
this.motorSpeed = 0.0;
|
||||
this.enableLimit = false;
|
||||
this.enableMotor = false;
|
||||
},
|
||||
|
||||
anchorPoint: null,
|
||||
lowerAngle: null,
|
||||
upperAngle: null,
|
||||
motorTorque: null,
|
||||
motorSpeed: null,
|
||||
enableLimit: null,
|
||||
enableMotor: null});
|
||||
|
10
lib/box2d-js/lib/AUTHORS
Normal file
@ -0,0 +1,10 @@
|
||||
ExplorerCanvas
|
||||
|
||||
Google Open Source:
|
||||
<http://code.google.com>
|
||||
<opensource@google.com>
|
||||
|
||||
Developers:
|
||||
Emil A Eklund <emil@eae.net>
|
||||
Erik Arvidsson <erik@eae.net>
|
||||
Glen Murphy <glen@glenmurphy.com>
|
202
lib/box2d-js/lib/COPYING
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
22
lib/box2d-js/lib/README
Normal file
@ -0,0 +1,22 @@
|
||||
ExplorerCanvas
|
||||
Copyright 2006 Google Inc.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
DESCRIPTION
|
||||
|
||||
Firefox, Safari and Opera 9 support the canvas tag to allow 2D command-based
|
||||
drawing operations. ExplorerCanvas brings the same functionality to Internet
|
||||
Explorer; web developers only need to include a single script tag in their
|
||||
existing canvas webpages to enable this support.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INSTALLATION
|
||||
|
||||
Include the ExplorerCanvas tag in the same directory as your HTML files, and
|
||||
add the following code to your page, preferably in the <head> tag.
|
||||
|
||||
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
|
||||
|
||||
If you run into trouble, please look at the included example code to see how
|
||||
to best implement this
|
19
lib/box2d-js/lib/excanvas-compressed.js
Normal file
@ -0,0 +1,19 @@
|
||||
if(!window.CanvasRenderingContext2D){(function(){var I=Math,i=I.round,L=I.sin,M=I.cos,m=10,A=m/2,Q={init:function(a){var b=a||document;if(/MSIE/.test(navigator.userAgent)&&!window.opera){var c=this;b.attachEvent("onreadystatechange",function(){c.r(b)})}},r:function(a){if(a.readyState=="complete"){if(!a.namespaces["s"]){a.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml")}var b=a.createStyleSheet();b.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}";
|
||||
var c=a.getElementsByTagName("canvas");for(var d=0;d<c.length;d++){if(!c[d].getContext){this.initElement(c[d])}}}},q:function(a){var b=a.outerHTML,c=a.ownerDocument.createElement(b);if(b.slice(-2)!="/>"){var d="/"+a.tagName,e;while((e=a.nextSibling)&&e.tagName!=d){e.removeNode()}if(e){e.removeNode()}}a.parentNode.replaceChild(c,a);return c},initElement:function(a){a=this.q(a);a.getContext=function(){if(this.l){return this.l}return this.l=new K(this)};a.attachEvent("onpropertychange",V);a.attachEvent("onresize",
|
||||
W);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+"px"}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+"px"}else{a.height=a.clientHeight}return a}};function V(a){var b=a.srcElement;switch(a.propertyName){case "width":b.style.width=b.attributes.width.nodeValue+"px";b.getContext().clearRect();break;case "height":b.style.height=b.attributes.height.nodeValue+"px";b.getContext().clearRect();break}}function W(a){var b=a.srcElement;
|
||||
if(b.firstChild){b.firstChild.style.width=b.clientWidth+"px";b.firstChild.style.height=b.clientHeight+"px"}}Q.init();var R=[];for(var E=0;E<16;E++){for(var F=0;F<16;F++){R[E*16+F]=E.toString(16)+F.toString(16)}}function J(){return[[1,0,0],[0,1,0],[0,0,1]]}function G(a,b){var c=J();for(var d=0;d<3;d++){for(var e=0;e<3;e++){var g=0;for(var h=0;h<3;h++){g+=a[d][h]*b[h][e]}c[d][e]=g}}return c}function N(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=
|
||||
a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.d=a.d;b.e=a.e}function O(a){var b,c=1;a=String(a);if(a.substring(0,3)=="rgb"){var d=a.indexOf("(",3),e=a.indexOf(")",d+1),g=a.substring(d+1,e).split(",");b="#";for(var h=0;h<3;h++){b+=R[Number(g[h])]}if(g.length==4&&a.substr(3,1)=="a"){c=g[3]}}else{b=a}return[b,c]}function S(a){switch(a){case "butt":return"flat";case "round":return"round";
|
||||
case "square":default:return"square"}}function K(a){this.a=J();this.m=[];this.k=[];this.c=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=m*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement("div");b.style.width=a.clientWidth+"px";b.style.height=a.clientHeight+"px";b.style.overflow="hidden";b.style.position="absolute";a.appendChild(b);this.j=b;this.d=1;this.e=1}var j=K.prototype;j.clearRect=function(){this.j.innerHTML=
|
||||
"";this.c=[]};j.beginPath=function(){this.c=[]};j.moveTo=function(a,b){this.c.push({type:"moveTo",x:a,y:b});this.f=a;this.g=b};j.lineTo=function(a,b){this.c.push({type:"lineTo",x:a,y:b});this.f=a;this.g=b};j.bezierCurveTo=function(a,b,c,d,e,g){this.c.push({type:"bezierCurveTo",cp1x:a,cp1y:b,cp2x:c,cp2y:d,x:e,y:g});this.f=e;this.g=g};j.quadraticCurveTo=function(a,b,c,d){var e=this.f+0.6666666666666666*(a-this.f),g=this.g+0.6666666666666666*(b-this.g),h=e+(c-this.f)/3,l=g+(d-this.g)/3;this.bezierCurveTo(e,
|
||||
g,h,l,c,d)};j.arc=function(a,b,c,d,e,g){c*=m;var h=g?"at":"wa",l=a+M(d)*c-A,n=b+L(d)*c-A,o=a+M(e)*c-A,f=b+L(e)*c-A;if(l==o&&!g){l+=0.125}this.c.push({type:h,x:a,y:b,radius:c,xStart:l,yStart:n,xEnd:o,yEnd:f})};j.rect=function(a,b,c,d){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath()};j.strokeRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.stroke()};j.fillRect=function(a,
|
||||
b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill()};j.createLinearGradient=function(a,b,c,d){var e=new H("gradient");return e};j.createRadialGradient=function(a,b,c,d,e,g){var h=new H("gradientradial");h.n=c;h.o=g;h.i.x=a;h.i.y=b;return h};j.drawImage=function(a,b){var c,d,e,g,h,l,n,o,f=a.runtimeStyle.width,k=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var q=a.width,r=a.height;a.runtimeStyle.width=
|
||||
f;a.runtimeStyle.height=k;if(arguments.length==3){c=arguments[1];d=arguments[2];h=(l=0);n=(e=q);o=(g=r)}else if(arguments.length==5){c=arguments[1];d=arguments[2];e=arguments[3];g=arguments[4];h=(l=0);n=q;o=r}else if(arguments.length==9){h=arguments[1];l=arguments[2];n=arguments[3];o=arguments[4];c=arguments[5];d=arguments[6];e=arguments[7];g=arguments[8]}else{throw"Invalid number of arguments";}var s=this.b(c,d),t=[],v=10,w=10;t.push(" <g_vml_:group",' coordsize="',m*v,",",m*w,'"',' coordorigin="0,0"',
|
||||
' style="width:',v,";height:",w,";position:absolute;");if(this.a[0][0]!=1||this.a[0][1]){var x=[];x.push("M11='",this.a[0][0],"',","M12='",this.a[1][0],"',","M21='",this.a[0][1],"',","M22='",this.a[1][1],"',","Dx='",i(s.x/m),"',","Dy='",i(s.y/m),"'");var p=s,y=this.b(c+e,d),z=this.b(c,d+g),B=this.b(c+e,d+g);p.x=Math.max(p.x,y.x,z.x,B.x);p.y=Math.max(p.y,y.y,z.y,B.y);t.push("padding:0 ",i(p.x/m),"px ",i(p.y/m),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",x.join(""),", sizingmethod='clip');")}else{t.push("top:",
|
||||
i(s.y/m),"px;left:",i(s.x/m),"px;")}t.push(' ">','<g_vml_:image src="',a.src,'"',' style="width:',m*e,";"," height:",m*g,';"',' cropleft="',h/q,'"',' croptop="',l/r,'"',' cropright="',(q-h-n)/q,'"',' cropbottom="',(r-l-o)/r,'"'," />","</g_vml_:group>");this.j.insertAdjacentHTML("BeforeEnd",t.join(""))};j.stroke=function(a){var b=[],c=O(a?this.fillStyle:this.strokeStyle),d=c[0],e=c[1]*this.globalAlpha,g=10,h=10;b.push("<g_vml_:shape",' fillcolor="',d,'"',' filled="',Boolean(a),'"',' style="position:absolute;width:',
|
||||
g,";height:",h,';"',' coordorigin="0 0" coordsize="',m*g," ",m*h,'"',' stroked="',!a,'"',' strokeweight="',this.lineWidth,'"',' strokecolor="',d,'"',' path="');var l={x:null,y:null},n={x:null,y:null};for(var o=0;o<this.c.length;o++){var f=this.c[o];if(f.type=="moveTo"){b.push(" m ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="lineTo"){b.push(" l ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="close"){b.push(" x ")}else if(f.type=="bezierCurveTo"){b.push(" c ");
|
||||
var k=this.b(f.x,f.y),q=this.b(f.cp1x,f.cp1y),r=this.b(f.cp2x,f.cp2y);b.push(i(q.x),",",i(q.y),",",i(r.x),",",i(r.y),",",i(k.x),",",i(k.y))}else if(f.type=="at"||f.type=="wa"){b.push(" ",f.type," ");var k=this.b(f.x,f.y),s=this.b(f.xStart,f.yStart),t=this.b(f.xEnd,f.yEnd);b.push(i(k.x-this.d*f.radius),",",i(k.y-this.e*f.radius)," ",i(k.x+this.d*f.radius),",",i(k.y+this.e*f.radius)," ",i(s.x),",",i(s.y)," ",i(t.x),",",i(t.y))}if(k){if(l.x==null||k.x<l.x){l.x=k.x}if(n.x==null||k.x>n.x){n.x=k.x}if(l.y==
|
||||
null||k.y<l.y){l.y=k.y}if(n.y==null||k.y>n.y){n.y=k.y}}}b.push(' ">');if(typeof this.fillStyle=="object"){var v={x:"50%",y:"50%"},w=n.x-l.x,x=n.y-l.y,p=w>x?w:x;v.x=i(this.fillStyle.i.x/w*100+50)+"%";v.y=i(this.fillStyle.i.y/x*100+50)+"%";var y=[];if(this.fillStyle.p=="gradientradial"){var z=this.fillStyle.n/p*100,B=this.fillStyle.o/p*100-z}else{var z=0,B=100}var C={offset:null,color:null},D={offset:null,color:null};this.fillStyle.h.sort(function(T,U){return T.offset-U.offset});for(var o=0;o<this.fillStyle.h.length;o++){var u=
|
||||
this.fillStyle.h[o];y.push(u.offset*B+z,"% ",u.color,",");if(u.offset>C.offset||C.offset==null){C.offset=u.offset;C.color=u.color}if(u.offset<D.offset||D.offset==null){D.offset=u.offset;D.color=u.color}}y.pop();b.push("<g_vml_:fill",' color="',D.color,'"',' color2="',C.color,'"',' type="',this.fillStyle.p,'"',' focusposition="',v.x,", ",v.y,'"',' colors="',y.join(""),'"',' opacity="',e,'" />')}else if(a){b.push('<g_vml_:fill color="',d,'" opacity="',e,'" />')}else{b.push("<g_vml_:stroke",' opacity="',
|
||||
e,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',S(this.lineCap),'"',' weight="',this.lineWidth,'px"',' color="',d,'" />')}b.push("</g_vml_:shape>");this.j.insertAdjacentHTML("beforeEnd",b.join(""));this.c=[]};j.fill=function(){this.stroke(true)};j.closePath=function(){this.c.push({type:"close"})};j.b=function(a,b){return{x:m*(a*this.a[0][0]+b*this.a[1][0]+this.a[2][0])-A,y:m*(a*this.a[0][1]+b*this.a[1][1]+this.a[2][1])-A}};j.save=function(){var a={};N(this,a);
|
||||
this.k.push(a);this.m.push(this.a);this.a=G(J(),this.a)};j.restore=function(){N(this.k.pop(),this);this.a=this.m.pop()};j.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];this.a=G(c,this.a)};j.rotate=function(a){var b=M(a),c=L(a),d=[[b,c,0],[-c,b,0],[0,0,1]];this.a=G(d,this.a)};j.scale=function(a,b){this.d*=a;this.e*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];this.a=G(c,this.a)};j.clip=function(){};j.arcTo=function(){};j.createPattern=function(){return new P};function H(a){this.p=a;this.n=0;this.o=
|
||||
0;this.h=[];this.i={x:0,y:0}}H.prototype.addColorStop=function(a,b){b=O(b);this.h.push({offset:1-a,color:b})};function P(){}G_vmlCanvasManager=Q;CanvasRenderingContext2D=K;CanvasGradient=H;CanvasPattern=P})()};
|
785
lib/box2d-js/lib/excanvas.js
Normal file
@ -0,0 +1,785 @@
|
||||
// Copyright 2006 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
// Known Issues:
|
||||
//
|
||||
// * Patterns are not implemented.
|
||||
// * Radial gradient are not implemented. The VML version of these look very
|
||||
// different from the canvas one.
|
||||
// * Clipping paths are not implemented.
|
||||
// * Coordsize. The width and height attribute have higher priority than the
|
||||
// width and height style values which isn't correct.
|
||||
// * Painting mode isn't implemented.
|
||||
// * Canvas width/height should is using content-box by default. IE in
|
||||
// Quirks mode will draw the canvas using border-box. Either change your
|
||||
// doctype to HTML5
|
||||
// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
|
||||
// or use Box Sizing Behavior from WebFX
|
||||
// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
|
||||
// * Optimize. There is always room for speed improvements.
|
||||
|
||||
// only add this code if we do not already have a canvas implementation
|
||||
if (!window.CanvasRenderingContext2D) {
|
||||
|
||||
(function () {
|
||||
|
||||
// alias some functions to make (compiled) code shorter
|
||||
var m = Math;
|
||||
var mr = m.round;
|
||||
var ms = m.sin;
|
||||
var mc = m.cos;
|
||||
|
||||
// this is used for sub pixel precision
|
||||
var Z = 10;
|
||||
var Z2 = Z / 2;
|
||||
|
||||
var G_vmlCanvasManager_ = {
|
||||
init: function (opt_doc) {
|
||||
var doc = opt_doc || document;
|
||||
if (/MSIE/.test(navigator.userAgent) && !window.opera) {
|
||||
var self = this;
|
||||
doc.attachEvent("onreadystatechange", function () {
|
||||
self.init_(doc);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
init_: function (doc) {
|
||||
if (doc.readyState == "complete") {
|
||||
// create xmlns
|
||||
if (!doc.namespaces["g_vml_"]) {
|
||||
doc.namespaces.add("g_vml_", "urn:schemas-microsoft-com:vml");
|
||||
}
|
||||
|
||||
// setup default css
|
||||
var ss = doc.createStyleSheet();
|
||||
ss.cssText = "canvas{display:inline-block;overflow:hidden;" +
|
||||
// default size is 300x150 in Gecko and Opera
|
||||
"text-align:left;width:300px;height:150px}" +
|
||||
"g_vml_\\:*{behavior:url(#default#VML)}";
|
||||
|
||||
// find all canvas elements
|
||||
var els = doc.getElementsByTagName("canvas");
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
if (!els[i].getContext) {
|
||||
this.initElement(els[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
fixElement_: function (el) {
|
||||
// in IE before version 5.5 we would need to add HTML: to the tag name
|
||||
// but we do not care about IE before version 6
|
||||
var outerHTML = el.outerHTML;
|
||||
|
||||
var newEl = el.ownerDocument.createElement(outerHTML);
|
||||
// if the tag is still open IE has created the children as siblings and
|
||||
// it has also created a tag with the name "/FOO"
|
||||
if (outerHTML.slice(-2) != "/>") {
|
||||
var tagName = "/" + el.tagName;
|
||||
var ns;
|
||||
// remove content
|
||||
while ((ns = el.nextSibling) && ns.tagName != tagName) {
|
||||
ns.removeNode();
|
||||
}
|
||||
// remove the incorrect closing tag
|
||||
if (ns) {
|
||||
ns.removeNode();
|
||||
}
|
||||
}
|
||||
el.parentNode.replaceChild(newEl, el);
|
||||
return newEl;
|
||||
},
|
||||
|
||||
/**
|
||||
* Public initializes a canvas element so that it can be used as canvas
|
||||
* element from now on. This is called automatically before the page is
|
||||
* loaded but if you are creating elements using createElement you need to
|
||||
* make sure this is called on the element.
|
||||
* @param {HTMLElement} el The canvas element to initialize.
|
||||
* @return {HTMLElement} the element that was created.
|
||||
*/
|
||||
initElement: function (el) {
|
||||
el = this.fixElement_(el);
|
||||
el.getContext = function () {
|
||||
if (this.context_) {
|
||||
return this.context_;
|
||||
}
|
||||
return this.context_ = new CanvasRenderingContext2D_(this);
|
||||
};
|
||||
|
||||
// do not use inline function because that will leak memory
|
||||
el.attachEvent('onpropertychange', onPropertyChange);
|
||||
el.attachEvent('onresize', onResize);
|
||||
|
||||
var attrs = el.attributes;
|
||||
if (attrs.width && attrs.width.specified) {
|
||||
// TODO: use runtimeStyle and coordsize
|
||||
// el.getContext().setWidth_(attrs.width.nodeValue);
|
||||
el.style.width = attrs.width.nodeValue + "px";
|
||||
} else {
|
||||
el.width = el.clientWidth;
|
||||
}
|
||||
if (attrs.height && attrs.height.specified) {
|
||||
// TODO: use runtimeStyle and coordsize
|
||||
// el.getContext().setHeight_(attrs.height.nodeValue);
|
||||
el.style.height = attrs.height.nodeValue + "px";
|
||||
} else {
|
||||
el.height = el.clientHeight;
|
||||
}
|
||||
//el.getContext().setCoordsize_()
|
||||
return el;
|
||||
}
|
||||
};
|
||||
|
||||
function onPropertyChange(e) {
|
||||
var el = e.srcElement;
|
||||
|
||||
switch (e.propertyName) {
|
||||
case 'width':
|
||||
el.style.width = el.attributes.width.nodeValue + "px";
|
||||
el.getContext().clearRect();
|
||||
break;
|
||||
case 'height':
|
||||
el.style.height = el.attributes.height.nodeValue + "px";
|
||||
el.getContext().clearRect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function onResize(e) {
|
||||
var el = e.srcElement;
|
||||
if (el.firstChild) {
|
||||
el.firstChild.style.width = el.clientWidth + 'px';
|
||||
el.firstChild.style.height = el.clientHeight + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
G_vmlCanvasManager_.init();
|
||||
|
||||
// precompute "00" to "FF"
|
||||
var dec2hex = [];
|
||||
for (var i = 0; i < 16; i++) {
|
||||
for (var j = 0; j < 16; j++) {
|
||||
dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
|
||||
}
|
||||
}
|
||||
|
||||
function createMatrixIdentity() {
|
||||
return [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
}
|
||||
|
||||
function matrixMultiply(m1, m2) {
|
||||
var result = createMatrixIdentity();
|
||||
|
||||
for (var x = 0; x < 3; x++) {
|
||||
for (var y = 0; y < 3; y++) {
|
||||
var sum = 0;
|
||||
|
||||
for (var z = 0; z < 3; z++) {
|
||||
sum += m1[x][z] * m2[z][y];
|
||||
}
|
||||
|
||||
result[x][y] = sum;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function copyState(o1, o2) {
|
||||
o2.fillStyle = o1.fillStyle;
|
||||
o2.lineCap = o1.lineCap;
|
||||
o2.lineJoin = o1.lineJoin;
|
||||
o2.lineWidth = o1.lineWidth;
|
||||
o2.miterLimit = o1.miterLimit;
|
||||
o2.shadowBlur = o1.shadowBlur;
|
||||
o2.shadowColor = o1.shadowColor;
|
||||
o2.shadowOffsetX = o1.shadowOffsetX;
|
||||
o2.shadowOffsetY = o1.shadowOffsetY;
|
||||
o2.strokeStyle = o1.strokeStyle;
|
||||
o2.arcScaleX_ = o1.arcScaleX_;
|
||||
o2.arcScaleY_ = o1.arcScaleY_;
|
||||
}
|
||||
|
||||
function processStyle(styleString) {
|
||||
var str, alpha = 1;
|
||||
|
||||
styleString = String(styleString);
|
||||
if (styleString.substring(0, 3) == "rgb") {
|
||||
var start = styleString.indexOf("(", 3);
|
||||
var end = styleString.indexOf(")", start + 1);
|
||||
var guts = styleString.substring(start + 1, end).split(",");
|
||||
|
||||
str = "#";
|
||||
for (var i = 0; i < 3; i++) {
|
||||
str += dec2hex[Number(guts[i])];
|
||||
}
|
||||
|
||||
if ((guts.length == 4) && (styleString.substr(3, 1) == "a")) {
|
||||
alpha = guts[3];
|
||||
}
|
||||
} else {
|
||||
str = styleString;
|
||||
}
|
||||
|
||||
return [str, alpha];
|
||||
}
|
||||
|
||||
function processLineCap(lineCap) {
|
||||
switch (lineCap) {
|
||||
case "butt":
|
||||
return "flat";
|
||||
case "round":
|
||||
return "round";
|
||||
case "square":
|
||||
default:
|
||||
return "square";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements CanvasRenderingContext2D interface as described by
|
||||
* the WHATWG.
|
||||
* @param {HTMLElement} surfaceElement The element that the 2D context should
|
||||
* be associated with
|
||||
*/
|
||||
function CanvasRenderingContext2D_(surfaceElement) {
|
||||
this.m_ = createMatrixIdentity();
|
||||
|
||||
this.mStack_ = [];
|
||||
this.aStack_ = [];
|
||||
this.currentPath_ = [];
|
||||
|
||||
// Canvas context properties
|
||||
this.strokeStyle = "#000";
|
||||
this.fillStyle = "#000";
|
||||
|
||||
this.lineWidth = 1;
|
||||
this.lineJoin = "miter";
|
||||
this.lineCap = "butt";
|
||||
this.miterLimit = Z * 1;
|
||||
this.globalAlpha = 1;
|
||||
this.canvas = surfaceElement;
|
||||
|
||||
var el = surfaceElement.ownerDocument.createElement('div');
|
||||
el.style.width = surfaceElement.clientWidth + 'px';
|
||||
el.style.height = surfaceElement.clientHeight + 'px';
|
||||
el.style.overflow = 'hidden';
|
||||
el.style.position = 'absolute';
|
||||
surfaceElement.appendChild(el);
|
||||
|
||||
this.element_ = el;
|
||||
this.arcScaleX_ = 1;
|
||||
this.arcScaleY_ = 1;
|
||||
};
|
||||
|
||||
var contextPrototype = CanvasRenderingContext2D_.prototype;
|
||||
contextPrototype.clearRect = function() {
|
||||
this.element_.innerHTML = "";
|
||||
this.currentPath_ = [];
|
||||
};
|
||||
|
||||
contextPrototype.beginPath = function() {
|
||||
// TODO: Branch current matrix so that save/restore has no effect
|
||||
// as per safari docs.
|
||||
|
||||
this.currentPath_ = [];
|
||||
};
|
||||
|
||||
contextPrototype.moveTo = function(aX, aY) {
|
||||
this.currentPath_.push({type: "moveTo", x: aX, y: aY});
|
||||
this.currentX_ = aX;
|
||||
this.currentY_ = aY;
|
||||
};
|
||||
|
||||
contextPrototype.lineTo = function(aX, aY) {
|
||||
this.currentPath_.push({type: "lineTo", x: aX, y: aY});
|
||||
this.currentX_ = aX;
|
||||
this.currentY_ = aY;
|
||||
};
|
||||
|
||||
contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
|
||||
aCP2x, aCP2y,
|
||||
aX, aY) {
|
||||
this.currentPath_.push({type: "bezierCurveTo",
|
||||
cp1x: aCP1x,
|
||||
cp1y: aCP1y,
|
||||
cp2x: aCP2x,
|
||||
cp2y: aCP2y,
|
||||
x: aX,
|
||||
y: aY});
|
||||
this.currentX_ = aX;
|
||||
this.currentY_ = aY;
|
||||
};
|
||||
|
||||
contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
|
||||
// the following is lifted almost directly from
|
||||
// http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
|
||||
var cp1x = this.currentX_ + 2.0 / 3.0 * (aCPx - this.currentX_);
|
||||
var cp1y = this.currentY_ + 2.0 / 3.0 * (aCPy - this.currentY_);
|
||||
var cp2x = cp1x + (aX - this.currentX_) / 3.0;
|
||||
var cp2y = cp1y + (aY - this.currentY_) / 3.0;
|
||||
this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, aX, aY);
|
||||
};
|
||||
|
||||
contextPrototype.arc = function(aX, aY, aRadius,
|
||||
aStartAngle, aEndAngle, aClockwise) {
|
||||
aRadius *= Z;
|
||||
var arcType = aClockwise ? "at" : "wa";
|
||||
|
||||
var xStart = aX + (mc(aStartAngle) * aRadius) - Z2;
|
||||
var yStart = aY + (ms(aStartAngle) * aRadius) - Z2;
|
||||
|
||||
var xEnd = aX + (mc(aEndAngle) * aRadius) - Z2;
|
||||
var yEnd = aY + (ms(aEndAngle) * aRadius) - Z2;
|
||||
|
||||
// IE won't render arches drawn counter clockwise if xStart == xEnd.
|
||||
if (xStart == xEnd && !aClockwise) {
|
||||
xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
|
||||
// that can be represented in binary
|
||||
}
|
||||
|
||||
this.currentPath_.push({type: arcType,
|
||||
x: aX,
|
||||
y: aY,
|
||||
radius: aRadius,
|
||||
xStart: xStart,
|
||||
yStart: yStart,
|
||||
xEnd: xEnd,
|
||||
yEnd: yEnd});
|
||||
|
||||
};
|
||||
|
||||
contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
};
|
||||
|
||||
contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
|
||||
// Will destroy any existing path (same as FF behaviour)
|
||||
this.beginPath();
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
this.stroke();
|
||||
};
|
||||
|
||||
contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
|
||||
// Will destroy any existing path (same as FF behaviour)
|
||||
this.beginPath();
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
this.fill();
|
||||
};
|
||||
|
||||
contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
|
||||
var gradient = new CanvasGradient_("gradient");
|
||||
return gradient;
|
||||
};
|
||||
|
||||
contextPrototype.createRadialGradient = function(aX0, aY0,
|
||||
aR0, aX1,
|
||||
aY1, aR1) {
|
||||
var gradient = new CanvasGradient_("gradientradial");
|
||||
gradient.radius1_ = aR0;
|
||||
gradient.radius2_ = aR1;
|
||||
gradient.focus_.x = aX0;
|
||||
gradient.focus_.y = aY0;
|
||||
return gradient;
|
||||
};
|
||||
|
||||
contextPrototype.drawImage = function (image, var_args) {
|
||||
var dx, dy, dw, dh, sx, sy, sw, sh;
|
||||
|
||||
// to find the original width we overide the width and height
|
||||
var oldRuntimeWidth = image.runtimeStyle.width;
|
||||
var oldRuntimeHeight = image.runtimeStyle.height;
|
||||
image.runtimeStyle.width = 'auto';
|
||||
image.runtimeStyle.height = 'auto';
|
||||
|
||||
// get the original size
|
||||
var w = image.width;
|
||||
var h = image.height;
|
||||
|
||||
// and remove overides
|
||||
image.runtimeStyle.width = oldRuntimeWidth;
|
||||
image.runtimeStyle.height = oldRuntimeHeight;
|
||||
|
||||
if (arguments.length == 3) {
|
||||
dx = arguments[1];
|
||||
dy = arguments[2];
|
||||
sx = sy = 0;
|
||||
sw = dw = w;
|
||||
sh = dh = h;
|
||||
} else if (arguments.length == 5) {
|
||||
dx = arguments[1];
|
||||
dy = arguments[2];
|
||||
dw = arguments[3];
|
||||
dh = arguments[4];
|
||||
sx = sy = 0;
|
||||
sw = w;
|
||||
sh = h;
|
||||
} else if (arguments.length == 9) {
|
||||
sx = arguments[1];
|
||||
sy = arguments[2];
|
||||
sw = arguments[3];
|
||||
sh = arguments[4];
|
||||
dx = arguments[5];
|
||||
dy = arguments[6];
|
||||
dw = arguments[7];
|
||||
dh = arguments[8];
|
||||
} else {
|
||||
throw "Invalid number of arguments";
|
||||
}
|
||||
|
||||
var d = this.getCoords_(dx, dy);
|
||||
|
||||
var w2 = sw / 2;
|
||||
var h2 = sh / 2;
|
||||
|
||||
var vmlStr = [];
|
||||
|
||||
var W = 10;
|
||||
var H = 10;
|
||||
|
||||
// For some reason that I've now forgotten, using divs didn't work
|
||||
vmlStr.push(' <g_vml_:group',
|
||||
' coordsize="', Z * W, ',', Z * H, '"',
|
||||
' coordorigin="0,0"' ,
|
||||
' style="width:', W, ';height:', H, ';position:absolute;');
|
||||
|
||||
// If filters are necessary (rotation exists), create them
|
||||
// filters are bog-slow, so only create them if abbsolutely necessary
|
||||
// The following check doesn't account for skews (which don't exist
|
||||
// in the canvas spec (yet) anyway.
|
||||
|
||||
if (this.m_[0][0] != 1 || this.m_[0][1]) {
|
||||
var filter = [];
|
||||
|
||||
// Note the 12/21 reversal
|
||||
filter.push("M11='", this.m_[0][0], "',",
|
||||
"M12='", this.m_[1][0], "',",
|
||||
"M21='", this.m_[0][1], "',",
|
||||
"M22='", this.m_[1][1], "',",
|
||||
"Dx='", mr(d.x / Z), "',",
|
||||
"Dy='", mr(d.y / Z), "'");
|
||||
|
||||
// Bounding box calculation (need to minimize displayed area so that
|
||||
// filters don't waste time on unused pixels.
|
||||
var max = d;
|
||||
var c2 = this.getCoords_(dx + dw, dy);
|
||||
var c3 = this.getCoords_(dx, dy + dh);
|
||||
var c4 = this.getCoords_(dx + dw, dy + dh);
|
||||
|
||||
max.x = Math.max(max.x, c2.x, c3.x, c4.x);
|
||||
max.y = Math.max(max.y, c2.y, c3.y, c4.y);
|
||||
|
||||
vmlStr.push("padding:0 ", mr(max.x / Z), "px ", mr(max.y / Z),
|
||||
"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",
|
||||
filter.join(""), ", sizingmethod='clip');")
|
||||
} else {
|
||||
vmlStr.push("top:", mr(d.y / Z), "px;left:", mr(d.x / Z), "px;")
|
||||
}
|
||||
|
||||
vmlStr.push(' ">' ,
|
||||
'<g_vml_:image src="', image.src, '"',
|
||||
' style="width:', Z * dw, ';',
|
||||
' height:', Z * dh, ';"',
|
||||
' cropleft="', sx / w, '"',
|
||||
' croptop="', sy / h, '"',
|
||||
' cropright="', (w - sx - sw) / w, '"',
|
||||
' cropbottom="', (h - sy - sh) / h, '"',
|
||||
' />',
|
||||
'</g_vml_:group>');
|
||||
|
||||
this.element_.insertAdjacentHTML("BeforeEnd",
|
||||
vmlStr.join(""));
|
||||
};
|
||||
|
||||
contextPrototype.stroke = function(aFill) {
|
||||
var lineStr = [];
|
||||
var lineOpen = false;
|
||||
var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
|
||||
var color = a[0];
|
||||
var opacity = a[1] * this.globalAlpha;
|
||||
|
||||
var W = 10;
|
||||
var H = 10;
|
||||
|
||||
lineStr.push('<g_vml_:shape',
|
||||
' fillcolor="', color, '"',
|
||||
' filled="', Boolean(aFill), '"',
|
||||
' style="position:absolute;width:', W, ';height:', H, ';"',
|
||||
' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
|
||||
' stroked="', !aFill, '"',
|
||||
' strokeweight="', this.lineWidth, '"',
|
||||
' strokecolor="', color, '"',
|
||||
' path="');
|
||||
|
||||
var newSeq = false;
|
||||
var min = {x: null, y: null};
|
||||
var max = {x: null, y: null};
|
||||
|
||||
for (var i = 0; i < this.currentPath_.length; i++) {
|
||||
var p = this.currentPath_[i];
|
||||
|
||||
if (p.type == "moveTo") {
|
||||
lineStr.push(" m ");
|
||||
var c = this.getCoords_(p.x, p.y);
|
||||
lineStr.push(mr(c.x), ",", mr(c.y));
|
||||
} else if (p.type == "lineTo") {
|
||||
lineStr.push(" l ");
|
||||
var c = this.getCoords_(p.x, p.y);
|
||||
lineStr.push(mr(c.x), ",", mr(c.y));
|
||||
} else if (p.type == "close") {
|
||||
lineStr.push(" x ");
|
||||
} else if (p.type == "bezierCurveTo") {
|
||||
lineStr.push(" c ");
|
||||
var c = this.getCoords_(p.x, p.y);
|
||||
var c1 = this.getCoords_(p.cp1x, p.cp1y);
|
||||
var c2 = this.getCoords_(p.cp2x, p.cp2y);
|
||||
lineStr.push(mr(c1.x), ",", mr(c1.y), ",",
|
||||
mr(c2.x), ",", mr(c2.y), ",",
|
||||
mr(c.x), ",", mr(c.y));
|
||||
} else if (p.type == "at" || p.type == "wa") {
|
||||
lineStr.push(" ", p.type, " ");
|
||||
var c = this.getCoords_(p.x, p.y);
|
||||
var cStart = this.getCoords_(p.xStart, p.yStart);
|
||||
var cEnd = this.getCoords_(p.xEnd, p.yEnd);
|
||||
|
||||
lineStr.push(mr(c.x - this.arcScaleX_ * p.radius), ",",
|
||||
mr(c.y - this.arcScaleY_ * p.radius), " ",
|
||||
mr(c.x + this.arcScaleX_ * p.radius), ",",
|
||||
mr(c.y + this.arcScaleY_ * p.radius), " ",
|
||||
mr(cStart.x), ",", mr(cStart.y), " ",
|
||||
mr(cEnd.x), ",", mr(cEnd.y));
|
||||
}
|
||||
|
||||
|
||||
// TODO: Following is broken for curves due to
|
||||
// move to proper paths.
|
||||
|
||||
// Figure out dimensions so we can do gradient fills
|
||||
// properly
|
||||
if(c) {
|
||||
if (min.x == null || c.x < min.x) {
|
||||
min.x = c.x;
|
||||
}
|
||||
if (max.x == null || c.x > max.x) {
|
||||
max.x = c.x;
|
||||
}
|
||||
if (min.y == null || c.y < min.y) {
|
||||
min.y = c.y;
|
||||
}
|
||||
if (max.y == null || c.y > max.y) {
|
||||
max.y = c.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineStr.push(' ">');
|
||||
|
||||
if (typeof this.fillStyle == "object") {
|
||||
var focus = {x: "50%", y: "50%"};
|
||||
var width = (max.x - min.x);
|
||||
var height = (max.y - min.y);
|
||||
var dimension = (width > height) ? width : height;
|
||||
|
||||
focus.x = mr((this.fillStyle.focus_.x / width) * 100 + 50) + "%";
|
||||
focus.y = mr((this.fillStyle.focus_.y / height) * 100 + 50) + "%";
|
||||
|
||||
var colors = [];
|
||||
|
||||
// inside radius (%)
|
||||
if (this.fillStyle.type_ == "gradientradial") {
|
||||
var inside = (this.fillStyle.radius1_ / dimension * 100);
|
||||
|
||||
// percentage that outside radius exceeds inside radius
|
||||
var expansion = (this.fillStyle.radius2_ / dimension * 100) - inside;
|
||||
} else {
|
||||
var inside = 0;
|
||||
var expansion = 100;
|
||||
}
|
||||
|
||||
var insidecolor = {offset: null, color: null};
|
||||
var outsidecolor = {offset: null, color: null};
|
||||
|
||||
// We need to sort 'colors' by percentage, from 0 > 100 otherwise ie
|
||||
// won't interpret it correctly
|
||||
this.fillStyle.colors_.sort(function (cs1, cs2) {
|
||||
return cs1.offset - cs2.offset;
|
||||
});
|
||||
|
||||
for (var i = 0; i < this.fillStyle.colors_.length; i++) {
|
||||
var fs = this.fillStyle.colors_[i];
|
||||
|
||||
colors.push( (fs.offset * expansion) + inside, "% ", fs.color, ",");
|
||||
|
||||
if (fs.offset > insidecolor.offset || insidecolor.offset == null) {
|
||||
insidecolor.offset = fs.offset;
|
||||
insidecolor.color = fs.color;
|
||||
}
|
||||
|
||||
if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) {
|
||||
outsidecolor.offset = fs.offset;
|
||||
outsidecolor.color = fs.color;
|
||||
}
|
||||
}
|
||||
colors.pop();
|
||||
|
||||
lineStr.push('<g_vml_:fill',
|
||||
' color="', outsidecolor.color, '"',
|
||||
' color2="', insidecolor.color, '"',
|
||||
' type="', this.fillStyle.type_, '"',
|
||||
' focusposition="', focus.x, ', ', focus.y, '"',
|
||||
' colors="', colors.join(""), '"',
|
||||
' opacity="', opacity, '" />');
|
||||
} else if (aFill) {
|
||||
lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, '" />');
|
||||
} else {
|
||||
lineStr.push(
|
||||
'<g_vml_:stroke',
|
||||
' opacity="', opacity,'"',
|
||||
' joinstyle="', this.lineJoin, '"',
|
||||
' miterlimit="', this.miterLimit, '"',
|
||||
' endcap="', processLineCap(this.lineCap) ,'"',
|
||||
' weight="', this.lineWidth, 'px"',
|
||||
' color="', color,'" />'
|
||||
);
|
||||
}
|
||||
|
||||
lineStr.push("</g_vml_:shape>");
|
||||
|
||||
this.element_.insertAdjacentHTML("beforeEnd", lineStr.join(""));
|
||||
|
||||
this.currentPath_ = [];
|
||||
};
|
||||
|
||||
contextPrototype.fill = function() {
|
||||
this.stroke(true);
|
||||
}
|
||||
|
||||
contextPrototype.closePath = function() {
|
||||
this.currentPath_.push({type: "close"});
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
contextPrototype.getCoords_ = function(aX, aY) {
|
||||
return {
|
||||
x: Z * (aX * this.m_[0][0] + aY * this.m_[1][0] + this.m_[2][0]) - Z2,
|
||||
y: Z * (aX * this.m_[0][1] + aY * this.m_[1][1] + this.m_[2][1]) - Z2
|
||||
}
|
||||
};
|
||||
|
||||
contextPrototype.save = function() {
|
||||
var o = {};
|
||||
copyState(this, o);
|
||||
this.aStack_.push(o);
|
||||
this.mStack_.push(this.m_);
|
||||
this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
|
||||
};
|
||||
|
||||
contextPrototype.restore = function() {
|
||||
copyState(this.aStack_.pop(), this);
|
||||
this.m_ = this.mStack_.pop();
|
||||
};
|
||||
|
||||
contextPrototype.translate = function(aX, aY) {
|
||||
var m1 = [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[aX, aY, 1]
|
||||
];
|
||||
|
||||
this.m_ = matrixMultiply(m1, this.m_);
|
||||
};
|
||||
|
||||
contextPrototype.rotate = function(aRot) {
|
||||
var c = mc(aRot);
|
||||
var s = ms(aRot);
|
||||
|
||||
var m1 = [
|
||||
[c, s, 0],
|
||||
[-s, c, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
|
||||
this.m_ = matrixMultiply(m1, this.m_);
|
||||
};
|
||||
|
||||
contextPrototype.scale = function(aX, aY) {
|
||||
this.arcScaleX_ *= aX;
|
||||
this.arcScaleY_ *= aY;
|
||||
var m1 = [
|
||||
[aX, 0, 0],
|
||||
[0, aY, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
|
||||
this.m_ = matrixMultiply(m1, this.m_);
|
||||
};
|
||||
|
||||
/******** STUBS ********/
|
||||
contextPrototype.clip = function() {
|
||||
// TODO: Implement
|
||||
};
|
||||
|
||||
contextPrototype.arcTo = function() {
|
||||
// TODO: Implement
|
||||
};
|
||||
|
||||
contextPrototype.createPattern = function() {
|
||||
return new CanvasPattern_;
|
||||
};
|
||||
|
||||
// Gradient / Pattern Stubs
|
||||
function CanvasGradient_(aType) {
|
||||
this.type_ = aType;
|
||||
this.radius1_ = 0;
|
||||
this.radius2_ = 0;
|
||||
this.colors_ = [];
|
||||
this.focus_ = {x: 0, y: 0};
|
||||
}
|
||||
|
||||
CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
|
||||
aColor = processStyle(aColor);
|
||||
this.colors_.push({offset: 1-aOffset, color: aColor});
|
||||
};
|
||||
|
||||
function CanvasPattern_() {}
|
||||
|
||||
// set up externs
|
||||
G_vmlCanvasManager = G_vmlCanvasManager_;
|
||||
CanvasRenderingContext2D = CanvasRenderingContext2D_;
|
||||
CanvasGradient = CanvasGradient_;
|
||||
CanvasPattern = CanvasPattern_;
|
||||
|
||||
})();
|
||||
|
||||
} // if
|
4221
lib/box2d-js/lib/prototype-1.6.0.2.js
vendored
Normal file
61
lib/box2d-js/style/box2d.css
Normal file
@ -0,0 +1,61 @@
|
||||
#canvas {
|
||||
padding:0;
|
||||
margin:0;
|
||||
border:1px solid white;
|
||||
position:absolute;
|
||||
background-color:#333388;
|
||||
}
|
||||
#CONTAINER {
|
||||
margin-left: 30px;
|
||||
}
|
||||
#HEADER h1 {
|
||||
margin-top: 95px;
|
||||
padding-right: 30px;
|
||||
text-align: center;
|
||||
font-size: xx-large;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
color: #ccccff;
|
||||
}
|
||||
#HEADER h1 b {
|
||||
color: #ffffff;
|
||||
font-size: 110%;
|
||||
}
|
||||
#spacer {
|
||||
height: 300px;
|
||||
}
|
||||
span.key {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#BODYBOX {
|
||||
background-image: url(images/bodybox_bg.png);
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
p {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.contact {
|
||||
border: 1px solid white;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
margin-left: 30px;
|
||||
width: 350px;
|
||||
}
|
||||
a{
|
||||
color: yellow;
|
||||
}
|
||||
a:hover {
|
||||
color: yellow;
|
||||
background-color: black;
|
||||
}
|
||||
a:visited {
|
||||
color: yellow;
|
||||
}
|
||||
a:active {
|
||||
color: yellow;
|
||||
}
|
||||
pre.prettyprint {
|
||||
margin-left: 30px;
|
||||
padding: 5px;
|
||||
background-color: #bbbbff;
|
||||
}
|
61
lib/box2d-js/style/box2d.css~
Normal file
@ -0,0 +1,61 @@
|
||||
#canvas {
|
||||
padding:0;
|
||||
margin:0;
|
||||
border:1px solid white;
|
||||
position:absolute;
|
||||
background-color:#333388;
|
||||
}
|
||||
#CONTAINER {
|
||||
margin-left: 30px;
|
||||
}
|
||||
#HEADER h1 {
|
||||
margin-top: 95px;
|
||||
padding-right: 30px;
|
||||
text-align: center;
|
||||
font-size: xx-large;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
color: #ccccff;
|
||||
}
|
||||
#HEADER h1 b {
|
||||
color: #ffffff;
|
||||
font-size: 110%;
|
||||
}
|
||||
#spacer {
|
||||
height: 300px;
|
||||
}
|
||||
span.key {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#BODYBOX {
|
||||
background-image: url(images/bodybox_bg.png);
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
p {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.contact {
|
||||
border: 1px solid white;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
margin-left: 30px;
|
||||
width: 350px;
|
||||
}
|
||||
a{
|
||||
color: yellow;
|
||||
}
|
||||
a:hover {
|
||||
color: yellow;
|
||||
background-color: black;
|
||||
}
|
||||
a:visited {
|
||||
color: yellow;
|
||||
}
|
||||
a:active {
|
||||
color: yellow;
|
||||
}
|
||||
pre.prettyprint {
|
||||
margin-left: 30px;
|
||||
padding: 5px;
|
||||
background-color: white;
|
||||
}
|
124
lib/box2d-js/style/distant-planet.css
Normal file
@ -0,0 +1,124 @@
|
||||
body {
|
||||
background-color: #787bad;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
#CONTAINER {
|
||||
background-color: #787bad;
|
||||
width: 800px;
|
||||
margin-left: 20%;
|
||||
}
|
||||
#HEADER {
|
||||
background-image: url(images/Distant-Planet_02.gif);
|
||||
float: left;
|
||||
height: 202px;
|
||||
width: 713px;
|
||||
}
|
||||
#NAVIGATION {
|
||||
background-image: url(images/Distant-Planet_04.gif);
|
||||
float: left;
|
||||
height: 39px;
|
||||
width: 713px;
|
||||
}
|
||||
#BODYBOX {
|
||||
background-color: #969ad0;
|
||||
float: left;
|
||||
width: 713px;
|
||||
}
|
||||
.LEFT {
|
||||
background-image: url(images/Distant-Planet_05.gif);
|
||||
float: left;
|
||||
width: 51px;
|
||||
height: 493px;
|
||||
}
|
||||
.MIDDLE {
|
||||
background-image: url(images/Distant-Planet_06.gif);
|
||||
float: left;
|
||||
width: 593px;
|
||||
padding-bottom: 14px;
|
||||
padding-top: 14px;
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.footertext {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.RIGHT {
|
||||
background-image: url(images/Distant-Planet_07.gif);
|
||||
float: left;
|
||||
width: 69px;
|
||||
height: 493px;
|
||||
}
|
||||
.Nav {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.links {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.links a {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.links a:visited {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.links a:hover {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
line-height: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
color: #FFFFFF;
|
||||
text-decoration: underline;
|
||||
}
|
||||
#FOOTER {
|
||||
background-image: url(images/Distant-Planet_08.gif);
|
||||
float: left;
|
||||
width: 713px;
|
||||
}
|
BIN
lib/box2d-js/style/images/Distant-Planet_01.gif
Normal file
After Width: | Height: | Size: 373 B |
BIN
lib/box2d-js/style/images/Distant-Planet_02.gif
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
lib/box2d-js/style/images/Distant-Planet_03.gif
Normal file
After Width: | Height: | Size: 268 B |
BIN
lib/box2d-js/style/images/Distant-Planet_04.gif
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
lib/box2d-js/style/images/Distant-Planet_05.gif
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
lib/box2d-js/style/images/Distant-Planet_06.gif
Normal file
After Width: | Height: | Size: 880 B |
BIN
lib/box2d-js/style/images/Distant-Planet_07.gif
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
lib/box2d-js/style/images/Distant-Planet_08.gif
Normal file
After Width: | Height: | Size: 823 B |
BIN
lib/box2d-js/style/images/bodybox_bg.png
Normal file
After Width: | Height: | Size: 824 B |
27
lib/box2d-js/style/prettify.css
Normal file
@ -0,0 +1,27 @@
|
||||
/* Pretty printing styles. Used with prettify.js. */
|
||||
|
||||
.str { color: #080; }
|
||||
.kwd { color: #008; }
|
||||
.com { color: #800; }
|
||||
.typ { color: #606; }
|
||||
.lit { color: #066; }
|
||||
.pun { color: #660; }
|
||||
.pln { color: #000; }
|
||||
.tag { color: #008; }
|
||||
.atn { color: #606; }
|
||||
.atv { color: #080; }
|
||||
.dec { color: #606; }
|
||||
pre.prettyprint { padding: 2px; border: 1px solid #888; }
|
||||
|
||||
@media print {
|
||||
.str { color: #060; }
|
||||
.kwd { color: #006; font-weight: bold; }
|
||||
.com { color: #600; font-style: italic; }
|
||||
.typ { color: #404; font-weight: bold; }
|
||||
.lit { color: #044; }
|
||||
.pun { color: #440; }
|
||||
.pln { color: #000; }
|
||||
.tag { color: #006; font-weight: bold; }
|
||||
.atn { color: #404; }
|
||||
.atv { color: #060; }
|
||||
}
|
1030
lib/box2d-js/style/prettify.js
Normal file
27
lib/utils.js
@ -1,3 +1,12 @@
|
||||
function uuidv4() {
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
||||
(
|
||||
c ^
|
||||
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
|
||||
).toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
function loadJavaScript(path) {
|
||||
const script = document.createElement("script");
|
||||
script.src = path;
|
||||
@ -74,5 +83,21 @@ function cartesianToPolara(x, y) {
|
||||
|
||||
// polar to cartesian
|
||||
function polarToCartesian(r, θ) {
|
||||
return { x: r * cos(θ), y: r * sin(θ) };
|
||||
return { x: r * cos(θ), y: -r * sin(θ) };
|
||||
}
|
||||
|
||||
function drawRect(x, y, w, h, c = "bottom") {
|
||||
push();
|
||||
switch (c) {
|
||||
case "top":
|
||||
break;
|
||||
case "left":
|
||||
break;
|
||||
case "right":
|
||||
break;
|
||||
default:
|
||||
rect(x - w / 2, y - h, w, h);
|
||||
break;
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|