Frame: add adaptive mesh refinement

This commit is contained in:
wyj committed 2026-08-28 23:06:53 -04:00
1 parent 4aa5f6666a
commit 48dcf4e707
7 files changed
+768 -72

No files matched your search

+52
View File
@@ -142,6 +142,58 @@ metric or its infinity criterion; frame, observer, and integrator use only
as `--coarse-cell-pixels`; it is a Phase-0 sampling knob, not a settled
production refinement threshold.
### Adaptive image mesh refinement
Adaptive refinement is disabled by default (`--refine-max-level 0`), so the
existing coarse-mesh renders remain unchanged. When enabled, its defaults are
an absolute direction error of `1e-3` degrees, relative error `0.1`, minimum
long edge `0.5` pixels, and minimum area `0.25` pixel-squared. Each value can
be overridden independently:
```text
--refine-max-level N
--refine-angle-abs-deg D
--refine-angle-rel R
--refine-min-edge-pixels P
--refine-min-area-pixels2 A
```
`N` caps the triangle refinement level. Let `e` be the angle between the
traced longest-edge midpoint direction and the normalized endpoint
interpolation, and let `s` be the angle between those two endpoint **camera
directions**. Both are evaluated internally in radians; the absolute CLI
threshold `D` is specified in degrees and converted before comparison. `s`
is the angular geometric size of the image triangle's test edge, not a
source-sky/lens-map length. A locally escaped triangle is split only when
**both** `e > D_rad` (the converted `--refine-angle-abs-deg D`) and
`e / max(s, 1e-15) > --refine-angle-rel`. `P` and `A`
prevent selecting a leaf already at or below the requested image-plane
long-edge and area scales.
Triangles whose three vertices disagree between capture and escape are split
independently of the direction-error thresholds, allowing the mesh to follow a
shadow boundary. This first implementation deliberately does not evaluate
orientation or Jacobian criteria.
For a short Schwarzschild diagnostic that permits at most one actual split
generation, for example:
```sh
./build/schwarzschild_sky --catalog assets/sky_grid_5deg.csv \
--width 48 --height 48 --coarse-cell-pixels 24 --fov-deg 40 \
--refine-max-level 1 --refine-angle-abs-deg 0.001 \
--refine-angle-rel 0.001 --refine-min-edge-pixels 1 \
--refine-min-area-pixels2 1 --draw-mesh \
--output output/imgs/schwarzschild_refinement.png
```
For movies, each refinement generation completes the full newest-to-oldest
time-slab sweep before any probe becomes a mesh vertex. Newly added vertices
are therefore traced only by the next generation; the renderer never returns
to a slab that has already been released. At the start of every generation,
newly inserted vertices and geometry-only longest-edge probes for its new
leaves are collected together, so both ray sets use the same parallel
`RayPool` pass.
`--look-ra-deg` and `--look-dec-deg` rotate that fixed tetrad so its forward
axis is the corresponding catalog direction; their defaults reproduce the
original `-Z` view. `--exposure` converts a catalog's physical flux