1use cgmath;
2use std::fmt;
3
4use crate::{DMat4, DQuat, DVec3, Mat4, Quat, Vec3};
5use approx::ApproxEq;
6
7#[derive(Clone, Copy, Debug, PartialEq)]
9pub struct Trs {
10 pub t: Vec3,
12
13 pub r: Quat,
15
16 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 pub fn new(t: Vec3, r: Quat, s: Vec3) -> Self {
35 Trs { t, r, s }
36 }
37
38 pub fn identity() -> Self {
40 Trs {
41 t: vec3!(),
42 r: quat!(),
43 s: vec3!(1.0),
44 }
45 }
46
47 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#[derive(Clone, Copy, Debug, PartialEq)]
95pub struct DTrs {
96 pub t: DVec3,
98
99 pub r: DQuat,
101
102 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 pub fn new(t: DVec3, r: DQuat, s: DVec3) -> Self {
121 DTrs { t, r, s }
122 }
123
124 pub fn identity() -> Self {
126 DTrs {
127 t: dvec3!(),
128 r: dquat!(),
129 s: dvec3!(1.0),
130 }
131 }
132
133 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}