Skip to content

Commit d9043b6

Browse files
committed
Eliminate redundant BVH build and point_in_mesh fallback
1. make_mesh_with_center: shift vertices before calling init_mesh so the BVH is only built once (was building twice when center was specified). 2. intersect_line_segment_with_mesh: determine inside/outside at the segment start from the full intersection list parity (count crossings before parameter 'a') instead of calling point_in_mesh as a fallback. Eliminates millions of extra ray casts during subpixel smoothing. ~20% faster set_epsilon on the Utah teapot (28.6s → 22.9s).
1 parent 573183d commit d9043b6

1 file changed

Lines changed: 34 additions & 44 deletions

File tree

utils/geom.c

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2542,27 +2542,27 @@ static double intersect_line_segment_with_mesh(const mesh *m, vector3 p, vector3
25422542
double slist[MESH_MAX_INTERSECTIONS];
25432543
int num = intersect_line_with_mesh(m, p, d, slist);
25442544

2545-
/* Find first intersection > a. */
2546-
int na = -1;
2547-
for (int i = 0; na == -1 && i < num; i++)
2548-
if (slist[i] > a) na = i;
2549-
if (na == -1) {
2550-
/* No intersections after a. Check if p+a*d is inside. */
2551-
vector3 pt = vector3_plus(p, vector3_scale(a, d));
2552-
if (point_in_mesh(m, pt))
2553-
return b - a;
2554-
return 0.0;
2555-
}
2556-
2557-
/* Determine if we start inside (even-odd parity). */
2558-
int inside = ((na % 2) == 0) ? 0 : 1;
2545+
/* The sorted intersection list gives all surface crossings along the
2546+
full ray. At t=-inf we are outside, so the parity after k crossings
2547+
tells us inside/outside: odd = inside, even = outside.
2548+
2549+
Count crossings before 'a' to determine if we start inside [a,b].
2550+
Then walk crossings within [a,b] toggling parity and accumulating
2551+
interior length. No point_in_mesh fallback needed. */
2552+
int crossings_before_a = 0;
2553+
for (int i = 0; i < num && slist[i] <= a; i++)
2554+
crossings_before_a++;
2555+
2556+
int inside = (crossings_before_a % 2 == 1);
25592557
double last_s = a, ds = 0.0;
2560-
for (int i = na; i < num; i++) {
2561-
double this_s = fmin(b, slist[i]);
2562-
if (inside) ds += (this_s - last_s);
2563-
if (b <= slist[i]) break;
2564-
inside = 1 - inside;
2565-
last_s = this_s;
2558+
for (int i = crossings_before_a; i < num; i++) {
2559+
if (slist[i] >= b) {
2560+
if (inside) ds += (b - last_s);
2561+
break;
2562+
}
2563+
if (inside) ds += (slist[i] - last_s);
2564+
inside = !inside;
2565+
last_s = slist[i];
25662566
}
25672567
if (inside && last_s < b) ds += (b - last_s);
25682568
return ds > 0.0 ? ds : 0.0;
@@ -2752,34 +2752,24 @@ geometric_object make_mesh_with_center(material_type material, vector3 center,
27522752
CHECK(m->face_indices, "out of memory");
27532753
memcpy(m->face_indices, triangles, 3 * num_triangles * sizeof(int));
27542754

2755-
/* Initialize derived data (normals, BVH, etc.). */
2756-
init_mesh(&o);
2757-
2758-
/* Set center. */
2759-
if (mesh_is_auto_center(center))
2760-
o.center = m->centroid;
2761-
else {
2762-
/* Shift vertices so centroid equals center. */
2763-
vector3 shift = vector3_minus(center, m->centroid);
2755+
/* Shift vertices before init so BVH is only built once. */
2756+
if (!mesh_is_auto_center(center)) {
2757+
/* Compute centroid to determine the shift. */
2758+
vector3 centroid = {0, 0, 0};
2759+
for (int i = 0; i < num_vertices; i++)
2760+
centroid = vector3_plus(centroid, m->vertices.items[i]);
2761+
centroid = vector3_scale(1.0 / num_vertices, centroid);
2762+
vector3 shift = vector3_minus(center, centroid);
27642763
for (int i = 0; i < num_vertices; i++)
27652764
m->vertices.items[i] = vector3_plus(m->vertices.items[i], shift);
2766-
m->centroid = center;
2767-
o.center = center;
2768-
2769-
/* Rebuild BVH after shifting vertices. */
2770-
free(m->bvh);
2771-
free(m->bvh_face_ids);
2772-
m->bvh_face_ids = (int *)malloc(m->num_faces * sizeof(int));
2773-
CHECK(m->bvh_face_ids, "out of memory");
2774-
for (int i = 0; i < m->num_faces; i++)
2775-
m->bvh_face_ids[i] = i;
2776-
int max_nodes = 2 * m->num_faces;
2777-
m->bvh = (mesh_bvh_node *)malloc(max_nodes * sizeof(mesh_bvh_node));
2778-
CHECK(m->bvh, "out of memory");
2779-
m->num_bvh_nodes = 0;
2780-
mesh_bvh_build(m, m->bvh_face_ids, 0, m->num_faces, m->bvh, &m->num_bvh_nodes);
27812765
}
27822766

2767+
/* Initialize derived data (normals, closure check, BVH). */
2768+
init_mesh(&o);
2769+
2770+
/* Set center from the (possibly shifted) centroid. */
2771+
o.center = m->centroid;
2772+
27832773
return o;
27842774
}
27852775

0 commit comments

Comments
 (0)