dimforge / rapier.js

Official JavaScript bindings for the Rapier physics engine.
https://rapier.rs
Apache License 2.0
397 stars 55 forks source link

Contact force behaviour changes upgrading from 0.11.2 to 0.12.0 #261

Closed isaac-mason closed 2 months ago

isaac-mason commented 5 months ago

In the process of updating @react-three/rapier from @dimforge/rapier3d-compat 0.11.2 to 0.12.0 we've noticed a difference in contact force behaviour.

Below is a minimal reproduction. Between 0.11.2 and 0.12.0 we get very different contact force values with default world integration parameters. When we set world.numSolverIterations = 1 in 0.12.0, the behaviour returns to what we get from 0.11.2 defaults.

I'm looking to understand if this is intended behaviour.

import Rapier from '@dimforge/rapier3d-compat'

await Rapier.init()

const gravity = new Rapier.Vector3(0.0, -9.81, 0.0)

const world = new Rapier.World(gravity)

const floor = world.createRigidBody(Rapier.RigidBodyDesc.fixed())
world.createCollider(Rapier.ColliderDesc.cuboid(10, 1, 10), floor)

const ball = world.createRigidBody(Rapier.RigidBodyDesc.dynamic())
ball.setTranslation(new Rapier.Vector3(0, 5, 0), true)
ball.setLinvel(new Rapier.Vector3(0, -1, 0), true)
const ballColliderDesc = Rapier.ColliderDesc.ball(1)
ballColliderDesc.setRestitution(1)
ballColliderDesc.setActiveEvents(Rapier.ActiveEvents.CONTACT_FORCE_EVENTS)
world.createCollider(ballColliderDesc, ball)

const eventQueue = new Rapier.EventQueue(false)

let time = 0
setInterval(() => {
  time += 1 / 60

  world.step(eventQueue)

  eventQueue.drainContactForceEvents((event) => {
    console.log('contact force event - totalForce', event.totalForce())
  })
}, 1000 / 60)
// @dimforge/rapier3d-compat@0.11.2
contact force event - totalForce iA {
  x: 0,
  y: 2945.241943359375,
  z: 0,
}

// @dimforge/rapier3d-compat@0.12.0 with numSolverIterations = 4 (default)
contact force event - totalForce GA {
  x: 0,
  y: 10.27295970916748,
  z: 0,
}

// @dimforge/rapier3d-compat@0.12.0 with numSolverIterations = 1
contact force event - totalForce GA {
  x: 0,
  y: 2945.2421875,
  z: 0,
}
chungwu commented 5 months ago

I'm also seeing the same, where I see collision events for many steps before I see a contact force event. Setting numSolverIterations to 1 is the only way to make sure I see contact force events when I expect to.

sebcrozet commented 5 months ago

This is a bug. The new solver runs multiple sub-steps for calculating forces, and the reported impulses don’t account for all the substeps.

sebcrozet commented 4 months ago

This will be fixed by https://github.com/dimforge/rapier/pull/607