1use crate::math_functions::{
11 abs_float, clamp_float, length, max_float, min_float, mul_sv, sub, Aabb, Vec3,
12};
13
14pub fn perimeter(a: Aabb) -> f32 {
19 let wx = a.upper_bound.x - a.lower_bound.x;
20 let wy = a.upper_bound.y - a.lower_bound.y;
21 let wz = a.upper_bound.z - a.lower_bound.z;
22 2.0 * (wx * wz + wy * wx + wz * wy)
23}
24
25pub fn enlarge_aabb(a: &mut Aabb, b: Aabb) -> bool {
29 let mut changed = false;
30 if b.lower_bound.x < a.lower_bound.x {
31 a.lower_bound.x = b.lower_bound.x;
32 changed = true;
33 }
34
35 if b.lower_bound.y < a.lower_bound.y {
36 a.lower_bound.y = b.lower_bound.y;
37 changed = true;
38 }
39
40 if b.lower_bound.z < a.lower_bound.z {
41 a.lower_bound.z = b.lower_bound.z;
42 changed = true;
43 }
44
45 if a.upper_bound.x < b.upper_bound.x {
46 a.upper_bound.x = b.upper_bound.x;
47 changed = true;
48 }
49
50 if a.upper_bound.y < b.upper_bound.y {
51 a.upper_bound.y = b.upper_bound.y;
52 changed = true;
53 }
54
55 if a.upper_bound.z < b.upper_bound.z {
56 a.upper_bound.z = b.upper_bound.z;
57 changed = true;
58 }
59
60 changed
61}
62
63pub fn farthest_point_on_aabb(b: Aabb, p: Vec3) -> Vec3 {
66 Vec3 {
67 x: if (p.x - b.lower_bound.x) > (b.upper_bound.x - p.x) {
68 b.lower_bound.x
69 } else {
70 b.upper_bound.x
71 },
72 y: if (p.y - b.lower_bound.y) > (b.upper_bound.y - p.y) {
73 b.lower_bound.y
74 } else {
75 b.upper_bound.y
76 },
77 z: if (p.z - b.lower_bound.z) > (b.upper_bound.z - p.z) {
78 b.lower_bound.z
79 } else {
80 b.upper_bound.z
81 },
82 }
83}
84
85fn clip_slab(
89 ray_component: f32,
90 ray_start: f32,
91 box_min: f32,
92 box_max: f32,
93 t_min: &mut f32,
94 t_max: &mut f32,
95) -> bool {
96 if abs_float(ray_component) < f32::EPSILON {
97 if ray_start < box_min || ray_start > box_max {
99 return false;
100 }
101 } else {
102 let mut t1 = (box_min - ray_start) / ray_component;
104 let mut t2 = (box_max - ray_start) / ray_component;
105
106 if t1 > t2 {
108 core::mem::swap(&mut t1, &mut t2);
109 }
110
111 *t_min = max_float(*t_min, t1);
113 *t_max = min_float(*t_max, t2);
114
115 if *t_min > *t_max {
117 return false;
118 }
119 }
120 true
121}
122
123pub fn ray_cast_aabb(
130 a: Aabb,
131 p1: Vec3,
132 p2: Vec3,
133 min_fraction: &mut f32,
134 max_fraction: &mut f32,
135) -> bool {
136 let d = sub(p2, p1);
138 let ray_length = length(d);
139
140 if ray_length < f32::EPSILON {
142 if p1.x >= a.lower_bound.x
144 && p1.x <= a.upper_bound.x
145 && p1.y >= a.lower_bound.y
146 && p1.y <= a.upper_bound.y
147 && p1.z >= a.lower_bound.z
148 && p1.z <= a.upper_bound.z
149 {
150 *min_fraction = 0.0;
151 *max_fraction = 0.0;
152 return true;
153 }
154
155 return false;
156 }
157
158 let ray_dir = mul_sv(1.0 / ray_length, d);
159
160 let mut t_min = 0.0;
162 let mut t_max = ray_length;
163
164 if !clip_slab(
165 ray_dir.x,
166 p1.x,
167 a.lower_bound.x,
168 a.upper_bound.x,
169 &mut t_min,
170 &mut t_max,
171 ) {
172 return false;
173 }
174
175 if !clip_slab(
176 ray_dir.y,
177 p1.y,
178 a.lower_bound.y,
179 a.upper_bound.y,
180 &mut t_min,
181 &mut t_max,
182 ) {
183 return false;
184 }
185
186 if !clip_slab(
187 ray_dir.z,
188 p1.z,
189 a.lower_bound.z,
190 a.upper_bound.z,
191 &mut t_min,
192 &mut t_max,
193 ) {
194 return false;
195 }
196
197 if t_max < 0.0 {
199 return false;
200 }
201
202 *min_fraction = clamp_float(t_min / ray_length, 0.0, 1.0);
204 *max_fraction = clamp_float(t_max / ray_length, 0.0, 1.0);
205
206 true
207}