We left off after I had completed the Broadphase transplant. Broadphase collision detection was now fast, but we were still spending lots of time in the narrowphase, as well as in other various parts of the physics engine. It seemed like a good time to go back to stage 1.
Turning Knobs Again
Our new Spatial Hashing Broadphase can handle as many small static bodies as we could ever throw at it, but it doesn’t do as well with larger bodies. Back in Part 1 I had consolidated the shapes of walls so that I had a few large bodies with lots of shapes on them. This worked well for p2’s SAPBroadphase, but it’s exactly the opposite of what our new Broadphase likes. I reverted those changes so we once again had a bunch of small bodies for walls, and voilá, collision detection time dropped to almost untraceable levels.
Speeding up the rest
At this point, performance was actually pretty good.
Physics were taking only about twice as long as rendering, down from the 10 times as long that I started at.
I could have stopped here, but I was on a roll.
There were two functions left where it seemed like a lot of time was being spent:
There were 5 places during the step that the world was iterating through all the bodies:
- Applying gravity
- Applying damping
- Waking up sleeping bodies
- Updating positions based on velocity and timestep (called integrating)
- Resetting forces
What’s one thing all of those have in common? None of them need to happen for static bodies.
The solution was pretty straightforward: keep track of dynamic and kinematic bodies separately.
When we add or remove a body from the world, don’t just add it to
this.bodies, also add it to
this.kinematicBodies if its type matches.
Now instead of applying gravity to each body in
this.bodies, we can apply it to only those in
Instead of integrating all bodies, we can integrate only those in
this.dynamicBodies and those in
You get the picture.
The solver is the thing that goes and does linear algebra and frankly is a bit above my head. What I can tell you though, is that it deals with things like moving bodies that are overlapping, and applying friction to bodies that are rubbing, and just like before, none of those things apply to static bodies.
This time making the change was even easier.
I just replaced the three places where we iterated through
world.dynamicBodies instead, and we were good to go.
With all these changes in place it was time for the final profiling.
Physics now takes less time than rendering, when it used to take more than 10 times as long! All that was left to do was to play my pinball game in peace without being disturbed by my laptop’s fans screaming at me.