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.
185 lines
7.3 KiB
C
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
|