← All posts

A Homemade Physics-Engine

Irregular Physics

Irregular physics is our own home made single-header realtime physics-engine, with no external dependencies. The user API is built for simple implementation in ANY projects thanks to its C-style and minimal overhead (keeping internal implementations out of the API). Our goal is to make it a functional and powerful engine while keeping it as simple as possible. Integrating it into a small Raylib project should be just as easy as using it in a professional Game/Graphics engine. It's in active development, currently including various rigidbody types such as spheres, capsules, planes and soon convex shapes.

The following blogs will walk you through our journey, the functionality and the progress of the engine, while also showing off most of the API.

Particles, the basics

Starting of, all the engine could do was "summon" particles and apply basic linear movement. The engine consisted of simple Vector implementations, a Rigidbody class which back then wasn't really a rigidbody and an Update loop which was used as the main loop. This is the very beginning of any engine, also used in game engines as particle systems.

A dt field has to be introduced to keep the simulation stable, eg: a timestep of 1/60 would run the simulation at about 60cps (cycles per second). Your first thoughts when talking about dynamics might be to just:

// All dynamics members can be considered 2D or 3D Vectors
object.acceleration += force / object.mass;
object.velocity += object.acceleration * dt;
object.position += object.velocity * dt;

And while this Euler approach is technically correct as F = ma and acceleration is just a change of velocity over time, this quickly becomes unstable at higher timesteps and velocities. With high velocites it easily becomes choppy and can later lead to collision misses.

The more used implementation and solution to this is the Velocity Verlet Integration: This approach uses velocity and acceleration averages to achieve a smooth and stable movement.

// Force is accumulated before the update and a gravity is applied.
Vector3 new_acceleration = force / object.mass;
object.position += object.velocity * dt + object.acceleration * (0.5 * dt * dt);
object.velocity += (object.acceleration + new_acceleration) * dt * 0.5;
object.acceleration = new_acceleration;

This is much more stable than the previous example. It uses the average acceleration of the previous and current frame and results in a more accurate calculation.

Conclusion

That's it for now — a look at where every physics engine has to start: particles, forces, and the integrator that ties them together. Getting it right matters more than it might seem. An unstable integration can lead to a lot of headaches later on.

From here we'll continue with angular dynamics and a stable solution to rotation, moment of inertia, collision tester and solver, building up a good response, tips for debugging and testing and so on.