@@ -2,16 +2,29 @@ use std::ops::Mul;
2
2
3
3
use crate :: core_types:: { Basis , Vector3 } ;
4
4
5
- /// 3D Transformation (3x4 matrix) Using basis + origin representation.
5
+ /// Affine 3D transform (3x4 matrix).
6
+ ///
7
+ /// Used for 3D linear transformations. Uses a basis + origin representation.
8
+ /// The
9
+ ///
10
+ /// Expressed as a 3x4 matrix, this transform consists of 3 basis (column) vectors `a`, `b`, `c`
11
+ /// as well as an origin `o`; more information in [`Self::from_basis_origin()`]:
12
+ /// ```text
13
+ /// [ a.x b.x c.x o.x ]
14
+ /// [ a.y b.y c.y o.y ]
15
+ /// [ a.z b.z c.z o.z ]
16
+ /// ```
17
+ ///
18
+ /// See also [Transform](https://docs.godotengine.org/en/stable/classes/class_transform.html) in the Godot API doc.
6
19
#[ repr( C ) ]
7
20
#[ derive( Copy , Clone , Debug , PartialEq ) ]
8
21
#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
9
22
pub struct Transform {
10
- /// The basis is a matrix containing 3 Vector3 as its columns: X axis, Y axis, and Z axis.
11
- /// These vectors can be interpreted as the basis vectors of local coordinate system
12
- /// traveling with the object.
23
+ /// The basis is a matrix containing 3 vectors as its columns. They can be interpreted
24
+ /// as the basis vectors of the transformed coordinate system.
13
25
pub basis : Basis ,
14
- /// The translation offset of the transform.
26
+
27
+ /// The new origin of the transformed coordinate system.
15
28
pub origin : Vector3 ,
16
29
}
17
30
@@ -23,45 +36,63 @@ impl Default for Transform {
23
36
}
24
37
25
38
impl Transform {
26
- #[ doc( hidden) ]
27
- #[ inline]
28
- pub fn sys ( & self ) -> * const sys:: godot_transform {
29
- unsafe {
30
- std:: mem:: transmute :: < * const Transform , * const sys:: godot_transform > ( self as * const _ )
31
- }
32
- }
39
+ /// Identity transform; leaves objects unchanged when applied.
40
+ pub const IDENTITY : Self = Self {
41
+ basis : Basis :: IDENTITY ,
42
+ origin : Vector3 :: ZERO ,
43
+ } ;
33
44
34
- #[ doc( hidden) ]
35
- #[ inline]
36
- pub fn from_sys ( c : sys:: godot_transform ) -> Self {
37
- unsafe { std:: mem:: transmute :: < sys:: godot_transform , Self > ( c) }
38
- }
45
+ /// Transform that mirrors along the **X axis** (perpendicular to the YZ plane).
46
+ pub const FLIP_X : Self = Self {
47
+ basis : Basis :: FLIP_X ,
48
+ origin : Vector3 :: ZERO ,
49
+ } ;
50
+
51
+ /// Transform that mirrors along the **Y axis** (perpendicular to the XZ plane).
52
+ pub const FLIP_Y : Self = Self {
53
+ basis : Basis :: FLIP_Y ,
54
+ origin : Vector3 :: ZERO ,
55
+ } ;
39
56
40
- pub const IDENTITY : Transform = Transform {
41
- basis : Basis :: identity ( ) ,
57
+ /// Transform that mirrors along the **Z axis** (perpendicular to the XY plane).
58
+ pub const FLIP_Z : Self = Self {
59
+ basis : Basis :: FLIP_Z ,
42
60
origin : Vector3 :: ZERO ,
43
61
} ;
44
62
45
- /// Creates a new transform from its three basis vectors and origin.
63
+ /// Creates a new transform from three basis vectors and the coordinate system's origin.
64
+ ///
65
+ /// Each vector represents a basis vector in the *transformed* coordinate system.
66
+ /// For example, `a` is the result of transforming the X unit vector `(1, 0, 0)`.
67
+ /// The 3 vectors need to be linearly independent.
68
+ ///
69
+ /// Basis vectors are stored as column vectors in the matrix, see also [`Basis::from_basis_vectors()`].
70
+ ///
71
+ /// The construction `Transform::from_basis_origin(a, b, c, o)` will create the following 3x4 matrix:
72
+ /// ```text
73
+ /// [ a.x b.x c.x o.x ]
74
+ /// [ a.y b.y c.y o.y ]
75
+ /// [ a.z b.z c.z o.z ]
76
+ /// ```
46
77
#[ inline]
47
- pub fn from_axis_origin (
48
- x_axis : Vector3 ,
49
- y_axis : Vector3 ,
50
- z_axis : Vector3 ,
78
+ pub const fn from_basis_origin (
79
+ basis_vector_a : Vector3 ,
80
+ basis_vector_b : Vector3 ,
81
+ basis_vector_c : Vector3 ,
51
82
origin : Vector3 ,
52
83
) -> Self {
53
84
Self {
85
+ basis : Basis :: from_basis_vectors ( basis_vector_a, basis_vector_b, basis_vector_c) ,
54
86
origin,
55
- basis : Basis :: from_elements ( [ x_axis, y_axis, z_axis] ) ,
56
87
}
57
88
}
58
89
59
90
/// Returns this transform, with its origin moved by a certain `translation`
60
91
#[ inline]
61
- pub fn translated ( & self , translation : Vector3 ) -> Transform {
92
+ pub fn translated ( & self , translation : Vector3 ) -> Self {
62
93
Self {
63
- origin : self . origin + translation,
64
94
basis : self . basis ,
95
+ origin : self . origin + translation,
65
96
}
66
97
}
67
98
@@ -85,24 +116,26 @@ impl Transform {
85
116
/// transformation is composed of rotation and translation (no scaling, use
86
117
/// affine_inverse for transforms with scaling).
87
118
#[ inline]
88
- pub fn inverse ( & self ) -> Transform {
119
+ pub fn inverse ( & self ) -> Self {
89
120
let basis_inv = self . basis . transposed ( ) ;
90
121
let origin_inv = basis_inv. xform ( -self . origin ) ;
91
- Transform {
92
- origin : origin_inv ,
122
+
123
+ Self {
93
124
basis : basis_inv,
125
+ origin : origin_inv,
94
126
}
95
127
}
96
128
97
129
/// Returns the inverse of the transform, under the assumption that the
98
130
/// transformation is composed of rotation, scaling and translation.
99
131
#[ inline]
100
- pub fn affine_inverse ( & self ) -> Transform {
132
+ pub fn affine_inverse ( & self ) -> Self {
101
133
let basis_inv = self . basis . inverted ( ) ;
102
134
let origin_inv = basis_inv. xform ( -self . origin ) ;
103
- Transform {
104
- origin : origin_inv ,
135
+
136
+ Self {
105
137
basis : basis_inv,
138
+ origin : origin_inv,
106
139
}
107
140
}
108
141
@@ -113,26 +146,40 @@ impl Transform {
113
146
/// fully aligned to the target by a further rotation around an axis
114
147
/// perpendicular to both the target and up vectors.
115
148
#[ inline]
116
- pub fn looking_at ( & self , target : Vector3 , up : Vector3 ) -> Transform {
149
+ pub fn looking_at ( & self , target : Vector3 , up : Vector3 ) -> Self {
117
150
let up = up. normalized ( ) ;
118
151
let v_z = ( self . origin - target) . normalized ( ) ;
119
152
let v_x = up. cross ( v_z) ;
120
153
let v_y = v_z. cross ( v_x) ;
121
154
122
- Transform {
123
- basis : Basis :: from_elements ( [ v_x, v_y, v_z] ) . transposed ( ) ,
155
+ Self {
156
+ basis : Basis :: from_rows ( v_x, v_y, v_z) . transposed ( ) ,
124
157
origin : self . origin ,
125
158
}
126
159
}
160
+
161
+ #[ doc( hidden) ]
162
+ #[ inline]
163
+ pub fn sys ( & self ) -> * const sys:: godot_transform {
164
+ unsafe {
165
+ std:: mem:: transmute :: < * const Transform , * const sys:: godot_transform > ( self as * const _ )
166
+ }
167
+ }
168
+
169
+ #[ doc( hidden) ]
170
+ #[ inline]
171
+ pub fn from_sys ( c : sys:: godot_transform ) -> Self {
172
+ unsafe { std:: mem:: transmute :: < sys:: godot_transform , Self > ( c) }
173
+ }
127
174
}
128
175
129
176
impl Mul < Transform > for Transform {
130
177
type Output = Transform ;
131
178
132
179
#[ inline]
133
- fn mul ( self , rhs : Transform ) -> Self :: Output {
180
+ fn mul ( self , rhs : Self ) -> Self :: Output {
134
181
let origin = self . xform ( rhs. origin ) ;
135
182
let basis = self . basis * rhs. basis ;
136
- Transform { origin, basis }
183
+ Self { origin, basis }
137
184
}
138
185
}
0 commit comments