3D Physics Engine Pt. 4

Hi folks! This is a continuation of my work on elm-physics. You can find all the posts here.

The new progress was triggered by Ian Mackenzie’s work on elm-3d-scene. I highly encourage you to check his talk “A 3D rendering engine for Elm”. His presentation included an example of rendering a physical simulation.

I wanted to make such examples easy to build. It used to be hard, because elm-physics doesn’t do rendering and webgl is a pretty low-level package. With elm-3d-scene rendering will become much more approachable. And the new API of elm-physics improves it even further by using the shared vocabulary, defined in elm-geometry and elm-units.

I am going to list all the elm-physics improvements further below, but first I would like to share an example.

I rewrote the interactive cover slide from my Elm Europe talk in just 375 lines of code to present at a meetup in Tokyo. You can flip the table here using a mouse.

So what were the improvements that led to such concise code? I had to change quite a few things.

Improvements from elm-units

To support elm-units, I replaced ambiguous floats with self-documenting types.

It feels very nice to be able to pass length in meters, mass in kilograms, acceleration in meters per second squared and duration in seconds. You can use imperial units too, but don’t you dare!

Improvements from elm-geometry

Most examples need the visual representation of an object (Mesh) to match its physical representation (Body). Using elm-geometry to construct both representations reduces the boilerplate code. It also allowed me to simplify elm-physics API, because elm-geometry deals with construction and positioning of Block3d and Sphere3d.

Using Point3d and Direction3d types helps to distinguish between points and normals. Axis3d encapsulates both a point and a direction, so I could simplify the type of the hinge constraint to take two axes instead of a record with 4 attributes.

I also replaced the functions that move and rotate physical bodies with the new ones that mimic elm-geometry API, so that the user doesn’t have to learn new concepts.

Another cool feature from elm-geometry is its awareness of the coordinate systems. elm-physics exposes two: body local coordinates and world coordinates. Encoding coordinate systems in types improves the documentation and helps to avoid bugs. Types force the user to use Frame3d in order to transform between local and world coordinates.

More improvements

James Carlson found it surprising that bodies of zero mass didn’t move. Such bodies were in fact treated as if they had infinite mass. To address this, I introduced body behavior, that can either be static or dynamic. The constructor for the dynamic behavior requires mass.

The last improvement was about the center of mass of a body created from multiple shapes. Previously, the documentation didn’t even mention that the origin of the body local coordinate system had to be in the center of mass. This forced the awareness and the calculation of the offsets on the user. Ian Mackenzie suggested me to automatically calculate the center of mass offset and use it internally, while letting users choose an arbitrary body local coordinate system. The transformation between the center of mass coordinates and the user-defined body local coordinates happens when the user moves or rotates the body.


Originally, I planned to extend the functionality of elm-physics, but chose to improve the API to make it easier for users to build fun demos.

I like it when demos drive requirements. Please let me know if something that you need is missing! I hope that new features will organically fit into the existing API.


This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.