1pub type Vec3 = [f64; 3];
5
6#[inline]
8pub fn add(a: Vec3, b: Vec3) -> Vec3 {
9 [a[0] + b[0], a[1] + b[1], a[2] + b[2]]
10}
11
12#[inline]
14pub fn sub(a: Vec3, b: Vec3) -> Vec3 {
15 [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
16}
17
18#[inline]
20pub fn scale(a: Vec3, s: f64) -> Vec3 {
21 [a[0] * s, a[1] * s, a[2] * s]
22}
23
24#[inline]
26pub fn dot(a: Vec3, b: Vec3) -> f64 {
27 a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
28}
29
30#[inline]
32pub fn cross(a: Vec3, b: Vec3) -> Vec3 {
33 [
34 a[1] * b[2] - a[2] * b[1],
35 a[2] * b[0] - a[0] * b[2],
36 a[0] * b[1] - a[1] * b[0],
37 ]
38}
39
40#[inline]
42pub fn norm(a: Vec3) -> f64 {
43 dot(a, a).sqrt()
44}
45
46#[inline]
48pub fn norm_squared(a: Vec3) -> f64 {
49 dot(a, a)
50}
51
52#[inline]
54pub fn normalize(a: Vec3) -> Vec3 {
55 let n = norm(a);
56 if n < 1e-12 {
57 [0.0, 0.0, 0.0]
58 } else {
59 [a[0] / n, a[1] / n, a[2] / n]
60 }
61}
62
63#[inline]
65pub fn distance(a: Vec3, b: Vec3) -> f64 {
66 norm(sub(a, b))
67}
68
69#[inline]
71pub fn lerp(a: Vec3, b: Vec3, t: f64) -> Vec3 {
72 [
73 a[0] + t * (b[0] - a[0]),
74 a[1] + t * (b[1] - a[1]),
75 a[2] + t * (b[2] - a[2]),
76 ]
77}
78
79#[inline]
81pub fn xy(v: Vec3) -> [f64; 2] {
82 [v[0], v[1]]
83}
84
85#[inline]
87pub fn from_xy(xy: [f64; 2], z: f64) -> Vec3 {
88 [xy[0], xy[1], z]
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn cross_of_basis_axes() {
97 assert_eq!(cross([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]), [0.0, 0.0, 1.0]);
98 }
99
100 #[test]
101 fn norm_of_unit_diagonal() {
102 let n = norm([1.0, 1.0, 1.0]);
103 assert!((n - 3f64.sqrt()).abs() < 1e-12);
104 }
105
106 #[test]
107 fn xy_roundtrip() {
108 let v: Vec3 = [1.0, 2.0, 3.0];
109 assert_eq!(xy(v), [1.0, 2.0]);
110 assert_eq!(from_xy(xy(v), v[2]), v);
111 }
112}