box3d_rust/math_functions/
transform.rs1use super::*;
5
6#[cfg(feature = "double-precision")]
7type PosScalar = f64;
8#[cfg(not(feature = "double-precision"))]
9type PosScalar = f32;
10
11pub fn mul_transforms(a: Transform, b: Transform) -> Transform {
15 Transform {
16 p: add(rotate_vector(a.q, b.p), a.p),
17 q: mul_quat(a.q, b.q),
18 }
19}
20
21pub fn inv_mul_transforms(a: Transform, b: Transform) -> Transform {
25 Transform {
26 p: inv_rotate_vector(a.q, sub(b.p, a.p)),
27 q: inv_mul_quat(a.q, b.q),
28 }
29}
30
31pub fn invert_transform(t: Transform) -> Transform {
33 Transform {
34 p: inv_rotate_vector(t.q, neg(t.p)),
35 q: conjugate(t.q),
36 }
37}
38
39pub fn transform_point(t: Transform, v: Vec3) -> Vec3 {
41 let rv = rotate_vector(t.q, v);
42 add(rv, t.p)
43}
44
45pub fn inv_transform_point(t: Transform, v: Vec3) -> Vec3 {
47 inv_rotate_vector(t.q, sub(v, t.p))
48}
49
50pub fn to_pos(v: Vec3) -> Pos {
56 Pos {
57 x: v.x as PosScalar,
58 y: v.y as PosScalar,
59 z: v.z as PosScalar,
60 }
61}
62
63pub fn to_vec3(p: Pos) -> Vec3 {
65 Vec3 {
66 x: p.x as f32,
67 y: p.y as f32,
68 z: p.z as f32,
69 }
70}
71
72#[cfg(feature = "double-precision")]
77pub fn round_down_float(x: f64) -> f32 {
78 let f = x as f32;
79 if f as f64 > x {
80 next_after_f32(f, f32::MIN)
81 } else {
82 f
83 }
84}
85
86#[cfg(feature = "double-precision")]
88pub fn round_up_float(x: f64) -> f32 {
89 let f = x as f32;
90 if (f as f64) < x {
91 next_after_f32(f, f32::MAX)
92 } else {
93 f
94 }
95}
96
97#[cfg(not(feature = "double-precision"))]
98pub fn round_down_float(x: f64) -> f32 {
99 x as f32
100}
101
102#[cfg(not(feature = "double-precision"))]
103pub fn round_up_float(x: f64) -> f32 {
104 x as f32
105}
106
107#[cfg(feature = "double-precision")]
109fn next_after_f32(from: f32, to: f32) -> f32 {
110 if from.is_nan() || to.is_nan() {
111 return f32::NAN;
112 }
113 if from == to {
114 return to;
115 }
116 if from == 0.0 {
117 return if to > 0.0 {
118 f32::from_bits(1)
119 } else {
120 -f32::from_bits(1)
121 };
122 }
123 let bits = from.to_bits();
124 let next = if (from < to) == (from > 0.0) {
125 bits + 1
126 } else {
127 bits - 1
128 };
129 f32::from_bits(next)
130}
131
132pub fn sub_pos(a: Pos, b: Pos) -> Vec3 {
134 Vec3 {
135 x: (a.x - b.x) as f32,
136 y: (a.y - b.y) as f32,
137 z: (a.z - b.z) as f32,
138 }
139}
140
141pub fn offset_pos(p: Pos, d: Vec3) -> Pos {
143 Pos {
144 x: p.x + d.x as PosScalar,
145 y: p.y + d.y as PosScalar,
146 z: p.z + d.z as PosScalar,
147 }
148}
149
150pub fn lerp_position(a: Pos, b: Pos, t: f32) -> Pos {
152 Pos {
153 x: (1.0 - t) as PosScalar * a.x + t as PosScalar * b.x,
154 y: (1.0 - t) as PosScalar * a.y + t as PosScalar * b.y,
155 z: (1.0 - t) as PosScalar * a.z + t as PosScalar * b.z,
156 }
157}
158
159pub fn transform_world_point(t: WorldTransform, p: Vec3) -> Pos {
161 let r = rotate_vector(t.q, p);
162 Pos {
163 x: t.p.x + r.x as PosScalar,
164 y: t.p.y + r.y as PosScalar,
165 z: t.p.z + r.z as PosScalar,
166 }
167}
168
169pub fn inv_transform_world_point(t: WorldTransform, p: Pos) -> Vec3 {
171 let d = Vec3 {
172 x: (p.x - t.p.x) as f32,
173 y: (p.y - t.p.y) as f32,
174 z: (p.z - t.p.z) as f32,
175 };
176 inv_rotate_vector(t.q, d)
177}
178
179pub fn inv_mul_world_transforms(a: WorldTransform, b: WorldTransform) -> Transform {
181 let d = Vec3 {
182 x: (b.p.x - a.p.x) as f32,
183 y: (b.p.y - a.p.y) as f32,
184 z: (b.p.z - a.p.z) as f32,
185 };
186 Transform {
187 q: inv_mul_quat(a.q, b.q),
188 p: inv_rotate_vector(a.q, d),
189 }
190}
191
192pub fn mul_world_transforms(a: WorldTransform, b: Transform) -> WorldTransform {
194 let r = rotate_vector(a.q, b.p);
195 WorldTransform {
196 q: mul_quat(a.q, b.q),
197 p: Pos {
198 x: a.p.x + r.x as PosScalar,
199 y: a.p.y + r.y as PosScalar,
200 z: a.p.z + r.z as PosScalar,
201 },
202 }
203}
204
205pub fn to_relative_transform(t: WorldTransform, base: Pos) -> Transform {
207 Transform {
208 q: t.q,
209 p: Vec3 {
210 x: (t.p.x - base.x) as f32,
211 y: (t.p.y - base.y) as f32,
212 z: (t.p.z - base.z) as f32,
213 },
214 }
215}
216
217pub fn make_world_transform(t: Transform) -> WorldTransform {
219 WorldTransform {
220 p: to_pos(t.p),
221 q: t.q,
222 }
223}
224
225pub fn offset_aabb(local_box: Aabb, origin: Pos) -> Aabb {
229 Aabb {
230 lower_bound: Vec3 {
231 x: round_down_float(origin.x as f64 + local_box.lower_bound.x as f64),
232 y: round_down_float(origin.y as f64 + local_box.lower_bound.y as f64),
233 z: round_down_float(origin.z as f64 + local_box.lower_bound.z as f64),
234 },
235 upper_bound: Vec3 {
236 x: round_up_float(origin.x as f64 + local_box.upper_bound.x as f64),
237 y: round_up_float(origin.y as f64 + local_box.upper_bound.y as f64),
238 z: round_up_float(origin.z as f64 + local_box.upper_bound.z as f64),
239 },
240 }
241}