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(
85 description = "Local scale of the transform",
86 setter = "set_scale_internal",
87 step = 0.1
88 )]
89 local_scale: InheritableVariable<Vector3<f32>>,
90
91 #[reflect(
92 description = "Local position of the transform",
93 setter = "set_position_internal",
94 step = 0.1
95 )]
96 local_position: InheritableVariable<Vector3<f32>>,
97
98 #[reflect(
99 description = "Local rotation of the transform",
100 setter = "set_rotation_internal",
101 step = 1.0
102 )]
103 local_rotation: InheritableVariable<UnitQuaternion<f32>>,
104
105 #[reflect(
106 description = "Pre rotation of the transform. Applied before local rotation.",
107 setter = "set_pre_rotation_internal",
108 step = 1.0
109 )]
110 pre_rotation: InheritableVariable<UnitQuaternion<f32>>,
111
112 #[reflect(
113 description = "Post rotation of the transform. Applied after local rotation.",
114 setter = "set_post_rotation_internal",
115 step = 1.0
116 )]
117 post_rotation: InheritableVariable<UnitQuaternion<f32>>,
118
119 #[reflect(
120 description = "Rotation offset of the transform.",
121 setter = "set_rotation_offset_internal",
122 step = 0.1
123 )]
124 rotation_offset: InheritableVariable<Vector3<f32>>,
125
126 #[reflect(
127 description = "Rotation pivot of the transform.",
128 setter = "set_rotation_pivot_internal",
129 step = 0.1
130 )]
131 rotation_pivot: InheritableVariable<Vector3<f32>>,
132
133 #[reflect(
134 description = "Scale offset of the transform.",
135 setter = "set_scaling_offset_internal",
136 step = 0.1
137 )]
138 scaling_offset: InheritableVariable<Vector3<f32>>,
139
140 #[reflect(
141 description = "Scale pivot of the transform.",
142 setter = "set_scaling_pivot_internal",
143 step = 0.1
144 )]
145 scaling_pivot: InheritableVariable<Vector3<f32>>,
146
147 #[reflect(hidden)]
149 matrix: Cell<Matrix4<f32>>,
150
151 #[reflect(hidden)]
152 post_rotation_matrix: Matrix3<f32>,
153}
154
155impl Visit for Transform {
156 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
157 let mut region = visitor.enter_region(name)?;
158
159 self.local_scale.visit("LocalScale", &mut region)?;
160 self.local_position.visit("LocalPosition", &mut region)?;
161 self.local_rotation.visit("LocalRotation", &mut region)?;
162 self.pre_rotation.visit("PreRotation", &mut region)?;
163 self.post_rotation.visit("PostRotation", &mut region)?;
164 self.rotation_offset.visit("RotationOffset", &mut region)?;
165 self.rotation_pivot.visit("RotationPivot", &mut region)?;
166 self.scaling_offset.visit("ScalingOffset", &mut region)?;
167 self.scaling_pivot.visit("ScalingPivot", &mut region)?;
168
169 drop(region);
170
171 if visitor.is_reading() {
172 self.post_rotation_matrix =
173 build_post_rotation_matrix(self.post_rotation.clone_inner());
174 }
175
176 Ok(())
177 }
178}
179
180impl Default for Transform {
181 fn default() -> Self {
182 Self::identity()
183 }
184}
185
186fn build_post_rotation_matrix(post_rotation: UnitQuaternion<f32>) -> Matrix3<f32> {
187 post_rotation
188 .to_rotation_matrix()
189 .matrix()
190 .try_inverse()
191 .unwrap_or_else(|| {
192 Log::writeln(
193 MessageKind::Warning,
194 "Unable to inverse post rotation matrix! Fallback to identity matrix.",
195 );
196 Matrix3::identity()
197 })
198}
199
200impl Transform {
201 pub fn identity() -> Self {
204 Self {
205 dirty: Cell::new(true),
206 local_position: InheritableVariable::new_modified(Vector3::default()),
207 local_scale: InheritableVariable::new_modified(Vector3::new(1.0, 1.0, 1.0)),
208 local_rotation: InheritableVariable::new_modified(UnitQuaternion::identity()),
209 pre_rotation: InheritableVariable::new_modified(UnitQuaternion::identity()),
210 post_rotation: InheritableVariable::new_modified(UnitQuaternion::identity()),
211 rotation_offset: InheritableVariable::new_modified(Vector3::default()),
212 rotation_pivot: InheritableVariable::new_modified(Vector3::default()),
213 scaling_offset: InheritableVariable::new_modified(Vector3::default()),
214 scaling_pivot: InheritableVariable::new_modified(Vector3::default()),
215 matrix: Cell::new(Matrix4::identity()),
216 post_rotation_matrix: Matrix3::identity(),
217 }
218 }
219
220 #[inline]
222 pub fn position(&self) -> &InheritableVariable<Vector3<f32>> {
223 &self.local_position
224 }
225
226 #[inline]
228 pub fn set_position(&mut self, local_position: Vector3<f32>) -> &mut Self {
229 if self.dirty.get() || *self.local_position != local_position {
230 self.set_position_internal(local_position);
231 }
232 self
233 }
234
235 #[inline]
236 fn set_position_internal(&mut self, local_position: Vector3<f32>) -> Vector3<f32> {
237 self.dirty.set(true);
238 self.local_position
239 .set_value_and_mark_modified(local_position)
240 }
241
242 #[inline]
244 pub fn rotation(&self) -> &InheritableVariable<UnitQuaternion<f32>> {
245 &self.local_rotation
246 }
247
248 #[inline]
250 pub fn set_rotation(&mut self, local_rotation: UnitQuaternion<f32>) -> &mut Self {
251 if self.dirty.get() || *self.local_rotation != local_rotation {
252 self.set_rotation_internal(local_rotation);
253 }
254 self
255 }
256
257 #[inline]
258 fn set_rotation_internal(
259 &mut self,
260 local_rotation: UnitQuaternion<f32>,
261 ) -> UnitQuaternion<f32> {
262 self.dirty.set(true);
263 self.local_rotation
264 .set_value_and_mark_modified(local_rotation)
265 }
266
267 #[inline]
269 pub fn scale(&self) -> &InheritableVariable<Vector3<f32>> {
270 &self.local_scale
271 }
272
273 #[inline]
275 pub fn set_scale(&mut self, local_scale: Vector3<f32>) -> &mut Self {
276 if self.dirty.get() || *self.local_scale != local_scale {
277 self.set_scale_internal(local_scale);
278 }
279 self
280 }
281
282 #[inline]
283 fn set_scale_internal(&mut self, local_scale: Vector3<f32>) -> Vector3<f32> {
284 self.dirty.set(true);
285 self.local_scale.set_value_and_mark_modified(local_scale)
286 }
287
288 #[inline]
292 pub fn set_pre_rotation(&mut self, pre_rotation: UnitQuaternion<f32>) -> &mut Self {
293 if self.dirty.get() || *self.pre_rotation != pre_rotation {
294 self.set_pre_rotation_internal(pre_rotation);
295 }
296 self
297 }
298
299 #[inline]
300 fn set_pre_rotation_internal(
301 &mut self,
302 pre_rotation: UnitQuaternion<f32>,
303 ) -> UnitQuaternion<f32> {
304 self.dirty.set(true);
305 self.pre_rotation.set_value_and_mark_modified(pre_rotation)
306 }
307
308 #[inline]
310 pub fn pre_rotation(&self) -> &InheritableVariable<UnitQuaternion<f32>> {
311 &self.pre_rotation
312 }
313
314 #[inline]
318 pub fn set_post_rotation(&mut self, post_rotation: UnitQuaternion<f32>) -> &mut Self {
319 if self.dirty.get() || *self.post_rotation != post_rotation {
320 self.set_post_rotation_internal(post_rotation);
321 }
322 self
323 }
324
325 #[inline]
326 fn set_post_rotation_internal(
327 &mut self,
328 post_rotation: UnitQuaternion<f32>,
329 ) -> UnitQuaternion<f32> {
330 self.post_rotation_matrix = build_post_rotation_matrix(post_rotation);
331 self.dirty.set(true);
332 self.post_rotation
333 .set_value_and_mark_modified(post_rotation)
334 }
335
336 #[inline]
338 pub fn post_rotation(&self) -> &InheritableVariable<UnitQuaternion<f32>> {
339 &self.post_rotation
340 }
341
342 #[inline]
345 pub fn set_rotation_offset(&mut self, rotation_offset: Vector3<f32>) -> &mut Self {
346 if self.dirty.get() || *self.rotation_offset != rotation_offset {
347 self.set_rotation_offset_internal(rotation_offset);
348 }
349 self
350 }
351
352 #[inline]
353 fn set_rotation_offset_internal(&mut self, rotation_offset: Vector3<f32>) -> Vector3<f32> {
354 self.dirty.set(true);
355 self.rotation_offset
356 .set_value_and_mark_modified(rotation_offset)
357 }
358
359 #[inline]
361 pub fn rotation_offset(&self) -> &InheritableVariable<Vector3<f32>> {
362 &self.rotation_offset
363 }
364
365 #[inline]
369 pub fn set_rotation_pivot(&mut self, rotation_pivot: Vector3<f32>) -> &mut Self {
370 if self.dirty.get() || *self.rotation_pivot != rotation_pivot {
371 self.set_rotation_pivot_internal(rotation_pivot);
372 }
373 self
374 }
375
376 #[inline]
377 fn set_rotation_pivot_internal(&mut self, rotation_pivot: Vector3<f32>) -> Vector3<f32> {
378 self.dirty.set(true);
379 self.rotation_pivot
380 .set_value_and_mark_modified(rotation_pivot)
381 }
382
383 #[inline]
385 pub fn rotation_pivot(&self) -> &InheritableVariable<Vector3<f32>> {
386 &self.rotation_pivot
387 }
388
389 #[inline]
392 pub fn set_scaling_offset(&mut self, scaling_offset: Vector3<f32>) -> &mut Self {
393 if self.dirty.get() || *self.scaling_offset != scaling_offset {
394 self.set_scaling_offset_internal(scaling_offset);
395 self.dirty.set(true);
396 }
397 self
398 }
399
400 #[inline]
401 fn set_scaling_offset_internal(&mut self, scaling_offset: Vector3<f32>) -> Vector3<f32> {
402 self.dirty.set(true);
403 self.scaling_offset
404 .set_value_and_mark_modified(scaling_offset)
405 }
406
407 #[inline]
409 pub fn scaling_offset(&self) -> &InheritableVariable<Vector3<f32>> {
410 &self.scaling_offset
411 }
412
413 #[inline]
416 pub fn set_scaling_pivot(&mut self, scaling_pivot: Vector3<f32>) -> &mut Self {
417 if self.dirty.get() || *self.scaling_pivot != scaling_pivot {
418 self.set_scaling_pivot_internal(scaling_pivot);
419 self.dirty.set(true);
420 }
421 self
422 }
423
424 #[inline]
425 fn set_scaling_pivot_internal(&mut self, scaling_pivot: Vector3<f32>) -> Vector3<f32> {
426 self.dirty.set(true);
427 self.scaling_pivot
428 .set_value_and_mark_modified(scaling_pivot)
429 }
430
431 #[inline]
433 pub fn scaling_pivot(&self) -> &InheritableVariable<Vector3<f32>> {
434 &self.scaling_pivot
435 }
436
437 #[inline]
440 pub fn offset(&mut self, vec: Vector3<f32>) -> &mut Self {
441 self.local_position
442 .set_value_and_mark_modified(*self.local_position + vec);
443 self.dirty.set(true);
444 self
445 }
446
447 fn calculate_local_transform(&self) -> Matrix4<f32> {
448 let por = &self.post_rotation_matrix;
450 let pr = *self.pre_rotation.to_rotation_matrix().matrix();
451 let r = *self.local_rotation.to_rotation_matrix().matrix();
452
453 let sx = self.local_scale.x;
454 let sy = self.local_scale.y;
455 let sz = self.local_scale.z;
456
457 let tx = self.local_position.x;
458 let ty = self.local_position.y;
459 let tz = self.local_position.z;
460
461 let rpx = self.rotation_pivot.x;
462 let rpy = self.rotation_pivot.y;
463 let rpz = self.rotation_pivot.z;
464
465 let rox = self.rotation_offset.x;
466 let roy = self.rotation_offset.y;
467 let roz = self.rotation_offset.z;
468
469 let spx = self.scaling_pivot.x;
470 let spy = self.scaling_pivot.y;
471 let spz = self.scaling_pivot.z;
472
473 let sox = self.scaling_offset.x;
474 let soy = self.scaling_offset.y;
475 let soz = self.scaling_offset.z;
476
477 let a0 = pr[0] * r[0] + pr[3] * r[1] + pr[6] * r[2];
494 let a1 = pr[1] * r[0] + pr[4] * r[1] + pr[7] * r[2];
495 let a2 = pr[2] * r[0] + pr[5] * r[1] + pr[8] * r[2];
496 let a3 = pr[0] * r[3] + pr[3] * r[4] + pr[6] * r[5];
497 let a4 = pr[1] * r[3] + pr[4] * r[4] + pr[7] * r[5];
498 let a5 = pr[2] * r[3] + pr[5] * r[4] + pr[8] * r[5];
499 let a6 = pr[0] * r[6] + pr[3] * r[7] + pr[6] * r[8];
500 let a7 = pr[1] * r[6] + pr[4] * r[7] + pr[7] * r[8];
501 let a8 = pr[2] * r[6] + pr[5] * r[7] + pr[8] * r[8];
502 let f0 = por[0] * a0 + por[1] * a3 + por[2] * a6;
503 let f1 = por[0] * a1 + por[1] * a4 + por[2] * a7;
504 let f2 = por[0] * a2 + por[1] * a5 + por[2] * a8;
505 let f3 = por[3] * a0 + por[4] * a3 + por[5] * a6;
506 let f4 = por[3] * a1 + por[4] * a4 + por[5] * a7;
507 let f5 = por[3] * a2 + por[4] * a5 + por[5] * a8;
508 let f6 = por[6] * a0 + por[7] * a3 + por[8] * a6;
509 let f7 = por[6] * a1 + por[7] * a4 + por[8] * a7;
510 let f8 = por[6] * a2 + por[7] * a5 + por[8] * a8;
511 let m0 = sx * f0;
512 let m1 = sx * f1;
513 let m2 = sx * f2;
514 let m3 = 0.0;
515 let m4 = sy * f3;
516 let m5 = sy * f4;
517 let m6 = sy * f5;
518 let m7 = 0.0;
519 let m8 = sz * f6;
520 let m9 = sz * f7;
521 let m10 = sz * f8;
522 let m11 = 0.0;
523 let k0 = spx * f0;
524 let k1 = spy * f3;
525 let k2 = spz * f6;
526 let m12 = rox + rpx + tx - rpx * f0 - rpy * f3 - rpz * f6
527 + sox * f0
528 + k0
529 + soy * f3
530 + k1
531 + soz * f6
532 + k2
533 - sx * k0
534 - sy * k1
535 - sz * k2;
536 let k3 = spx * f1;
537 let k4 = spy * f4;
538 let k5 = spz * f7;
539 let m13 = roy + rpy + ty - rpx * f1 - rpy * f4 - rpz * f7
540 + sox * f1
541 + k3
542 + soy * f4
543 + k4
544 + soz * f7
545 + k5
546 - sx * k3
547 - sy * k4
548 - sz * k5;
549 let k6 = spx * f2;
550 let k7 = spy * f5;
551 let k8 = spz * f8;
552 let m14 = roz + rpz + tz - rpx * f2 - rpy * f5 - rpz * f8
553 + sox * f2
554 + k6
555 + soy * f5
556 + k7
557 + soz * f8
558 + k8
559 - sx * k6
560 - sy * k7
561 - sz * k8;
562 let m15 = 1.0;
563 Matrix4::new(
564 m0, m4, m8, m12, m1, m5, m9, m13, m2, m6, m10, m14, m3, m7, m11, m15,
565 )
566 }
567
568 pub fn matrix(&self) -> Matrix4<f32> {
571 if self.dirty.get() {
572 self.matrix.set(self.calculate_local_transform());
573 self.dirty.set(false)
574 }
575 self.matrix.get()
576 }
577}
578
579pub struct TransformBuilder {
582 local_scale: Vector3<f32>,
583 local_position: Vector3<f32>,
584 local_rotation: UnitQuaternion<f32>,
585 pre_rotation: UnitQuaternion<f32>,
586 post_rotation: UnitQuaternion<f32>,
587 rotation_offset: Vector3<f32>,
588 rotation_pivot: Vector3<f32>,
589 scaling_offset: Vector3<f32>,
590 scaling_pivot: Vector3<f32>,
591}
592
593impl Default for TransformBuilder {
594 fn default() -> Self {
595 Self::new()
596 }
597}
598
599impl TransformBuilder {
600 pub fn new() -> Self {
603 Self {
604 local_scale: Vector3::new(1.0, 1.0, 1.0),
605 local_position: Default::default(),
606 local_rotation: UnitQuaternion::identity(),
607 pre_rotation: UnitQuaternion::identity(),
608 post_rotation: UnitQuaternion::identity(),
609 rotation_offset: Default::default(),
610 rotation_pivot: Default::default(),
611 scaling_offset: Default::default(),
612 scaling_pivot: Default::default(),
613 }
614 }
615
616 pub fn with_local_scale(mut self, scale: Vector3<f32>) -> Self {
618 self.local_scale = scale;
619 self
620 }
621
622 pub fn with_local_position(mut self, position: Vector3<f32>) -> Self {
624 self.local_position = position;
625 self
626 }
627
628 pub fn with_local_rotation(mut self, rotation: UnitQuaternion<f32>) -> Self {
630 self.local_rotation = rotation;
631 self
632 }
633
634 pub fn with_pre_rotation(mut self, rotation: UnitQuaternion<f32>) -> Self {
636 self.pre_rotation = rotation;
637 self
638 }
639
640 pub fn with_post_rotation(mut self, rotation: UnitQuaternion<f32>) -> Self {
642 self.post_rotation = rotation;
643 self
644 }
645
646 pub fn with_rotation_offset(mut self, offset: Vector3<f32>) -> Self {
648 self.rotation_offset = offset;
649 self
650 }
651
652 pub fn with_rotation_pivot(mut self, pivot: Vector3<f32>) -> Self {
654 self.rotation_pivot = pivot;
655 self
656 }
657
658 pub fn with_scaling_offset(mut self, offset: Vector3<f32>) -> Self {
660 self.scaling_offset = offset;
661 self
662 }
663
664 pub fn with_scaling_pivot(mut self, pivot: Vector3<f32>) -> Self {
666 self.scaling_pivot = pivot;
667 self
668 }
669
670 pub fn build(self) -> Transform {
672 Transform {
673 dirty: Cell::new(true),
674 local_scale: self.local_scale.into(),
675 local_position: self.local_position.into(),
676 local_rotation: self.local_rotation.into(),
677 pre_rotation: self.pre_rotation.into(),
678 post_rotation: self.post_rotation.into(),
679 rotation_offset: self.rotation_offset.into(),
680 rotation_pivot: self.rotation_pivot.into(),
681 scaling_offset: self.scaling_offset.into(),
682 scaling_pivot: self.scaling_pivot.into(),
683 matrix: Cell::new(Matrix4::identity()),
684 post_rotation_matrix: build_post_rotation_matrix(self.post_rotation),
685 }
686 }
687}