Skip to content

Commit

Permalink
initial work on compound bodies
Browse files Browse the repository at this point in the history
  • Loading branch information
liabru committed Jan 29, 2015
1 parent b3921fb commit 243fce4
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 45 deletions.
1 change: 1 addition & 0 deletions demo/dev.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ <h1>Matter.js Demo (Dev. Build)</h1>
<div class="controls-container">
<select id="demo-select">
<option value="mixed">Mixed Shapes</option>
<option value="concave">Concave Shapes</option>
<option value="mixedSolid">Solid Rendering</option>
<option value="newtonsCradle">Newton's Cradle</option>
<option value="wreckingBall">Wrecking Ball</option>
Expand Down
50 changes: 49 additions & 1 deletion demo/js/Demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,55 @@

World.add(_world, stack);

var renderOptions = _engine.render.options;
var renderOptions = _engine.render.options;
};

Demo.concave = function() {
var _world = _engine.world;

Demo.reset();

var s = 50;
//var vertices = [{ x: 0, y: 0 }, { x: 0, y: 2 * s },
// { x: 1 * s, y: 2 * s }, { x: 1 * s, y: 1 * s },
// { x: 2 * s, y: 1 * s }, { x: 2 * s, y: 0 }];

//var vertices = Matter.Vertices.fromPath('-5 78,70 126,57 195,114 139,191 201,161 136,217 83,151 83,122 -1,82 85');

var partA = Bodies.rectangle(200, 200, 200, 20);
var partB = Bodies.rectangle(200, 200, 20, 200);
var middle = Bodies.rectangle(200, 200, 20, 20);
//var parent = Bodies.rectangle(200, 200, 200, 200);

var vertices = Matter.Vertices.create(partA.vertices.concat(partB.vertices.concat(middle.vertices)), true);
Matter.Vertices.clockwiseSort(vertices);

//debugger;

var hull = Matter.Vertices.hull(vertices);

console.log(vertices);
console.log(hull);

var parent = Body.create({
position: { x: 200, y: 200 },
vertices: hull
});

//debugger;

partA.parent = parent;
partB.parent = parent;

parent.parts = [parent, partA, partB];

World.add(_world, parent);

_world.gravity.y = 0;

var renderOptions = _engine.render.options;
renderOptions.showCollisions = true;
renderOptions.showBounds = true;
};

Demo.slingshot = function() {
Expand Down
20 changes: 14 additions & 6 deletions src/body/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ var Body = {};
anglePrev: body.anglePrev || body.angle,
vertices: body.vertices,
isStatic: body.isStatic,
isSleeping: body.isSleeping
isSleeping: body.isSleeping,
parts: body.parts || [body]
});

Vertices.rotate(body.vertices, body.angle, body.position);
Expand Down Expand Up @@ -313,6 +314,8 @@ var Body = {};

Vertices.translate(body.vertices, delta);
Bounds.update(body.bounds, body.vertices, body.velocity);

//Common.each(body.children, Body.setPosition, position);
};

/**
Expand All @@ -330,6 +333,8 @@ var Body = {};
Vertices.rotate(body.vertices, delta, body.position);
Axes.rotate(body.axes, delta);
Bounds.update(body.bounds, body.vertices, body.velocity);

//Common.each(body.children, Body.setAngle, angle);
};

/**
Expand Down Expand Up @@ -439,12 +444,15 @@ var Body = {};
body.angularSpeed = Math.abs(body.angularVelocity);

// transform the body geometry
Vertices.translate(body.vertices, body.velocity);
if (body.angularVelocity !== 0) {
Vertices.rotate(body.vertices, body.angularVelocity, body.position);
Axes.rotate(body.axes, body.angularVelocity);
for (var i = 0; i < body.parts.length; i++) {
var part = body.parts[i];
Vertices.translate(part.vertices, body.velocity);
if (body.angularVelocity !== 0) {
Vertices.rotate(part.vertices, body.angularVelocity, body.position);
Axes.rotate(part.axes, body.angularVelocity);
}
Bounds.update(part.bounds, body.vertices, body.velocity);
}
Bounds.update(body.bounds, body.vertices, body.velocity);
};

/**
Expand Down
64 changes: 37 additions & 27 deletions src/collision/Detector.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,43 @@ var Detector = {};

// mid phase
if (Bounds.overlaps(bodyA.bounds, bodyB.bounds)) {

// find a previous collision we could reuse
var pairId = Pair.id(bodyA, bodyB),
pair = pairsTable[pairId],
previousCollision;

if (pair && pair.isActive) {
previousCollision = pair.collision;
} else {
previousCollision = null;
}

// narrow phase
var collision = SAT.collides(bodyA, bodyB, previousCollision);

// @if DEBUG
metrics.narrowphaseTests += 1;
if (collision.reused)
metrics.narrowReuseCount += 1;
// @endif

if (collision.collided) {
collisions.push(collision);
// @if DEBUG
metrics.narrowDetections += 1;
// @endif
}
/*for (var j = 1; j < bodyA.parts.length; j++) {
var partA = bodyA.parts[j];
for (var k = 1; k < bodyB.parts.length; k++) {
var partB = bodyB.parts[k];
if (Bounds.overlaps(partA.bounds, partB.bounds)) {*/

// find a previous collision we could reuse
var pairId = Pair.id(bodyA, bodyB),
pair = pairsTable[pairId],
previousCollision;

if (pair && pair.isActive) {
previousCollision = pair.collision;
} else {
previousCollision = null;
}

// narrow phase
var collision = SAT.collides(bodyA, bodyB, previousCollision);

// @if DEBUG
metrics.narrowphaseTests += 1;
if (collision.reused)
metrics.narrowReuseCount += 1;
// @endif

if (collision.collided) {
collisions.push(collision);
// @if DEBUG
metrics.narrowDetections += 1;
// @endif
}
//}
//}
//}
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/collision/Resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@ var Resolver = {};
body.positionPrev.y += body.positionImpulse.y;

// update body geometry
Vertices.translate(body.vertices, body.positionImpulse);
Bounds.update(body.bounds, body.vertices, body.velocity);
for (var j = 0; j < body.parts.length; j++) {
var part = body.parts[j];
Vertices.translate(part.vertices, body.positionImpulse);
Bounds.update(part.bounds, body.vertices, body.velocity);
}

// dampen accumulator to warm the next step
body.positionImpulse.x *= _positionWarming;
Expand Down
17 changes: 10 additions & 7 deletions src/constraint/Constraint.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,18 @@ var Constraint = {};
impulse = body.constraintImpulse;

// update geometry and reset
Vertices.translate(body.vertices, impulse);
for (var j = 0; j < body.parts.length; j++) {
var part = body.parts[j];
Vertices.translate(part.vertices, impulse);

if (impulse.angle !== 0) {
Vertices.rotate(body.vertices, impulse.angle, body.position);
Axes.rotate(body.axes, impulse.angle);
impulse.angle = 0;
}
if (impulse.angle !== 0) {
Vertices.rotate(part.vertices, impulse.angle, body.position);
Axes.rotate(part.axes, impulse.angle);
impulse.angle = 0;
}

Bounds.update(body.bounds, body.vertices);
Bounds.update(part.bounds, body.vertices);
}

impulse.x = 0;
impulse.y = 0;
Expand Down
12 changes: 12 additions & 0 deletions src/geometry/Vector.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ var Vector = {};
return (vectorA.x * vectorB.y) - (vectorA.y * vectorB.x);
};

/**
* Returns the cross-product of three vectors.
* @method cross3
* @param {vector} vectorA
* @param {vector} vectorB
* @param {vector} vectorC
* @return {number} The cross product of the three vectors
*/
Vector.cross3 = function(vectorA, vectorB, vectorC) {
return (vectorB.x - vectorA.x) * (vectorC.y - vectorA.y) - (vectorB.y - vectorA.y) * (vectorC.x - vectorA.x);
};

/**
* Adds the two vectors.
* @method add
Expand Down
86 changes: 86 additions & 0 deletions src/geometry/Vertices.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,23 @@ var Vertices = {};
return Vector.div(centre, 6 * area);
};

/**
* Returns the average (mean) of the set of vertices.
* @method mean
* @param {vertices} vertices
* @return {vector} The average point
*/
Vertices.mean = function(vertices) {
var average = { x: 0, y: 0 };

for (var i = 0; i < vertices.length; i++) {
average.x += vertices[i].x;
average.y += vertices[i].y;
}

return Vector.div(average, vertices.length);
};

/**
* Returns the area of the set of vertices.
* @method area
Expand Down Expand Up @@ -306,4 +323,73 @@ var Vertices = {};
return newVertices;
};

/**
* Sorts the input vertices into clockwise order in place.
* @method clockwiseSort
* @param {vertices} vertices
* @return {vertices} vertices
*/
Vertices.clockwiseSort = function(vertices) {
var mean = Vertices.mean(vertices);

vertices.sort(function(vertexA, vertexB) {
return Vector.angle(mean, vertexA) - Vector.angle(mean, vertexB);
});

return vertices;
}

/**
* Returns the convex hull of the input vertices as a new array of points.
* @method hull
* @param {vertices} vertices
* @return [vertex] vertices
*/
Vertices.hull = function(vertices) {
// http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain

var upper = [],
lower = [],
vertex,
i;

// sort vertices on x-axis (y-axis for ties)
vertices = vertices.slice(0);
vertices.sort(function(vertexA, vertexB) {
var dx = vertexA.x - vertexB.x;
return dx !== 0 ? dx : vertexA.y - vertexB.y;
});

// build lower hull
for (i = 0; i < vertices.length; i++) {
vertex = vertices[i];

while (lower.length >= 2
&& Vector.cross3(lower[lower.length - 2], lower[lower.length - 1], vertex) <= 0) {
lower.pop();
}

lower.push(vertex);
}

// build upper hull
for (i = vertices.length - 1; i >= 0; i--) {
vertex = vertices[i];

while (upper.length >= 2
&& Vector.cross3(upper[upper.length - 2], upper[upper.length - 1], vertex) <= 0) {
upper.pop();
}

upper.push(vertex);
}

// concatenation of the lower and upper hulls gives the convex hull
// omit last points because they are repeated at the beginning of the other list
upper.pop();
lower.pop();

return upper.concat(lower);
};

})();
38 changes: 36 additions & 2 deletions src/render/Render.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,14 +448,15 @@ var Render = {};
Render.bodyWireframes = function(engine, bodies, context) {
var c = context,
i,
j;
j,
k;

c.beginPath();

for (i = 0; i < bodies.length; i++) {
var body = bodies[i];

if (!body.render.visible)
if (!body.render.visible || body.parts.length === 1)
continue;

c.moveTo(body.vertices[0].x, body.vertices[0].y);
Expand All @@ -467,6 +468,39 @@ var Render = {};
c.lineTo(body.vertices[0].x, body.vertices[0].y);
}

c.lineWidth = 1;
c.strokeStyle = '#9E9277';
c.stroke();

for (i = 0; i < bodies.length; i++) {
var body = bodies[i];
for (j = 0; j < body.vertices.length; j++) {
c.fillStyle = 'yellow';
c.fillText(j, body.vertices[j].x, body.vertices[j].y + 10);
}
}

c.beginPath();

for (i = 0; i < bodies.length; i++) {
var body = bodies[i];

if (!body.render.visible)
continue;

for (k = body.parts.length > 1 ? 1 : 0; k < body.parts.length; k++) {
var part = body.parts[k];

c.moveTo(part.vertices[0].x, part.vertices[0].y);

for (j = 1; j < part.vertices.length; j++) {
c.lineTo(part.vertices[j].x, part.vertices[j].y);
}

c.lineTo(part.vertices[0].x, part.vertices[0].y);
}
}

c.lineWidth = 1;
c.strokeStyle = '#bbb';
c.stroke();
Expand Down

0 comments on commit 243fce4

Please sign in to comment.