Skip to content

Commit

Permalink
Add Mat4::project_point3a.
Browse files Browse the repository at this point in the history
Fixes #568.
  • Loading branch information
bitshifter committed Oct 30, 2024
1 parent 7013983 commit 06482fd
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 7 deletions.
23 changes: 22 additions & 1 deletion codegen/templates/mat.rs.tera
Original file line number Diff line number Diff line change
Expand Up @@ -1989,7 +1989,7 @@ impl {{ self_t }} {
res = self.y_axis.mul(rhs.y).add(res);
res = self.z_axis.mul(rhs.z).add(res);
res = self.w_axis.add(res);
res = res.mul(res.wwww().recip());
res = res.div(res.w);
res.xyz()
}

Expand Down Expand Up @@ -2039,6 +2039,27 @@ impl {{ self_t }} {
{% endif %}

{% if self_t == "Mat4" %}
/// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
/// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
///
/// This method assumes that `self` contains a projective transform.
#[inline]
#[must_use]
pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
{% if is_scalar %}
self.project_point3(rhs.into()).into()
{% else %}
let mut res = self.x_axis.mul(rhs.xxxx());
res = self.y_axis.mul(rhs.yyyy()).add(res);
res = self.z_axis.mul(rhs.zzzz()).add(res);
res = self.w_axis.add(res);
res = res.div(res.wwww());
Vec3A::from_vec4(res)
{% endif %}
}

/// Transforms the given [`Vec3A`] as 3D point.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
Expand Down
19 changes: 18 additions & 1 deletion src/f32/coresimd/mat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ impl Mat4 {
res = self.y_axis.mul(rhs.y).add(res);
res = self.z_axis.mul(rhs.z).add(res);
res = self.w_axis.add(res);
res = res.mul(res.wwww().recip());
res = res.div(res.w);
res.xyz()
}

Expand Down Expand Up @@ -1168,6 +1168,23 @@ impl Mat4 {
res.xyz()
}

/// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
/// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
///
/// This method assumes that `self` contains a projective transform.
#[inline]
#[must_use]
pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxxx());
res = self.y_axis.mul(rhs.yyyy()).add(res);
res = self.z_axis.mul(rhs.zzzz()).add(res);
res = self.w_axis.add(res);
res = res.div(res.wwww());
Vec3A::from_vec4(res)
}

/// Transforms the given [`Vec3A`] as 3D point.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
Expand Down
19 changes: 18 additions & 1 deletion src/f32/neon/mat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ impl Mat4 {
res = self.y_axis.mul(rhs.y).add(res);
res = self.z_axis.mul(rhs.z).add(res);
res = self.w_axis.add(res);
res = res.mul(res.wwww().recip());
res = res.div(res.w);
res.xyz()
}

Expand Down Expand Up @@ -1173,6 +1173,23 @@ impl Mat4 {
res.xyz()
}

/// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
/// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
///
/// This method assumes that `self` contains a projective transform.
#[inline]
#[must_use]
pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxxx());
res = self.y_axis.mul(rhs.yyyy()).add(res);
res = self.z_axis.mul(rhs.zzzz()).add(res);
res = self.w_axis.add(res);
res = res.div(res.wwww());
Vec3A::from_vec4(res)
}

/// Transforms the given [`Vec3A`] as 3D point.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
Expand Down
14 changes: 13 additions & 1 deletion src/f32/scalar/mat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ impl Mat4 {
res = self.y_axis.mul(rhs.y).add(res);
res = self.z_axis.mul(rhs.z).add(res);
res = self.w_axis.add(res);
res = res.mul(res.wwww().recip());
res = res.div(res.w);
res.xyz()
}

Expand Down Expand Up @@ -1090,6 +1090,18 @@ impl Mat4 {
res.xyz()
}

/// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
/// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
///
/// This method assumes that `self` contains a projective transform.
#[inline]
#[must_use]
pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
self.project_point3(rhs.into()).into()
}

/// Transforms the given [`Vec3A`] as 3D point.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
Expand Down
19 changes: 18 additions & 1 deletion src/f32/sse2/mat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1130,7 +1130,7 @@ impl Mat4 {
res = self.y_axis.mul(rhs.y).add(res);
res = self.z_axis.mul(rhs.z).add(res);
res = self.w_axis.add(res);
res = res.mul(res.wwww().recip());
res = res.div(res.w);
res.xyz()
}

Expand Down Expand Up @@ -1177,6 +1177,23 @@ impl Mat4 {
res.xyz()
}

/// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
/// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
///
/// This method assumes that `self` contains a projective transform.
#[inline]
#[must_use]
pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxxx());
res = self.y_axis.mul(rhs.yyyy()).add(res);
res = self.z_axis.mul(rhs.zzzz()).add(res);
res = self.w_axis.add(res);
res = res.div(res.wwww());
Vec3A::from_vec4(res)
}

/// Transforms the given [`Vec3A`] as 3D point.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
Expand Down
19 changes: 18 additions & 1 deletion src/f32/wasm32/mat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ impl Mat4 {
res = self.y_axis.mul(rhs.y).add(res);
res = self.z_axis.mul(rhs.z).add(res);
res = self.w_axis.add(res);
res = res.mul(res.wwww().recip());
res = res.div(res.w);
res.xyz()
}

Expand Down Expand Up @@ -1168,6 +1168,23 @@ impl Mat4 {
res.xyz()
}

/// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
/// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
///
/// This method assumes that `self` contains a projective transform.
#[inline]
#[must_use]
pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxxx());
res = self.y_axis.mul(rhs.yyyy()).add(res);
res = self.z_axis.mul(rhs.zzzz()).add(res);
res = self.w_axis.add(res);
res = res.div(res.wwww());
Vec3A::from_vec4(res)
}

/// Transforms the given [`Vec3A`] as 3D point.
///
/// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
Expand Down
2 changes: 1 addition & 1 deletion src/f64/dmat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ impl DMat4 {
res = self.y_axis.mul(rhs.y).add(res);
res = self.z_axis.mul(rhs.z).add(res);
res = self.w_axis.add(res);
res = res.mul(res.wwww().recip());
res = res.div(res.w);
res.xyz()
}

Expand Down
29 changes: 29 additions & 0 deletions tests/mat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,35 @@ mod mat4 {
);
});

glam_test!(test_transform_vec3a, {
use glam::Vec3A;
let m = Mat4::from_axis_angle(Vec3::Z, deg(90.0));
let result3 = m.transform_vector3a(Vec3A::Y);
assert_approx_eq!(Vec3A::new(-1.0, 0.0, 0.0), result3);

let m = Mat4::from_scale_rotation_translation(
Vec3::new(0.5, 1.5, 2.0),
Quat::from_rotation_x(deg(90.0)),
Vec3::new(1.0, 2.0, 3.0),
);
let result3 = m.transform_vector3a(Vec3A::Y);
assert_approx_eq!(Vec3A::new(0.0, 0.0, 1.5), result3, 1.0e-6);

let result3 = m.transform_point3a(Vec3A::Y);
assert_approx_eq!(Vec3A::new(1.0, 2.0, 4.5), result3, 1.0e-6);

let m = Mat4::from_cols(
vec4(8.0, 0.0, 0.0, 0.0),
vec4(0.0, 4.0, 0.0, 0.0),
vec4(0.0, 0.0, 2.0, 2.0),
vec4(0.0, 0.0, 0.0, 0.0),
);
assert_approx_eq!(
Vec3A::new(4.0, 2.0, 1.0),
m.project_point3a(Vec3A::new(2.0, 2.0, 2.0))
);
});

glam_test!(test_as, {
use glam::DMat4;
assert_eq!(
Expand Down

0 comments on commit 06482fd

Please sign in to comment.