Frame: localize shadow boundary refinement
This commit is contained in:
1 parent
e47005ea6b
commit
09923b9b18
2 files changed
+247
-69
No files matched your search
@@ -7,6 +7,56 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int mesh_has_hanging_vertex(const FrameLensMesh *mesh) {
|
||||
for (size_t triangle = 0; triangle < mesh->triangle_count; ++triangle)
|
||||
for (size_t side = 0; side < 3; ++side) {
|
||||
const LensVertex *a = &mesh->vertices[mesh->triangles[triangle].vertex[side]];
|
||||
const LensVertex *b =
|
||||
&mesh->vertices[mesh->triangles[triangle].vertex[(side + 1) % 3]];
|
||||
const double dx = b->image_x - a->image_x;
|
||||
const double dy = b->image_y - a->image_y;
|
||||
const double length_squared = dx * dx + dy * dy;
|
||||
for (size_t vertex = 0; vertex < mesh->vertex_count; ++vertex) {
|
||||
if (vertex == mesh->triangles[triangle].vertex[side] ||
|
||||
vertex == mesh->triangles[triangle].vertex[(side + 1) % 3])
|
||||
continue;
|
||||
const LensVertex *p = &mesh->vertices[vertex];
|
||||
const double px = p->image_x - a->image_x;
|
||||
const double py = p->image_y - a->image_y;
|
||||
const double cross = px * dy - py * dx;
|
||||
const double position = (px * dx + py * dy) / length_squared;
|
||||
if (fabs(cross) <= 1e-12 * length_squared && position > 1e-12 &&
|
||||
position < 1.0 - 1e-12)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mesh_has_same_winding_shared_edge(const FrameLensMesh *mesh) {
|
||||
for (size_t left_triangle = 0; left_triangle < mesh->triangle_count;
|
||||
++left_triangle)
|
||||
for (size_t left_side = 0; left_side < 3; ++left_side) {
|
||||
const size_t from = mesh->triangles[left_triangle].vertex[left_side];
|
||||
const size_t to =
|
||||
mesh->triangles[left_triangle].vertex[(left_side + 1) % 3];
|
||||
for (size_t right_triangle = left_triangle + 1;
|
||||
right_triangle < mesh->triangle_count; ++right_triangle)
|
||||
for (size_t right_side = 0; right_side < 3; ++right_side) {
|
||||
const size_t other_from =
|
||||
mesh->triangles[right_triangle].vertex[right_side];
|
||||
const size_t other_to =
|
||||
mesh->triangles[right_triangle].vertex[(right_side + 1) % 3];
|
||||
if ((from == other_from && to == other_to) ||
|
||||
(from == other_to && to == other_from)) {
|
||||
if (from == other_from && to == other_to)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const int width = 100, height = 100;
|
||||
const double test_exposure = 1e-3;
|
||||
@@ -213,6 +263,72 @@ int main(void) {
|
||||
goto done;
|
||||
}
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
/* A capture/escape discontinuity is a shadow boundary, not a smooth map
|
||||
* error: request all three midpoint rays and red-refine in one generation. */
|
||||
if (frame_lens_mesh_build_coarse(&adaptive_mesh, width, height, 100, 30.0))
|
||||
goto done;
|
||||
adaptive_mesh.triangle_count = 1;
|
||||
for (size_t i = 0; i < adaptive_mesh.vertex_count; ++i) {
|
||||
adaptive_mesh.vertices[i].traced = 1;
|
||||
adaptive_mesh.vertices[i].status = RAY_ENDPOINT_ESCAPED;
|
||||
adaptive_mesh.vertices[i].n_infinity[0] = 1.0;
|
||||
}
|
||||
adaptive_mesh.vertices[0].status = RAY_ENDPOINT_CAPTURED;
|
||||
refine.max_level = 1;
|
||||
refine.angle_absolute_rad = 3.14159265358979323846;
|
||||
refine.angle_relative = 1e6;
|
||||
refine.jacobian_minimum = 1e-12;
|
||||
if (frame_lens_mesh_prepare_generation(&adaptive_mesh, &refine) != 3) {
|
||||
fputs("shadow-boundary red-probe setup regression failed\n", stderr);
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
goto done;
|
||||
}
|
||||
for (size_t i = 0; i < adaptive_mesh.sample_count; ++i)
|
||||
if (frame_lens_mesh_install_sample(&adaptive_mesh, i, &bent_probe)) {
|
||||
fputs("shadow-boundary red-probe installation regression failed\n", stderr);
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
goto done;
|
||||
}
|
||||
if (frame_lens_mesh_finish_generation(&adaptive_mesh, &refine) != 3 ||
|
||||
adaptive_mesh.vertex_count != 7 || adaptive_mesh.triangle_count != 4) {
|
||||
fputs("shadow-boundary red-refinement regression failed\n", stderr);
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
goto done;
|
||||
}
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
/* Two shadow leaves can force two edges of an escaped neighbour. That
|
||||
* neighbour must use a local three-child blue split, not create a third
|
||||
* requested edge that spreads red refinement farther outward. */
|
||||
if (frame_lens_mesh_build_coarse(&adaptive_mesh, 200, 100, 100, 30.0))
|
||||
goto done;
|
||||
adaptive_mesh.triangle_count = 3;
|
||||
for (size_t i = 0; i < adaptive_mesh.vertex_count; ++i) {
|
||||
adaptive_mesh.vertices[i].traced = 1;
|
||||
adaptive_mesh.vertices[i].status = RAY_ENDPOINT_ESCAPED;
|
||||
adaptive_mesh.vertices[i].n_infinity[0] = 1.0;
|
||||
}
|
||||
adaptive_mesh.vertices[3].status = RAY_ENDPOINT_CAPTURED;
|
||||
adaptive_mesh.vertices[5].status = RAY_ENDPOINT_CAPTURED;
|
||||
if (frame_lens_mesh_prepare_generation(&adaptive_mesh, &refine) != 6) {
|
||||
fputs("shadow-boundary blue-neighbour probe setup regression failed\n", stderr);
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
goto done;
|
||||
}
|
||||
for (size_t i = 0; i < adaptive_mesh.sample_count; ++i)
|
||||
if (frame_lens_mesh_install_sample(&adaptive_mesh, i, &bent_probe)) {
|
||||
fputs("shadow-boundary blue-neighbour probe installation regression failed\n", stderr);
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
goto done;
|
||||
}
|
||||
if (frame_lens_mesh_finish_generation(&adaptive_mesh, &refine) != 6 ||
|
||||
adaptive_mesh.vertex_count != 12 || adaptive_mesh.triangle_count != 11 ||
|
||||
mesh_has_hanging_vertex(&adaptive_mesh) ||
|
||||
mesh_has_same_winding_shared_edge(&adaptive_mesh)) {
|
||||
fputs("shadow-boundary blue-neighbour refinement regression failed\n", stderr);
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
goto done;
|
||||
}
|
||||
frame_lens_mesh_destroy(&adaptive_mesh);
|
||||
const RayEndpoint flat_probe = {.n_infinity = {1.0, 0.0, 0.0},
|
||||
.frequency_ratio = 1.0,
|
||||
.status = RAY_ENDPOINT_ESCAPED};
|
||||
|
||||
Reference in new issue
Block a user