obvhs/
ray.rs

1//! A ray in 3D space.
2
3use glam::{Vec3A, vec3a};
4
5/// Computes the inverse of `x` avoiding division by zero.
6pub fn safe_inverse(x: f32) -> f32 {
7    if x.abs() <= f32::EPSILON {
8        x.signum() / f32::EPSILON
9    } else {
10        1.0 / x
11    }
12}
13
14/// A struct representing a ray in 3D space.
15#[derive(Clone, Copy, Debug)]
16#[repr(C)]
17pub struct Ray {
18    /// The starting point of the ray.
19    pub origin: Vec3A,
20    /// The direction vector of the ray.
21    pub direction: Vec3A,
22    /// The inverse of the direction vector components.
23    /// Used to avoid division in ray/aabb tests. Seems to improve performance in
24    /// some cases on the cpu, but not the gpu in some others.
25    pub inv_direction: Vec3A,
26    /// The minimum `t` (distance) value for intersection tests.
27    pub tmin: f32,
28    /// The maximum `t` (distance) value for intersection tests.
29    pub tmax: f32,
30}
31
32impl Ray {
33    /// Creates a new `Ray` with the given origin, direction, and `t` (distance) range.
34    pub fn new(origin: Vec3A, direction: Vec3A, min: f32, max: f32) -> Self {
35        let ray = Ray {
36            origin,
37            direction,
38            inv_direction: vec3a(
39                safe_inverse(direction.x),
40                safe_inverse(direction.y),
41                safe_inverse(direction.z),
42            ),
43            tmin: min,
44            tmax: max,
45        };
46
47        debug_assert!(ray.inv_direction.is_finite());
48        debug_assert!(ray.direction.is_finite());
49        debug_assert!(origin.is_finite());
50
51        ray
52    }
53
54    /// Creates a new infinite `Ray` with the given origin, direction.
55    pub fn new_inf(origin: Vec3A, direction: Vec3A) -> Self {
56        Self::new(origin, direction, 0.0, f32::INFINITY)
57    }
58}
59
60/// A struct representing a hit record in ray tracing.
61/// A `Hit` record contains the IDs of the primitive, geometry and instance that
62/// were hit, as well as the `t` (distance) value at which the hit occurred.
63#[derive(Clone, Copy, Debug)]
64#[repr(C)]
65pub struct RayHit {
66    pub primitive_id: u32,
67    pub geometry_id: u32,
68    pub instance_id: u32,
69    pub t: f32,
70}
71
72pub const INVALID_ID: u32 = u32::MAX;
73
74impl RayHit {
75    /// Creates a new `RayHit` instance representing no hit.
76    pub fn none() -> Self {
77        Self {
78            primitive_id: INVALID_ID,
79            geometry_id: INVALID_ID,
80            instance_id: INVALID_ID,
81            t: f32::INFINITY,
82        }
83    }
84}