0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2025-01-12 16:08:50 -05:00

further work on compound implementation

This commit is contained in:
liabru 2015-02-01 13:57:56 +00:00
parent f554d6c9a6
commit d2f79b4689
5 changed files with 128 additions and 71 deletions

View file

@ -244,21 +244,27 @@
Demo.reset(); Demo.reset();
var bodyA = Bodies.rectangle(100, 200, 50, 50), var bodyA = Bodies.rectangle(100, 200, 50, 50, { isStatic: true }),
bodyB = Bodies.rectangle(200, 200, 50, 50), bodyB = Bodies.rectangle(200, 200, 50, 50),
bodyC = Bodies.rectangle(300, 200, 50, 50), bodyC = Bodies.rectangle(300, 200, 50, 50),
bodyD = Bodies.rectangle(400, 200, 50, 50), bodyD = Bodies.rectangle(400, 200, 50, 50),
bodyE = Bodies.rectangle(550, 200, 50, 50), bodyE = Bodies.rectangle(550, 200, 50, 50),
bodyF = Bodies.rectangle(700, 200, 50, 50), bodyF = Bodies.rectangle(700, 200, 50, 50),
bodyG = Bodies.circle(400, 100, 25); bodyG = Bodies.circle(400, 100, 25),
partA = Bodies.rectangle(600, 200, 120, 50),
partB = Bodies.rectangle(660, 200, 50, 190),
compound = Body.create({
parts: [partA, partB],
isStatic: true
});
World.add(_world, [bodyA, bodyB, bodyC, bodyD, bodyE, bodyF, bodyG]); World.add(_world, [bodyA, bodyB, bodyC, bodyD, bodyE, bodyF, bodyG, compound]);
var counter = 0, var counter = 0,
scaleFactor = 1.01; scaleFactor = 1.01;
_sceneEvents.push( _sceneEvents.push(
Events.on(_engine, 'tick', function(event) { Events.on(_engine, 'beforeUpdate', function(event) {
counter += 1; counter += 1;
if (counter === 40) if (counter === 40)
@ -266,6 +272,7 @@
if (scaleFactor > 1) { if (scaleFactor > 1) {
Body.scale(bodyF, scaleFactor, scaleFactor); Body.scale(bodyF, scaleFactor, scaleFactor);
Body.scale(compound, 0.995, 0.995);
// modify bodyE vertices // modify bodyE vertices
bodyE.vertices[0].x -= 0.2; bodyE.vertices[0].x -= 0.2;
@ -277,7 +284,11 @@
// make bodyA move up and down and rotate constantly // make bodyA move up and down and rotate constantly
Body.setPosition(bodyA, { x: 100, y: 300 + 100 * Math.sin(_engine.timing.timestamp * 0.005) }); Body.setPosition(bodyA, { x: 100, y: 300 + 100 * Math.sin(_engine.timing.timestamp * 0.005) });
Body.setAngularVelocity(bodyA, 0.02); Body.rotate(bodyA, 0.02);
// make compound body move up and down and rotate constantly
Body.setPosition(compound, { x: 600, y: 300 + 100 * Math.sin(_engine.timing.timestamp * 0.005) });
Body.rotate(compound, 0.02);
// every 1.5 sec // every 1.5 sec
if (counter >= 60 * 1.5) { if (counter >= 60 * 1.5) {
@ -293,9 +304,10 @@
); );
var renderOptions = _engine.render.options; var renderOptions = _engine.render.options;
renderOptions.wireframes = false;
renderOptions.showAxes = true; renderOptions.showAxes = true;
renderOptions.showCollisions = true; renderOptions.showCollisions = true;
renderOptions.showPositions = true;
renderOptions.showConvexHulls = true;
}; };
Demo.compositeManipulation = function() { Demo.compositeManipulation = function() {

View file

@ -32,6 +32,7 @@ var Body = {};
id: Common.nextId(), id: Common.nextId(),
type: 'body', type: 'body',
label: 'Body', label: 'Body',
parts: [],
angle: 0, angle: 0,
vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'), vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
@ -118,7 +119,7 @@ var Body = {};
isStatic: body.isStatic, isStatic: body.isStatic,
isSleeping: body.isSleeping, isSleeping: body.isSleeping,
parent: body.parent || body, parent: body.parent || body,
parts: body.parts || [body] parts: body.parts
}); });
Vertices.rotate(body.vertices, body.angle, body.position); Vertices.rotate(body.vertices, body.angle, body.position);
@ -313,26 +314,31 @@ var Body = {};
* @param {bool} [autoHull=true] * @param {bool} [autoHull=true]
*/ */
Body.setParts = function(body, parts, autoHull) { Body.setParts = function(body, parts, autoHull) {
autoHull = typeof autoHull !== 'undefined' ? autoHull : true; var i;
// ensure the body is always at index 0 // add all the parts, ensuring that the first part is always the parent body
var index = Common.indexOf(parts, body); parts = parts.slice(0);
if (index > -1) { body.parts.length = 0;
parts.splice(index, 1); body.parts.push(body);
body.parent = body;
for (i = 0; i < parts.length; i++) {
var part = parts[i];
if (part !== body) {
part.parent = body;
body.parts.push(part);
}
} }
parts.unshift(body); if (body.parts.length === 1)
body.parts = parts;
if (parts.length === 1)
return; return;
var i; autoHull = typeof autoHull !== 'undefined' ? autoHull : true;
// find the convex hull of all parts to set on the parent body // find the convex hull of all parts to set on the parent body
if (autoHull) { if (autoHull) {
var vertices = []; var vertices = [];
for (i = 1; i < parts.length; i++) { for (i = 0; i < parts.length; i++) {
vertices = vertices.concat(parts[i].vertices); vertices = vertices.concat(parts[i].vertices);
} }
@ -342,36 +348,22 @@ var Body = {};
hullCentre = Vertices.centre(hull); hullCentre = Vertices.centre(hull);
Body.setVertices(body, hull); Body.setVertices(body, hull);
Body.setPosition(body, hullCentre); Vertices.translate(body.vertices, hullCentre);
} }
// find the combined properties of all parts to set on the parent body // sum the properties of all compound parts of the parent body
var mass = 0, var total = _totalProperties(body);
area = 0,
inertia = 0,
centroid = { x: 0, y: 0 };
for (i = 1; i < parts.length; i++) { body.area = total.area;
var part = parts[i];
part.parent = body;
mass += part.mass;
area += part.area;
inertia += part.inertia;
Vector.add(centroid, part.position, centroid);
}
centroid = Vector.div(centroid, parts.length - 1);
body.area = area;
body.parent = body; body.parent = body;
body.position.x = centroid.x; body.position.x = total.centre.x;
body.position.y = centroid.y; body.position.y = total.centre.y;
body.positionPrev.x = centroid.x; body.positionPrev.x = total.centre.x;
body.positionPrev.y = centroid.y; body.positionPrev.y = total.centre.y;
Body.setMass(body, mass); Body.setMass(body, total.mass);
Body.setInertia(body, inertia); Body.setInertia(body, total.inertia);
Body.setPosition(body, centroid); Body.setPosition(body, total.centre);
}; };
/** /**
@ -382,14 +374,16 @@ var Body = {};
*/ */
Body.setPosition = function(body, position) { Body.setPosition = function(body, position) {
var delta = Vector.sub(position, body.position); var delta = Vector.sub(position, body.position);
body.position.x = position.x;
body.position.y = position.y;
body.positionPrev.x += delta.x; body.positionPrev.x += delta.x;
body.positionPrev.y += delta.y; body.positionPrev.y += delta.y;
Vertices.translate(body.vertices, delta); for (var i = 0; i < body.parts.length; i++) {
Bounds.update(body.bounds, body.vertices, body.velocity); var part = body.parts[i];
part.position.x += delta.x;
part.position.y += delta.y;
Vertices.translate(part.vertices, delta);
Bounds.update(part.bounds, part.vertices, body.velocity);
}
}; };
/** /**
@ -400,13 +394,15 @@ var Body = {};
*/ */
Body.setAngle = function(body, angle) { Body.setAngle = function(body, angle) {
var delta = angle - body.angle; var delta = angle - body.angle;
body.angle = angle;
body.anglePrev += delta; body.anglePrev += delta;
Vertices.rotate(body.vertices, delta, body.position); for (var i = 0; i < body.parts.length; i++) {
Axes.rotate(body.axes, delta); var part = body.parts[i];
Bounds.update(body.bounds, body.vertices, body.velocity); part.angle += delta;
Vertices.rotate(part.vertices, delta, body.position);
Axes.rotate(part.axes, delta);
Bounds.update(part.bounds, part.vertices, body.velocity);
}
}; };
/** /**
@ -464,21 +460,35 @@ var Body = {};
* @param {vector} [point] * @param {vector} [point]
*/ */
Body.scale = function(body, scaleX, scaleY, point) { Body.scale = function(body, scaleX, scaleY, point) {
// scale vertices for (var i = 0; i < body.parts.length; i++) {
Vertices.scale(body.vertices, scaleX, scaleY, point); var part = body.parts[i];
// update properties // scale vertices
body.axes = Axes.fromVertices(body.vertices); Vertices.scale(part.vertices, scaleX, scaleY, body.position);
body.area = Vertices.area(body.vertices);
Body.setMass(body, body.density * body.area);
// update inertia (requires vertices to be at origin) // update properties
Vertices.translate(body.vertices, { x: -body.position.x, y: -body.position.y }); part.axes = Axes.fromVertices(part.vertices);
Body.setInertia(body, Vertices.inertia(body.vertices, body.mass));
Vertices.translate(body.vertices, { x: body.position.x, y: body.position.y });
// update bounds if (!body.isStatic) {
Bounds.update(body.bounds, body.vertices, body.velocity); part.area = Vertices.area(part.vertices);
Body.setMass(part, body.density * part.area);
// update inertia (requires vertices to be at origin)
Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y });
Body.setInertia(part, Vertices.inertia(part.vertices, part.mass));
Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });
}
// update bounds
Bounds.update(part.bounds, part.vertices, body.velocity);
}
if (!body.isStatic) {
var total = _totalProperties(body);
body.area = total.area;
Body.setMass(body, total.mass);
Body.setInertia(body, total.inertia);
}
}; };
/** /**
@ -545,6 +555,35 @@ var Body = {};
body.torque += (offset.x * force.y - offset.y * force.x) * body.inverseInertia; body.torque += (offset.x * force.y - offset.y * force.x) * body.inverseInertia;
}; };
/**
* Returns the sums of the properties of all compound parts of the parent body.
* @method _totalProperties
* @private
* @param {body} body
* @return {}
*/
var _totalProperties = function(body) {
var properties = {
mass: 0,
area: 0,
inertia: 0,
centre: { x: 0, y: 0 }
};
// sum the properties of all compound parts of the parent body
for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
var part = body.parts[i];
properties.mass += part.mass;
properties.area += part.area;
properties.inertia += part.inertia;
Vector.add(properties.centre, part.position, properties.centre);
}
properties.centre = Vector.div(properties.centre, body.parts.length - 1);
return properties;
};
/* /*
* *
* Properties Documentation * Properties Documentation

View file

@ -78,6 +78,12 @@ var Composite = {};
switch (obj.type) { switch (obj.type) {
case 'body': case 'body':
// skip adding compound parts
if (obj.parent !== obj) {
Common.log('Composite.add: skipped adding a compound body part (you must add its parent instead)', 'warn');
break;
}
Composite.addBody(composite, obj); Composite.addBody(composite, obj);
break; break;
case 'constraint': case 'constraint':

View file

@ -67,8 +67,8 @@ var Sleeping = {};
continue; continue;
var collision = pair.collision, var collision = pair.collision,
bodyA = collision.bodyA, bodyA = collision.bodyA.parent,
bodyB = collision.bodyB; bodyB = collision.bodyB.parent;
// don't wake if at least one body is static // don't wake if at least one body is static
if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic) if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic)

View file

@ -399,7 +399,7 @@ var Render = {};
var sprite = part.render.sprite, var sprite = part.render.sprite,
texture = _getTexture(render, sprite.texture); texture = _getTexture(render, sprite.texture);
if (options.showSleeping && part.isSleeping) if (options.showSleeping && body.isSleeping)
c.globalAlpha = 0.5; c.globalAlpha = 0.5;
c.translate(part.position.x, part.position.y); c.translate(part.position.x, part.position.y);
@ -412,7 +412,7 @@ var Render = {};
c.rotate(-part.angle); c.rotate(-part.angle);
c.translate(-part.position.x, -part.position.y); c.translate(-part.position.x, -part.position.y);
if (options.showSleeping && part.isSleeping) if (options.showSleeping && body.isSleeping)
c.globalAlpha = 1; c.globalAlpha = 1;
} else { } else {
// part polygon // part polygon
@ -429,7 +429,7 @@ var Render = {};
} }
if (!options.wireframes) { if (!options.wireframes) {
if (options.showSleeping && part.isSleeping) { if (options.showSleeping && body.isSleeping) {
c.fillStyle = Common.shadeColor(part.render.fillStyle, 50); c.fillStyle = Common.shadeColor(part.render.fillStyle, 50);
} else { } else {
c.fillStyle = part.render.fillStyle; c.fillStyle = part.render.fillStyle;
@ -442,7 +442,7 @@ var Render = {};
} else { } else {
c.lineWidth = 1; c.lineWidth = 1;
c.strokeStyle = '#bbb'; c.strokeStyle = '#bbb';
if (options.showSleeping && part.isSleeping) if (options.showSleeping && body.isSleeping)
c.strokeStyle = 'rgba(255,255,255,0.2)'; c.strokeStyle = 'rgba(255,255,255,0.2)';
c.stroke(); c.stroke();
} }