Our homebrew physics library uses Dagmar’s entity component system to efficiently iterate through entities which have a rigid body component. This produces realistic collision responses in real-time.
Collision Detection & Response
Our system currently supports two types of rigid body collider primitives, which are components in our ECS. The first are spheres, and the second are Axis Aligned Bounding Boxes (AABBs). Even with just these two primitives, a wide array of fun and realistic scenes can be produced with ease.
Collision between two sphere rigid bodies is a quick calculation checking that the distance between their centers is no more than the sum of their two radii. If this is true, there is a collision. The collision response then sets the sphere positions to be so that their surfaces just touch, and their force and velocity are reflected over the vector between the two centers.
Collision between two AABBs is also a relatively quick calculation, however slower than the previous sections. We perform checks for whether there is any overlap between the volumes defined by the AABBs. If there is, the collision response involves once again setting the position of each AABB so that the collided pair only just touches. We then calculate which faces are intersecting, and use their normal vectors as the force reflection vector, similar to sphere-sphere collision. There is also a normalization process that takes place (as AABBs are rarely perfect cubes). Finally, a similar process to AABB-AABB collision takes place for AABB-sphere collision and response.
Multi-Threading
While we considered using GPU compute shaders, we found it to be unnecessary, both because we were getting good results on the CPU for our test sets, and also because of project time constraints. We did, however, multi-thread the process.
We were able to split up the outer loop of our iteration, and divide it into disjoint sections based on the number of threads allocated to physics. Because the sets of entities were disjoint, we did not have to worry about common multi-threading issues like race conditions. We were also able to orchestrate a system for dynamically re-allocating the number of physics threads. Each thread would check a signal each loop, and if triggered, would wait for all threads to shut down. We would then set off a new batch of threads. This should allow for capping the resources consumed by physics in real-time if required by the system.
Voxel Optimisations
The final aspect of the physics system was to optimise AABB and sphere collision with the voxel world. A naïve solution would be to iterate over each individual voxel to check for collision, however this gets ridiculously slow, very quickly. Instead, we calculate the positions of each voxel the surfaces of our rigid bodies could be intersecting with, and check whether they are active. This reduces the complexity of collision check in most cases, as long as our voxel structure is larger than our intersecting objects. Since a single voxel is guaranteed to be an AABB, we reuse the previous algorithms for AABB-voxel and sphere-voxel response.