How to create a distance joint constraint?

Hi there,

I’m having trouble trying to create a distance joint between two entities.

Basically I want EntityA (with a dynamic rigid body) and EntityB (with a static rigid body) to always be the same distance from each other.

My script:

var Hooked = pc.createScript('hooked');

Hooked.attributes.add("hook", { type: "entity" });

// initialize code called once per entity
Hooked.prototype.initialize = function() {
    this.on('attr:hook', function (value, prev) {
        this.onHookChange(value, prev);
    });
    if(this.hook) this.onHookChange(this.hook, null);
};

var center = new Ammo.btVector3( 0, 0, 0 );

Hooked.prototype.onHookChange = function(value, prev) {
    if(this.joint) {
        console.log("destroy join");
    }
    if(value) {
        console.log("create joint");
        this.joint = new Ammo.btPoint2PointConstraint( this.entity.rigidbody.body , this.hook.rigidbody.body, center, center);
        console.log("joint:", this.joint);
        this.app.systems.rigidbody.dynamicsWorld.addConstraint(this.joint, false);
    }
};

// update code called every frame
Hooked.prototype.update = function(dt) {
    if (this.joint) {
        // render a line between the 2 entities
    }
};

Currently this.entity (EntityA) is attracted by this.hook (EntityB) until they collide: how can I add a fixed distance? I tried playing with pivots but couldn’t make it work.

Thank you!

When you create joint, IIRC there is an offset that can be applied of where pivot point of the joint is.

Hey, I’m not sure what you mean. Ammo.btPoint2PointConstraint accepts at most 4 arguments, no length or offset.

By the way, I couldn’t find Ammo documentation, does PlayCanvas exposes it somewhere?

I recommend reading this thread:

Ammo is a complied version of Bullet so I had to look up documentation for Bullet to apply Ammo.

You can see the functions/API/classes that are exposed for Ammo here: https://github.com/playcanvas/ammo.js/blob/master/ammo.idl

There’s also Will’s ragdoll project here which can help: https://playcanvas.com/editor/scene/468930

And be sure to read this page in the User Guide:

https://developer.playcanvas.com/en/user-manual/physics/calling-ammo/

Thank you for your answers.

I’ve already read the thread about the robot arm but it seemed very complicated for a simple distance joint.

If I understand correctly, in order to achieve what I want, I will need 3rd body which will have 2 point2pointConstraints : one with the dynamic body and one with the static body.

If entity A needs to be freely rotating around its pivot point then yes, it does sound like you need 2 joints.

I have modified my script and it’s now working as intended.

Here’s the code:

var Hooked = pc.createScript('hooked');

Hooked.attributes.add("hook", { type: "entity" });

// initialize code called once per entity
Hooked.prototype.initialize = function() {
    this.on('attr:hook', function (value, prev) {
        this.onHookChange(value, prev);
    });
    if(this.hook) this.onHookChange(this.hook, null);
};

var center = new Ammo.btVector3( 0, 0, 0 );

Hooked.prototype.onHookChange = function(value, prev) {
    if(this.rope) {
        console.log("destroy join");
    }
    if(value) {
        console.log("create joint");
        
        // create rope body
        this.rope = new pc.Entity("Rope");
        this.rope.addComponent("rigidbody", {
            type: "dynamic",
        });
        this.rope.addComponent("collision", {
            type:"box",
        });
        
        // add rope to world
        this.app.systems.rigidbody.dynamicsWorld.addRigidBody(this.rope.rigidbody.body);
        
        var pos = this.entity.getPosition();
        var to = this.hook.getPosition();
        var dist = new Ammo.btVector3( pos.x - to.x, pos.y - to.y, pos.z - to.z );
        // create joint between entity and rope
        this.joint1 = new Ammo.btPoint2PointConstraint( this.entity.rigidbody.body , this.rope.rigidbody.body, center, dist);
        this.app.systems.rigidbody.dynamicsWorld.addConstraint(this.joint1, true);
        
        // create joint between hook and rope
        this.joint2 = new Ammo.btPoint2PointConstraint( this.hook.rigidbody.body , this.rope.rigidbody.body, center, center);
        this.app.systems.rigidbody.dynamicsWorld.addConstraint(this.joint2, true);
    }
};

// update code called every frame
Hooked.prototype.update = function(dt) {
    if (this.joint) {
        // this.app.renderLine(this.entity.getPosition(), this.hook.getPosition(), [1,0,0]);
    }
};

Thanks again for your replies

I don’t get why you needed to edit the script. Did you look at this project:

https://playcanvas.com/project/618829/overview/physics-constraints

In particular, this part of the scene:

That’s essentially a rope attached to a fixed point. You could keep chaining point to point constraints from the bottom to add more articulations.

Hi,

I needed to create a script because I need to create the constraint programmatically, when user clicks for example.

I’m very new to playcanvas so maybe I’m doing it wrong.

You can create the structures in my project programmatically too. You should be able to use my script without making any changes.

Hi again,

I forked your project to try your physics scripts.

Please take a look at this project:
https://playcanvas.com/project/630736/overview/phys-fork

I have set up 2 entities : “working2d” and “broken2d”.
The only difference is the Ball’s collision sphere radius (Ball1 radius=0.5, Ball2 radius=0.14).

I don’t get why “broken2” behaves like this ?

Thank you for your time