1use crate::core::{
68 algebra::{Matrix3, Matrix4, UnitQuaternion, Vector3},
69 log::{Log, MessageKind},
70 reflect::prelude::*,
71 variable::InheritableVariable,
72 visitor::{Visit, VisitResult, Visitor},
73};
74use std::cell::Cell;
75
76#[derive(Clone, Debug, Reflect)]
78pub struct Transform {
79 #[reflect(hidden)]
82 dirty: Cell<bool>,
83
84 #[reflect(setter = "set_scale_internal", step = 0.1)]
86 local_scale: InheritableVariable<Vector3<f32>>,
87
88 #[reflect(setter = "set_position_internal", step = 0.1)]
90 local_position: InheritableVariable<Vector3<f32>>,
91
92 #[reflect(setter = "set_rotation_internal", step = 1.0)]
94 local_rotation: InheritableVariable<UnitQuaternion<f32>>,
95
96 #[reflect(setter = "set_pre_rotation_internal", step = 1.0)]
98 pre_rotation: InheritableVariable<UnitQuaternion<f32>>,
99
100 #[reflect(setter = "set_post_rotation_internal", step = 1.0)]
102 post_rotation: InheritableVariable<UnitQuaternion<f32>>,
103
104 #[reflect(setter = "set_rotation_offset_internal", step = 0.1)]
106 rotation_offset: InheritableVariable<Vector3<f32>>,
107
108 #[reflect(setter = "set_rotation_pivot_internal", step = 0.1)]
110 rotation_pivot: InheritableVariable<Vector3<f32>>,
111
112 #[reflect(setter = "set_scaling_offset_internal", step = 0.1)]
114 scaling_offset: InheritableVariable<Vector3<f32>>,
115
116 #[reflect(setter = "set_scaling_pivot_internal", step = 0.1)]
118 scaling_pivot: InheritableVariable<Vector3<f32>>,
119
120 #[reflect(hidden)]
122 matrix: Cell<Matrix4<f32>>,
123
124 #[reflect(hidden)]
125 post_rotation_matrix: Matrix3<f32>,
126}
127
128impl Visit for Transform {
129 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
130 let mut region = visitor.enter_region(name)?;
131
132 self.local_scale.visit("LocalScale", &mut region)?;
133 self.local_position.visit("LocalPosition", &mut region)?;
134 self.local_rotation.visit("LocalRotation", &mut region)?;
135 self.pre_rotation.visit("PreRotation", &mut region)?;
136 self.post_rotation.visit("PostRotation", &mut region)?;
137 self.rotation_offset.visit("RotationOffset", &mut region)?;
138 self.rotation_pivot.visit("RotationPivot", &mut region)?;
139 self.scaling_offset.visit("ScalingOffset", &mut region)?;
140 self.scaling_pivot.visit("ScalingPivot", &mut region)?;
141
142 drop(region);
143
144 if visitor.is_reading() {
145 self.post_rotation_matrix =
146 build_post_rotation_matrix(self.post_rotation.clone_inner());
147 }
148
149 Ok(())
150 }
151}
152
153impl Default for Transform {
154 fn default() -> Self {
155 Self::identity()
156 }
157}
158
159fn build_post_rotation_matrix(post_rotation: UnitQuaternion<f32>) -> Matrix3<f32> {
160 post_rotation
161 .to_rotation_matrix()
162 .matrix()
163 .try_inverse()
164 .unwrap_or_else(|| {
165 Log::writeln(
166 MessageKind::Warning,
167 "Unable to inverse post rotation matrix! Fallback to identity matrix.",
168 );
169 Matrix3::identity()
170 })
171}
172
173impl Transform {
174 pub fn identity() -> Self {
177 Self {
178 dirty: Cell::new(true),
179 local_position: InheritableVariable::new_modified(Vector3::default()),
180 local_scale: InheritableVariable::new_modified(Vector3::new(1.0, 1.0, 1.0)),
181 local_rotation: InheritableVariable::new_modified(UnitQuaternion::identity()),
182 pre_rotation: InheritableVariable::new_modified(UnitQuaternion::identity()),
183 post_rotation: InheritableVariable::new_modified(UnitQuaternion::identity()),
184 rotation_offset: InheritableVariable::new_modified(Vector3::default()),
185 rotation_pivot: InheritableVariable::new_modified(Vector3::default()),
186 scaling_offset: InheritableVariable::new_modified(Vector3::default()),
187 scaling_pivot: InheritableVariable::new_modified(Vector3::default()),
188 matrix: Cell::new(Matrix4::identity()),
189 post_rotation_matrix: Matrix3::identity(),
190 }
191 }
192
193 #[inline]
195 pub fn position(&self) -> &InheritableVariable<Vector3<f32>> {
196 &self.local_position
197 }
198
199 #[inline]
201 pub fn set_position(&mut self, local_position: Vector3<f32>) -> &mut Self {
202 if self.dirty.get() || *self.local_position != local_position {
203 self.set_position_internal(local_position);
204 }
205 self
206 }
207
208 #[inline]
209 fn set_position_internal(&mut self, local_position: Vector3<f32>) -> Vector3<f32> {
210 self.dirty.set(true);
211 self.local_position
212 .set_value_and_mark_modified(local_position)
213 }
214
215 #[inline]
217 pub fn rotation(&self) -> &InheritableVariable<UnitQuaternion<f32>> {
218 &self.local_rotation
219 }
220
221 #[inline]
223 pub fn set_rotation(&mut self, local_rotation: UnitQuaternion<f32>) -> &mut Self {
224 if self.dirty.get() || *self.local_rotation != local_rotation {
225 self.set_rotation_internal(local_rotation);
226 }
227 self
228 }
229
230 #[inline]
231 fn set_rotation_internal(
232 &mut self,
233 local_rotation: UnitQuaternion<f32>,
234 ) -> UnitQuaternion<f32> {
235 self.dirty.set(true);
236 self.local_rotation
237 .set_value_and_mark_modified(local_rotation)
238 }
239
240 #[inline]
242 pub fn scale(&self) -> &InheritableVariable<Vector3<f32>> {
243 &self.local_scale
244 }
245
246 #[inline]
248 pub fn set_scale(&mut self, local_scale: Vector3<f32>) -> &mut Self {
249 if self.dirty.get() || *self.local_scale != local_scale {
250 self.set_scale_internal(local_scale);
251 }
252 self
253 }
254
255 #[inline]
256 fn set_scale_internal(&mut self, local_scale: Vector3<f32>) -> Vector3<f32> {
257 self.dirty.set(true);
258 self.local_scale.set_value_and_mark_modified(local_scale)
259 }
260
261 #[inline]
265 pub fn set_pre_rotation(&mut self, pre_rotation: UnitQuaternion<f32>) -> &mut Self {
266 if self.dirty.get() || *self.pre_rotation != pre_rotation {
267 self.set_pre_rotation_internal(pre_rotation);
268 }
269 self
270 }
271
272 #[inline]
273 fn set_pre_rotation_internal(
274 &mut self,
275 pre_rotation: UnitQuaternion<f32>,
276 ) -> UnitQuaternion<f32> {
277 self.dirty.set(true);
278 self.pre_rotation.set_value_and_mark_modified(pre_rotation)
279 }
280
281 #[inline]
283 pub fn pre_rotation(&self) -> &InheritableVariable<UnitQuaternion<f32>> {
284 &self.pre_rotation
285 }
286
287 #[inline]
291 pub fn set_post_rotation(&mut self, post_rotation: UnitQuaternion<f32>) -> &mut Self {
292 if self.dirty.get() || *self.post_rotation != post_rotation {
293 self.set_post_rotation_internal(post_rotation);
294 }
295 self
296 }
297
298 #[inline]
299 fn set_post_rotation_internal(
300 &mut self,
301 post_rotation: UnitQuaternion<f32>,
302 ) -> UnitQuaternion<f32> {
303 self.post_rotation_matrix = build_post_rotation_matrix(post_rotation);
304 self.dirty.set(true);
305 self.post_rotation
306 .set_value_and_mark_modified(post_rotation)
307 }
308
309 #[inline]
311 pub fn post_rotation(&self) -> &InheritableVariable<UnitQuaternion<f32>> {
312 &self.post_rotation
313 }
314
315 #[inline]
318 pub fn set_rotation_offset(&mut self, rotation_offset: Vector3<f32>) -> &mut Self {
319 if self.dirty.get() || *self.rotation_offset != rotation_offset {
320 self.set_rotation_offset_internal(rotation_offset);
321 }
322 self
323 }
324
325 #[inline]
326 fn set_rotation_offset_internal(&mut self, rotation_offset: Vector3<f32>) -> Vector3<f32> {
327 self.dirty.set(true);
328 self.rotation_offset
329 .set_value_and_mark_modified(rotation_offset)
330 }
331
332 #[inline]
334 pub fn rotation_offset(&self) -> &InheritableVariable<Vector3<f32>> {
335 &self.rotation_offset
336 }
337
338 #[inline]
342 pub fn set_rotation_pivot(&mut self, rotation_pivot: Vector3<f32>) -> &mut Self {
343 if self.dirty.get() || *self.rotation_pivot != rotation_pivot {
344 self.set_rotation_pivot_internal(rotation_pivot);
345 }
346 self
347 }
348
349 #[inline]
350 fn set_rotation_pivot_internal(&mut self, rotation_pivot: Vector3<f32>) -> Vector3<f32> {
351 self.dirty.set(true);
352 self.rotation_pivot
353 .set_value_and_mark_modified(rotation_pivot)
354 }
355
356 #[inline]
358 pub fn rotation_pivot(&self) -> &InheritableVariable<Vector3<f32>> {
359 &self.rotation_pivot
360 }
361
362 #[inline]
365 pub fn set_scaling_offset(&mut self, scaling_offset: Vector3<f32>) -> &mut Self {
366 if self.dirty.get() || *self.scaling_offset != scaling_offset {
367 self.set_scaling_offset_internal(scaling_offset);
368 self.dirty.set(true);
369 }
370 self
371 }
372
373 #[inline]
374 fn set_scaling_offset_internal(&mut self, scaling_offset: Vector3<f32>) -> Vector3<f32> {
375 self.dirty.set(true);
376 self.scaling_offset
377 .set_value_and_mark_modified(scaling_offset)
378 }
379
380 #[inline]
382 pub fn scaling_offset(&self) -> &InheritableVariable<Vector3<f32>> {
383 &self.scaling_offset
384 }
385
386 #[inline]
389 pub fn set_scaling_pivot(&mut self, scaling_pivot: Vector3<f32>) -> &mut Self {
390 if self.dirty.get() || *self.scaling_pivot != scaling_pivot {
391 self.set_scaling_pivot_internal(scaling_pivot);
392 self.dirty.set(true);
393 }
394 self
395 }
396
397 #[inline]
398 fn set_scaling_pivot_internal(&mut self, scaling_pivot: Vector3<f32>) -> Vector3<f32> {
399 self.dirty.set(true);
400 self.scaling_pivot
401 .set_value_and_mark_modified(scaling_pivot)
402 }
403
404 #[inline]
406 pub fn scaling_pivot(&self) -> &InheritableVariable<Vector3<f32>> {
407 &self.scaling_pivot
408 }
409
410 #[inline]
413 pub fn offset(&mut self, vec: Vector3<f32>) -> &mut Self {
414 self.local_position
415 .set_value_and_mark_modified(*self.local_position + vec);
416 self.dirty.set(true);
417 self
418 }
419
420 fn calculate_local_transform(&self) -> Matrix4<f32> {
421 let por = &self.post_rotation_matrix;
423 let pr = *self.pre_rotation.to_rotation_matrix().matrix();
424 let r = *self.local_rotation.to_rotation_matrix().matrix();
425
426 let sx = self.local_scale.x;
427 let sy = self.local_scale.y;
428 let sz = self.local_scale.z;
429
430 let tx = self.local_position.x;
431 let ty = self.local_position.y;
432 let tz = self.local_position.z;
433
434 let rpx = self.rotation_pivot.x;
435 let rpy = self.rotation_pivot.y;
436 let rpz = self.rotation_pivot.z;
437
438 let rox = self.rotation_offset.x;
439 let roy = self.rotation_offset.y;
440 let roz = self.rotation_offset.z;
441
442 let spx = self.scaling_pivot.x;
443 let spy = self.scaling_pivot.y;
444 let spz = self.scaling_pivot.z;
445
446 let sox = self.scaling_offset.x;
447 let soy = self.scaling_offset.y;
448 let soz = self.scaling_offset.z;
449
450 let a0 = pr[0] * r[0] + pr[3] * r[1] + pr[6] * r[2];
467 let a1 = pr[1] * r[0] + pr[4] * r[1] + pr[7] * r[2];
468 let a2 = pr[2] * r[0] + pr[5] * r[1] + pr[8] * r[2];
469 let a3 = pr[0] * r[3] + pr[3] * r[4] + pr[6] * r[5];
470 let a4 = pr[1] * r[3] + pr[4] * r[4] + pr[7] * r[5];
471 let a5 = pr[2] * r[3] + pr[5] * r[4] + pr[8] * r[5];
472 let a6 = pr[0] * r[6] + pr[3] * r[7] + pr[6] * r[8];
473 let a7 = pr[1] * r[6] + pr[4] * r[7] + pr[7] * r[8];
474 let a8 = pr[2] * r[6] + pr[5] * r[7] + pr[8] * r[8];
475 let f0 = por[0] * a0 + por[1] * a3 + por[2] * a6;
476 let f1 = por[0] * a1 + por[1] * a4 + por[2] * a7;
477 let f2 = por[0] * a2 + por[1] * a5 + por[2] * a8;
478 let f3 = por[3] * a0 + por[4] * a3 + por[5] * a6;
479 let f4 = por[3] * a1 + por[4] * a4 + por[5] * a7;
480 let f5 = por[3] * a2 + por[4] * a5 + por[5] * a8;
481 let f6 = por[6] * a0 + por[7] * a3 + por[8] * a6;
482 let f7 = por[6] * a1 + por[7] * a4 + por[8] * a7;
483 let f8 = por[6] * a2 + por[7] * a5 + por[8] * a8;
484 let m0 = sx * f0;
485 let m1 = sx * f1;
486 let m2 = sx * f2;
487 let m3 = 0.0;
488 let m4 = sy * f3;
489 let m5 = sy * f4;
490 let m6 = sy * f5;
491 let m7 = 0.0;
492 let m8 = sz * f6;
493 let m9 = sz * f7;
494 let m10 = sz * f8;
495 let m11 = 0.0;
496 let k0 = spx * f0;
497 let k1 = spy * f3;
498 let k2 = spz * f6;
499 let m12 = rox + rpx + tx - rpx * f0 - rpy * f3 - rpz * f6
500 + sox * f0
501 + k0
502 + soy * f3
503 + k1
504 + soz * f6
505 + k2
506 - sx * k0
507 - sy * k1
508 - sz * k2;
509 let k3 = spx * f1;
510 let k4 = spy * f4;
511 let k5 = spz * f7;
512 let m13 = roy + rpy + ty - rpx * f1 - rpy * f4 - rpz * f7
513 + sox * f1
514 + k3
515 + soy * f4
516 + k4
517 + soz * f7
518 + k5
519 - sx * k3
520 - sy * k4
521 - sz * k5;
522 let k6 = spx * f2;
523 let k7 = spy * f5;
524 let k8 = spz * f8;
525 let m14 = roz + rpz + tz - rpx * f2 - rpy * f5 - rpz * f8
526 + sox * f2
527 + k6
528 + soy * f5
529 + k7
530 + soz * f8
531 + k8
532 - sx * k6
533 - sy * k7
534 - sz * k8;
535 let m15 = 1.0;
536 Matrix4::new(
537 m0, m4, m8, m12, m1, m5, m9, m13, m2, m6, m10, m14, m3, m7, m11, m15,
538 )
539 }
540
541 pub fn matrix(&self) -> Matrix4<f32> {
544 if self.dirty.get() {
545 self.matrix.set(self.calculate_local_transform());
546 self.dirty.set(false)
547 }
548 self.matrix.get()
549 }
550}
551
552pub struct TransformBuilder {
555 local_scale: Vector3<f32>,
556 local_position: Vector3<f32>,
557 local_rotation: UnitQuaternion<f32>,
558 pre_rotation: UnitQuaternion<f32>,
559 post_rotation: UnitQuaternion<f32>,
560 rotation_offset: Vector3<f32>,
561 rotation_pivot: Vector3<f32>,
562 scaling_offset: Vector3<f32>,
563 scaling_pivot: Vector3<f32>,
564}
565
566impl Default for TransformBuilder {
567 fn default() -> Self {
568 Self::new()
569 }
570}
571
572impl TransformBuilder {
573 pub fn new() -> Self {
576 Self {
577 local_scale: Vector3::new(1.0, 1.0, 1.0),
578 local_position: Default::default(),
579 local_rotation: UnitQuaternion::identity(),
580 pre_rotation: UnitQuaternion::identity(),
581 post_rotation: UnitQuaternion::identity(),
582 rotation_offset: Default::default(),
583 rotation_pivot: Default::default(),
584 scaling_offset: Default::default(),
585 scaling_pivot: Default::default(),
586 }
587 }
588
589 pub fn with_local_scale(mut self, scale: Vector3<f32>) -> Self {
591 self.local_scale = scale;
592 self
593 }
594
595 pub fn with_local_position(mut self, position: Vector3<f32>) -> Self {
597 self.local_position = position;
598 self
599 }
600
601 pub fn with_local_rotation(mut self, rotation: UnitQuaternion<f32>) -> Self {
603 self.local_rotation = rotation;
604 self
605 }
606
607 pub fn with_pre_rotation(mut self, rotation: UnitQuaternion<f32>) -> Self {
609 self.pre_rotation = rotation;
610 self
611 }
612
613 pub fn with_post_rotation(mut self, rotation: UnitQuaternion<f32>) -> Self {
615 self.post_rotation = rotation;
616 self
617 }
618
619 pub fn with_rotation_offset(mut self, offset: Vector3<f32>) -> Self {
621 self.rotation_offset = offset;
622 self
623 }
624
625 pub fn with_rotation_pivot(mut self, pivot: Vector3<f32>) -> Self {
627 self.rotation_pivot = pivot;
628 self
629 }
630
631 pub fn with_scaling_offset(mut self, offset: Vector3<f32>) -> Self {
633 self.scaling_offset = offset;
634 self
635 }
636
637 pub fn with_scaling_pivot(mut self, pivot: Vector3<f32>) -> Self {
639 self.scaling_pivot = pivot;
640 self
641 }
642
643 pub fn build(self) -> Transform {
645 Transform {
646 dirty: Cell::new(true),
647 local_scale: self.local_scale.into(),
648 local_position: self.local_position.into(),
649 local_rotation: self.local_rotation.into(),
650 pre_rotation: self.pre_rotation.into(),
651 post_rotation: self.post_rotation.into(),
652 rotation_offset: self.rotation_offset.into(),
653 rotation_pivot: self.rotation_pivot.into(),
654 scaling_offset: self.scaling_offset.into(),
655 scaling_pivot: self.scaling_pivot.into(),
656 matrix: Cell::new(Matrix4::identity()),
657 post_rotation_matrix: build_post_rotation_matrix(self.post_rotation),
658 }
659 }
660}