@@ -2,11 +2,21 @@ use crate::core_types::{IsEqualApprox, Quat, Vector3};
2
2
use core:: ops:: Mul ;
3
3
use glam:: Mat3 ;
4
4
5
- /// A 3x3 matrix, usually used as an orthogonal basis for [`Transform`].
5
+ /// A 3x3 matrix, typically used as an orthogonal basis for [`Transform`][crate::core_types::Transform].
6
+ ///
7
+ /// The basis vectors are the column vectors of the matrix, while the [`elements`][Self::elements]
8
+ /// field represents the row vectors.
9
+ ///
10
+ /// See also [Basis](https://docs.godotengine.org/en/stable/classes/class_basis.html) in the Godot API doc.
6
11
#[ repr( C ) ]
7
12
#[ derive( Copy , Clone , Debug , PartialEq ) ]
8
13
#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
9
14
pub struct Basis {
15
+ /// Matrix rows. These are **not** the basis vectors!
16
+ ///
17
+ /// This is a transposed view for performance. <br>
18
+ /// To read basis vectors, see [`x()`][Self::x], [`y()`][Self::y], [`z()`][Self::z]. <br>
19
+ /// To write them, see [`set_x()`][Self::set_x], [`set_y()`][Self::set_x], [`set_z()`][Self::set_x].
10
20
pub elements : [ Vector3 ; 3 ] ,
11
21
}
12
22
@@ -18,10 +28,10 @@ impl Default for Basis {
18
28
}
19
29
20
30
impl Basis {
21
- /// The identity basis.
31
+ /// The identity basis. Basis vectors are unit vectors along each axis X, Y and Z.
22
32
///
23
33
/// Equivalent to calling [`Basis::default()`].
24
- pub const IDENTITY : Basis = Self {
34
+ pub const IDENTITY : Self = Self {
25
35
elements : [
26
36
Vector3 :: new ( 1.0 , 0.0 , 0.0 ) ,
27
37
Vector3 :: new ( 0.0 , 1.0 , 0.0 ) ,
@@ -30,30 +40,69 @@ impl Basis {
30
40
} ;
31
41
32
42
/// The basis that will flip something along the **X axis** when used in a transformation.
33
- pub const FLIP_X : Self = Basis :: from_diagonal ( Vector3 :: new ( -1.0 , 1.0 , 1.0 ) ) ;
43
+ pub const FLIP_X : Self = Self :: from_diagonal ( Vector3 :: new ( -1.0 , 1.0 , 1.0 ) ) ;
34
44
35
45
/// The basis that will flip something along the **Y axis** when used in a transformation.
36
- pub const FLIP_Y : Self = Basis :: from_diagonal ( Vector3 :: new ( 1.0 , -1.0 , 1.0 ) ) ;
46
+ pub const FLIP_Y : Self = Self :: from_diagonal ( Vector3 :: new ( 1.0 , -1.0 , 1.0 ) ) ;
37
47
38
48
/// The basis that will flip something along the **Z axis** when used in a transformation.
39
- pub const FLIP_Z : Self = Basis :: from_diagonal ( Vector3 :: new ( 1.0 , 1.0 , -1.0 ) ) ;
49
+ pub const FLIP_Z : Self = Self :: from_diagonal ( Vector3 :: new ( 1.0 , 1.0 , -1.0 ) ) ;
40
50
41
- /// Creates a Basis from the given [`Vector3`](./type.Vector3.html)
51
+ /// Constructs a basis matrix from 3 linearly independent basis vectors (matrix columns).
52
+ ///
53
+ /// This is the typical way to construct a basis. If you want to fill in the elements one-by-one,
54
+ /// consider using [`Self::from_rows()`] instead.
42
55
#[ inline]
43
- pub const fn from_diagonal ( p_diag : Vector3 ) -> Self {
56
+ pub const fn from_basis_vectors ( a : Vector3 , b : Vector3 , c : Vector3 ) -> Self {
44
57
Self {
45
58
elements : [
46
- Vector3 :: new ( p_diag . x , 0.0 , 0.0 ) ,
47
- Vector3 :: new ( 0.0 , p_diag . y , 0.0 ) ,
48
- Vector3 :: new ( 0.0 , 0.0 , p_diag . z ) ,
59
+ Vector3 :: new ( a . x , b . x , c . x ) ,
60
+ Vector3 :: new ( a . y , b . y , c . y ) ,
61
+ Vector3 :: new ( a . z , b . z , c . z ) ,
49
62
] ,
50
63
}
51
64
}
52
65
53
- /// Creates a `Basis` from 3 vectors
66
+ /// Creates a basis from 3 row vectors. These are **not** basis vectors.
67
+ ///
68
+ /// This constructor is mostly useful if you want to write matrix elements
69
+ /// in matrix syntax:
70
+ /// ```
71
+ /// # use gdnative::core_types::{Vector3, Basis};
72
+ /// # let a = Vector3::RIGHT;
73
+ /// # let b = Vector3::UP;
74
+ /// # let c = Vector3::BACK;
75
+ /// let basis = Basis::from_rows(
76
+ /// Vector3::new(a.x, b.x, c.x),
77
+ /// Vector3::new(a.y, b.y, c.y),
78
+ /// Vector3::new(a.z, b.z, c.z),
79
+ /// );
80
+ /// ```
81
+ /// In that case, the vectors `a`, `b` and `c` are the basis vectors.
82
+ #[ inline]
83
+ pub const fn from_rows (
84
+ x_components : Vector3 ,
85
+ y_components : Vector3 ,
86
+ z_components : Vector3 ,
87
+ ) -> Self {
88
+ Self {
89
+ elements : [ x_components, y_components, z_components] ,
90
+ }
91
+ }
92
+
93
+ /// Creates a diagonal matrix from the given vector.
94
+ ///
95
+ /// Can be used as a basis for a scaling transform.
96
+ /// Each component of `scale` represents the scale factor in the corresponding direction.
54
97
#[ inline]
55
- pub const fn from_elements ( elements : [ Vector3 ; 3 ] ) -> Self {
56
- Self { elements }
98
+ pub const fn from_diagonal ( scale : Vector3 ) -> Self {
99
+ Self {
100
+ elements : [
101
+ Vector3 :: new ( scale. x , 0.0 , 0.0 ) ,
102
+ Vector3 :: new ( 0.0 , scale. y , 0.0 ) ,
103
+ Vector3 :: new ( 0.0 , 0.0 , scale. z ) ,
104
+ ] ,
105
+ }
57
106
}
58
107
59
108
/// Creates a rotation matrix from Euler angles.
@@ -62,35 +111,35 @@ impl Basis {
62
111
/// first **Z**, then **X**, and **Y** last.
63
112
#[ inline]
64
113
pub fn from_euler ( euler_angles : Vector3 ) -> Self {
65
- let mut b = Basis :: default ( ) ;
66
- b. set_euler_yxz ( & euler_angles) ;
114
+ let mut b = Self :: default ( ) ;
115
+ b. set_euler_yxz ( euler_angles) ;
67
116
b
68
117
}
69
118
70
119
#[ inline]
71
- fn set_euler_yxz ( & mut self , euler : & Vector3 ) {
120
+ fn set_euler_yxz ( & mut self , euler : Vector3 ) {
72
121
let c = euler. x . cos ( ) ;
73
122
let s = euler. x . sin ( ) ;
74
- let xmat = Basis :: from_elements ( [
123
+ let xmat = Self :: from_rows (
75
124
Vector3 :: new ( 1.0 , 0.0 , 0.0 ) ,
76
125
Vector3 :: new ( 0.0 , c, -s) ,
77
126
Vector3 :: new ( 0.0 , s, c) ,
78
- ] ) ;
127
+ ) ;
79
128
let c = euler. y . cos ( ) ;
80
129
let s = euler. y . sin ( ) ;
81
- let ymat = Basis :: from_elements ( [
130
+ let ymat = Self :: from_rows (
82
131
Vector3 :: new ( c, 0.0 , s) ,
83
132
Vector3 :: new ( 0.0 , 1.0 , 0.0 ) ,
84
133
Vector3 :: new ( -s, 0.0 , c) ,
85
- ] ) ;
134
+ ) ;
86
135
87
136
let c = euler. z . cos ( ) ;
88
137
let s = euler. z . sin ( ) ;
89
- let zmat = Basis :: from_elements ( [
138
+ let zmat = Self :: from_rows (
90
139
Vector3 :: new ( c, -s, 0.0 ) ,
91
140
Vector3 :: new ( s, c, 0.0 ) ,
92
141
Vector3 :: new ( 0.0 , 0.0 , 1.0 ) ,
93
- ] ) ;
142
+ ) ;
94
143
95
144
* self = ymat * xmat * zmat;
96
145
}
@@ -99,29 +148,29 @@ impl Basis {
99
148
#[ inline]
100
149
pub fn from_quat ( quat : Quat ) -> Self {
101
150
let basis = Mat3 :: from_quat ( quat. glam ( ) ) . to_cols_array_2d ( ) ;
102
- let basis = [
151
+
152
+ Self :: from_rows (
103
153
Vector3 :: new ( basis[ 0 ] [ 0 ] , basis[ 1 ] [ 0 ] , basis[ 2 ] [ 0 ] ) ,
104
154
Vector3 :: new ( basis[ 0 ] [ 1 ] , basis[ 1 ] [ 1 ] , basis[ 2 ] [ 1 ] ) ,
105
155
Vector3 :: new ( basis[ 0 ] [ 2 ] , basis[ 1 ] [ 2 ] , basis[ 2 ] [ 2 ] ) ,
106
- ] ;
107
- Basis :: from_elements ( basis)
156
+ )
108
157
}
109
158
110
159
/// Rotation matrix from axis and angle.
111
160
///
112
- /// See <https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle >
161
+ /// See <https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle >
113
162
///
114
163
/// # Panics
115
164
///
116
165
/// If `axis` is not normalized.
117
166
#[ inline]
118
- pub fn from_axis_angle ( axis : & Vector3 , phi : f32 ) -> Self {
167
+ pub fn from_axis_angle ( axis : Vector3 , phi : f32 ) -> Self {
119
168
assert ! (
120
169
axis. length( ) . is_equal_approx( 1.0 ) ,
121
170
"The axis Vector3 must be normalized."
122
171
) ;
123
172
124
- let mut basis = Basis :: default ( ) ;
173
+ let mut basis = Self :: default ( ) ;
125
174
let [ x, y, z] = & mut basis. elements ;
126
175
127
176
let axis_sq = Vector3 :: new ( axis. x * axis. x , axis. y * axis. y , axis. z * axis. z ) ;
@@ -283,7 +332,7 @@ impl Basis {
283
332
/// of the 3D object. `rotated()` here refers to rotation of the object (which is `R * self`), not the matrix itself.
284
333
#[ inline]
285
334
pub fn rotated ( & self , axis : Vector3 , phi : f32 ) -> Self {
286
- let rot = Basis :: from_axis_angle ( & axis, phi) ;
335
+ let rot = Basis :: from_axis_angle ( axis, phi) ;
287
336
rot * ( * self )
288
337
}
289
338
@@ -316,7 +365,7 @@ impl Basis {
316
365
317
366
/// Introduce an additional scaling specified by the given 3D scaling factor.
318
367
#[ inline]
319
- pub fn scaled ( & self , scale : & Vector3 ) -> Self {
368
+ pub fn scaled ( & self , scale : Vector3 ) -> Self {
320
369
let mut copy = * self ;
321
370
copy. scale_self ( scale) ;
322
371
copy
@@ -326,7 +375,7 @@ impl Basis {
326
375
///
327
376
/// See the comment for [Basis::rotated](#method.rotated) for further explanation.
328
377
#[ inline]
329
- fn scale_self ( & mut self , s : & Vector3 ) {
378
+ fn scale_self ( & mut self , s : Vector3 ) {
330
379
self . elements [ 0 ] *= s. x ;
331
380
self . elements [ 1 ] *= s. y ;
332
381
self . elements [ 2 ] *= s. z ;
@@ -349,7 +398,7 @@ impl Basis {
349
398
let det = matrix. determinant ( ) ;
350
399
if det < 0.0 {
351
400
// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
352
- matrix. scale_self ( & Vector3 :: new ( -1.0 , -1.0 , -1.0 ) ) ;
401
+ matrix. scale_self ( Vector3 :: new ( -1.0 , -1.0 , -1.0 ) ) ;
353
402
}
354
403
355
404
assert ! ( matrix. is_rotation( ) , "Basis must be normalized in order to be casted to a Quaternion. Use to_quat() or call orthonormalized() instead." ) ;
@@ -469,59 +518,59 @@ impl Basis {
469
518
)
470
519
}
471
520
472
- /// Transposed dot product with the **X axis ** of the matrix.
521
+ /// Transposed dot product with the **X basis vector ** of the matrix.
473
522
#[ inline]
474
- pub fn tdotx ( & self , v : Vector3 ) -> f32 {
475
- self . elements [ 0 ] . x * v . x + self . elements [ 1 ] . x * v . y + self . elements [ 2 ] . x * v . z
523
+ pub ( crate ) fn tdotx ( & self , v : Vector3 ) -> f32 {
524
+ self . x ( ) . dot ( v )
476
525
}
477
526
478
- /// Transposed dot product with the **Y axis ** of the matrix.
527
+ /// Transposed dot product with the **Y basis vector ** of the matrix.
479
528
#[ inline]
480
- pub fn tdoty ( & self , v : Vector3 ) -> f32 {
481
- self . elements [ 0 ] . y * v . x + self . elements [ 1 ] . y * v . y + self . elements [ 2 ] . y * v . z
529
+ pub ( crate ) fn tdoty ( & self , v : Vector3 ) -> f32 {
530
+ self . y ( ) . dot ( v )
482
531
}
483
532
484
- /// Transposed dot product with the **Z axis ** of the matrix.
533
+ /// Transposed dot product with the **Z basis vector ** of the matrix.
485
534
#[ inline]
486
- pub fn tdotz ( & self , v : Vector3 ) -> f32 {
487
- self . elements [ 0 ] . z * v . x + self . elements [ 1 ] . z * v . y + self . elements [ 2 ] . z * v . z
535
+ pub ( crate ) fn tdotz ( & self , v : Vector3 ) -> f32 {
536
+ self . z ( ) . dot ( v )
488
537
}
489
538
490
- /// Get the **X axis ** of the matrix
539
+ /// Get the **X basis vector ** (first column vector of the matrix).
491
540
#[ inline]
492
541
pub fn x ( & self ) -> Vector3 {
493
542
Vector3 :: new ( self . elements [ 0 ] . x , self . elements [ 1 ] . x , self . elements [ 2 ] . x )
494
543
}
495
544
496
- /// Set the **X axis ** of the matrix
545
+ /// Set the **X basis vector ** (first column vector of the matrix).
497
546
#[ inline]
498
547
pub fn set_x ( & mut self , v : Vector3 ) {
499
548
self . elements [ 0 ] . x = v. x ;
500
549
self . elements [ 1 ] . x = v. y ;
501
550
self . elements [ 2 ] . x = v. z ;
502
551
}
503
552
504
- /// Get the **Y axis ** of the matrix
553
+ /// Get the **Y basis vector ** (second column vector of the matrix).
505
554
#[ inline]
506
555
pub fn y ( & self ) -> Vector3 {
507
556
Vector3 :: new ( self . elements [ 0 ] . y , self . elements [ 1 ] . y , self . elements [ 2 ] . y )
508
557
}
509
558
510
- /// Set the **Y axis ** of the matrix
559
+ /// Set the **Y basis vector ** (second column vector of the matrix).
511
560
#[ inline]
512
561
pub fn set_y ( & mut self , v : Vector3 ) {
513
562
self . elements [ 0 ] . y = v. x ;
514
563
self . elements [ 1 ] . y = v. y ;
515
564
self . elements [ 2 ] . y = v. z ;
516
565
}
517
566
518
- /// Get the **Z axis ** of the matrix
567
+ /// Get the **Z basis vector ** (third column vector of the matrix).
519
568
#[ inline]
520
569
pub fn z ( & self ) -> Vector3 {
521
570
Vector3 :: new ( self . elements [ 0 ] . z , self . elements [ 1 ] . z , self . elements [ 2 ] . z )
522
571
}
523
572
524
- /// Set the **Z axis ** of the matrix
573
+ /// Set the **Z basis vector ** (third column vector of the matrix).
525
574
#[ inline]
526
575
pub fn set_z ( & mut self , v : Vector3 ) {
527
576
self . elements [ 0 ] . z = v. x ;
@@ -547,7 +596,7 @@ impl Mul<Basis> for Basis {
547
596
548
597
#[ inline]
549
598
fn mul ( self , rhs : Self ) -> Self {
550
- Basis :: from_elements ( [
599
+ Basis :: from_rows (
551
600
Vector3 :: new (
552
601
rhs. tdotx ( self . elements [ 0 ] ) ,
553
602
rhs. tdoty ( self . elements [ 0 ] ) ,
@@ -563,7 +612,7 @@ impl Mul<Basis> for Basis {
563
612
rhs. tdoty ( self . elements [ 2 ] ) ,
564
613
rhs. tdotz ( self . elements [ 2 ] ) ,
565
614
) ,
566
- ] )
615
+ )
567
616
}
568
617
}
569
618
@@ -657,36 +706,36 @@ mod tests {
657
706
fn orthonormalized ( ) {
658
707
let ( b, _bn) = test_inputs ( ) ;
659
708
660
- let expected = Basis :: from_elements ( [
709
+ let expected = Basis :: from_rows (
661
710
Vector3 :: new ( 0.077431 , -0.165055 , 0.98324 ) ,
662
711
Vector3 :: new ( -0.288147 , 0.94041 , 0.180557 ) ,
663
712
Vector3 :: new ( -0.95445 , -0.297299 , 0.025257 ) ,
664
- ] ) ;
713
+ ) ;
665
714
assert ! ( expected. is_equal_approx( & b. orthonormalized( ) ) ) ;
666
715
}
667
716
668
717
#[ test]
669
718
fn scaled ( ) {
670
719
let ( b, _bn) = test_inputs ( ) ;
671
720
672
- let expected = Basis :: from_elements ( [
721
+ let expected = Basis :: from_rows (
673
722
Vector3 :: new ( 0.052484 , -0.111876 , 0.666453 ) ,
674
723
Vector3 :: new ( 0.012407 , -0.040492 , -0.007774 ) ,
675
724
Vector3 :: new ( -0.682131 , -0.212475 , 0.018051 ) ,
676
- ] ) ;
677
- assert ! ( expected. is_equal_approx( & b. scaled( & Vector3 :: new( 0.677813 , -0.043058 , 0.714685 ) ) ) ) ;
725
+ ) ;
726
+ assert ! ( expected. is_equal_approx( & b. scaled( Vector3 :: new( 0.677813 , -0.043058 , 0.714685 ) ) ) ) ;
678
727
}
679
728
680
729
#[ test]
681
730
fn rotated ( ) {
682
731
let ( b, _bn) = test_inputs ( ) ;
683
732
684
733
let r = Vector3 :: new ( -50.167156 , 60.67781 , -70.04305 ) . normalized ( ) ;
685
- let expected = Basis :: from_elements ( [
734
+ let expected = Basis :: from_rows (
686
735
Vector3 :: new ( -0.676245 , 0.113805 , 0.727833 ) ,
687
736
Vector3 :: new ( -0.467094 , 0.697765 , -0.54309 ) ,
688
737
Vector3 :: new ( -0.569663 , -0.707229 , -0.418703 ) ,
689
- ] ) ;
738
+ ) ;
690
739
assert ! ( expected. is_equal_approx( & b. rotated( r, 1.0 ) ) ) ;
691
740
}
692
741
@@ -713,11 +762,11 @@ mod tests {
713
762
#[ test]
714
763
fn transposed ( ) {
715
764
let ( b, _bn) = test_inputs ( ) ;
716
- let expected = Basis :: from_elements ( [
765
+ let expected = Basis :: from_rows (
717
766
Vector3 :: new ( 0.077431 , -0.288147 , -0.95445 ) ,
718
767
Vector3 :: new ( -0.165055 , 0.94041 , -0.297299 ) ,
719
768
Vector3 :: new ( 0.98324 , 0.180557 , 0.025257 ) ,
720
- ] ) ;
769
+ ) ;
721
770
assert ! ( expected. is_equal_approx( & b. transposed( ) ) ) ;
722
771
}
723
772
@@ -741,11 +790,11 @@ mod tests {
741
790
fn inverse ( ) {
742
791
let ( b, _bn) = test_inputs ( ) ;
743
792
744
- let expected = Basis :: from_elements ( [
793
+ let expected = Basis :: from_rows (
745
794
Vector3 :: new ( 0.077431 , -0.288147 , -0.95445 ) ,
746
795
Vector3 :: new ( -0.165055 , 0.94041 , -0.297299 ) ,
747
796
Vector3 :: new ( 0.98324 , 0.180557 , 0.025257 ) ,
748
- ] ) ;
797
+ ) ;
749
798
assert ! ( expected. is_equal_approx( & b. inverted( ) ) ) ;
750
799
}
751
800
}
0 commit comments