| 66 | } |
| 67 | if node.count > 0 { |
| 68 | let range = node.start as usize..(node.start + node.count) as usize; |
| 69 | result.extend(self.order[range].iter().map(|&i| i as usize)); |
| 70 | } else { |
| 71 | stack.push(node.left as usize); |
| 72 | stack.push(node.right as usize); |
| 73 | } |
| 74 | } |
| 75 | result |
| 76 | } |
| 77 | |
| 78 | /// Find the nearest cached solid-polyline hit along a ray. The BVH rejects |
| 79 | /// distant objects before `eligible` is called, so visibility/opacity |
| 80 | /// checks and polyline tests scale with ray-local candidates rather than |
| 81 | /// every object in the document. |
| 82 | pub(crate) fn nearest_filled_polyline_hit(&self, origin: DVec3, direction: DVec3, mut eligible: impl FnMut(usize) -> bool) -> Option<DVec3> { |
| 83 | if self.nodes.is_empty() || !origin.is_finite() || !direction.is_finite() || direction.length_squared() <= f64::EPSILON { |
| 84 | return None; |
| 85 | } |
| 86 | |
| 87 | let mut stack = vec![0usize]; |
| 88 | let mut nearest_distance = f64::INFINITY; |
| 89 | while let Some(node_index) = stack.pop() { |
| 90 | let node = self.nodes[node_index]; |
| 91 | if !ray_box(origin, direction, node.min, node.max, nearest_distance) { |
| 92 | continue; |
| 93 | } |
| 94 | if node.count == 0 { |
| 95 | stack.push(node.left as usize); |
| 96 | stack.push(node.right as usize); |
| 97 | continue; |
| 98 | } |
| 99 | |
| 100 | let range = node.start as usize..(node.start + node.count) as usize; |
| 101 | for &object_index in &self.order[range] { |
| 102 | let object_index = object_index as usize; |
| 103 | let Some(Some(polyline)) = self.filled_polylines.get(object_index) else { |
| 104 | continue; |
| 105 | }; |
| 106 | let Some(&(min, max)) = self.bboxes.get(object_index) else { |
| 107 | continue; |
| 108 | }; |
| 109 | if !ray_box(origin, direction, min, max, nearest_distance) || !eligible(object_index) { |
| 110 | continue; |
| 111 | } |
| 112 | let Some(distance) = polyline.ray_distance(origin, direction) else { |
| 113 | continue; |
| 114 | }; |
| 115 | if distance < nearest_distance { |
| 116 | nearest_distance = distance; |
| 117 | } |