2

I've been experimenting with the excellent PhysicsJS library, especially constraints and collisions. What I'm trying to achieve is a polygon which can spin about a fixed rotation point. As a real world example, imagine a wide shelf nailed to a wall with just one long nail through the very center, so that it spins round maybe half or one revolution when something off-center drops on it from above.

Here is an example fiddle: http://jsfiddle.net/2HRGW/41/

and the code:

Physics(function (world) {
var renderer = Physics.renderer('canvas', {
    el: 'viewport',
    width: 500,
    height: 400
});
world.add(renderer);

var nail = Physics.body('circle', {
    x: 250,
    y: 200,
    radius: 5,
    mass: 1,
    fixed: true
});
world.add(nail);

var shelf = Physics.body('convex-polygon', {
    x: 250,
    y: 200,
    vertices: [{
        x: -100,
        y: -10
    }, {
        x: 100,
        y: -10
    }, {
        x: 100,
        y: 10
    }, {
        x: -100,
        y: 10
    }],
    mass: 100,
    restitution: 0.5
});
world.add(shelf);

var ball = Physics.body('circle', {
    x: 175,
    y: 50,
    radius: 20,
    mass: 10
});
world.add(ball);

world.add(Physics.integrator('verlet', {
    drag: 0.003
}));

var verletConstraints = Physics.behavior('verlet-constraints', {
    iterations: 2
});
verletConstraints.distanceConstraint(shelf, nail, 1);
world.add(verletConstraints);

world.add(Physics.behavior('constant-acceleration'));
world.add(Physics.behavior('body-collision-detection'));
world.add(Physics.behavior('body-impulse-response'));
world.add(Physics.behavior('sweep-prune'));
world.add(Physics.behavior('verlet-constraints'));

var bounds = Physics.aabb(0, 0, 500, 400);

world.add(Physics.behavior('edge-collision-detection', {
    aabb: bounds,
    restitution: 0.01
}));

Physics.util.ticker.subscribe(function (time, dt) {
    world.step(time);
});

world.render();

Physics.util.ticker.start();

world.subscribe('step', function () {
    world.render();
});
});

I define a fixed circle for the nail and a non-fixed polygon for the shelf and add a distance constraint linking the polygon to the circle. As you can see, there are 2 problems. Firstly, the shelf immediately drops down slightly until its top edge is flush with the top of the nail, rather than remaining evenly positioned around the nail. Secondly, when the ball drops onto the shelf, the shelf goes crazy spinning round endlessly, despite having mass and various restitution settings tried. Adjusting its position slightly, sometimes it can even detach completely and fly off.

Am I on the right track using constraints in this way, or is there a simpler solution?

Tom W Hall
  • 5,273
  • 4
  • 29
  • 35
  • The shelf is spinning wildly because it's colliding with the nail and PhysicsJS is trying to resolve the collision. – Snowball Nov 19 '13 at 08:37
  • OK - but is this the correct overall approach? If so, what needs to be adjusted? If not, could you provide an example? – Tom W Hall Nov 19 '13 at 08:41
  • 1
    Here's a patch to conditionally disable collision response on bodies: https://gist.github.com/anonymous/86c0ba8b4f1f85b11f0e . It also takes care of the 'slightly off center' issue. – Snowball Nov 19 '13 at 09:05
  • 1
    Overall, the approach is fine. You just reached a deficiency in PhysicsJS--it's a relatively new library, after all. If you don't want to go through the trouble of patching PhysicsJS yourself, here's one with the patch from my last comment applied: https://gist.github.com/anonymous/5716ef7004dc4fa20173 – Snowball Nov 19 '13 at 09:09
  • Thanks for that, combined with sokie's point about the mass, that's perfect - now I can get the shelf to either slowly swing round while the ball rolls off (using a low ball mass setting), or spin round wildly (with a high ball mass). I'll leave this question open for another day or so just in case there are other alternative approaches to consider. Thanks heaps! – Tom W Hall Nov 19 '13 at 09:35
  • @Snowball thanks for the patch, used it on my .js lib as well! – sokie Nov 19 '13 at 09:49
  • @Snowball I need to accept Jasper's answer as it is cleaner to extend the library with my own (perhaps temporary) behaviour rather than patch it - but you helped me out in my understanding of the library and if you write up your suggestion as an answer I'll upvote it. Cheers! – Tom W Hall Nov 20 '13 at 01:18
  • @TomHall: No worries! Jasper's answer is definitely the better way to do it. – Snowball Nov 20 '13 at 22:23

2 Answers2

7

As other users have mentioned, this is a current limitation of PhysicsJS. It's being worked out:

In the mean time, instead of patching the library, why not create a custom pin constraint behavior. For a simple pin constraint behavior that pins the body centroid to a target position, it's quite easy. Here's a jsFiddle of your example with a custom pin constraint manager defined at the beginning.

http://jsfiddle.net/wellcaffeinated/2HRGW/50/

// create a behavior to handle pin constraints
Physics.behavior('pin-constraints', function( parent ){
    return {
        init: function( opts ){
            parent.init.call( this, opts );
            this.pins = [];
        },

        add: function( body, targetPos ){
            this.pins.push({
                body: body,
                target: Physics.vector( targetPos )
            });
        },

        behave: function( data ){

            var pins = this.pins
                ,pin
                ;

            for (var i = 0, l = pins.length; i < l; i++){
                pin = pins[ i ];
                // move body to correct position
                pin.body.state.pos.clone( pin.target );
            }
        }
    };
});
Jasper
  • 1,193
  • 1
  • 9
  • 14
2

Your overall implementation is correct. The only thing you got wrong is the mass of the convex-polygon, 100 is a wild value. A mass of around 0.2 should be enough for that object.

sokie
  • 1,966
  • 22
  • 37
  • Wow, you're right, that mostly does it. How, though, can I get the center of the shelf to remain fixed to the center of the circle? Currently the shelf drops down slightly and then remains off-center. – Tom W Hall Nov 19 '13 at 08:54