Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contact detection bugs with kinematic bodies #96

Open
brianpeiris opened this issue Sep 6, 2020 · 0 comments
Open

Contact detection bugs with kinematic bodies #96

brianpeiris opened this issue Sep 6, 2020 · 0 comments

Comments

@brianpeiris
Copy link

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);
    }
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant