I spent some of my downtime over the past few months working on client-side brick physics for Blockland. The feature has finally been announced, so I can talk about it. The video shows off most of the features; the main one that isn’t shown is the interaction between players/vehicles and bricks; they will push bricks around but aren’t affected themselves. Watch it in full screen, it’s full 720p HD video.
There were two big problems related to doing physics for Blockland. The first was the scale of the problem – there can be well over 100,000 bricks in a single server, which is beyond the capabilities of most physics SDKs to simulate as discrete objects. I started with PhysX, and moved to Bullet after realizing that the PhysX runtime is 80mb, far more than could be included in the Blockland download (which weighs in at 20 mb). Both of these libraries broke in different ways with large numbers of objects.
At first, I implemented a management system for brick proxies, so that it kept them under the hard limit in the SDK (around 2**16). PhysX accepted this, but Bullet’s broadphase has some stuff that’s O(# objects) or worse, so it fell down. Eventually, I moved everything into the same system used for static world geometry, which was a grid of static meshes. It turns out that Bullet is a bit faster at creating these mesh objects than PhysX was.
The static mesh cache took quite a bit work to get solid. Because the simulation is for aesthetic purposes, it can tolerate a fair amount of “fudge,” which I take full advantage of. Nearly every kind of update is timesliced so that only a little bit is done each tick. This keeps things smooth, even at the cost of the physical state being inconsistent for a tick or two. Most updates are lazy, as well, only done if a dynamically moving brick, player, or vehicle comes into the area.
The other problem is the wide variability of Blockland user’s computers and usage patterns. Not every user has enough CPU to run physics. And every user has the potential to build something that is very resource intensive to simulate. I spent a lot of time implementing a “physics diaper” – logic to detect when physics calculations were taking too much time, and scaling back the simulation until it’s fast again. This takes two forms. First, if physics ticks are too slow, the simulation is decimated – every other brick on the list of moving bricks is converted to a lighter weight parametric simulation that doesn’t consider collisions. If they remain too slow, then eventually the physics simulation is disabled entirely, until the user turns it back on. This can help with very complex builds or very slow computers.
Thanks to good physics middleware (I include both PhysX and Bullet under the “good” category, even though PhysX is a little on the bloated side), I was able to solve a pretty tough problem – simulating motion for hundreds of thousands of bricks on commodity hardware – in short order. And I have to thank my friend Eric for making such an awesome sandbox and letting me play in it.