parry3d/query/sweep_toi/
sweep.rs1use crate::math::{Pose, Real, Rotation, Vector};
2
3#[inline]
5pub(crate) fn rotate_vec(q: &Rotation, v: Vector) -> Vector {
6 #[cfg(feature = "dim2")]
7 {
8 q.transform_vector(v)
9 }
10 #[cfg(feature = "dim3")]
11 {
12 *q * v
13 }
14}
15
16#[inline]
18pub(crate) fn inv_rotate_vec(q: &Rotation, v: Vector) -> Vector {
19 #[cfg(feature = "dim2")]
20 {
21 q.inverse_transform_vector(v)
22 }
23 #[cfg(feature = "dim3")]
24 {
25 q.inverse() * v
26 }
27}
28
29#[inline]
31pub(crate) fn nlerp(q1: &Rotation, q2: &Rotation, t: Real) -> Rotation {
32 #[cfg(feature = "dim2")]
33 {
34 q1.lerp(*q2, t).normalize()
35 }
36 #[cfg(feature = "dim3")]
37 {
38 let q1 = if q1.dot(*q2) < 0.0 { -*q1 } else { *q1 };
39 (q1 * (1.0 - t) + *q2 * t).normalize()
40 }
41}
42
43#[derive(Copy, Clone, Debug, PartialEq)]
51#[cfg_attr(
52 feature = "serde-serialize",
53 derive(serde::Serialize, serde::Deserialize)
54)]
55pub struct Sweep {
56 pub local_center: Vector,
58 pub c1: Vector,
60 pub c2: Vector,
62 pub q1: Rotation,
64 pub q2: Rotation,
66}
67
68impl Sweep {
69 pub fn from_poses(start: &Pose, end: &Pose, local_center: Vector) -> Self {
71 Self {
72 local_center,
73 c1: start.transform_point(local_center),
74 c2: end.transform_point(local_center),
75 q1: start.rotation,
76 q2: end.rotation,
77 }
78 }
79
80 pub fn constant(pose: &Pose, local_center: Vector) -> Self {
82 Self::from_poses(pose, pose, local_center)
83 }
84
85 pub fn transform_at(&self, t: Real) -> Pose {
90 let q = nlerp(&self.q1, &self.q2, t);
91 let p = self.c1.lerp(self.c2, t) - rotate_vec(&q, self.local_center);
92 Pose::from_parts(p, q)
93 }
94
95 pub fn final_transform(&self) -> Pose {
97 let p = self.c2 - rotate_vec(&self.q2, self.local_center);
98 Pose::from_parts(p, self.q2)
99 }
100
101 pub fn shifted(&self, origin: Vector) -> Self {
105 Self {
106 local_center: self.local_center,
107 c1: self.c1 - origin,
108 c2: self.c2 - origin,
109 q1: self.q1,
110 q2: self.q2,
111 }
112 }
113}