euler/
trs.rs

1use cgmath;
2use std::fmt;
3
4use crate::{DMat4, DQuat, DVec3, Mat4, Quat, Vec3};
5use approx::ApproxEq;
6
7/// Single-precision translation + rotation + non-uniform scale transform.
8#[derive(Clone, Copy, Debug, PartialEq)]
9pub struct Trs {
10    /// Translation vector.
11    pub t: Vec3,
12
13    /// Rotation quaternion.
14    pub r: Quat,
15
16    /// *Non-uniform* scale factor.
17    pub s: Vec3,
18}
19
20impl fmt::Display for Trs {
21    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22        write!(f, "{:?}", (self.t, self.r, self.s))
23    }
24}
25
26impl Default for Trs {
27    fn default() -> Self {
28        Self::identity()
29    }
30}
31
32impl Trs {
33    /// Full constructor.
34    pub fn new(t: Vec3, r: Quat, s: Vec3) -> Self {
35        Trs { t, r, s }
36    }
37
38    /// Identity constructor.
39    pub fn identity() -> Self {
40        Trs {
41            t: vec3!(),
42            r: quat!(),
43            s: vec3!(1.0),
44        }
45    }
46
47    /// Returns the equivalent matrix representation for this transform.
48    pub fn matrix(&self) -> Mat4 {
49        let t =
50            cgmath::Matrix4::from_translation(cgmath::Vector3::new(self.t.x, self.t.y, self.t.z));
51        let r = cgmath::Matrix4::from(cgmath::Quaternion::new(
52            self.r.s, self.r.x, self.r.y, self.r.z,
53        ));
54        let s = cgmath::Matrix4::from_nonuniform_scale(self.s.x, self.s.y, self.s.z);
55        let m: [[f32; 4]; 4] = (t * r * s).into();
56        Mat4::from(m)
57    }
58}
59
60impl ApproxEq for Trs {
61    type Epsilon = <f32 as ApproxEq>::Epsilon;
62
63    fn default_epsilon() -> Self::Epsilon {
64        <f32 as ApproxEq>::default_epsilon()
65    }
66
67    fn default_max_relative() -> Self::Epsilon {
68        <f32 as ApproxEq>::default_max_relative()
69    }
70
71    fn default_max_ulps() -> u32 {
72        <f32 as ApproxEq>::default_max_ulps()
73    }
74
75    fn relative_eq(
76        &self,
77        other: &Self,
78        epsilon: Self::Epsilon,
79        max_relative: Self::Epsilon,
80    ) -> bool {
81        self.t.relative_eq(&other.t, epsilon, max_relative)
82            && self.r.relative_eq(&other.r, epsilon, max_relative)
83            && self.s.relative_eq(&other.s, epsilon, max_relative)
84    }
85
86    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
87        self.t.ulps_eq(&other.t, epsilon, max_ulps)
88            && self.r.ulps_eq(&other.r, epsilon, max_ulps)
89            && self.s.ulps_eq(&other.s, epsilon, max_ulps)
90    }
91}
92
93/// Double-precision translation + rotation + non-uniform scale transform.
94#[derive(Clone, Copy, Debug, PartialEq)]
95pub struct DTrs {
96    /// Translation vector.
97    pub t: DVec3,
98
99    /// Rotation quaternion.
100    pub r: DQuat,
101
102    /// *Non-uniform* scale factor.
103    pub s: DVec3,
104}
105
106impl fmt::Display for DTrs {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        write!(f, "{:?}", (self.t, self.r, self.s))
109    }
110}
111
112impl Default for DTrs {
113    fn default() -> Self {
114        Self::identity()
115    }
116}
117
118impl DTrs {
119    /// Full constructor.
120    pub fn new(t: DVec3, r: DQuat, s: DVec3) -> Self {
121        DTrs { t, r, s }
122    }
123
124    /// Identity constructor.
125    pub fn identity() -> Self {
126        DTrs {
127            t: dvec3!(),
128            r: dquat!(),
129            s: dvec3!(1.0),
130        }
131    }
132
133    /// Returns the equivalent matrix representation for this transform.
134    pub fn matrix(&self) -> DMat4 {
135        let t =
136            cgmath::Matrix4::from_translation(cgmath::Vector3::new(self.t.x, self.t.y, self.t.z));
137        let r = cgmath::Matrix4::from(cgmath::Quaternion::new(
138            self.r.s, self.r.x, self.r.y, self.r.z,
139        ));
140        let s = cgmath::Matrix4::from_nonuniform_scale(self.s.x, self.s.y, self.s.z);
141        let m: [[f64; 4]; 4] = (t * r * s).into();
142        DMat4::from(m)
143    }
144}
145
146impl ApproxEq for DTrs {
147    type Epsilon = <f64 as ApproxEq>::Epsilon;
148
149    fn default_epsilon() -> Self::Epsilon {
150        <f64 as ApproxEq>::default_epsilon()
151    }
152
153    fn default_max_relative() -> Self::Epsilon {
154        <f64 as ApproxEq>::default_max_relative()
155    }
156
157    fn default_max_ulps() -> u32 {
158        <f64 as ApproxEq>::default_max_ulps()
159    }
160
161    fn relative_eq(
162        &self,
163        other: &Self,
164        epsilon: Self::Epsilon,
165        max_relative: Self::Epsilon,
166    ) -> bool {
167        self.t.relative_eq(&other.t, epsilon, max_relative)
168            && self.r.relative_eq(&other.r, epsilon, max_relative)
169            && self.s.relative_eq(&other.s, epsilon, max_relative)
170    }
171
172    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
173        self.t.ulps_eq(&other.t, epsilon, max_ulps)
174            && self.r.ulps_eq(&other.r, epsilon, max_ulps)
175            && self.s.ulps_eq(&other.s, epsilon, max_ulps)
176    }
177}