Files
GR-raytracing/src/frame.h
T
wyj 09a7417961 Feat: Add directed asymptotic escape and analytic Schwarzschild exterior
Replace radius-only escape termination with a common asymptotic exterior protocol: declared ends, moving escape worldtubes, directed inside->outside crossings, and a PENDING_ENTRY lifecycle shared by single-frame and movie tracing.

Add an analytic Carlson-integral Schwarzschild monopole exterior (angle primitive, bracketed turning radius, ingoing Kerr-Schild coordinate-time transfer, conserved-energy frequency) so a camera outside the escape sphere is traced through an entry event.

Make the lifecycle tri-state (no ends / ready / protocol error), carry end_id through the endpoint and lens mesh, validate sources in constructors via spacetime_source_finalize(), and refresh the Schwarzschild reference images for the corrected finish.
2026-10-04 03:32:28 -04:00

185 lines
7.3 KiB
C

#ifndef FRAME_H
#define FRAME_H
#include "catalog.h"
#include "geodesic.h"
#include "optics.h"
#include "observer.h"
#include "spacetime.h"
#include <stddef.h>
typedef struct {
double image_x, image_y;
double camera_direction[3];
double n_infinity[3];
double log_frequency_ratio;
RayEndpointStatus status;
/* Asymptotic end this escaped vertex belongs to; a triangle must not
* interpolate across two different ends. */
SpacetimeEndId end_id;
int traced;
} LensVertex;
typedef struct {
size_t vertex[3];
unsigned int level;
int evaluated;
} LensTriangle;
/* Per-frame staged wall-clock breakdown for one movie frame. All fields are
* seconds and are zero-initialized by the caller. Hot loops never call a
* clock; each phase is timed exactly once around its bulk operation. */
typedef struct {
double catalog_mark_seconds;
double catalog_load_seconds;
double fast_clear_seconds;
double catalog_splat_seconds;
double fftw_zero_pack_seconds;
double fftw_forward_seconds;
double fftw_multiply_seconds;
double fftw_inverse_seconds;
double fftw_crop_seconds;
double fftw_total_seconds;
double tone_map_seconds;
double png_encode_write_seconds;
double writer_queue_wait_seconds;
double frame_total_seconds;
} MovieFrameTiming;
typedef struct {
unsigned int max_level;
double angle_absolute_rad;
double angle_relative;
double jacobian_minimum;
double min_edge_pixels;
double min_area_pixels2;
} RefinementConfig;
typedef enum {
FRAME_SAMPLE_VERTEX,
FRAME_SAMPLE_PROBE
} FrameSampleKind;
typedef struct {
FrameSampleKind kind;
size_t vertex_id;
size_t edge_vertex[2];
LensVertex vertex;
} FrameSample;
typedef struct {
LensVertex *vertices;
LensTriangle *triangles;
size_t vertex_count, vertex_capacity;
size_t triangle_count, triangle_capacity;
FrameSample *samples;
/* Current generation's vertex/probe requests, retained through result
* installation and cleared by finish_generation; not a pending-ray count. */
size_t sample_count, sample_capacity;
int samples_include_probes;
size_t *probe_slots;
size_t probe_slot_capacity;
} FrameLensMesh;
typedef enum {
FRAME_SPLAT_PROGRESS_PREFETCH_BEGIN,
FRAME_SPLAT_PROGRESS_PREFETCH_END,
FRAME_SPLAT_PROGRESS_BEGIN,
FRAME_SPLAT_PROGRESS_END
} FrameSplatProgressStage;
typedef void (*FrameSplatProgressCallback)(void *context,
FrameSplatProgressStage stage,
size_t completed, size_t total);
/* Invoked by the splat worker itself. `triangle_count` is local to that
* worker; callers must not infer global completion order from it. */
typedef void (*FrameSplatWorkerProgressCallback)(void *context,
size_t worker_id,
size_t worker_count,
size_t triangle_count,
int finished);
typedef struct {
FrameSplatProgressCallback callback;
FrameSplatWorkerProgressCallback worker_callback;
void *context;
} FrameSplatProgress;
typedef void (*FrameRefinementProgressCallback)(void *context,
size_t generation,
size_t sample_count,
size_t vertex_count,
size_t triangle_count,
int added_vertices,
int finished);
int frame_lens_mesh_build_coarse(FrameLensMesh *mesh, int width, int height,
int cell_pixels, double horizontal_fov_deg);
int frame_lens_mesh_trace(FrameLensMesh *mesh, const SpacetimeSource *spacetime,
const ObserverState *observer,
const GeodesicTraceConfig *trace);
/* Builds one generation of vertex/probe ray requests. Returns the request
* count, zero when this frame needs no work, or -1 on failure. Results are
* installed only after the caller has completed the generation's sweep. */
int frame_lens_mesh_prepare_generation(FrameLensMesh *mesh,
const RefinementConfig *config);
const FrameSample *frame_lens_mesh_samples(const FrameLensMesh *mesh,
size_t *count);
int frame_lens_mesh_install_sample(FrameLensMesh *mesh, size_t sample_id,
const RayEndpoint *endpoint);
/* Applies a nonempty completed generation; callers skip frames for which
* prepare_generation returned zero. Returns the number of newly added
* vertices, zero when no topology change was made, or -1 on failure. */
int frame_lens_mesh_finish_generation(FrameLensMesh *mesh,
const RefinementConfig *config);
int frame_lens_mesh_refine(FrameLensMesh *mesh,
const SpacetimeSource *spacetime,
const ObserverState *observer,
const GeodesicTraceConfig *trace,
const RefinementConfig *config);
int frame_lens_mesh_refine_with_progress(
FrameLensMesh *mesh, const SpacetimeSource *spacetime,
const ObserverState *observer, const GeodesicTraceConfig *trace,
const RefinementConfig *config, FrameRefinementProgressCallback callback,
void *context);
/* Whether frame_splat_catalog() should run the per-frame catalog prefetch or
* rely on a movie-level union prefetch that already completed. */
typedef enum {
FRAME_CATALOG_PREFETCH_FRAME,
FRAME_CATALOG_PREFETCH_ALREADY_COMPLETE
} FrameCatalogPrefetchMode;
/* Adds every one-degree tile that can intersect a usable source triangle of
* the finalized mesh to `set`. Kept in the frame module so catalog.h does not
* depend on FrameLensMesh. */
int frame_mark_catalog_tiles(const FrameLensMesh *mesh, CatalogTileSet *set);
/* Each locally invertible escaped triangle contributes one image per contained
* star. When `fast` is non-NULL, each image is deposited into its shared
* supersampled buffer and the whole frame is resolved once at the end instead
* of splatting a per-event PSF. */
size_t frame_splat_catalog(const FrameLensMesh *mesh,
StarCatalog *catalog, double *hdr, int width,
int height, double exposure,
const PointSpreadFunction *psf,
const PsfKernelCache *psf_cache,
double max_magnification,
double max_cache_psf_flux,
double psf_relative_tail,
double psf_min_y,
int limit_workers_by_memory,
int catalog_load_workers,
FrameCatalogPrefetchMode catalog_prefetch_mode,
CatalogPrefetchStats *prefetch_stats,
PsfSplatStats *psf_stats,
const FrameSplatProgress *progress,
FastPsfAccumulator *fast,
MovieFrameTiming *timing);
void frame_draw_mesh(const FrameLensMesh *mesh, double *hdr, int width,
int height, double gray, double opacity);
void frame_lens_mesh_destroy(FrameLensMesh *mesh);
#endif