@@ -1935,28 +1935,24 @@ geometric_object make_ellipsoid(material_type material, vector3 center, vector3
19351935/* Triangle utilities */
19361936/***************************************************************/
19371937
1938- /* Helper to get a geom_box from a BVH node. */
1939- static geom_box bvh_node_box (const mesh_bvh_node * node ) {
1940- geom_box b ;
1941- b .low = node -> bbox_low ;
1942- b .high = node -> bbox_high ;
1943- return b ;
1944- }
1945-
19461938/* Helper to set a BVH node's bbox from a geom_box. */
19471939static void bvh_node_set_box (mesh_bvh_node * node , const geom_box * box ) {
19481940 node -> bbox_low = box -> low ;
19491941 node -> bbox_high = box -> high ;
19501942}
19511943
1944+ /* Fetch the three vertices of a triangle. */
1945+ static void mesh_triangle_vertices (const mesh * m , int face_id ,
1946+ vector3 * v0 , vector3 * v1 , vector3 * v2 ) {
1947+ * v0 = m -> vertices .items [m -> face_indices [3 * face_id ]];
1948+ * v1 = m -> vertices .items [m -> face_indices [3 * face_id + 1 ]];
1949+ * v2 = m -> vertices .items [m -> face_indices [3 * face_id + 2 ]];
1950+ }
1951+
19521952/* Compute the AABB of a single triangle. */
19531953static void mesh_triangle_bbox (const mesh * m , int face_id , geom_box * box ) {
1954- int i0 = m -> face_indices [3 * face_id ];
1955- int i1 = m -> face_indices [3 * face_id + 1 ];
1956- int i2 = m -> face_indices [3 * face_id + 2 ];
1957- vector3 v0 = m -> vertices .items [i0 ];
1958- vector3 v1 = m -> vertices .items [i1 ];
1959- vector3 v2 = m -> vertices .items [i2 ];
1954+ vector3 v0 , v1 , v2 ;
1955+ mesh_triangle_vertices (m , face_id , & v0 , & v1 , & v2 );
19601956 box -> low .x = fmin (v0 .x , fmin (v1 .x , v2 .x ));
19611957 box -> low .y = fmin (v0 .y , fmin (v1 .y , v2 .y ));
19621958 box -> low .z = fmin (v0 .z , fmin (v1 .z , v2 .z ));
@@ -1967,19 +1963,31 @@ static void mesh_triangle_bbox(const mesh *m, int face_id, geom_box *box) {
19671963
19681964/* Compute the centroid of a triangle. */
19691965static vector3 mesh_triangle_centroid (const mesh * m , int face_id ) {
1970- int i0 = m -> face_indices [3 * face_id ];
1971- int i1 = m -> face_indices [3 * face_id + 1 ];
1972- int i2 = m -> face_indices [3 * face_id + 2 ];
1973- vector3 v0 = m -> vertices .items [i0 ];
1974- vector3 v1 = m -> vertices .items [i1 ];
1975- vector3 v2 = m -> vertices .items [i2 ];
1966+ vector3 v0 , v1 , v2 ;
1967+ mesh_triangle_vertices (m , face_id , & v0 , & v1 , & v2 );
19761968 vector3 c ;
19771969 c .x = (v0 .x + v1 .x + v2 .x ) / 3.0 ;
19781970 c .y = (v0 .y + v1 .y + v2 .y ) / 3.0 ;
19791971 c .z = (v0 .z + v1 .z + v2 .z ) / 3.0 ;
19801972 return c ;
19811973}
19821974
1975+ /* Compute the AABB and centroid of a triangle in one pass. */
1976+ static void mesh_triangle_bbox_centroid (const mesh * m , int face_id ,
1977+ geom_box * box , vector3 * centroid ) {
1978+ vector3 v0 , v1 , v2 ;
1979+ mesh_triangle_vertices (m , face_id , & v0 , & v1 , & v2 );
1980+ box -> low .x = fmin (v0 .x , fmin (v1 .x , v2 .x ));
1981+ box -> low .y = fmin (v0 .y , fmin (v1 .y , v2 .y ));
1982+ box -> low .z = fmin (v0 .z , fmin (v1 .z , v2 .z ));
1983+ box -> high .x = fmax (v0 .x , fmax (v1 .x , v2 .x ));
1984+ box -> high .y = fmax (v0 .y , fmax (v1 .y , v2 .y ));
1985+ box -> high .z = fmax (v0 .z , fmax (v1 .z , v2 .z ));
1986+ centroid -> x = (v0 .x + v1 .x + v2 .x ) / 3.0 ;
1987+ centroid -> y = (v0 .y + v1 .y + v2 .y ) / 3.0 ;
1988+ centroid -> z = (v0 .z + v1 .z + v2 .z ) / 3.0 ;
1989+ }
1990+
19831991/* Compute the surface area of a geom_box. */
19841992static double geom_box_surface_area (const geom_box * b ) {
19851993 double dx = b -> high .x - b -> low .x ;
@@ -2047,7 +2055,9 @@ static int mesh_bvh_build(mesh *m, int *face_ids, int start, int count,
20472055
20482056 double inv_range = MESH_BVH_NUM_BINS / (hi - lo );
20492057 for (int i = 0 ; i < count ; i ++ ) {
2050- vector3 c = mesh_triangle_centroid (m , face_ids [start + i ]);
2058+ geom_box fb ;
2059+ vector3 c ;
2060+ mesh_triangle_bbox_centroid (m , face_ids [start + i ], & fb , & c );
20512061 double val ;
20522062 switch (axis ) {
20532063 case 0 : val = c .x ; break ;
@@ -2058,8 +2068,6 @@ static int mesh_bvh_build(mesh *m, int *face_ids, int start, int count,
20582068 if (bin < 0 ) bin = 0 ;
20592069 if (bin >= MESH_BVH_NUM_BINS ) bin = MESH_BVH_NUM_BINS - 1 ;
20602070 bin_counts [bin ]++ ;
2061- geom_box fb ;
2062- mesh_triangle_bbox (m , face_ids [start + i ], & fb );
20632071 geom_box_union (& bin_boxes [bin ], & bin_boxes [bin ], & fb );
20642072 }
20652073
@@ -2354,8 +2362,25 @@ static int find_closest_face(const mesh *m, vector3 p, double *dist2) {
23542362 }
23552363 } else {
23562364 if (stack_top + 2 > 64 ) continue ;
2357- stack [stack_top ++ ] = node -> left_child ;
2358- stack [stack_top ++ ] = node -> right_child ;
2365+ /* Push the farther child first so the nearer child is popped first,
2366+ giving better pruning of the farther subtree. */
2367+ const mesh_bvh_node * left = & m -> bvh [node -> left_child ];
2368+ const mesh_bvh_node * right = & m -> bvh [node -> right_child ];
2369+ double ldx = fmax (0 , fmax (left -> bbox_low .x - p .x , p .x - left -> bbox_high .x ));
2370+ double ldy = fmax (0 , fmax (left -> bbox_low .y - p .y , p .y - left -> bbox_high .y ));
2371+ double ldz = fmax (0 , fmax (left -> bbox_low .z - p .z , p .z - left -> bbox_high .z ));
2372+ double rdx = fmax (0 , fmax (right -> bbox_low .x - p .x , p .x - right -> bbox_high .x ));
2373+ double rdy = fmax (0 , fmax (right -> bbox_low .y - p .y , p .y - right -> bbox_high .y ));
2374+ double rdz = fmax (0 , fmax (right -> bbox_low .z - p .z , p .z - right -> bbox_high .z ));
2375+ double ld2 = ldx * ldx + ldy * ldy + ldz * ldz ;
2376+ double rd2 = rdx * rdx + rdy * rdy + rdz * rdz ;
2377+ if (ld2 < rd2 ) {
2378+ stack [stack_top ++ ] = node -> right_child ; /* farther pushed first */
2379+ stack [stack_top ++ ] = node -> left_child ;
2380+ } else {
2381+ stack [stack_top ++ ] = node -> left_child ;
2382+ stack [stack_top ++ ] = node -> right_child ;
2383+ }
23592384 }
23602385 }
23612386
0 commit comments