Voxel Physics Engine
Solo 24 weeks C++ (Custom Engine)
For a technical explanation of the physics go to Physics Explained →
Inspiration
For a school project we had make a custom engine feature. So I wanted to work on a physics project because it has always been interesting to me. I also wanted to try something different than the norm, so I remembered Teardown which has voxel physics with destruction, and I really wanted to recreate it. Altough it didn’t really seem reasonable to get a result close to the physics in Teardown, I still wanted to see how close I could get. So I started this project with the goal of making 3D box physics, so no interesting shapes, just boxes. Then I worked on this project for a bit more than half a year. And ended up with result I’m very happy with.
Physics
When I started this project I already had the goal in mind of creating voxel physics, but because it was my first 3D physics project I started out by working on 3D physics with OBB’s (Oriented Bounding Boxes). This step was crucial for me to find out more about different types of collision detection and resolution methods. I started off using a Direct Impulse Resolution method, but I could not get a stable simulation. That was until I found out about Sequential Impulses. Because of Box2D and their excelent documentation, and some other sources I was able to quickly implement Sequential Impulses for my OBB’s.
After getting physics in an acceptable state for OBB’s I change the collision detection and contact generation to support voxel objects. The OBB’s are still used for the early out, but not for creating contacts. The contacts are generated per voxel. It didn’t take me a long time to implement this, but using a brute force approach has horible performance and has a few other differences. Another new issue that was introduced was mulitple voxels penetration which I solved by storing an 5 bit lookup number for the normal so it would not get inverted, the other 3 bits where used to determine what type of voxel it was, which is used to reduce the number of voxel to voxel checks. So the voxel physics data is only 1 byte per voxel.
So with some optimizations which include: basic sleep states, SAT early out, only checking overlapping areas and voxel types. My proof of concept looked like this.
Kudzu
Because of the succes of my voxel physics proof of concept we got the chance to work on the chance to build a game engine from my project. So the Kudzu engine was created. This was a group project with multiple engine, tools, graphics and gameplay programmers. We worked with a total of 7 people on this engine. I continued to add features and performance optimizations to my physics, while integrating it into Kudzu. These features include collision layers, triggers, callbacks, scripting interface and destruction. Later in the project I also helped with creating the demo game.
Destruction
Part of my responsibilities for kudzu was making functional realtime destruction. With the inspiration being Teardown again. For getting the destruction working a few things needed to happen. I had to find if and where objects seperate when a voxel is destroyed, create a new object for each seperate piece, and recalculate the physics data for each given piece. Seperating the objects, and recalulating the physics data was pretty simple. But effectively and quickly finding where voxel objects seperate was quite difficult. I did this by doing a floodfill over the whole object over multiple frames. This works well because you can define how much performance you want to put in the destruction at the cost of the object having a delay reaction to the destruction. For most objects this is unnoticable (it only takes 1 to 3 frames), but this approach doesn’t scale linearly in complexity. For objects that are for example 256^3 it can take a noticable amount of time (20 to 40 frames). This can still be improved alot, but the current aproach works functionally.
After 8 weeks of working on Kudzu, we got the opportunity to make a full game with the engine. This game became Zentera. This game showed what our engine is capable of. During the development time of Zentera, a lot of effort still went into developing the engine.