Our project is a simulation of an asteroid impacting the Earth. We were inspired by this GitHub repo.
After the first collision, there are 552 particles being simulated at:
- 60 FPS running on Ubuntu 20.04 (i5-8300H, GTX 1060M)
- 20 FPS running on Windows 10 (i7-7820, GTX 1070)
Without GPU-accelerated computation, these would be running at 20 FPS and 1.5 FPS respectively.
How it works
At the beginning, there are two particles, an asteroid and a planet, on a collision course with each other. When they collide, they are deleted and replaced with 64 chunks and 488 chunks respectively.
Our chunks were made in Blender by slicing meshes and filling them in.
Our physics engine runs in the following 4 steps:
1. GPU Phase
The GPU runs through the cartesian product of all particles, and calculates both gravitational force and intersections. Gravitational force is summed up per-particle, and intersections are recorded in a array list.
When the CPU receives the GPU’s output, the gravity is written to the particles and the intersecting ones are recorded in a contact index.
2. Intersection Bookkeeping
Contacts keep track of an internal state to improve the stability of low-relative velocity contacts. This phase performs the following tasks:
Creates new contacts that did not previously exist Updates old contacts that still exist Deletes old contacts that no longer exist
3. Contact Solving
I describe this step in detail in this blog post.
This phase performs a single Euler step of position and rotation.
Position is integrated with
where is position, is velocity, and is the time step.
Rotation is stored in a matrix to avoid gimbal lock. Angular velocity is a vector which is in the direction that the axis the object is rotating around using the right-hand rule, scaled to the speed in radians per second.
Suppose is the matrix representing a rotation of around . Thus, we integrate rotation with