geo_nd/
fqarray.rs

1//a Imports
2use serde::Serialize;
3
4use crate::FArray;
5use crate::{Float, QArray, Quaternion, SqMatrix4, Transform, Vector};
6
7//tp FQArrayTrans
8/// A transformation that is a translation . scaling . rotation
9/// (i.e. it applies the rotation to an object, then scales it, then
10/// translates it)
11///
12/// This should probably mirror the QArray in using an F, V3 and V4.
13#[derive(Clone, Copy, Debug)] //, Serialize, Deserialize)]
14pub struct FQArrayTrans<F>
15where
16    F: Float + Serialize,
17    FArray<F, 4>: Vector<F, 4>,
18    QArray<F>: Quaternion<F>,
19{
20    /// Quaternion of the rotation
21    quat: QArray<F>,
22    /// Translation and scaling
23    trans_scale: [F; 4],
24}
25
26//mi fqarray_basic_traits!
27macro_rules! fqarray_basic_traits {
28    { $f:ty, $ty:ty } => {
29
30        //ip Default
31        impl std::default::Default for $ty
32        {
33            fn default() -> Self {
34                use num_traits::{One, Zero};
35                Self {
36                    quat: QArray::default(),
37                    trans_scale: [<$f>::zero(), <$f>
38                                  ::zero(), <$f>::zero(), <$f>::one()]
39                }
40            }
41        }
42
43        //ip Display
44        impl std::fmt::Display for $ty
45        {
46            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
47                write!(
48                    f,
49                    "trans[+({},{},{}) rot{} *{}]",
50                    self.trans_scale[0],
51                    self.trans_scale[1],
52                    self.trans_scale[2],
53                    self.quat,
54                    self.trans_scale[3],
55                )
56            }
57        }
58    }
59}
60
61//mi fqarray_transform_trait!
62macro_rules! fqarray_transform_trait {
63    { $f:ty,  $v:ty, $q:ty, $ty:ty } => {
64
65        //ip Transform for FQArrayTrans
66        impl Transform<$f, $v, $q> for $ty
67        {
68            //fp of_trs
69            /// Create an [FQArrayTrans] from a Vector3 translation, Quat
70            /// rotation and Float scaling
71            fn of_trs(t: $v, r: $q, s: $f) -> Self {
72                Self {
73                    quat: r,
74                    trans_scale: [t[0], t[1], t[2], s],
75                }
76            }
77
78            //mp scale
79            /// Get the scaling of the transformation
80            fn scale(&self) -> $f {
81                self.trans_scale[3]
82            }
83
84            //mp translation
85            /// Get the translation of the transformation
86            fn translation(&self) -> $v {
87                [
88                    self.trans_scale[0],
89                    self.trans_scale[1],
90                    self.trans_scale[2],
91                ]
92                    .into()
93            }
94
95            //mp rotation
96            /// Get the rotation of the transformation
97            fn rotation(&self) -> QArray<$f> {
98                self.quat
99            }
100
101            //cp inverse
102            /// Get a transformation that is the inverse of this
103            fn inverse(&self) -> Self {
104                use num_traits::{Float, One};
105                let scale = self.trans_scale[3];
106                if scale.abs() < <$f>::epsilon() {
107                    Self::default()
108                } else {
109                    let scale = <$f>::one() / scale;
110                    let trans: $v  = [
111                        self.trans_scale[0],
112                        self.trans_scale[1],
113                        self.trans_scale[2],
114                    ]
115                        .into();
116                    let iquat = self.quat.conjugate();
117                    let trans = iquat.apply3(&trans);
118                    let trans = trans * -scale;
119                    Self::of_trs(trans, iquat, scale)
120                }
121            }
122
123            //mp invert
124            /// Invert this transformation
125            fn invert(&mut self) {
126                *self = self.inverse();
127            }
128
129            //mp as_mat
130            /// Return the matrix
131            fn as_mat<M: SqMatrix4<$f>>(&self) -> M {
132                let mut m = M::default();
133                self.quat.set_rotation4(&mut m);
134                m *= self.trans_scale[3];
135                m[3] = self.trans_scale[0];
136                m[7] = self.trans_scale[1];
137                m[11] = self.trans_scale[2];
138                m
139            }
140        }
141    }
142}
143
144//a New
145//mi fqarray_traits
146macro_rules! fqarray_traits {
147    { $f:ty,  $v:ty, $q:ty, $ty:ty } => {
148        fqarray_basic_traits! {$f, $ty}
149        fqarray_transform_trait! {$f, $v, $q, $ty}
150    }
151}
152
153fqarray_traits! {f32, FArray<f32,3>,  QArray<f32>, FQArrayTrans<f32>}
154fqarray_traits! {f64, FArray<f64,3>,  QArray<f64>, FQArrayTrans<f64>}