Skip to main content

geo_nd/
transformation.rs

1use crate::{FArray, Float, Quaternion, SqMatrix3, SqMatrix4, Transform, Vector3, Vector4, vector};
2
3/// A transformation that is a translation . rotation . scaling
4/// (i.e. it applies a scaling to an object, then the rotation then
5/// translates it)
6#[derive(Clone, Copy, Debug, PartialEq)]
7pub struct Transformation<F, Q>
8where
9    F: Float,
10    Q: Quaternion<F>,
11{
12    /// Quaternion of the rotation
13    rotation: Q,
14    /// Translation
15    translation: FArray<F, 3>,
16    /// Scaling, for  all three axes
17    scale: FArray<F, 3>,
18}
19
20impl<F, Q> std::default::Default for Transformation<F, Q>
21where
22    F: Float,
23    Q: Quaternion<F>,
24    FArray<F, 3>: Vector3<F>,
25{
26    fn default() -> Self {
27        Self {
28            rotation: Q::default(),
29            translation: FArray::<F, 3>::default(),
30            scale: [F::ONE; 3].into(),
31        }
32    }
33}
34
35impl<F, Q> std::fmt::Display for Transformation<F, Q>
36where
37    F: Float,
38    Q: Quaternion<F>,
39    FArray<F, 3>: Vector3<F>,
40{
41    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
42        write!(
43            f,
44            "trans[+({},{},{}) rot{} *{}]",
45            self.translation[0],
46            self.translation[1],
47            self.translation[2],
48            self.rotation,
49            self.scale,
50        )
51    }
52}
53
54impl<F, Q> std::ops::Mul<FArray<F, 4>> for Transformation<F, Q>
55where
56    F: Float,
57    Q: Quaternion<F>,
58    FArray<F, 3>: Vector3<F>,
59    FArray<F, 4>: Vector4<F>,
60{
61    type Output = FArray<F, 4>;
62    fn mul(self, v: FArray<F, 4>) -> Self::Output {
63        let v_sc: FArray<F, 3> = [
64            self.scale[0] * v[0],
65            self.scale[1] * v[1],
66            self.scale[2] * v[2],
67        ]
68        .into();
69        let r = self.rotation.apply3(&v_sc) + (self.translation * v[3]);
70        [r[0], r[1], r[2], v[3]].into()
71    }
72}
73
74impl<F, Q> std::ops::Mul<F> for Transformation<F, Q>
75where
76    F: Float,
77    Q: Quaternion<F>,
78    FArray<F, 3>: Vector3<F>,
79{
80    type Output = Self;
81    fn mul(mut self, f: F) -> Self::Output {
82        self.scale *= f;
83        self.translation *= f;
84        self
85    }
86}
87
88impl<F, Q> std::ops::MulAssign<F> for Transformation<F, Q>
89where
90    F: Float,
91    Q: Quaternion<F>,
92    FArray<F, 3>: Vector3<F>,
93{
94    fn mul_assign(&mut self, f: F) {
95        *self = *self * f;
96    }
97}
98
99impl<F, Q> std::ops::Div<F> for Transformation<F, Q>
100where
101    F: Float,
102    Q: Quaternion<F>,
103    FArray<F, 3>: Vector3<F>,
104{
105    type Output = Self;
106    fn div(mut self, f: F) -> Self::Output {
107        self.scale /= f;
108        self.translation /= f;
109        self
110    }
111}
112
113impl<F, Q> std::ops::DivAssign<F> for Transformation<F, Q>
114where
115    F: Float,
116    Q: Quaternion<F>,
117    FArray<F, 3>: Vector3<F>,
118{
119    fn div_assign(&mut self, f: F) {
120        *self = *self / f;
121    }
122}
123
124impl<F, Q> Transform<F> for Transformation<F, Q>
125where
126    F: Float,
127    Q: Quaternion<F>,
128    FArray<F, 3>: Vector3<F>,
129    FArray<F, 4>: Vector4<F>,
130{
131    const UNIFORM_SCALING: bool = false;
132    type Vec3 = FArray<F, 3>;
133    type Vec4 = FArray<F, 4>;
134    type Quat = Q;
135    fn of_trs<A: AsRef<[F; 3]>>(t: A, r: Q, s: A) -> Option<Self> {
136        Some(Self {
137            rotation: r,
138            translation: t.as_ref().into(),
139            scale: s.as_ref().into(),
140        })
141    }
142
143    fn of_trsu<A: AsRef<[F; 3]>>(t: A, r: Q, s: F) -> Self {
144        Self {
145            rotation: r,
146            translation: t.as_ref().into(),
147            scale: [s; 3].into(),
148        }
149    }
150
151    fn is_uniform_scale(&self) -> bool {
152        self.scale[0] == self.scale[1] && self.scale[0] == self.scale[2]
153    }
154
155    fn scale(&self) -> Option<Self::Vec3> {
156        Some(self.scale)
157    }
158
159    fn uniform_scale(&self) -> Option<F> {
160        if self.is_uniform_scale() {
161            Some(self.scale[0])
162        } else {
163            None
164        }
165    }
166
167    fn translation(&self) -> Self::Vec3 {
168        self.translation
169    }
170
171    fn rotation(&self) -> Option<Q> {
172        Some(self.rotation)
173    }
174
175    fn set_identity(&mut self) {
176        self.rotation.set_identity();
177        self.translation = FArray::default();
178        self.scale = [F::ONE; 3].into();
179    }
180
181    fn set_scale<A: AsRef<[F; 3]>>(&mut self, scale: A) -> bool {
182        self.scale = scale.as_ref().into();
183        true
184    }
185
186    fn set_uniform_scale(&mut self, scale: F) {
187        self.scale = [scale; 3].into();
188    }
189
190    fn set_translation<A: AsRef<[F; 3]>>(&mut self, translation: A) {
191        self.translation = translation.as_ref().into();
192    }
193
194    fn set_rotation(&mut self, rotation: Q) {
195        self.rotation = rotation;
196    }
197
198    fn scale_uniform_by(&mut self, scale: F) {
199        self.translation *= scale;
200        self.scale *= scale;
201    }
202
203    fn scale_by<A: AsRef<[F; 3]>>(&mut self, scale: A) -> bool {
204        if self.rotation.as_rijk().0 != F::ONE {
205            return false;
206        }
207        let scale = scale.as_ref();
208        self.translation[0] = self.translation[0] * scale[0];
209        self.translation[1] = self.translation[1] * scale[1];
210        self.translation[2] = self.translation[2] * scale[2];
211        self.scale[0] = self.scale[0] * scale[0];
212        self.scale[1] = self.scale[1] * scale[1];
213        self.scale[2] = self.scale[2] * scale[2];
214        true
215    }
216
217    fn translate_by<A: AsRef<[F; 3]>>(&mut self, translation: A, scale: F) {
218        let translation: Self::Vec3 = translation.as_ref().into();
219        self.translation += translation * scale;
220    }
221
222    fn rotate_by(&mut self, quaternion: &Q) {
223        self.translation = quaternion.apply3(&self.translation);
224        self.rotation = *quaternion * self.rotation;
225    }
226
227    fn transform_by<T: Transform<F, Quat = Self::Quat>>(&mut self, transformer: &T) -> bool {
228        let Some(scale) = transformer.uniform_scale() else {
229            return false;
230        };
231        let Some(rotation) = transformer.rotation() else {
232            return false;
233        };
234        self.scale *= scale;
235        self.translation *= scale;
236        self.rotation = rotation * self.rotation;
237        let translation: [F; 3] = transformer.translation().into();
238        self.translation = rotation.apply3(&self.translation) + &translation;
239        true
240    }
241
242    fn inverse_transform(&self) -> Option<Self> {
243        if !self.is_uniform_scale() {
244            return None;
245        }
246        let scale = self.scale[0];
247        if scale.abs() < F::epsilon() {
248            Some(Self::default())
249        } else {
250            let scale = scale.recip();
251            let iquat = self.rotation.conjugate();
252            let trans = iquat.apply3(&self.translation);
253            let trans = trans * -scale;
254            Self::of_trs(trans, iquat, [scale; 3].into())
255        }
256    }
257
258    fn apply3_arr(&self, other: &[F; 3]) -> [F; 3] {
259        let v: Self::Vec3 = vector::comp_mult(*self.scale, other).into();
260        *(self.rotation.apply3(&v) + self.translation)
261    }
262
263    fn apply4_arr(&self, other: &[F; 4]) -> [F; 4] {
264        let v: Self::Vec3 = vector::comp_mult(*self.scale, &[other[0], other[1], other[2]]).into();
265        let r = self.rotation.apply3(&v) + (self.translation * other[3]);
266        [r[0], r[1], r[2], other[3]]
267    }
268
269    fn as_mat3<M: SqMatrix3<F>>(&self) -> M {
270        let mut m = M::default();
271        self.rotation.set_rotation3(&mut m);
272        for (i, c) in m.iter_mut().enumerate() {
273            *c = *c * self.scale[i % 3];
274        }
275        m
276    }
277
278    fn as_mat4<M: SqMatrix4<F>>(&self) -> M {
279        let mut m = M::default();
280        self.rotation.set_rotation4(&mut m);
281        for (i, c) in m.iter_mut().take(12).enumerate() {
282            if (i % 4) == 3 {
283                *c = self.translation[i / 4];
284            } else {
285                *c = *c * self.scale[i % 4];
286            }
287        }
288        m
289    }
290}
291
292#[cfg(feature = "serde")]
293#[derive(serde::Deserialize, serde::Serialize)]
294#[serde(rename = "Transformation")]
295struct X<F, Q>
296where
297    F: Float,
298    Q: Quaternion<F>,
299    FArray<F, 3>: Vector3<F> + serde::de::DeserializeOwned + serde::Serialize,
300{
301    rotation: Q,
302    /// Translation
303    translation: FArray<F, 3>,
304    /// Scaling, for  all three axes
305    scale: FArray<F, 3>,
306}
307
308#[cfg(feature = "serde")]
309impl<F, Q> serde::Serialize for Transformation<F, Q>
310where
311    F: Float + for<'de> serde::de::Deserialize<'de> + serde::Serialize,
312    Q: Quaternion<F> + for<'de> serde::de::Deserialize<'de> + serde::Serialize,
313    FArray<F, 3>: Vector3<F> + serde::de::DeserializeOwned + serde::Serialize,
314    FArray<F, 4>: Vector4<F> + serde::Serialize,
315{
316    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
317    where
318        S: serde::Serializer,
319    {
320        (X {
321            rotation: self.rotation,
322            translation: self.translation,
323            scale: self.scale,
324        })
325        .serialize(serializer)
326    }
327}
328
329#[cfg(feature = "serde")]
330impl<'de, F, Q> serde::Deserialize<'de> for Transformation<F, Q>
331where
332    F: Float + serde::de::Deserialize<'de> + serde::Serialize,
333    Q: Quaternion<F> + serde::de::Deserialize<'de> + serde::Serialize,
334    FArray<F, 3>: Vector3<F> + serde::de::DeserializeOwned + serde::Serialize,
335    FArray<F, 4>: Vector4<F>,
336{
337    fn deserialize<DE>(deserializer: DE) -> Result<Self, DE::Error>
338    where
339        DE: serde::Deserializer<'de>,
340    {
341        let x = X::<F, Q>::deserialize(deserializer)?;
342        Ok(Self {
343            rotation: x.rotation,
344            translation: x.translation,
345            scale: x.scale,
346        })
347    }
348}