Feat: support general single-frame cameras and add a near-horizon example

This commit is contained in:
wyj committed 2026-09-06 04:00:21 -04:00
1 parent 94149d75e4
commit 6ae223a642
15 files changed
+771 -166

No files matched your search

+75 -11
View File
@@ -14,19 +14,83 @@ processing are documented in [assets/2mass/README.md](assets/2mass/README.md).
synthetic test catalog; `--exposure 1e15` is a starting point, to be adjusted
for the field and camera.
## Schwarzschild camera
## Single-frame camera
`schwarzschild_sky` uses an analytic Schwarzschild metric in Cartesian ingoing
Kerr–Schild coordinates, with mass `M=1`. The default camera is static at
coordinate radius `30`. `--look-ra-deg` and `--look-dec-deg` set the direction
from the camera to the hole; the camera is placed on the opposite side of the
origin and points radially inward. `--observer-radius R` requires `R > 2`.
`--observer-inward-speed V` applies a local inward boost relative to the static
observer, with `0 <= V < 1` and default `0`.
Both backends accept the same instantaneous camera parameters. Position and
velocity use the backend's coordinates; velocity means `dx/dt, dy/dt, dz/dt`,
not a local physical speed. The analytic single-frame event is at `t=0`.
The analytic setup uses escape radius `256` and capture radius `1.5`, inside
the horizon at `r=2`. These are current demonstration settings; they do not
establish termination criteria for future numerical-relativity data.
| Option | Meaning / default |
| --- | --- |
| `--observer-position X Y Z` | Coordinate position; if look is omitted, point toward the origin |
| `--look-ra-deg RA`, `--look-dec-deg DEC` | Coordinate look direction; missing angle defaults to RA=90°, Dec=-90° |
| `--observer-radius R` | Positive radius used only to infer position, default 30; conflicts with explicit position |
| `--observer-velocity VX VY VZ` | Coordinate velocity, default `0 0 0`; must be future-timelike in the local metric |
| `--camera-roll-deg ANGLE` | Rotate the camera up axis toward its right axis, default 0° |
When position and look are both supplied, they are independent. Look alone
implies position `-R * look_direction`, in either backend. Radius alone uses
the default look. With no position/look/radius options, Minkowski keeps the
origin camera and Schwarzschild keeps its radius-30 camera on +Z; both look
along -Z. Velocity and roll alone do not alter these defaults.
An explicit origin position requires a look angle. Position-derived directions
on the Z axis use RA=0° to fix the pole orientation deterministically.
The axes are right-handed ICRS: X=RA 0°/Dec 0°, Y=RA 90°/Dec 0°,
Z=Dec +90°. The coordinate look vector `(cos(dec) cos(ra), cos(dec) sin(ra),
sin(dec))` is projected into the moving camera's rest space. The coordinate
north and west seeds are then orthogonalized there to form up and right.
Consequently the look angles specify a projected coordinate orientation;
they do not lock a lensed sky object to the image center. Positive roll uses
`up' = cos(roll) up + sin(roll) right`,
`right' = -sin(roll) up + cos(roll) right`.
No static observer is needed. The metric determines whether `(1,VX,VY,VZ)`
is timelike; there is no Euclidean `|V| < 1` check in curved coordinates.
Invalid velocities are rejected before loading catalogs or building the PSF
cache, with the velocity and its metric norm in the diagnostic.
`--observer-inward-speed` has been removed.
Single-frame camera options cannot be combined with `--observer-track`,
`--frames-dir`, or `--lens-map-input`.
Schwarzschild uses Cartesian ingoing Kerr–Schild coordinates with `M=1`.
Cameras at and inside the horizon `r=2` are allowed with a valid timelike
coordinate velocity. The current backend excludes camera positions at or
inside its capture cutoff `r=1.5`; its finite escape radius is `256`.
These remain analytic demonstration settings, not criteria for future NR data.
Zero coordinate velocity at or inside the horizon is not timelike and is rejected.
The following complete examples use the bundled synthetic catalog:
```sh
make -j PSF_BACKEND=cpu SPACETIME=minkowski backend
mkdir -p output/imgs
./build/Release/minkowski_sky --catalog assets/sky_grid_5deg.csv \
--observer-position 3 -4 5 --observer-velocity 0.2 -0.1 0.3 \
--look-ra-deg 37 --look-dec-deg -23 --camera-roll-deg 19 \
--width 64 --height 48 --fov-deg 80 --exposure 0.1 \
--coarse-cell-pixels 8 --refine-max-level 0 --psf-direct \
--output output/imgs/minkowski_moving.png
make -j PSF_BACKEND=cpu SPACETIME=schwarzschild backend
./build/Release/schwarzschild_sky --catalog assets/sky_grid_5deg.csv \
--observer-position 3 -4 5 --observer-velocity 0.2 -0.1 0.3 \
--look-ra-deg 37 --look-dec-deg -23 --camera-roll-deg 19 \
--width 64 --height 48 --fov-deg 80 --exposure 0.1 \
--coarse-cell-pixels 8 --refine-max-level 0 --psf-direct \
--output output/imgs/schwarzschild_off_axis.png
./build/Release/schwarzschild_sky --catalog assets/sky_grid_5deg.csv \
--observer-position 1.75 0 0 --observer-velocity -0.5 0 0 \
--look-ra-deg 0 --look-dec-deg 0 \
--width 64 --height 48 --fov-deg 80 --exposure 0.1 \
--coarse-cell-pixels 8 --refine-max-level 0 --psf-direct \
--output output/imgs/schwarzschild_inside_horizon.png
```
The last example points outward from a camera moving inward inside the horizon.
It needs no CSV trajectory or movie wrapper. These small images are camera
checks; increase resolution and refinement for production renders.
## Movie image sequences