Skip to content

Commit c3dab06

Browse files
bors[bot]setzer22
andauthored
Merge #821
821: Implement some methods of the Transform API r=Bromeon a=setzer22 Here are some more Transform methods. I followed the same strategy as for #791, where the implementation was done by translating the C++ code to Rust. I can also add some tests similar to the ones from the previous PR if you'd like 👍 Although the code for Transform is far simpler, because it delegates most of the implementation to `Vector3` and `Basis`. Co-authored-by: Setzer22 <[email protected]>
2 parents 164beb8 + 3363986 commit c3dab06

File tree

1 file changed

+103
-3
lines changed

1 file changed

+103
-3
lines changed

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

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::Mul;
2+
13
use crate::core_types::{Basis, Vector3};
24

35
/// 3D Transformation (3x4 matrix) Using basis + origin representation.
@@ -13,6 +15,13 @@ pub struct Transform {
1315
pub origin: Vector3,
1416
}
1517

18+
impl Default for Transform {
19+
#[inline]
20+
fn default() -> Self {
21+
Self::IDENTITY
22+
}
23+
}
24+
1625
impl Transform {
1726
#[doc(hidden)]
1827
#[inline]
@@ -28,11 +37,102 @@ impl Transform {
2837
unsafe { std::mem::transmute::<sys::godot_transform, Self>(c) }
2938
}
3039

40+
pub const IDENTITY: Transform = Transform {
41+
basis: Basis::identity(),
42+
origin: Vector3::ZERO,
43+
};
44+
45+
/// Creates a new transform from its three basis vectors and origin.
3146
#[inline]
32-
pub fn translate(origin: Vector3) -> Transform {
33-
Transform {
34-
basis: Basis::identity(),
47+
pub fn from_axis_origin(
48+
x_axis: Vector3,
49+
y_axis: Vector3,
50+
z_axis: Vector3,
51+
origin: Vector3,
52+
) -> Self {
53+
Self {
3554
origin,
55+
basis: Basis::from_elements([x_axis, y_axis, z_axis]),
56+
}
57+
}
58+
59+
/// Returns this transform, with its origin moved by a certain `translation`
60+
#[inline]
61+
pub fn translated(&self, translation: Vector3) -> Transform {
62+
Self {
63+
origin: self.origin + translation,
64+
basis: self.basis,
65+
}
66+
}
67+
68+
/// Returns a vector transformed (multiplied) by the matrix.
69+
#[inline]
70+
pub fn xform(&self, v: Vector3) -> Vector3 {
71+
self.basis.xform(v) + self.origin
72+
}
73+
74+
/// Returns a vector transformed (multiplied) by the transposed basis
75+
/// matrix.
76+
///
77+
/// **Note:** This results in a multiplication by the inverse of the matrix
78+
/// only if it represents a rotation-reflection.
79+
#[inline]
80+
pub fn xform_inv(&self, v: Vector3) -> Vector3 {
81+
self.basis.xform_inv(v - self.origin)
82+
}
83+
84+
/// Returns the inverse of the transform, under the assumption that the
85+
/// transformation is composed of rotation and translation (no scaling, use
86+
/// affine_inverse for transforms with scaling).
87+
#[inline]
88+
pub fn inverse(&self) -> Transform {
89+
let basis_inv = self.basis.transposed();
90+
let origin_inv = basis_inv.xform(-self.origin);
91+
Transform {
92+
origin: origin_inv,
93+
basis: basis_inv,
94+
}
95+
}
96+
97+
/// Returns the inverse of the transform, under the assumption that the
98+
/// transformation is composed of rotation, scaling and translation.
99+
#[inline]
100+
pub fn affine_inverse(&self) -> Transform {
101+
let basis_inv = self.basis.inverted();
102+
let origin_inv = basis_inv.xform(-self.origin);
103+
Transform {
104+
origin: origin_inv,
105+
basis: basis_inv,
36106
}
37107
}
108+
109+
/// Returns a copy of the transform rotated such that its -Z axis points
110+
/// towards the target position.
111+
///
112+
/// The transform will first be rotated around the given up vector, and then
113+
/// fully aligned to the target by a further rotation around an axis
114+
/// perpendicular to both the target and up vectors.
115+
#[inline]
116+
pub fn looking_at(&self, target: Vector3, up: Vector3) -> Transform {
117+
let up = up.normalized();
118+
let v_z = (self.origin - target).normalized();
119+
let v_x = up.cross(v_z);
120+
let v_y = v_z.cross(v_x);
121+
122+
Transform {
123+
basis: Basis::from_elements([v_x, v_y, v_z]).transposed(),
124+
origin: self.origin,
125+
}
126+
}
127+
}
128+
129+
impl Mul<Transform> for Transform {
130+
type Output = Transform;
131+
132+
#[inline]
133+
fn mul(self, rhs: Transform) -> Self::Output {
134+
let origin = self.xform(rhs.origin);
135+
let basis = self.basis * rhs.basis;
136+
Transform { origin, basis }
137+
}
38138
}

0 commit comments

Comments
 (0)