A 4D tesseract in three.js: edges from XOR, rotation in XW/YW/ZW

The Experiments world of my portfolio is a glass tesseract you can look at full screen: Interstellar's Tesseract — 4D Hypercube in WebGL · Jonás Javier

Three things made it work, all small.

Edges from bits. Each of the 16 vertices is a number 0–15; bit 0 is X, 1 is Y, 2 is Z, 3 is W, coordinates ±0.5. Two vertices share an edge exactly when they differ in one bit, so XOR finds all 32 without searching:

for (let v = 0; v < 16; v++)
  for (let axis = 0; axis < 4; axis++) {
    const o = v ^ (1 << axis);
    if (v < o) edges.push([v, o]);
  }

Every vertex has degree 4, which is even, so an Eulerian circuit exists: Hierholzer’s algorithm gives the single stroke a point of light uses to trace all 32 edges every 18 s.

Rotate only in XW, YW and ZW. The three planes that don’t touch W are ordinary 3D rotations and show nothing new. The pose comes from absolute time (not per-frame increments, so 120 Hz doesn’t spin twice as fast), warped by two sine harmonics: it moves at 0.71× its average speed on the readable poses and 1.21× on the confusing ones, never below 0.7, so it never runs backwards.

Depth in W as hierarchy. The first version read as a wire cage. Perspective from a camera at W = 1.65 gives each vertex a depth, normalised 0–1 every frame; tube radius goes 0.58–1.42× and brightness follows it. A fixed range lost the hierarchy exactly when the cube faced you squarely. The geometry (~1,700 vertices) is rewritten every frame with DynamicDrawUsage and fixed bounding spheres.

What I haven’t solved: the rhythm is tuned by eye to these three speeds; change them and the slow-downs miss the readable poses.

How do you decide which 4D poses read well? Is there a measure better than watching it?

Write-up: 4D Tesseract in Three.js: How to Draw a Hypercube · Jonás Javier