@@ -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