MCPcopy Create free account
hub / github.com/Bloom-Engine/engine / raycast_scene

Function raycast_scene

native/shared/src/picking.rs:80–147  ·  view source on GitHub ↗

Raycast against all visible scene nodes. Returns the closest hit.

(
    scene: &SceneGraph,
    origin: &[f32; 3],
    direction: &[f32; 3],
)

Source from the content-addressed store, hash-verified

78
79/// Raycast against all visible scene nodes. Returns the closest hit.
80pub fn raycast_scene(
81 scene: &SceneGraph,
82 origin: &[f32; 3],
83 direction: &[f32; 3],
84) -> PickResult {
85 let mut best = PickResult::miss();
86 let mut best_dist = f32::MAX;
87
88 for (handle, node) in scene.nodes.iter() {
89 if !node.visible || node.indices.is_empty() {
90 continue;
91 }
92
93 // Transform ray into node's local space via inverse transform
94 let inv_transform = mat4_inverse_local(&node.transform);
95 let local_origin = mat4_transform_point(&inv_transform, origin);
96 let local_dir = mat4_transform_dir(&inv_transform, direction);
97
98 // Test against all triangles
99 for tri in node.indices.chunks(3) {
100 if tri.len() < 3 { continue; }
101 let v0 = &node.vertices[tri[0] as usize];
102 let v1 = &node.vertices[tri[1] as usize];
103 let v2 = &node.vertices[tri[2] as usize];
104
105 if let Some((t, u, v)) = ray_triangle_intersection(
106 &local_origin, &local_dir,
107 &v0.position, &v1.position, &v2.position,
108 ) {
109 if t > 0.0 && t < best_dist {
110 best_dist = t;
111
112 // Compute hit point in world space
113 let hit_local = [
114 local_origin[0] + local_dir[0] * t,
115 local_origin[1] + local_dir[1] * t,
116 local_origin[2] + local_dir[2] * t,
117 ];
118 let hit_world = mat4_transform_point(&node.transform, &hit_local);
119
120 // Interpolate normal
121 let w = 1.0 - u - v;
122 let normal = [
123 v0.normal[0] * w + v1.normal[0] * u + v2.normal[0] * v,
124 v0.normal[1] * w + v1.normal[1] * u + v2.normal[1] * v,
125 v0.normal[2] * w + v1.normal[2] * u + v2.normal[2] * v,
126 ];
127 let nl = (normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]).sqrt();
128 let normal = if nl > 1e-6 {
129 [normal[0]/nl, normal[1]/nl, normal[2]/nl]
130 } else {
131 [0.0, 1.0, 0.0]
132 };
133
134 best = PickResult {
135 hit: true,
136 handle,
137 distance: t,

Callers 4

bloom_scene_pickFunction · 0.85
bloom_scene_pickFunction · 0.85
bloom_scene_pickFunction · 0.85
bloom_scene_pickFunction · 0.85

Calls 5

mat4_inverse_localFunction · 0.85
mat4_transform_dirFunction · 0.85
iterMethod · 0.80
mat4_transform_pointFunction · 0.70

Tested by

no test coverage detected