Cannon, world.step and delta time

So I’ve noticed (for a long time) that with quite some frequency my scene would have some very obvious stutter even though the frame rate is pretty stable otherwise and for a scene that is not heavy (at least I think it’s pretty lightweight). I was using world.step(1/ 60, delta) believing that is the most robust way to do it, mirroring what use-cannon is doing as well. If I change it to passing delta directly as first argument (which is what it’s currently doing), the stutter is gone. How can that be? Is this fix simply covering over some underlying issue I have? Running in Chrome with a performance throttling of 4 it’s still smooth, and even at 10x slowdown there some very light jank but pretty stable still. When doing the same with the initial stepping, the jank would be even more pronounced.

I’ve actually noticed the same kind of stutter with use-cannon and reported a bug about it, but it is still there: Shaky body when using api.velocity.set() with fixed velocity · Issue #239 · pmndrs/use-cannon · GitHub.

1 Like

In short.. it’s complicated.

The fact that there are 2 parameters makes it extra confusing. The first param being the fixed step size.. second being desired fixed step size.

Using DT directly gets you smoother behavior, but any changes/spikes in the deltaT then can break the determinism of your simulation, or cause momentary problematic effects like tunneling through the terrain because the step gets too big.. or a step too small that it generates values too close to zero internally.

I don’t know if cannon works the same way, but in ammo, it maintains 2 snapshots.. one for each fixed step.. and then has a method to retrieve the interpolated value between the snapshots.. which is pretty much the ideal. you still have deterministic fixed timestep but the visual appearance of the body reflects actual time between the snapshots.

The gaffer article referenced in the docs is a good read.. and also the concept of interpolating between fixed snapshots is a really good general tool to have in your arsenal both in the context of physics, but really anything like network state snapshots, or animation in an app, or something where the simulation phase is very expensive so you have to timeslice it across multiple frames, but you still want a smooth appearance between those snapshots.

For simple toy/fun simulations I often just use deltaT directly, but make sure I filter out deltaTs that are > 2 or 3x the desired “fixed” timestep, to prevent the problems caused by spikes.. but for anything more complex (especially deterministic-ish stuff or networked sims), you kinda will end up having to learn and understand this all a bit deeper.

my impression was that passing in fixed step and delta would make cannon do the interpolation for me? it also looks a little like a variable delta for the first param appears smoother, but also causes joints to jitter a little. so i think its more covering up something rather than fixing it.

That would be my instinct as well.. but I can’t speak to the design of cannon.js.

My anecdotal ranking of the physics engines in terms of complexity and quality are:

PhysX - made by nvidia.. robust and fast.. used in robotics and sciences.. so basically state of the art.. but isn’t targeted specifically at games.

Havok - fast and less robust, but sometimes more perceptually stable. It makes internal tradeoffs to keep it fast at the expense of accuracy, since it’s mainly targetting games. Docs are terrible/non-existent. The wasm/js bindings are still not super mature and can require a lot of digging to make it work stably.

Ammo - a port of Bullet which is quite robust and has been around for a Looong time, so very debugged.. but not quite as modern. A bit slower, but potentially more accurate. Better docs since it’s been around forever.

Rapier - a rust engine.. relatively new.. which makes me wary about it. It’s easy to make a new physics engine and claim high performance, while still missing a lot of important optimizations and architectural decisions that the larger engines have.. but it seems fast, and is used in r3f, so its getting lots of eyeballs/attention, which is good for getting the bugs out of a physics engine.

Cannon also falls into this category with the additional downside of being pure JS which means its forced to do 64 bit math in js, and it’s also a handrolled engine by ~1 guy.. so doesn’t have the historical legacy and complexity of the larger engines. It’s not “bad”, but I don’t have a very solid level of trust about it that I do with PhysX/Ammo.

Oimo - similar case as cannon.. (but more mature, but also a deader project).

Jolt is a special case.. It’s a less “mature” engine, but has the benefit of actually having been used in a commercial game (HZD) so you can extrapolate that if you’re target use case is similar.. and you can match how it was used in a commerical product, you may have good luck with it.

It’s a huuuge topic and there are a lot of anecdotal opinions. Feel free to DM me if you want to talk more about it.

2 Likes

This is cool!

2 Likes

Yeah your comment made me check out the actual sim.. and it does look quite good and the vehicle physics feel good.. so whatever engine is being used is probably a good fit!

2 Likes