Fix: Skip empty movie refinement generations

Allow frames to finish refinement independently without aborting the movie. Report genuine refinement errors with generation and frame identifiers, and clarify the sample batch contract.

Add a two-frame Schwarzschild regression covering unequal refinement progress. Validated Release and Debug make test suites and 640x360 rendering of the final eight free-fall frames in both builds.
This commit is contained in:
wyj committed 2026-09-06 08:10:29 -04:00
1 parent b69c9cfd45
commit 8cf6106127
4 files changed
+36 -7

No files matched your search

+7 -3
View File
@@ -51,6 +51,8 @@ typedef struct {
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;
@@ -94,15 +96,17 @@ int frame_lens_mesh_build_coarse(FrameLensMesh *mesh, int width, int height,
int frame_lens_mesh_trace(FrameLensMesh *mesh, const SpacetimeSource *spacetime,
const ObserverState *observer,
const GeodesicTraceConfig *trace);
/* Builds one generation of vertex/probe ray requests. Results are installed
* only after the caller has completed the generation's sweep. */
/* 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 the completed generation. Returns the number of newly added
/* 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);
+7 -1
View File
@@ -782,10 +782,16 @@ static int trace_movie_generation(Movie *movie, const Settings *s,
fprintf(stderr, "Ray trace generation %zu: installing endpoints and refining meshes.\n",
generation);
for (size_t f = 0; f < movie->frame_count; ++f) {
/* Frames converge independently; only finish those traced this pass. */
if (movie->frames[f].mesh.sample_count == 0)
continue;
const int added = frame_lens_mesh_finish_generation(&movie->frames[f].mesh,
&s->refinement);
if (added < 0)
if (added < 0) {
fprintf(stderr, "Ray trace generation %zu: frame %zu refinement failed.\n",
generation, movie->frames[f].frame_id);
return -1;
}
total_added += (size_t)added;
if (s->verbose && added > 0)
fprintf(stderr, "Ray trace generation %zu: frame %zu added %d vertices.\n",