Skip to content

Commit e1ecbc3

Browse files
bors[bot]Bromeon
andauthored
Merge #827
827: API consistency + documentation for geometric types r=Bromeon a=Bromeon Primarily improves APIs of `Basis`, `Transform`, `Transform2D`. Changes: * General * Documentation improvements, especially w.r.t row/column vectors * Add links to Godot API doc * Replace some named types with `Self` * Group some methods according to functionality; sys() and from_sys() at end of impl * Move some types to `geom` module (internal only) * Remove dead code * **`Transform`** * Remove `from_axis_origin()`, confusing semantics * Add `from_basis_origin()` instead * Add `FLIP_X`, `FLIP_Y`, `FLIP_Z` constants * **`Basis`** * Rename `from_elements()` -> `from_rows()` * Add `from_basis_vectors()` constructor * `IDENTITY`, `FLIP_X`, `FLIP_Y`, `FLIP_Z` now constants instead of functions * Rename basis vectors `x, y, z` -> `a, b, c` * Rename `to_scale()` -> `scale()` * Change parameters `self` -> `&self` (except operators) * Change vector parameters to pass-by-value * Make modifying methods like `invert()`, `orthonormalize()`, `rotate()` private * Make `tdotx()` etc. private for now * Reuse code (use of dot products) * **`Transform2D`** * Rename `from_axis_origin()` -> `from_basis_origin()` * Rename basis vectors `x, y` -> `a, b` Co-authored-by: Jan Haller <[email protected]>
2 parents d9a9f9b + 16aa18e commit e1ecbc3

File tree

11 files changed

+483
-373
lines changed

11 files changed

+483
-373
lines changed

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

Lines changed: 242 additions & 229 deletions
Large diffs are not rendered by default.

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@
33
mod aabb;
44
mod basis;
55
mod plane;
6+
mod quat;
7+
mod rect2;
68
mod transform;
9+
mod transform2d;
710

8-
pub use self::aabb::Aabb;
9-
pub use self::basis::Basis;
10-
pub use self::plane::Plane;
11-
pub use self::transform::Transform;
11+
pub use aabb::*;
12+
pub use basis::*;
13+
pub use plane::*;
14+
pub use quat::*;
15+
pub use rect2::*;
16+
pub use transform::*;
17+
pub use transform2d::*;

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,18 @@ pub struct Plane {
1010
}
1111

1212
impl Plane {
13-
#[doc(hidden)]
14-
#[inline]
15-
pub fn sys(&self) -> *const sys::godot_plane {
16-
unsafe { std::mem::transmute::<*const Plane, *const sys::godot_plane>(self as *const _) }
17-
}
18-
19-
#[doc(hidden)]
20-
#[inline]
21-
pub fn from_sys(c: sys::godot_plane) -> Self {
22-
unsafe { std::mem::transmute::<sys::godot_plane, Self>(c) }
23-
}
24-
2513
/// Creates a new `Plane` from the ['Vector3'](./type.Vector3.html) normal and the distance from the origin.
2614
#[inline]
27-
pub fn new(normal: Vector3, d: f32) -> Plane {
28-
Plane { normal, d }
15+
pub fn new(normal: Vector3, d: f32) -> Self {
16+
Self { normal, d }
2917
}
3018

3119
/// Creates a new `Plane` from four floats.
3220
/// a, b, c are used for the normal ['Vector3'](./type.Vector3.html).
3321
/// d is the distance from the origin.
3422
#[inline]
35-
pub fn from_coordinates(a: f32, b: f32, c: f32, d: f32) -> Plane {
36-
Plane {
23+
pub fn from_coordinates(a: f32, b: f32, c: f32, d: f32) -> Self {
24+
Self {
3725
normal: Vector3::new(a, b, c),
3826
d,
3927
}
@@ -42,13 +30,13 @@ impl Plane {
4230
/// Creates a new `Plane` from three [`Vector3`](./type.Vector3.html), given in clockwise order.
4331
/// If all three points are collinear, returns `None`.
4432
#[inline]
45-
pub fn from_points(a: Vector3, b: Vector3, c: Vector3) -> Option<Plane> {
33+
pub fn from_points(a: Vector3, b: Vector3, c: Vector3) -> Option<Self> {
4634
let normal = (a - c).cross(a - b).normalized();
4735

4836
if normal.x.is_nan() || normal.y.is_nan() || normal.z.is_nan() {
4937
None
5038
} else {
51-
Some(Plane {
39+
Some(Self {
5240
normal,
5341
d: normal.dot(a),
5442
})
@@ -151,7 +139,7 @@ impl Plane {
151139

152140
/// Returns the `Plane` normalized.
153141
#[inline]
154-
pub fn normalize(mut self) -> Plane {
142+
pub fn normalize(mut self) -> Self {
155143
let l = self.normal.length();
156144

157145
if l == 0.0 {
@@ -170,6 +158,18 @@ impl Plane {
170158
pub fn project(&self, point: Vector3) -> Vector3 {
171159
point - self.normal * self.distance_to(point)
172160
}
161+
162+
#[doc(hidden)]
163+
#[inline]
164+
pub fn sys(&self) -> *const sys::godot_plane {
165+
unsafe { std::mem::transmute::<*const Plane, *const sys::godot_plane>(self as *const _) }
166+
}
167+
168+
#[doc(hidden)]
169+
#[inline]
170+
pub fn from_sys(c: sys::godot_plane) -> Self {
171+
unsafe { std::mem::transmute::<sys::godot_plane, Self>(c) }
172+
}
173173
}
174174

175175
#[cfg(test)]

gdnative-core/src/core_types/quat.rs renamed to gdnative-core/src/core_types/geom/quat.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
use super::{Basis, IsEqualApprox, Vector3, CMP_EPSILON};
1+
use crate::core_types::{Basis, IsEqualApprox, Vector3, CMP_EPSILON};
22
use glam::EulerRot;
33
use std::ops::{Mul, Neg};
44

5+
/// Quaternion, used to represent 3D rotations.
6+
///
7+
/// Quaternions need to be [normalized][Self::normalized()] before all operations.
8+
///
9+
/// See also [Quat](https://docs.godotengine.org/en/stable/classes/class_quat.html) in the Godot API doc.
510
#[derive(Copy, Clone, Debug, PartialEq)]
611
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
712
#[repr(C)]
@@ -248,11 +253,11 @@ mod test {
248253
#[test]
249254
fn to_basis() {
250255
let quat = Quat::new(0.485489, 0.142796, -0.862501, 0.001113);
251-
let expect = Basis::from_elements([
256+
let expect = Basis::from_rows(
252257
Vector3::new(-0.528598, 0.140572, -0.837152),
253258
Vector3::new(0.136732, -0.959216, -0.247404),
254259
Vector3::new(-0.837788, -0.245243, 0.487819),
255-
]);
260+
);
256261
let basis = Basis::from_quat(quat);
257262
assert!(basis.is_equal_approx(&expect));
258263
}

gdnative-core/src/core_types/rect2.rs renamed to gdnative-core/src/core_types/geom/rect2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::Vector2;
1+
use crate::core_types::Vector2;
22

33
#[derive(Copy, Clone, Debug, PartialEq)]
44
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]

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

Lines changed: 85 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,29 @@ use std::ops::Mul;
22

33
use crate::core_types::{Basis, Vector3};
44

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.
619
#[repr(C)]
720
#[derive(Copy, Clone, Debug, PartialEq)]
821
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
922
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.
1325
pub basis: Basis,
14-
/// The translation offset of the transform.
26+
27+
/// The new origin of the transformed coordinate system.
1528
pub origin: Vector3,
1629
}
1730

@@ -23,45 +36,63 @@ impl Default for Transform {
2336
}
2437

2538
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+
};
3344

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+
};
3956

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,
4260
origin: Vector3::ZERO,
4361
};
4462

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+
/// ```
4677
#[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,
5182
origin: Vector3,
5283
) -> Self {
5384
Self {
85+
basis: Basis::from_basis_vectors(basis_vector_a, basis_vector_b, basis_vector_c),
5486
origin,
55-
basis: Basis::from_elements([x_axis, y_axis, z_axis]),
5687
}
5788
}
5889

5990
/// Returns this transform, with its origin moved by a certain `translation`
6091
#[inline]
61-
pub fn translated(&self, translation: Vector3) -> Transform {
92+
pub fn translated(&self, translation: Vector3) -> Self {
6293
Self {
63-
origin: self.origin + translation,
6494
basis: self.basis,
95+
origin: self.origin + translation,
6596
}
6697
}
6798

@@ -85,24 +116,26 @@ impl Transform {
85116
/// transformation is composed of rotation and translation (no scaling, use
86117
/// affine_inverse for transforms with scaling).
87118
#[inline]
88-
pub fn inverse(&self) -> Transform {
119+
pub fn inverse(&self) -> Self {
89120
let basis_inv = self.basis.transposed();
90121
let origin_inv = basis_inv.xform(-self.origin);
91-
Transform {
92-
origin: origin_inv,
122+
123+
Self {
93124
basis: basis_inv,
125+
origin: origin_inv,
94126
}
95127
}
96128

97129
/// Returns the inverse of the transform, under the assumption that the
98130
/// transformation is composed of rotation, scaling and translation.
99131
#[inline]
100-
pub fn affine_inverse(&self) -> Transform {
132+
pub fn affine_inverse(&self) -> Self {
101133
let basis_inv = self.basis.inverted();
102134
let origin_inv = basis_inv.xform(-self.origin);
103-
Transform {
104-
origin: origin_inv,
135+
136+
Self {
105137
basis: basis_inv,
138+
origin: origin_inv,
106139
}
107140
}
108141

@@ -113,26 +146,40 @@ impl Transform {
113146
/// fully aligned to the target by a further rotation around an axis
114147
/// perpendicular to both the target and up vectors.
115148
#[inline]
116-
pub fn looking_at(&self, target: Vector3, up: Vector3) -> Transform {
149+
pub fn looking_at(&self, target: Vector3, up: Vector3) -> Self {
117150
let up = up.normalized();
118151
let v_z = (self.origin - target).normalized();
119152
let v_x = up.cross(v_z);
120153
let v_y = v_z.cross(v_x);
121154

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(),
124157
origin: self.origin,
125158
}
126159
}
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+
}
127174
}
128175

129176
impl Mul<Transform> for Transform {
130177
type Output = Transform;
131178

132179
#[inline]
133-
fn mul(self, rhs: Transform) -> Self::Output {
180+
fn mul(self, rhs: Self) -> Self::Output {
134181
let origin = self.xform(rhs.origin);
135182
let basis = self.basis * rhs.basis;
136-
Transform { origin, basis }
183+
Self { origin, basis }
137184
}
138185
}

0 commit comments

Comments
 (0)