box3d_rust/math_functions/
internal.rs1use super::*;
5
6pub fn arbitrary_perp(v: Vec3) -> Vec3 {
8 let p = if v.x < -0.5 || 0.5 < v.x {
12 let a = 0.67;
16 let b = -0.42;
17 Vec3 {
18 x: a * v.y + b * v.z,
19 y: -a * v.x,
20 z: -b * v.x,
21 }
22 } else if v.y < -0.5 || 0.5 < v.y {
23 let a = 0.67;
28 let c = -0.42;
29 Vec3 {
30 x: a * v.y,
31 y: -a * v.x + c * v.z,
32 z: -c * v.y,
33 }
34 } else {
35 debug_assert!(v.z < -0.5 || 0.5 < v.z);
37
38 let a = 0.67;
43 let b = -0.42;
44 Vec3 {
45 x: a * v.z,
46 y: b * v.z,
47 z: -a * v.x - b * v.y,
48 }
49 };
50
51 debug_assert!(length_squared(p) > 0.1);
52 debug_assert!(abs_float(dot(p, v)) < 100.0 * f32::EPSILON);
53
54 normalize(p)
55}
56
57pub fn scalar_triple_product(a: Vec3, b: Vec3, c: Vec3) -> f32 {
59 let d = Vec3 {
60 x: b.y * c.z - b.z * c.y,
61 y: b.z * c.x - b.x * c.z,
62 z: b.x * c.y - b.y * c.x,
63 };
64 a.x * d.x + a.y * d.y + a.z * d.z
65}
66
67pub const SQRT3: f32 = 1.732050808;
69
70pub const BOUNDS3_EMPTY: Aabb = Aabb {
72 lower_bound: Vec3 {
73 x: f32::MAX,
74 y: f32::MAX,
75 z: f32::MAX,
76 },
77 upper_bound: Vec3 {
78 x: -f32::MAX,
79 y: -f32::MAX,
80 z: -f32::MAX,
81 },
82};
83
84pub fn align_up8(x: usize) -> usize {
86 (x + 7) & !7
87}
88
89pub fn modified_cross(a: Vec3, b: Vec3) -> Vec3 {
92 Vec3 {
93 x: a.y * b.z + a.z * b.y,
94 y: a.z * b.x + a.x * b.z,
95 z: a.x * b.y + a.y * b.x,
96 }
97}
98
99pub fn dot2(v1: Vec2, v2: Vec2) -> f32 {
101 v1.x * v2.x + v1.y * v2.y
102}
103
104pub fn length2(v: Vec2) -> f32 {
106 dot2(v, v).sqrt()
107}
108
109pub fn length_squared2(v: Vec2) -> f32 {
111 dot2(v, v)
112}
113
114pub fn add2(a: Vec2, b: Vec2) -> Vec2 {
116 Vec2 {
117 x: a.x + b.x,
118 y: a.y + b.y,
119 }
120}
121
122pub fn sub2(a: Vec2, b: Vec2) -> Vec2 {
124 Vec2 {
125 x: a.x - b.x,
126 y: a.y - b.y,
127 }
128}
129
130pub fn mul_sv2(s: f32, v: Vec2) -> Vec2 {
132 Vec2 {
133 x: s * v.x,
134 y: s * v.y,
135 }
136}
137
138pub fn cross2(a: Vec2, b: Vec2) -> f32 {
140 a.x * b.y - a.y * b.x
141}
142
143pub fn distance_squared2(a: Vec2, b: Vec2) -> f32 {
145 let dx = b.x - a.x;
146 let dy = b.y - a.y;
147 dx * dx + dy * dy
148}
149
150pub fn make_normal_from_points(point1: Vec3, point2: Vec3, point3: Vec3) -> Vec3 {
152 normalize(cross(sub(point2, point1), sub(point3, point1)))
153}
154
155pub fn max_element_index(v: Vec3) -> i32 {
157 if v.x < v.y {
158 if v.y < v.z {
159 2
160 } else {
161 1
162 }
163 } else if v.x < v.z {
164 2
165 } else {
166 0
167 }
168}
169
170pub fn major_axis(v: Vec3) -> i32 {
172 max_element_index(v)
173}
174
175pub fn get_by_index(v: Vec3, index: i32) -> f32 {
177 debug_assert!((0..3).contains(&index));
178 match index {
179 0 => v.x,
180 1 => v.y,
181 2 => v.z,
182 _ => unreachable!(),
183 }
184}
185
186pub fn signed_volume(v1: Vec3, v2: Vec3, v3: Vec3, p: Vec3) -> f32 {
188 let e1 = sub(v2, v1);
189 let e2 = sub(v3, v1);
190 let n = cross(e1, e2);
191 dot(n, sub(p, v1))
192}
193
194pub const TWO_PI: f32 = 6.283185307;
196
197pub fn make_diagonal_matrix(a: f32, b: f32, c: f32) -> Matrix3 {
199 Matrix3 {
200 cx: Vec3 {
201 x: a,
202 y: 0.0,
203 z: 0.0,
204 },
205 cy: Vec3 {
206 x: 0.0,
207 y: b,
208 z: 0.0,
209 },
210 cz: Vec3 {
211 x: 0.0,
212 y: 0.0,
213 z: c,
214 },
215 }
216}
217
218pub fn is_within_segments(result: &SegmentDistanceResult) -> bool {
220 (0.0 <= result.fraction1 && result.fraction1 <= 1.0)
221 && (0.0 <= result.fraction2 && result.fraction2 <= 1.0)
222}
223
224pub fn make_plane_from_normal_and_point(normal: Vec3, point: Vec3) -> Plane {
226 Plane {
227 normal,
228 offset: dot(normal, point),
229 }
230}
231
232pub fn make_plane_from_points(point1: Vec3, point2: Vec3, point3: Vec3) -> Plane {
234 let mut plane = Plane {
235 normal: cross(sub(point2, point1), sub(point3, point1)),
236 offset: 0.0,
237 };
238 plane.normal = normalize(plane.normal);
239 plane.offset = dot(plane.normal, point1);
240 plane
241}
242
243pub fn transform_plane(transform: Transform, plane: Plane) -> Plane {
245 let normal = rotate_vector(transform.q, plane.normal);
246 Plane {
247 normal,
248 offset: plane.offset + dot(normal, transform.p),
249 }
250}
251
252pub fn plane_separation(plane: Plane, point: Vec3) -> f32 {
254 dot(plane.normal, point) - plane.offset
255}
256
257pub fn rotate_inertia(q: Quat, central_inertia: Matrix3) -> Matrix3 {
259 let rotation_matrix = make_matrix_from_quat(q);
260 mul_mm(
261 rotation_matrix,
262 mul_mm(central_inertia, transpose(rotation_matrix)),
263 )
264}
265
266pub fn box_inertia(mass: f32, min: Vec3, max: Vec3) -> Matrix3 {
269 let delta = sub(max, min);
270 let ixx = mass * (delta.y * delta.y + delta.z * delta.z) / 12.0;
271 let iyy = mass * (delta.x * delta.x + delta.z * delta.z) / 12.0;
272 let izz = mass * (delta.x * delta.x + delta.y * delta.y) / 12.0;
273 make_diagonal_matrix(ixx, iyy, izz)
274}
275
276pub fn sphere_inertia(mass: f32, radius: f32) -> Matrix3 {
278 let i = 0.4 * mass * radius * radius;
279 make_diagonal_matrix(i, i, i)
280}
281
282pub fn cylinder_inertia(mass: f32, radius: f32, height: f32) -> Matrix3 {
285 let ixx = mass * (3.0 * radius * radius + height * height) / 12.0;
286 let iyy = 0.5 * mass * radius * radius;
287 make_diagonal_matrix(ixx, iyy, ixx)
288}
289
290#[derive(Debug, Clone, Copy, PartialEq, Default)]
293pub struct Triangle {
294 pub vertices: [Vec3; 3],
295 pub i1: i32,
296 pub i2: i32,
297 pub i3: i32,
298 pub flags: i32,
299}
300
301#[derive(Debug, Clone, Copy, PartialEq)]
304pub struct TrianglePoint {
305 pub point: Vec3,
306 pub feature: crate::manifold::TriangleFeature,
307}
308
309pub fn closest_point_on_triangle(a: Vec3, b: Vec3, c: Vec3, q: Vec3) -> TrianglePoint {
312 use crate::manifold::TriangleFeature;
313
314 let ab = sub(b, a);
316 let ac = sub(c, a);
317 let aq = sub(q, a);
318
319 let d1 = dot(ab, aq);
320 let d2 = dot(ac, aq);
321 if d1 <= 0.0 && d2 <= 0.0 {
322 return TrianglePoint {
323 point: a,
324 feature: TriangleFeature::Vertex1,
325 };
326 }
327
328 let bq = sub(q, b);
330
331 let d3 = dot(ab, bq);
332 let d4 = dot(ac, bq);
333 if d3 > 0.0 && d4 <= d3 {
334 return TrianglePoint {
335 point: b,
336 feature: TriangleFeature::Vertex2,
337 };
338 }
339
340 let vc = d1 * d4 - d3 * d2;
342 if vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0 {
343 let t = d1 / (d1 - d3);
344 return TrianglePoint {
345 point: mul_add(a, t, ab),
346 feature: TriangleFeature::Edge1,
347 };
348 }
349
350 let cq = sub(q, c);
352
353 let d5 = dot(ab, cq);
354 let d6 = dot(ac, cq);
355 if d6 >= 0.0 && d5 <= d6 {
356 return TrianglePoint {
357 point: c,
358 feature: TriangleFeature::Vertex3,
359 };
360 }
361
362 let vb = d5 * d2 - d1 * d6;
364 if vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0 {
365 let t = d2 / (d2 - d6);
366 return TrianglePoint {
367 point: mul_add(a, t, ac),
368 feature: TriangleFeature::Edge3,
369 };
370 }
371
372 let va = d3 * d6 - d5 * d4;
374 if va <= 0.0 && d4 >= d3 && d5 >= d6 {
375 let bc = sub(c, b);
376 let t = (d4 - d3) / ((d4 - d3) + (d5 - d6));
377 return TrianglePoint {
378 point: mul_add(b, t, bc),
379 feature: TriangleFeature::Edge2,
380 };
381 }
382
383 let t1 = vb / (va + vb + vc);
385 let t2 = vc / (va + vb + vc);
386
387 let mut p = mul_add(a, t1, ab);
388 p = mul_add(p, t2, ac);
389 TrianglePoint {
390 point: p,
391 feature: TriangleFeature::TriangleFace,
392 }
393}