1use crate::rot3::{DRot3, Rot3};
4use core::ops::{Mul, MulAssign};
5
6macro_rules! impl_pose3 {
8 ($Pose3:ident, $Rot3:ident, $Real:ty, $Vec3:ty, $Mat4: ty $(, #[$attr:meta])*) => {
9 #[doc = concat!("A 3D pose (rotation + translation), representing a rigid body transformation (", stringify!($Real), " precision).")]
10 #[derive(Copy, Clone, Debug, PartialEq)]
11 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12 #[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
13 $(#[$attr])*
14 pub struct $Pose3 {
15 pub rotation: $Rot3,
17 pub translation: $Vec3,
19 }
20
21 impl $Pose3 {
22 pub const IDENTITY: Self = Self {
24 rotation: $Rot3::IDENTITY,
25 translation: <$Vec3>::ZERO,
26 };
27
28 #[inline]
30 pub fn identity() -> Self {
31 Self::IDENTITY
32 }
33
34 #[inline]
36 pub fn from_translation(translation: $Vec3) -> Self {
37 Self {
38 rotation: $Rot3::IDENTITY,
39 translation,
40 }
41 }
42
43 #[inline]
45 pub fn translation(x: $Real, y: $Real, z: $Real) -> Self {
46 Self::from_translation(<$Vec3>::new(x, y, z))
47 }
48
49 #[inline]
51 pub fn from_rotation(rotation: $Rot3) -> Self {
52 Self {
53 rotation,
54 translation: <$Vec3>::ZERO,
55 }
56 }
57
58 #[inline]
60 pub fn from_parts(translation: $Vec3, rotation: $Rot3) -> Self {
61 Self {
62 rotation,
63 translation,
64 }
65 }
66
67 #[inline]
69 pub fn new(translation: $Vec3, axisangle: $Vec3) -> Self {
70 let rotation = $Rot3::from_scaled_axis(axisangle.into());
71 Self {
72 rotation,
73 translation,
74 }
75 }
76
77 #[inline]
79 pub fn rotation(axisangle: $Vec3) -> Self {
80 Self {
81 rotation: $Rot3::from_scaled_axis(axisangle.into()),
82 translation: <$Vec3>::ZERO,
83 }
84 }
85
86 #[inline]
88 pub fn prepend_translation(self, translation: $Vec3) -> Self {
89 Self {
90 rotation: self.rotation,
91 translation: self.translation + self.rotation * translation,
92 }
93 }
94
95 #[inline]
97 pub fn append_translation(self, translation: $Vec3) -> Self {
98 Self {
99 rotation: self.rotation,
100 translation: self.translation + translation,
101 }
102 }
103
104 #[inline]
106 pub fn inverse(&self) -> Self {
107 let inv_rot = self.rotation.inverse();
108 Self {
109 rotation: inv_rot,
110 translation: inv_rot * (-self.translation),
111 }
112 }
113
114 #[inline]
116 pub fn inv_mul(&self, rhs: &Self) -> Self {
117 let inv_rot1 = self.rotation.inverse();
118 let tr_12 = rhs.translation - self.translation;
119 $Pose3 {
120 translation: inv_rot1 * tr_12,
121 rotation: inv_rot1 * rhs.rotation,
122 }
123 }
124
125 #[inline]
129 pub fn transform_point(&self, p: $Vec3) -> $Vec3 {
130 self.rotation * p + self.translation
131 }
132
133 #[inline]
137 pub fn transform_vector(&self, v: $Vec3) -> $Vec3 {
138 self.rotation * v
139 }
140
141 #[inline]
143 pub fn inverse_transform_point(&self, p: $Vec3) -> $Vec3 {
144 self.rotation.inverse() * (p - self.translation)
145 }
146
147 #[inline]
149 pub fn inverse_transform_vector(&self, v: $Vec3) -> $Vec3 {
150 self.rotation.inverse() * v
151 }
152
153 #[inline]
157 pub fn lerp(&self, other: &Self, t: $Real) -> Self {
158 Self {
159 rotation: self.rotation.slerp(other.rotation, t),
160 translation: self.translation.lerp(other.translation, t),
161 }
162 }
163
164 #[inline]
166 pub fn is_finite(&self) -> bool {
167 self.rotation.is_finite() && self.translation.is_finite()
168 }
169
170 #[inline]
172 pub fn is_nan(&self) -> bool {
173 self.rotation.is_nan() || self.translation.is_nan()
174 }
175
176 #[inline]
178 pub fn to_mat4(&self) -> $Mat4 {
179 <$Mat4>::from_rotation_translation(self.rotation, self.translation.into())
180 }
181
182 #[inline]
187 pub fn from_mat4(mat: $Mat4) -> Self {
188 let (_, rotation, translation) = mat.to_scale_rotation_translation();
189 Self {
190 rotation,
191 translation: translation.into(),
192 }
193 }
194
195 #[inline]
206 pub fn look_at_rh(eye: $Vec3, target: $Vec3, up: $Vec3) -> $Pose3 {
207 let rotation = <$Rot3>::look_at_rh(eye.into(), target.into(), up.into());
208 let translation = rotation * (-eye);
209
210 $Pose3 {
211 rotation,
212 translation,
213 }
214 }
215
216 #[inline]
227 pub fn face_towards(eye: $Vec3, target: $Vec3, up: $Vec3) -> $Pose3 {
228 $Pose3 {
229 rotation: <$Rot3>::look_at_lh(eye.into(), target.into(), up.into()).inverse(),
230 translation: eye,
231 }
232 }
233 }
234
235 impl Mul<$Pose3> for $Pose3 {
237 type Output = Self;
238
239 #[inline]
240 fn mul(self, rhs: Self) -> Self::Output {
241 Self {
242 rotation: self.rotation * rhs.rotation,
243 translation: self.translation + self.rotation * rhs.translation,
244 }
245 }
246 }
247
248 impl MulAssign<$Pose3> for $Pose3 {
249 #[inline]
250 fn mul_assign(&mut self, rhs: Self) {
251 *self = *self * rhs;
252 }
253 }
254
255 impl Mul<$Vec3> for $Pose3 {
257 type Output = $Vec3;
258
259 #[inline]
260 fn mul(self, rhs: $Vec3) -> Self::Output {
261 self.transform_point(rhs)
262 }
263 }
264
265 impl Mul<$Vec3> for &$Pose3 {
266 type Output = $Vec3;
267
268 #[inline]
269 fn mul(self, rhs: $Vec3) -> Self::Output {
270 self.transform_point(rhs)
271 }
272 }
273
274 impl Mul<&$Vec3> for $Pose3 {
275 type Output = $Vec3;
276
277 #[inline]
278 fn mul(self, rhs: &$Vec3) -> Self::Output {
279 self.transform_point(*rhs)
280 }
281 }
282
283 impl Mul<&$Pose3> for &$Pose3 {
285 type Output = $Pose3;
286
287 #[inline]
288 fn mul(self, rhs: &$Pose3) -> Self::Output {
289 *self * *rhs
290 }
291 }
292
293 impl Mul<&$Pose3> for $Pose3 {
295 type Output = $Pose3;
296
297 #[inline]
298 fn mul(self, rhs: &$Pose3) -> Self::Output {
299 self * *rhs
300 }
301 }
302
303 impl Mul<$Pose3> for &$Pose3 {
305 type Output = $Pose3;
306
307 #[inline]
308 fn mul(self, rhs: $Pose3) -> Self::Output {
309 *self * rhs
310 }
311 }
312
313 impl Default for $Pose3 {
314 fn default() -> Self {
315 Self::IDENTITY
316 }
317 }
318
319 impl Mul<$Pose3> for $Rot3 {
320 type Output = $Pose3;
321
322 #[inline]
323 fn mul(self, rhs: $Pose3) -> Self::Output {
324 $Pose3 {
325 translation: self * rhs.translation,
326 rotation: self * rhs.rotation,
327 }
328 }
329 }
330
331 impl Mul<$Rot3> for $Pose3 {
332 type Output = $Pose3;
333
334 #[inline]
335 fn mul(self, rhs: $Rot3) -> Self::Output {
336 $Pose3 {
337 translation: self.translation,
338 rotation: self.rotation * rhs,
339 }
340 }
341 }
342
343 impl MulAssign<$Rot3> for $Pose3 {
344 #[inline]
345 fn mul_assign(&mut self, rhs: $Rot3) {
346 *self = *self * rhs;
347 }
348 }
349
350 impl From<$Rot3> for $Pose3 {
351 #[inline]
352 fn from(rotation: $Rot3) -> Self {
353 Self::from_rotation(rotation)
354 }
355 }
356
357 #[cfg(feature = "approx")]
358 impl approx::AbsDiffEq for $Pose3 {
359 type Epsilon = $Real;
360
361 fn default_epsilon() -> Self::Epsilon {
362 <$Real>::EPSILON
363 }
364
365 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
366 self.rotation.abs_diff_eq(other.rotation, epsilon)
367 && self.translation.abs_diff_eq(other.translation, epsilon)
368 }
369 }
370
371 #[cfg(feature = "approx")]
372 impl approx::RelativeEq for $Pose3 {
373 fn default_max_relative() -> Self::Epsilon {
374 <$Real>::EPSILON
375 }
376
377 fn relative_eq(
378 &self,
379 other: &Self,
380 epsilon: Self::Epsilon,
381 max_relative: Self::Epsilon,
382 ) -> bool {
383 self.rotation.abs_diff_eq(other.rotation, epsilon.max(max_relative))
384 && self.translation.abs_diff_eq(other.translation, epsilon.max(max_relative))
385 }
386 }
387 };
388}
389
390impl_pose3!(Pose3, Rot3, f32, glam::Vec3, glam::Mat4);
391impl_pose3!(Pose3A, Rot3, f32, glam::Vec3A, glam::Mat4);
392impl_pose3!(DPose3, DRot3, f64, glam::DVec3, glam::DMat4);
393
394impl From<Pose3> for DPose3 {
396 #[inline]
397 fn from(p: Pose3) -> Self {
398 Self {
399 rotation: p.rotation.as_dquat(),
400 translation: p.translation.as_dvec3(),
401 }
402 }
403}
404
405impl From<DPose3> for Pose3 {
406 #[inline]
407 fn from(p: DPose3) -> Self {
408 Self {
409 rotation: p.rotation.as_quat(),
410 translation: p.translation.as_vec3(),
411 }
412 }
413}
414
415impl From<Pose3A> for DPose3 {
416 #[inline]
417 fn from(p: Pose3A) -> Self {
418 Self {
419 rotation: p.rotation.as_dquat(),
420 translation: p.translation.as_dvec3(),
421 }
422 }
423}
424
425impl From<DPose3> for Pose3A {
426 #[inline]
427 fn from(p: DPose3) -> Self {
428 Self {
429 rotation: p.rotation.as_quat(),
430 translation: p.translation.as_vec3a(),
431 }
432 }
433}
434
435impl From<Pose3> for Pose3A {
437 #[inline]
438 fn from(p: Pose3) -> Self {
439 Self {
440 rotation: p.rotation,
441 translation: p.translation.into(),
442 }
443 }
444}
445
446impl From<Pose3A> for Pose3 {
447 #[inline]
448 fn from(p: Pose3A) -> Self {
449 Self {
450 rotation: p.rotation,
451 translation: p.translation.into(),
452 }
453 }
454}
455
456#[cfg(feature = "nalgebra")]
458mod nalgebra_conv {
459 use super::*;
460
461 impl From<Pose3> for nalgebra::Isometry3<f32> {
462 fn from(p: Pose3) -> Self {
463 nalgebra::Isometry3 {
464 translation: p.translation.into(),
465 rotation: p.rotation.into(),
466 }
467 }
468 }
469
470 impl From<nalgebra::Isometry3<f32>> for Pose3 {
471 fn from(iso: nalgebra::Isometry3<f32>) -> Self {
472 Self {
473 rotation: glam::Quat::from_xyzw(
474 iso.rotation.i,
475 iso.rotation.j,
476 iso.rotation.k,
477 iso.rotation.w,
478 ),
479 translation: glam::Vec3::new(
480 iso.translation.x,
481 iso.translation.y,
482 iso.translation.z,
483 ),
484 }
485 }
486 }
487
488 impl From<DPose3> for nalgebra::Isometry3<f64> {
489 fn from(p: DPose3) -> Self {
490 nalgebra::Isometry3 {
491 translation: p.translation.into(),
492 rotation: p.rotation.into(),
493 }
494 }
495 }
496
497 impl From<nalgebra::Isometry3<f64>> for DPose3 {
498 fn from(iso: nalgebra::Isometry3<f64>) -> Self {
499 Self {
500 rotation: iso.rotation.into(),
501 translation: iso.translation.into(),
502 }
503 }
504 }
505}
506
507#[cfg(test)]
508mod tests {
509 use super::*;
510 use approx::assert_relative_eq;
511 use core::f32::consts::PI;
512
513 #[test]
514 fn test_pose3_identity() {
515 let p = Pose3::IDENTITY;
516 assert_eq!(p.rotation, Rot3::IDENTITY);
517 assert_eq!(p.translation, glam::Vec3::ZERO);
518 assert!(p.is_finite());
519 }
520
521 #[test]
522 fn test_pose3_from_translation() {
523 let t = glam::Vec3::new(1.0, 2.0, 3.0);
524 let p = Pose3::from_translation(t);
525 assert_eq!(p.translation, t);
526 assert_eq!(p.rotation, Rot3::IDENTITY);
527 }
528
529 #[test]
530 fn test_pose3_from_rotation_translation() {
531 let t = glam::Vec3::new(1.0, 2.0, 3.0);
532 let r = Rot3::from_rotation_z(PI / 4.0);
533 let p = Pose3::from_parts(t, r);
534 assert_eq!(p.translation, t);
535 assert_eq!(p.rotation, r);
536 }
537
538 #[test]
539 fn test_pose3_transform_point() {
540 let axisangle = glam::Vec3::new(0.0, 0.0, PI / 2.0);
541 let p = Pose3::new(glam::Vec3::new(1.0, 0.0, 0.0), axisangle);
542 let point = glam::Vec3::new(1.0, 0.0, 0.0);
543 let result = p.transform_point(point);
544 assert_relative_eq!(result.x, 1.0, epsilon = 1e-6);
545 assert_relative_eq!(result.y, 1.0, epsilon = 1e-6);
546 assert_relative_eq!(result.z, 0.0, epsilon = 1e-6);
547 let result2 = p * point;
549 assert_relative_eq!(result2.x, 1.0, epsilon = 1e-6);
550 assert_relative_eq!(result2.y, 1.0, epsilon = 1e-6);
551 assert_relative_eq!(result2.z, 0.0, epsilon = 1e-6);
552 }
553
554 #[test]
555 fn test_pose3_transform_vector() {
556 let axisangle = glam::Vec3::new(0.0, 0.0, PI / 2.0);
557 let p = Pose3::new(glam::Vec3::new(100.0, 200.0, 300.0), axisangle);
558 let vector = glam::Vec3::new(1.0, 0.0, 0.0);
559 let result = p.transform_vector(vector);
561 assert_relative_eq!(result.x, 0.0, epsilon = 1e-6);
562 assert_relative_eq!(result.y, 1.0, epsilon = 1e-6);
563 assert_relative_eq!(result.z, 0.0, epsilon = 1e-6);
564 }
565
566 #[test]
567 fn test_pose3_inverse() {
568 let axisangle = glam::Vec3::new(0.1, 0.2, 0.3);
569 let p = Pose3::new(axisangle, glam::Vec3::new(1.0, 2.0, 3.0));
570 let inv = p.inverse();
571 let identity = p * inv;
572 assert_relative_eq!(identity.rotation, Rot3::IDENTITY, epsilon = 1e-6);
573 assert_relative_eq!(identity.translation.x, 0.0, epsilon = 1e-6);
574 assert_relative_eq!(identity.translation.y, 0.0, epsilon = 1e-6);
575 assert_relative_eq!(identity.translation.z, 0.0, epsilon = 1e-6);
576 }
577
578 #[test]
579 fn test_pose3_to_from_mat4() {
580 let axisangle = glam::Vec3::new(0.1, 0.2, 0.3);
581 let p = Pose3::new(axisangle, glam::Vec3::new(1.0, 2.0, 3.0));
582 let m = p.to_mat4();
583 let p2 = Pose3::from_mat4(m);
584 assert_relative_eq!(p.rotation.x, p2.rotation.x, epsilon = 1e-5);
585 assert_relative_eq!(p.rotation.y, p2.rotation.y, epsilon = 1e-5);
586 assert_relative_eq!(p.rotation.z, p2.rotation.z, epsilon = 1e-5);
587 assert_relative_eq!(p.rotation.w, p2.rotation.w, epsilon = 1e-5);
588 assert_relative_eq!(p.translation.x, p2.translation.x, epsilon = 1e-6);
589 assert_relative_eq!(p.translation.y, p2.translation.y, epsilon = 1e-6);
590 assert_relative_eq!(p.translation.z, p2.translation.z, epsilon = 1e-6);
591 }
592
593 #[test]
594 fn test_dpose3_new() {
595 let axisangle = glam::DVec3::new(0.1, 0.2, 0.3);
596 let p = DPose3::new(glam::DVec3::new(1.0, 2.0, 3.0), axisangle);
597 assert_relative_eq!(p.translation.x, 1.0, epsilon = 1e-10);
598 assert_relative_eq!(p.translation.y, 2.0, epsilon = 1e-10);
599 assert_relative_eq!(p.translation.z, 3.0, epsilon = 1e-10);
600 }
601}