screenshot.gif

A work-in-progress 4-dimensional renderer written in Rust using OpenGL 4.5+.

After seeing videos of Miegakure gameplay, I became very interested in the idea of 4-dimensional rendering. It turns out there are several ways to visualize 4D objects. Perhaps the simplest method involves a projection from 4D to 3D. This is similar to how "typical" 3D engines display objects onto the surface of a 2D screen (your display). Similar to this classic 3D -> 2D projection, a 4D -> 3D projection can either be a perspective projection or parallel projection (orthographic).

Most people are familiar with this form of visualization. When a 4D -> 3D perspective projection is applied to the hypercube (or tesseract), the result is the familiar animation of an "outer" cube with a smaller, nested "inner" cube that appears to unfold itself via a series of 4-dimensional plane rotations. The reason why this inner cube appears smaller is because it is "further away" in the 4th dimensional (the w-axis of our 4D coordinate system).

Another way to visualize 4-dimensional objects is via a "slicing" procedure, which produces a series of 3-dimensional cross-sections of the full polytope. This is analogous to cutting 3D polyhedra with a plane (think MRI scans). Luckily, much of the math carries over to 4D. In order to facilitate this process, meshes in four are first decomposed into a set of tetrahedrons. This is similar to how we can decompose the faces of a regular polyhedron into triangles. In particular, any 3D convex polyhedron can be decomposed into tetrahedrons by first subdividing its faces into triangles. Next, we pick a vertex from the polyhedron (any vertex will do). We connect all of the other face triangles to the chosen vertex to form a set of tetrahedra (obviously, ignoring faces that contain the chosen vertex). This is not necessarily the "minimal tetrahedral decomposition" of the polyhedron (which is an active area of research for many polytopes), but it always works. This is the method I used to render the 120-cell above.

More information can be found in the code on my Github