Skip to main content

geo_nd/
transformation_uniform.rs

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