Connect physics objects with constraints (Physics V2 replaces joints with PhysicsConstraint):

// Create a hinge constraint (like a door hinge) using Physics V2

// Create a fixed anchor point
const anchor = BABYLON.MeshBuilder.CreateBox("anchor", {size: 0.5}, scene);
anchor.position = new BABYLON.Vector3(0, 5, 0);
const anchorAggregate = new BABYLON.PhysicsAggregate(
    anchor, BABYLON.PhysicsShapeType.BOX,
    { mass: 0 }, scene // mass 0 = static
);

// Create a panel to act as a door
const door = BABYLON.MeshBuilder.CreateBox("door", {
    width: 0.5, height: 6, depth: 4
}, scene);
door.position = new BABYLON.Vector3(2, 5, 0);
const doorAggregate = new BABYLON.PhysicsAggregate(
    door, BABYLON.PhysicsShapeType.BOX,
    { mass: 5, friction: 0.5 }, scene
);

// Create a hinge constraint between anchor and door
const hingeConstraint = new BABYLON.HingeConstraint(
    new BABYLON.Vector3(0, 0, 0),  // pivot on anchor
    new BABYLON.Vector3(-2, 0, 0), // pivot on door
    new BABYLON.Vector3(0, 1, 0),  // hinge axis on anchor
    new BABYLON.Vector3(0, 1, 0),  // hinge axis on door
    scene
);
anchorAggregate.body.addConstraint(doorAggregate.body, hingeConstraint);

Physics V2 constraint types available with Havok:

// Ball-and-socket constraint (allows rotation in all directions)
const ballConstraint = new BABYLON.BallAndSocketConstraint(
    new BABYLON.Vector3(0, 0, 0),  // pivot on body A
    new BABYLON.Vector3(0, 2, 0),  // pivot on body B
    scene
);
bodyA.addConstraint(bodyB, ballConstraint);

// Distance constraint (maintains fixed distance)
const distConstraint = new BABYLON.DistanceConstraint(
    5, // distance to maintain
    scene
);
bodyA.addConstraint(bodyB, distConstraint);

// Prismatic constraint (allows movement along one axis)
const prismaticConstraint = new BABYLON.PrismaticConstraint(
    new BABYLON.Vector3(0, 0, 0),  // pivot on body A
    new BABYLON.Vector3(0, 0, 0),  // pivot on body B
    new BABYLON.Vector3(1, 0, 0),  // axis on body A
    new BABYLON.Vector3(1, 0, 0),  // axis on body B
    scene
);
bodyA.addConstraint(bodyB, prismaticConstraint);

// Lock constraint (completely fixes two bodies together)
const lockConstraint = new BABYLON.LockConstraint(
    new BABYLON.Vector3(0, 0, 0),
    new BABYLON.Vector3(0, 2, 0),
    new BABYLON.Vector3(0, 1, 0),
    new BABYLON.Vector3(0, 1, 0),
    scene
);
bodyA.addConstraint(bodyB, lockConstraint);

Create spring-like behavior with Physics V2 constraints:

// Create spring-like behavior using Physics V2 with a 6DoF constraint

// Create anchor point (static)
const springAnchor = BABYLON.MeshBuilder.CreateSphere("anchor", {diameter: 1}, scene);
springAnchor.position.y = 15;
const anchorAgg = new BABYLON.PhysicsAggregate(
    springAnchor, BABYLON.PhysicsShapeType.SPHERE,
    { mass: 0 }, scene
);

// Create suspended object (dynamic)
const bob = BABYLON.MeshBuilder.CreateSphere("bob", {diameter: 2}, scene);
bob.position.y = 10;
const bobAgg = new BABYLON.PhysicsAggregate(
    bob, BABYLON.PhysicsShapeType.SPHERE,
    { mass: 2, restitution: 0.6 }, scene
);

// Create a 6 degrees of freedom constraint with spring-like limits
const constraint = new BABYLON.Physics6DoFConstraint(
    { pivotA: new BABYLON.Vector3(0, 0, 0), pivotB: new BABYLON.Vector3(0, 5, 0) },
    [{ axis: BABYLON.PhysicsConstraintAxis.LINEAR_DISTANCE,
       minLimit: 0, maxLimit: 8 }],
    scene
);
anchorAgg.body.addConstraint(bobAgg.body, constraint);

// Visualize the spring connection with a line
let springLine = BABYLON.MeshBuilder.CreateLines("springLine", {
    points: [springAnchor.position, bob.position],
    updatable: true
}, scene);

// Update the line in the render loop
scene.onBeforeRenderObservable.add(() => {
    springLine = BABYLON.MeshBuilder.CreateLines("springLine", {
        points: [springAnchor.position, bob.position],
        instance: springLine
    });
});