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.
This commit is contained in:
wyj committed 2026-10-04 03:32:28 -04:00
1 parent 04611e3e5a
commit 09a7417961
24 files changed
+3566 -58

No files matched your search

+42
View File
@@ -33,9 +33,47 @@ static void minkowski_destroy(SpacetimeSource *source) {
source->ops = NULL;
}
static size_t minkowski_asymptotic_end_count(const SpacetimeSource *source) {
(void)source;
return 1;
}
static int minkowski_asymptotic_end(const SpacetimeSource *source,
size_t index, SpacetimeAsymptoticEnd *out) {
(void)source;
if (index != 0)
return -1;
*out = (SpacetimeAsymptoticEnd){
.end_id = 0,
.exterior_kind = ASYMPTOTIC_EXTERIOR_MINKOWSKI,
.mass = 0.0,
.frame_origin = {0.0, 0.0, 0.0},
.frame_axes = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}};
return 0;
}
static int minkowski_escape_worldtube_sample(
const SpacetimeSource *source, SpacetimeEndId end_id, double t,
SpacetimeEscapeWorldtubeSample *out) {
const MinkowskiContext *context = source->context;
if (end_id != 0)
return -1;
*out = (SpacetimeEscapeWorldtubeSample){.center = {0.0, 0.0, 0.0},
.velocity = {0.0, 0.0, 0.0},
.radius = context->escape_radius,
.radius_rate = 0.0,
.velocity_constant = 1,
.valid = 1};
(void)t;
return 0;
}
static const SpacetimeOps minkowski_ops = {
.eval = minkowski_eval,
.classify = minkowski_classify,
.asymptotic_end_count = minkowski_asymptotic_end_count,
.asymptotic_end = minkowski_asymptotic_end,
.escape_worldtube_sample = minkowski_escape_worldtube_sample,
.destroy = minkowski_destroy,
};
@@ -48,6 +86,10 @@ int spacetime_create_minkowski(SpacetimeSource *source, double escape_radius) {
context->escape_radius = escape_radius;
source->ops = &minkowski_ops;
source->context = context;
if (spacetime_source_finalize(source)) {
minkowski_destroy(source);
return -1;
}
return 0;
}