Skip to content

Spatial Acceleration for Occlusion

Started: 2026-02-08 Status: Research

Problem

Occlusion is brute-force O(edges × faces) — every edge checks every front-facing face from every other object. Intersection lines add O(face_pairs × faces) on top. Fine for a handful of objects, but will choke at scale.

Goal

Accelerate the broad phase so only nearby face candidates are checked per edge. Keep the existing narrow-phase logic.

Research

No drop-in JS/TS library does HLR with intersecting objects without a GPU.

Libraries Considered

LibraryHLR?
[[3D.primer]]
Intersecting objects?Verdict
three-plotter-rendererYesNo — explicitly warns against itPen-plotter world, skips our hard case
three-svg-rendererYesUnknownExperimental, GPL-3, sparse docs
plotter-visionYesNoDemo-quality, O(n²)
opencascade.jsYes (exact)YesIndustrial CAD kernel via WASM. Enormous bundle, C++-style API

Building Blocks

LibraryWhat it doesFit
flatbushStatic 2D R-tree (Mapbox). Zero-dep, tiny, battle-testedBest candidate — project face bounding boxes into screen space, query per edge, cull 90%+ of candidates
rbushDynamic 2D R-treeNeeded only if faces change frame-to-frame without full rebuild
isectSegment intersection detection (uses flatbush)Useful for edge-face boundary crossings in 2D
three-mesh-bvh3D BVH for raycasting
[[3D.primer]]
Fast but coupled to three.js

Recommendation

flatbush as a spatial index for the existing algorithm. We already have the core logic — the brute force is just the broad phase. Flatbush turns it from O(n) to O(log n) per edge query. That's the "tiled bins" idea from code.debt, essentially.

opencascade.js is the "right" answer but it's bringing a crane to hang a picture.

Plan

  • Add flatbush dependency
  • After projection, build a flatbush index from all front-facing face bounding boxes (screen space)
  • For each edge, query the index for overlapping faces instead of iterating all
  • Benchmark before/after