简体   繁体   中英

Prevent relative rotation in Matter.js constraint

I'm using Matter.js and I want two rectangles with a constraint to make them act if they where a single rigid object.

I am basically setting stiffness to 1, so the contraint acts like a rigid bar instead of a spring. Also to prevent the object from rotating, I'm setting the intertia to Infinity.

  // a 20x20 square with 0 friction and infinite inertia
  let objectA = Bodies.rectangle(0, 0, 20, 20, {
      frictionAir: 0,
      inertia: 'Infinity'
  });
  let objectB = Bodies.rectangle(30, 0, 20, 20, {
      frictionAir: 0,
      inertia: 'Infinity'
  });

  let constraint = Constraint.create({
      bodyA: objectB,
      bodyB: objectB,
      length: 30,
      stiffness: 1);

This indeed creates 2 objects with a fixed distance and they do not rotate (both squares always have the same absolute orientation)

在此处输入图像描述

However the objects can rotate between them, the constrain acts as a linear constraint but not as an angular constraint. This picture shows how the distance between objects is kept, how the absolute orientation of the objects has not changed but how the objects rotate around each other.

How can I get rid of this rotation and have the two objects act if they were a single object?

在此处输入图像描述

I use a different approach: building a Body from parts instead of using constraints. The result is a single rigid object. Matter handles the parts still separately, so you can eg drop a ball in the cart created with the code below.

let cart = bodyWithParts(200, 150, { isStatic: true, friction: 0.0 });

function bodyWithParts(x, y, options) {
  options = options || {}
  let w = 4;
  options.parts = [];
  options.parts.push(Matter.Bodies.rectangle(w, 20, 5, 20));
  options.parts.push(Matter.Bodies.rectangle(40 - w, 20, 5, 20));
  options.parts.push(Matter.Bodies.rectangle(20, 40 - w, 50, 5))
  let body = Matter.Body.create(options)
  Matter.Body.setPosition(body, { x: x, y: y });
  return body;
}

Building a Body to of parts can be useful, however, the strength of the orientation "constraint" cannot be lowered. The orientation stays fixed in any situation.

Therefore, I've written the following TypeScript function which adds two constraints of zero length to two Body objects. Constraints allows us to set the stiffness parameter.

Note that removing one the constraints allows one of the bodies to rotate around its own position ("midpoint") but it cannot change its position relative the other body.

/** 
 * Adds constraints to `bodyA` and `bodyB` such that their current
 * relative position and orientaion is preseved (depending on `stiffness`).
 * 
 * @param bodyA the first body of the constraint
 * @param bodyB the second body of the constraint
 * @param stiffness the stiffness of the constraint connecting `bodyA` and `bodyB`
 * @param offsetA the constraint offset on `bodyA` in its coordinate system
 * @param offsetB the constraint offset on `bodyB` in its coordinate system
 */ 
function addRigidBodyConstraints(
    bodyA: Body, bodyB: Body,
    stiffness: number = 0.1,
    offsetA: Vector = Vector.create(0, 0),
    offsetB: Vector = Vector.create(0, 0)
    ) {

    function makeConstraint(posA: Vector, posB: Vector): Constraint {
        return Constraint.create({
            bodyA: bodyA, bodyB: bodyB,
            pointA: posA, pointB: posB,
            // stiffness larger than 0.1 is sometimes unstable
            stiffness: stiffness
        })
    }

    // add constraints to world or compound body
    World.add(world, [
        makeConstraint(Vector.sub(bodyB.position, bodyA.position), offsetB),
        makeConstraint(offsetA, Vector.sub(bodyA.position, bodyB.position))
    ])
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM