Skip to content

Commit 38719eb

Browse files
committed
Improve naming + documentation for transforms (row/column vectors)
Changes: * Documentation + links to Godot API doc * Transform * Remove from_axis_origin(), confusing semantics * Add from_basis_origin() instead * Add FLIP_X, FLIP_Y, FLIP_Z * Transform2D * Rename from_axis_origin() -> from_basis_origin() * Basis * Rename from_elements() -> from_rows() * Add from_basis_vectors() * Pass vectors by value * Make tdotx() etc. private for now (used internally by Transform)
1 parent 627df7a commit 38719eb

File tree

6 files changed

+241
-96
lines changed

6 files changed

+241
-96
lines changed

gdnative-core/src/core_types/geom/basis.rs

Lines changed: 110 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,21 @@ use crate::core_types::{IsEqualApprox, Quat, Vector3};
22
use core::ops::Mul;
33
use glam::Mat3;
44

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.
611
#[repr(C)]
712
#[derive(Copy, Clone, Debug, PartialEq)]
813
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
914
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].
1020
pub elements: [Vector3; 3],
1121
}
1222

@@ -18,10 +28,10 @@ impl Default for Basis {
1828
}
1929

2030
impl Basis {
21-
/// The identity basis.
31+
/// The identity basis. Basis vectors are unit vectors along each axis X, Y and Z.
2232
///
2333
/// Equivalent to calling [`Basis::default()`].
24-
pub const IDENTITY: Basis = Self {
34+
pub const IDENTITY: Self = Self {
2535
elements: [
2636
Vector3::new(1.0, 0.0, 0.0),
2737
Vector3::new(0.0, 1.0, 0.0),
@@ -30,30 +40,69 @@ impl Basis {
3040
};
3141

3242
/// 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));
3444

3545
/// 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));
3747

3848
/// 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));
4050

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.
4255
#[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 {
4457
Self {
4558
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),
4962
],
5063
}
5164
}
5265

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.
5497
#[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+
}
57106
}
58107

59108
/// Creates a rotation matrix from Euler angles.
@@ -62,35 +111,35 @@ impl Basis {
62111
/// first **Z**, then **X**, and **Y** last.
63112
#[inline]
64113
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);
67116
b
68117
}
69118

70119
#[inline]
71-
fn set_euler_yxz(&mut self, euler: &Vector3) {
120+
fn set_euler_yxz(&mut self, euler: Vector3) {
72121
let c = euler.x.cos();
73122
let s = euler.x.sin();
74-
let xmat = Basis::from_elements([
123+
let xmat = Self::from_rows(
75124
Vector3::new(1.0, 0.0, 0.0),
76125
Vector3::new(0.0, c, -s),
77126
Vector3::new(0.0, s, c),
78-
]);
127+
);
79128
let c = euler.y.cos();
80129
let s = euler.y.sin();
81-
let ymat = Basis::from_elements([
130+
let ymat = Self::from_rows(
82131
Vector3::new(c, 0.0, s),
83132
Vector3::new(0.0, 1.0, 0.0),
84133
Vector3::new(-s, 0.0, c),
85-
]);
134+
);
86135

87136
let c = euler.z.cos();
88137
let s = euler.z.sin();
89-
let zmat = Basis::from_elements([
138+
let zmat = Self::from_rows(
90139
Vector3::new(c, -s, 0.0),
91140
Vector3::new(s, c, 0.0),
92141
Vector3::new(0.0, 0.0, 1.0),
93-
]);
142+
);
94143

95144
*self = ymat * xmat * zmat;
96145
}
@@ -99,29 +148,29 @@ impl Basis {
99148
#[inline]
100149
pub fn from_quat(quat: Quat) -> Self {
101150
let basis = Mat3::from_quat(quat.glam()).to_cols_array_2d();
102-
let basis = [
151+
152+
Self::from_rows(
103153
Vector3::new(basis[0][0], basis[1][0], basis[2][0]),
104154
Vector3::new(basis[0][1], basis[1][1], basis[2][1]),
105155
Vector3::new(basis[0][2], basis[1][2], basis[2][2]),
106-
];
107-
Basis::from_elements(basis)
156+
)
108157
}
109158

110159
/// Rotation matrix from axis and angle.
111160
///
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>
113162
///
114163
/// # Panics
115164
///
116165
/// If `axis` is not normalized.
117166
#[inline]
118-
pub fn from_axis_angle(axis: &Vector3, phi: f32) -> Self {
167+
pub fn from_axis_angle(axis: Vector3, phi: f32) -> Self {
119168
assert!(
120169
axis.length().is_equal_approx(1.0),
121170
"The axis Vector3 must be normalized."
122171
);
123172

124-
let mut basis = Basis::default();
173+
let mut basis = Self::default();
125174
let [x, y, z] = &mut basis.elements;
126175

127176
let axis_sq = Vector3::new(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
@@ -283,7 +332,7 @@ impl Basis {
283332
/// of the 3D object. `rotated()` here refers to rotation of the object (which is `R * self`), not the matrix itself.
284333
#[inline]
285334
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);
287336
rot * (*self)
288337
}
289338

@@ -316,7 +365,7 @@ impl Basis {
316365

317366
/// Introduce an additional scaling specified by the given 3D scaling factor.
318367
#[inline]
319-
pub fn scaled(&self, scale: &Vector3) -> Self {
368+
pub fn scaled(&self, scale: Vector3) -> Self {
320369
let mut copy = *self;
321370
copy.scale_self(scale);
322371
copy
@@ -326,7 +375,7 @@ impl Basis {
326375
///
327376
/// See the comment for [Basis::rotated](#method.rotated) for further explanation.
328377
#[inline]
329-
fn scale_self(&mut self, s: &Vector3) {
378+
fn scale_self(&mut self, s: Vector3) {
330379
self.elements[0] *= s.x;
331380
self.elements[1] *= s.y;
332381
self.elements[2] *= s.z;
@@ -349,7 +398,7 @@ impl Basis {
349398
let det = matrix.determinant();
350399
if det < 0.0 {
351400
// 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));
353402
}
354403

355404
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 {
469518
)
470519
}
471520

472-
/// Transposed dot product with the **X axis** of the matrix.
521+
/// Transposed dot product with the **X basis vector** of the matrix.
473522
#[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)
476525
}
477526

478-
/// Transposed dot product with the **Y axis** of the matrix.
527+
/// Transposed dot product with the **Y basis vector** of the matrix.
479528
#[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)
482531
}
483532

484-
/// Transposed dot product with the **Z axis** of the matrix.
533+
/// Transposed dot product with the **Z basis vector** of the matrix.
485534
#[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)
488537
}
489538

490-
/// Get the **X axis** of the matrix
539+
/// Get the **X basis vector** (first column vector of the matrix).
491540
#[inline]
492541
pub fn x(&self) -> Vector3 {
493542
Vector3::new(self.elements[0].x, self.elements[1].x, self.elements[2].x)
494543
}
495544

496-
/// Set the **X axis** of the matrix
545+
/// Set the **X basis vector** (first column vector of the matrix).
497546
#[inline]
498547
pub fn set_x(&mut self, v: Vector3) {
499548
self.elements[0].x = v.x;
500549
self.elements[1].x = v.y;
501550
self.elements[2].x = v.z;
502551
}
503552

504-
/// Get the **Y axis** of the matrix
553+
/// Get the **Y basis vector** (second column vector of the matrix).
505554
#[inline]
506555
pub fn y(&self) -> Vector3 {
507556
Vector3::new(self.elements[0].y, self.elements[1].y, self.elements[2].y)
508557
}
509558

510-
/// Set the **Y axis** of the matrix
559+
/// Set the **Y basis vector** (second column vector of the matrix).
511560
#[inline]
512561
pub fn set_y(&mut self, v: Vector3) {
513562
self.elements[0].y = v.x;
514563
self.elements[1].y = v.y;
515564
self.elements[2].y = v.z;
516565
}
517566

518-
/// Get the **Z axis** of the matrix
567+
/// Get the **Z basis vector** (third column vector of the matrix).
519568
#[inline]
520569
pub fn z(&self) -> Vector3 {
521570
Vector3::new(self.elements[0].z, self.elements[1].z, self.elements[2].z)
522571
}
523572

524-
/// Set the **Z axis** of the matrix
573+
/// Set the **Z basis vector** (third column vector of the matrix).
525574
#[inline]
526575
pub fn set_z(&mut self, v: Vector3) {
527576
self.elements[0].z = v.x;
@@ -547,7 +596,7 @@ impl Mul<Basis> for Basis {
547596

548597
#[inline]
549598
fn mul(self, rhs: Self) -> Self {
550-
Basis::from_elements([
599+
Basis::from_rows(
551600
Vector3::new(
552601
rhs.tdotx(self.elements[0]),
553602
rhs.tdoty(self.elements[0]),
@@ -563,7 +612,7 @@ impl Mul<Basis> for Basis {
563612
rhs.tdoty(self.elements[2]),
564613
rhs.tdotz(self.elements[2]),
565614
),
566-
])
615+
)
567616
}
568617
}
569618

@@ -657,36 +706,36 @@ mod tests {
657706
fn orthonormalized() {
658707
let (b, _bn) = test_inputs();
659708

660-
let expected = Basis::from_elements([
709+
let expected = Basis::from_rows(
661710
Vector3::new(0.077431, -0.165055, 0.98324),
662711
Vector3::new(-0.288147, 0.94041, 0.180557),
663712
Vector3::new(-0.95445, -0.297299, 0.025257),
664-
]);
713+
);
665714
assert!(expected.is_equal_approx(&b.orthonormalized()));
666715
}
667716

668717
#[test]
669718
fn scaled() {
670719
let (b, _bn) = test_inputs();
671720

672-
let expected = Basis::from_elements([
721+
let expected = Basis::from_rows(
673722
Vector3::new(0.052484, -0.111876, 0.666453),
674723
Vector3::new(0.012407, -0.040492, -0.007774),
675724
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))));
678727
}
679728

680729
#[test]
681730
fn rotated() {
682731
let (b, _bn) = test_inputs();
683732

684733
let r = Vector3::new(-50.167156, 60.67781, -70.04305).normalized();
685-
let expected = Basis::from_elements([
734+
let expected = Basis::from_rows(
686735
Vector3::new(-0.676245, 0.113805, 0.727833),
687736
Vector3::new(-0.467094, 0.697765, -0.54309),
688737
Vector3::new(-0.569663, -0.707229, -0.418703),
689-
]);
738+
);
690739
assert!(expected.is_equal_approx(&b.rotated(r, 1.0)));
691740
}
692741

@@ -713,11 +762,11 @@ mod tests {
713762
#[test]
714763
fn transposed() {
715764
let (b, _bn) = test_inputs();
716-
let expected = Basis::from_elements([
765+
let expected = Basis::from_rows(
717766
Vector3::new(0.077431, -0.288147, -0.95445),
718767
Vector3::new(-0.165055, 0.94041, -0.297299),
719768
Vector3::new(0.98324, 0.180557, 0.025257),
720-
]);
769+
);
721770
assert!(expected.is_equal_approx(&b.transposed()));
722771
}
723772

@@ -741,11 +790,11 @@ mod tests {
741790
fn inverse() {
742791
let (b, _bn) = test_inputs();
743792

744-
let expected = Basis::from_elements([
793+
let expected = Basis::from_rows(
745794
Vector3::new(0.077431, -0.288147, -0.95445),
746795
Vector3::new(-0.165055, 0.94041, -0.297299),
747796
Vector3::new(0.98324, 0.180557, 0.025257),
748-
]);
797+
);
749798
assert!(expected.is_equal_approx(&b.inverted()));
750799
}
751800
}

0 commit comments

Comments
 (0)