Skip to content

Contact detection bugs with kinematic bodies #96

@brianpeiris

Description

@brianpeiris

I've run into some blocking bugs with Oimo's kinematic bodies. It seems particularly problematic with rotated kinematic bodies. Code to reproduce is included below. The code can be pasted into Oimo's demo editor.

Steps to reproduce:

  1. The first bug appears immediately after you run the code for the first time. The smallest boxes rendered by the test code represent the contact points returned by getContact.
  2. BUG1 Oimo reports incorrect contact points between kinematic bodies the very first time the world is stepped, even if the bodies are not actually in contact.
  3. To workaround the stepping issue, set stepTwice to true in the code. This will run world.step() twice before each test case is rendered.
  4. When the output updates, see that no contact points are shown at first. This is correct.
  5. Click on the demo output area and press the spacebar to test the next case.
  6. The blue box moves into the red box and some approximately correct contact points are shown.
  7. Press the space bar again.
  8. BUG2 The blue box moves to the edge of the red box and now two of the contact points are incorrect.

I realize this library isn't actively maintained anymore, but I thought I'd post this bug for anyone else running into these issues.

var stationaryBody, stationaryMesh, movingBody, movingMesh;
var contactPointMeshes;
var testStep = 0;

// Press SPACE to step through the test cases.

// Test parameters:
var stepTwice = false;
var stationaryBodyRotation = 10;
var movingBodyRotation = -10;

function demo() {
  cam(40, 20, 15);

  world = new OIMO.World();
  view.hideGrid();

  var stationaryBodyOptions = {
    size: [10, 10, 10],
    rot: [0, stationaryBodyRotation, 0],
    move: true,
    noSleep: true,
    kinematic: true,
  };
  stationaryBody = world.add(stationaryBodyOptions);
  stationaryMesh = view.add(stationaryBodyOptions);
  stationaryMesh.material = new THREE.MeshStandardMaterial({ color: "red", transparent: true, opacity: 0.5 });

  var movingBodyOptions = {
    size: [2, 2, 2],
    rot: [0, movingBodyRotation, 0],
    move: true,
    noSleep: true,
    kinematic: true,
  };
  movingBody = world.add(movingBodyOptions);
  movingMesh = view.add(movingBodyOptions);
  movingMesh.material = new THREE.MeshStandardMaterial({ color: "blue" });

  contactPointMeshes = [
    view.add({ size: [1, 1, 1] }),
    view.add({ size: [1, 1, 1] }),
    view.add({ size: [1, 1, 1] }),
    view.add({ size: [1, 1, 1] }),
  ];

  contactPointMeshes[0].material = new THREE.MeshStandardMaterial({ color: "green" });
  contactPointMeshes[1].material = new THREE.MeshStandardMaterial({ color: "orange" });
  contactPointMeshes[2].material = new THREE.MeshStandardMaterial({ color: "yellow" });
  contactPointMeshes[3].material = new THREE.MeshStandardMaterial({ color: "violet" });

  runTestStep();
}

var keyWasDown = false;
function update() {
  if (!keyWasDown && user.key[4]) {
    runTestStep();
    keyWasDown = true;
  }
  if (!user.key[4]) {
    keyWasDown = false;
  }
}

function runTestStep() {
  console.log(testStep);

  switch (testStep) {
    case 0:
      movingBody.setPosition({ x: 0, y: 0, z: 8 });
      break;
    case 1:
      movingBody.setPosition({ x: 0, y: 0, z: 5 });
      break;
    case 2:
      movingBody.setPosition({ x: 5, y: 0, z: 5 });
      break;
  }

  world.step();
  if (stepTwice) world.step();

  movingMesh.position.copy(movingBody.getPosition());

  updateContacts();

  testStep = (testStep + 1) % 3;
}

function updateContacts() {
  contactPointMeshes.forEach((m) => (m.visible = false));

  const contact = world.getContact(stationaryBody, movingBody);

  if (contact) {
    console.log(
      contact.points
        .map((p) => [p.position.x.toFixed(2), p.position.y.toFixed(2), p.position.z.toFixed(2)].join(", "))
        .join(" | ")
    );

    for (let i = 0; i < contact.points.length; i++) {
      contactPointMeshes[i].visible = true;
      contactPointMeshes[i].position.copy(contact.points[i].position);
    }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions