mirror of
https://github.com/liabru/matter-js.git
synced 2025-01-12 16:08:50 -05:00
initial work on compound bodies
This commit is contained in:
parent
b3921fb72e
commit
243fce47c9
9 changed files with 245 additions and 40 deletions
|
@ -30,6 +30,7 @@
|
|||
<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>
|
||||
|
|
|
@ -117,6 +117,54 @@
|
|||
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() {
|
||||
var _world = _engine.world;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,33 +41,43 @@ var Detector = {};
|
|||
|
||||
// mid phase
|
||||
if (Bounds.overlaps(bodyA.bounds, bodyB.bounds)) {
|
||||
/*for (var j = 1; j < bodyA.parts.length; j++) {
|
||||
var partA = bodyA.parts[j];
|
||||
|
||||
// find a previous collision we could reuse
|
||||
var pairId = Pair.id(bodyA, bodyB),
|
||||
pair = pairsTable[pairId],
|
||||
previousCollision;
|
||||
for (var k = 1; k < bodyB.parts.length; k++) {
|
||||
var partB = bodyB.parts[k];
|
||||
|
||||
if (pair && pair.isActive) {
|
||||
previousCollision = pair.collision;
|
||||
} else {
|
||||
previousCollision = null;
|
||||
}
|
||||
if (Bounds.overlaps(partA.bounds, partB.bounds)) {*/
|
||||
|
||||
// narrow phase
|
||||
var collision = SAT.collides(bodyA, bodyB, previousCollision);
|
||||
// find a previous collision we could reuse
|
||||
var pairId = Pair.id(bodyA, bodyB),
|
||||
pair = pairsTable[pairId],
|
||||
previousCollision;
|
||||
|
||||
// @if DEBUG
|
||||
metrics.narrowphaseTests += 1;
|
||||
if (collision.reused)
|
||||
metrics.narrowReuseCount += 1;
|
||||
// @endif
|
||||
if (pair && pair.isActive) {
|
||||
previousCollision = pair.collision;
|
||||
} else {
|
||||
previousCollision = null;
|
||||
}
|
||||
|
||||
if (collision.collided) {
|
||||
collisions.push(collision);
|
||||
// @if DEBUG
|
||||
metrics.narrowDetections += 1;
|
||||
// @endif
|
||||
}
|
||||
// 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
|
||||
}
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -249,16 +249,19 @@ 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(part.bounds, body.vertices);
|
||||
}
|
||||
|
||||
Bounds.update(body.bounds, body.vertices);
|
||||
|
||||
impulse.x = 0;
|
||||
impulse.y = 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
|
@ -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);
|
||||
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue