mod3d_base/
transformation.rs1use geo_nd::{matrix, quat, vector};
3
4use crate::{Mat4, Quat, Vec3};
5
6#[derive(Clone, Copy, Debug)]
13pub struct Transformation {
14 translation: Vec3,
16 rotation: Quat,
18 scale: Vec3,
20}
21
22impl std::default::Default for Transformation {
23 fn default() -> Self {
24 let translation = vector::zero();
25 let scale = [1.; 3];
26 let rotation = quat::new();
27 Self {
28 translation,
29 scale,
30 rotation,
31 }
32 }
33}
34
35impl Transformation {
37 pub fn new() -> Self {
40 Default::default()
41 }
42
43 pub fn with_scale(mut self, scale: Vec3) -> Self {
46 self.scale = scale;
47 self
48 }
49
50 pub fn with_translation(mut self, translation: Vec3) -> Self {
53 self.translation = translation;
54 self
55 }
56
57 pub fn with_rotation(mut self, rotation: Quat) -> Self {
60 self.rotation = rotation;
61 self
62 }
63
64 pub fn scale(&mut self) -> Vec3 {
67 self.scale
68 }
69
70 pub fn translation(&mut self) -> Vec3 {
73 self.translation
74 }
75
76 pub fn rotation(&self) -> Quat {
79 self.rotation
80 }
81
82 pub fn set_scale(&mut self, scale: Vec3) {
85 self.scale = scale;
86 }
87
88 pub fn set_translation(&mut self, translation: Vec3) {
91 self.translation = translation;
92 }
93
94 pub fn set_rotation(&mut self, rotation: Quat) {
97 self.rotation = rotation;
98 }
99
100 pub fn copy_from(&mut self, other: &Self) {
103 self.translation = other.translation;
104 self.scale = other.scale;
105 self.rotation = other.rotation;
106 }
107
108 pub fn combine(&mut self, base: &Self, other: &Self) {
113 self.rotation = quat::multiply(&base.rotation, &other.rotation);
114 self.translation = base.translation;
115 self.translation = vector::add(self.translation, &other.translation, 1.);
116 for i in 0..3 {
117 self.scale[i] = base.scale[i] * other.scale[i];
118 }
119 }
120
121 pub fn translate(&mut self, translation: &Vec3, scale: f32) {
124 self.translation = vector::add(self.translation, translation, scale);
125 }
126
127 pub fn rotate_axis_angle(&mut self, axis: &Vec3, angle: f32) {
130 let q = quat::of_axis_angle(axis, angle);
131 self.rotation = quat::multiply(&q, &self.rotation);
132 }
135
136 pub fn rotate_by(&mut self, quaternion: &Quat) {
139 self.rotation = quat::multiply(quaternion, &self.rotation);
140 }
141
142 pub fn mat4(&self) -> Mat4 {
145 let mut m = matrix::from_quat4(self.rotation);
146 for i in 0..3 {
147 m[4 * i] *= self.scale[i];
148 m[4 * i + 1] *= self.scale[i];
149 m[4 * i + 2] *= self.scale[i];
150 }
151 m[12] += self.translation[0];
152 m[13] += self.translation[1];
153 m[14] += self.translation[2];
154 m
155 }
156
157 pub fn mat4_inverse(&self) -> Mat4 {
160 let r = quat::conjugate(&self.rotation);
161 let mut m = matrix::from_quat4(r);
162 for i in 0..3 {
163 let sc = 1. / self.scale[i];
164 m[i] *= sc;
165 m[i + 4] *= sc;
166 m[i + 8] *= sc;
167 }
168 m[12] -= self.translation[0];
169 m[13] -= self.translation[1];
170 m[14] -= self.translation[2];
171 m
172 }
173
174 pub fn from_mat4(&mut self, m: Mat4) {
177 self.translation = [m[12], m[13], m[14]];
178 let mut rotation = [0.; 9];
179 for i in 0..3 {
180 let v = [m[4 * i], m[4 * i + 1], m[4 * i + 2]];
181 let l = vector::length(&v);
182 self.scale[i] = l;
183 rotation[3 * i] = v[0] / l;
184 rotation[3 * i + 1] = v[1] / l;
185 rotation[3 * i + 2] = v[2] / l;
186 }
187 self.rotation = quat::of_rotation(&rotation);
188 }
189
190 pub fn mat4_after(&self, pre_mat: &Mat4) -> Mat4 {
193 let m = self.mat4();
194 matrix::multiply4(pre_mat, &m)
195 }
196
197 pub fn interpolate(&mut self, t: f32, in0: &Self, in1: &Self) {
200 let tn = 1.0 - t;
201 for i in 0..3 {
202 self.translation[i] = t * in0.translation[i] + tn * in1.translation[i];
203 self.scale[i] = t * in0.scale[i] + tn * in1.scale[i];
204 }
205 self.rotation = quat::nlerp(t, &in0.rotation, &in1.rotation);
206 }
207
208 pub fn distance(&self, other: &Self) -> f32 {
211 let td = vector::distance(&self.translation, &other.translation);
212 let sd = vector::distance(&self.scale, &other.scale);
213 let qd = quat::distance(&self.rotation, &other.rotation);
214 td + sd + qd
215 }
216 }
218
219impl std::fmt::Display for Transformation {
221 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
222 write!(
223 f,
224 "Transform +{:?}:@{:?}:*{:?}",
225 self.translation, self.rotation, self.scale
226 )
227 }
228}