use godot::{ classes::{PhysicsRayQueryParameters3D, World3D}, prelude::*, }; pub fn cast_ray( from: Vector3, to: Vector3, world: &Option>, exclude: &Array, ) -> Option { let ray = PhysicsRayQueryParameters3D::create(from, to); if let Some(mut ray) = ray { ray.set_collision_mask(0b1111); ray.set_hit_back_faces(false); ray.set_hit_from_inside(false); ray.set_collide_with_bodies(true); ray.set_exclude(&exclude); if let Some(world) = world && let Some(mut space) = world.get_direct_space_state() { let results = space.intersect_ray(&ray); if let Some(position) = results.get("position") && let Some(collider) = results.get("collider") && let Some(normal) = results.get("normal") { Some(RaycastResult { position: Vector3::from_variant(&position), normal: Vector3::from_variant(&normal), collider: Gd::from_variant(&collider), }) } else { None } } else { None } } else { None } } pub fn shotgun_ray( from: Vector3, to: Vector3, up: Vector3, world: &Option>, exclude: &Array, density: u8, angle: f32, distance: f32, ) -> Vec { let mut results = Vec::new(); let original_dir = (to - from).normalized(); let step = angle / density as f32; let up = up.normalized(); let right = original_dir.cross(up).normalized(); for y in 0..density { let y_rot = -(angle / 2.) + step * y as f32; for x in 0..density { let x_rot = -(angle / 2.) + step * x as f32; let dir = original_dir.rotated(up, x_rot).rotated(right, y_rot); let to = from + dir * distance; if let Some(res) = cast_ray(from, to, world, exclude) { results.push(res); } } } results } #[derive(Debug, Clone)] pub struct RaycastResult { pub position: Vector3, pub normal: Vector3, pub collider: Gd, }