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:
1 parent
04611e3e5a
commit
09a7417961
24 files changed
+3566
-58
No files matched your search
+14
-1
@@ -116,6 +116,7 @@ int frame_lens_mesh_trace(FrameLensMesh *mesh, const SpacetimeSource *spacetime,
|
||||
RayEndpoint endpoint = geodesic_trace_past(spacetime, observer,
|
||||
vertex->camera_direction, trace);
|
||||
vertex->status = endpoint.status;
|
||||
vertex->end_id = endpoint.end_id;
|
||||
vertex->traced = 1;
|
||||
if (endpoint.status == RAY_ENDPOINT_ESCAPED) {
|
||||
for (int axis = 0; axis < 3; ++axis)
|
||||
@@ -437,11 +438,20 @@ static int all_vertices_traced(const FrameLensMesh *mesh) {
|
||||
|
||||
static int terminal_mismatch(const LensVertex *a, const LensVertex *b,
|
||||
const LensVertex *c) {
|
||||
int escaped = 0, captured = 0;
|
||||
int escaped = 0, captured = 0, have_end = 0;
|
||||
SpacetimeEndId end = SPACETIME_END_NONE;
|
||||
const LensVertex *vertices[] = {a, b, c};
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
escaped |= vertices[i]->status == RAY_ENDPOINT_ESCAPED;
|
||||
captured |= vertices[i]->status == RAY_ENDPOINT_CAPTURED;
|
||||
if (vertices[i]->status == RAY_ENDPOINT_ESCAPED) {
|
||||
if (!have_end) {
|
||||
end = vertices[i]->end_id;
|
||||
have_end = 1;
|
||||
} else if (vertices[i]->end_id != end) {
|
||||
return 1; /* two different infinity ends must not be interpolated */
|
||||
}
|
||||
}
|
||||
}
|
||||
return escaped && captured;
|
||||
}
|
||||
@@ -576,6 +586,7 @@ int frame_lens_mesh_install_sample(FrameLensMesh *mesh, size_t sample_id,
|
||||
? &mesh->vertices[sample->vertex_id]
|
||||
: &sample->vertex;
|
||||
vertex->status = endpoint->status;
|
||||
vertex->end_id = endpoint->end_id;
|
||||
vertex->traced = 1;
|
||||
if (endpoint->status == RAY_ENDPOINT_ESCAPED) {
|
||||
for (int axis = 0; axis < 3; ++axis)
|
||||
@@ -610,6 +621,8 @@ static int discrete_jacobian(const FrameLensMesh *mesh,
|
||||
if (a->status != RAY_ENDPOINT_ESCAPED || b->status != RAY_ENDPOINT_ESCAPED ||
|
||||
c->status != RAY_ENDPOINT_ESCAPED)
|
||||
return 0;
|
||||
if (a->end_id != b->end_id || a->end_id != c->end_id)
|
||||
return 0;
|
||||
const double image_area = spherical_signed_area(
|
||||
a->camera_direction, b->camera_direction, c->camera_direction);
|
||||
if (!isfinite(image_area) || fabs(image_area) <= 1e-15)
|
||||
|
||||
Reference in new issue
Block a user