bepu / bepuphysics2

Pure C# 3D real time physics simulation library, now with a higher version number.
Apache License 2.0
2.25k stars 261 forks source link

Upgrade Issues from 2.4.0-beta8 to 2.4.0 #204

Closed felix-ri closed 2 years ago

felix-ri commented 2 years ago

Cubestack Stability Deterioration

felix-ri commented 2 years ago

Also I didn't quite get the VelocityIterationCount.

felix-ri commented 2 years ago
RossNordby commented 2 years ago

I could reproduce this with a modified version of the Colosseum Demo, in which I put our cubestacks: old - new

In the newer version of the demo, the provided SolveDescription only allows the solver to use 1 velocity iteration. In the older version, it uses the default of 8. If the velocity iteration count is increased in the SolveDescription to 8 to match the old version, it works as expected.

For reference, 2.3's Solver.IterationCount and 2.4's Solver.VelocityIterationCount are the same thing. I just renamed it since IterationCount alone could be a bit ambiguous with SubstepCount. VelocityIterationCount refers to the number of velocity solving passes constraints undergo in a single (sub)step. Each velocity solve brings body velocities closer to obeying all their connected velocity constraints.

As far as I understood, the substepcount is simply how many solver/velocityIntegration pairs are executed for every CollisionDetection step.

That's correct; it executes multiple solves and integration steps. The integration steps also include position integration, though.

(because the solver is somehow cheaper than CollisionDetection and can get away with older contact points)

The savings is in 1) not having to re-run collision detection every substep, 2) a tighter bundling of execution that avoids thread sync points, and 3) more efficient memory access patterns.

Why would you split up the velocity integration in smaller parts, if the forces don't change inbetween?

They do change.

See the substepping documentation for more information: https://github.com/bepu/bepuphysics2/blob/master/Documentation/Substepping.md

We also had simulated surface velocities by modifying the angular and linear velocity before the solver ran and restoring the normal ones afterwards (before the position integrator) How can this be done now, since integration and solving is now tied together and I can't find a callback inbeen them?

If you are using only one substep, the execution flow is extremely similar to 2.3's PositionLastTimestepper. The frame goes like this (check https://github.com/bepu/bepuphysics2/blob/master/BepuPhysics/DefaultTimestepper.cs for details):

  1. attempt sleeps
  2. predict needed bounding boxes (this invokes velocity integration for the full frame timestep duration, but does not mutate body velocities)
  3. detect collisions
  4. integrate velocities
  5. solve constraints
  6. integrate positions with new velocities
  7. Incremental optimization

The DefaultTimestepper doesn't expose a callback between 5 and 6 since they're both within the Simulation.Solve call, but you could create a custom ITimestepper that does or hook the Solver.SubstepEnded event (see below).

Also, rather than resetting the velocity before the position integration, you could simply reset the position afterwards. Whichever's simpler and works for what you need.

If you are using more than one substep, things get a little trickier. The second substep and beyond will do position integration for the previous substep at the start of the current substep, and the Solver exposes a SubstepStarted and SubstepEnded event. So the call to Simulation.Solve for 3 substeps could conceptually look like:

  1. SubstepStarted(0)
  2. integrate velocities
  3. solve constraints
  4. SubstepEnded(0)
  5. SubstepStarted(1)
  6. integrate positions, and then integrate velocities
  7. solve constraints
  8. SubstepEnded(1)
  9. SubstepStarted(2)
  10. integrate positions, and then integrate velocities
  11. solve constraints
  12. SubstepEnded(2)
  13. integrate positions after substepping

By hooking the SubstepEnded event, you could reset velocities. Note that, when the timestep is given an IThreadDispatcher, the SubstepStarted/SubstepEnded events are called from thread 0 in the IThreadDispatcher. Using that same IThreadDispatcher instance from within those events would require that the IThreadDispatcher implementation is reentrant, which the built in ThreadDispatcher is not.

felix-ri commented 2 years ago

Thanks. We are only using one substep, so the first suggestion worked.

For reference, 2.3's Solver.IterationCount and 2.4's Solver.VelocityIterationCount are the same thing

Ahh, now I understand.