INTERACTIVE · WEBGL + COMPUTATIONAL GEOMETRY · REAL-TIME

Section Studio.

METHOD
INTERFACE

One plane equation, computed two ways — a GPU visual cut and a CPU-measured contour — forced to agree.

Drag a cutting plane through a procedurally-generated solid and two things happen in the same frame. The GPU clips the mesh so you see it cut open. On the CPU, every triangle is intersected with that same plane to recover the exact section contour — which is measured for area, perimeter, and bounds, drawn as a crisp 2D line, and exported as SVG. Same plane, two pipelines, one truth.

THE PROBLEM

To reason about a solid you slice it — a floor plate in a massing, wall thickness in a machined part, strut density in a lattice. But a rendered cut only looks right: it gives you a picture, not a number. And a bare list of numbers with no visible cut is impossible to trust or explain.

THE IDEA

Drive one cutting plane into two independent pipelines: a GPU clip that renders the cut, and a CPU solver that measures it. Because both consume the identical plane equation, the picture and the numbers must describe the same locus — each is a live check on the other.

WHY IT'S USEFUL

The read-outs and the SVG export are what turn a demo into an instrument. The section updates continuously as the plane moves, and the exported contour is a resolution-independent drawing suitable for drafting or documentation.

2 independent pipelines
1 shared plane equation
0 model files — all procedural
3 solids, each a different stress test

↑ PICK A SOLID · SET THE PLANE AXIS · DRAG OFFSET · ORBIT THE VIEW · EXPORT THE SECTION

01 RENDER vs. MEASURE — THE SPINE

The interesting engineering here is not that a solid can be cut open on screen, nor that a polygon's area can be computed. It is that one movable plane is asked to do both jobs through two pipelines that never talk to each other — and the results have to line up exactly. The GPU path is fast and approximate-feeling; the CPU path is exact and slower. Running them off the same n·x = d turns each into a sanity check on the other. That duality is the idea; everything else is plumbing.

One cutting plane driving two independent pipelines: a GPU visual cut and a CPU-measured contour that must agree. The plane equation n dot x equals d fans into two rows. The top row (render, GPU) feeds material clipping planes, the GPU discards the far half-space, and a cut-open mesh is rendered. The bottom row (measure, CPU) computes a signed distance per triangle, finds edge crossings, welds and stitches closed loops, and measures area, perimeter, and bounding box plus an SVG export. Both rows converge on a node marked "must agree — one locus, two proofs". ONE PLANE · TWO PIPELINES The same plane equation n·x = d drives a GPU visual cut and a CPU-measured contour — and the two must agree. RENDER · GPU — WHAT YOU SEE MEASURE · CPU — WHAT YOU CAN TRUST CUTTING PLANE n·x = d same n, d same n, d material.clippingPlanes localClippingEnabled GPU discards far side per fragment · per frame Cut-open mesh rendered solid + cap Signed distance per triangle Edge crossings → segments Weld + stitch → closed loops Measure area · perim · bbox + SVG export MUST AGREE one locus, two proofs
One cutting plane, two pipelines. The GPU clips the mesh so you see the cut; the CPU intersects every triangle to measure it and redraw it as an exportable contour. Because both consume the identical plane equation, render and measurement describe the same locus — each validates the other.
02 WHAT EACH PIPELINE DOES

The GPU cut — what you see

The solid is rendered with three and @react-three/fiber. A single world-space clipping plane is handed to the material (renderer.localClippingEnabled + material.clippingPlanes), so the GPU discards every fragment on the far side of the cut, every frame, while you orbit — no geometry is modified, the clip is purely a per-pixel test. The cut face is then filled with a translucent cap so the model reads as a genuine solid rather than a hollow shell.

The CPU section — what you can trust

The showcase is the section itself. For each triangle I compute the signed distance of its three vertices to the plane, find the edges that straddle it, and interpolate the crossing points into a line segment. Thousands of these segments are then welded at shared endpoints and stitched into closed contour loops — the same marching-triangles idea that underpins contouring and slicing. From the loops I derive section area (hole-aware, via an even-odd nesting rule), perimeter, and the bounding box. This path is exact: it is the answer I would stake a measurement on.

An instrument, not an animation

The whole plane–mesh intersection reruns over the full triangle soup on every frame the plane moves — comfortably real-time in plain JavaScript. The claim I'll actually stand behind is the narrow one: the inner per-triangle crossing math is allocation-free, reusing three scratch slots and touching no heap. The surrounding pass is not — the segment buffers and the weld-and-stitch bookkeeping are rebuilt each frame — but keeping the hottest loop tight is what buys the real-time feel. The continuously-updating read-outs and the clean SVG export are what make this a tool you could actually reason with, rather than a canned clip.

03 THE THREE SOLIDS

Each solid is chosen to exercise the sectioning in a different way — all generated procedurally at load, with no model files:

  • Stepped massing — stacked, set-back floor slabs. A vertical cut traces the stepped silhouette across every floor plate at once; a horizontal cut isolates the plate at whatever level the plane sits.
  • Machined bracket — an extruded plate with a central bore, mounting holes, and lightening reliefs. Scanning the plane across it opens and closes holes, so the section count and area jump as features come and go.
  • Gyroid lattice — a solid slice of the gyroid triply-periodic minimal surface, meshed with a self-contained marching-tetrahedra iso-surfacer. Its section is a field of interlocking loops — the visual signature of a TPMS lattice, and a deliberate stress test for the contour stitcher.
04 LIMITATIONS & WHAT'S NEXT

The honest edges of the build — a senior tool states them plainly:

  • Not eyeballed frame-by-frame. The 3D viewport needs live WebGL, which the static build environment can't exercise. The scene has been reasoned about and instrumented, but not visually QA'd against a running GPU. What I would stake correctness on is the CPU side — the measurements, the 2D contour, and the SVG export are pure, deterministic functions of the triangle soup and the plane.
  • The measurement is exact; one visual is a heuristic. Section area, perimeter, bounds, and the 2D drawing come straight from the plane–triangle math and are correct for any watertight input. The translucent 3D cap that fills the cut face is a secondary convenience, triangulated from the same loops via an even-odd shape build; for the gyroid's many interlocking loops the hole/nesting assignment is best-effort, so the cap can occasionally mis-fill even while the 2D section and the numbers stay right.
  • Non-watertight input degrades gracefully, not silently. Open meshes yield open polylines instead of closed loops; area is only meaningful for closed contours, so it is reported as the even-odd sum and can be misleading on genuinely non-solid input.

What's next: a robust loop-nesting pass for the cap (an explicit winding/containment tree rather than even-odd depth parity), so the gyroid cap matches the always-correct 2D section; a Web Worker to offload the intersection so very large soups keep a steady frame rate; and a proper visual QA pass once a live GPU is in the loop. A first ergonomic fix already shipped — the orbit camera auto-reframes when you switch solids, since the three differ in scale and the view previously stayed put.

05 STACK

Astro island rendered client:only (WebGL can't server-render), three + @react-three/fiber + @react-three/drei for the scene and orbit controls. The section solver, contour stitcher, measurement code, marching-tetrahedra mesher, and SVG serializer are hand-written TypeScript with no geometry libraries. Every surrounding control and panel is painted with the site's design tokens, so the whole instrument flips correctly between light and dark; only the WebGL stage stays dark in both, on purpose, to hold geometry contrast steady.