Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Unreleased

- Add `padding` field to `Pose3` for better compatibility with `bytemuck` and `spirv`.
- Fix various internal implementation details that are incompatible with `spirv`/`naga`.
- Update to `glam 0.32`.

# v0.1.3

- Add `From`/`Into` conversions between f32 and f64 type variants.
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Sébastien Crozet <developer@crozet.re>"]
description = "Extensions for glam: Pose2, Pose3, Rot2, and matrix utilities."
documentation = "https://docs.rs/glamx"
homepage = "https://dimforge.com"
repository = "https://github.com/dimforge/parry"
repository = "https://github.com/dimforge/glamx"
readme = "README.md"
keywords = ["math", "geometry", "rotation", "pose", "glam"]
categories = ["mathematics", "game-development", "no-std"]
Expand Down Expand Up @@ -61,15 +61,15 @@ rand = ["glam/rand"]
encase = ["glam/encase"]

[dependencies]
glam = { version = "0.30", default-features = false }
glam = { version = "0.32", default-features = false }
simba = { version = "0.9", default-features = false }
num-traits = { version = "0.2", default-features = false, features = ["libm"] }
approx = { version = "0.5", default-features = false, optional = true }
serde = { version = "1.0", optional = true, features = ["derive"] }
bytemuck = { version = "1", features = ["derive"], optional = true }
nalgebra = { version = "0.34", default-features = false, features = ["convert-glam030"], optional = true }
nalgebra = { version = "0.34", default-features = false, features = ["convert-glam032"], optional = true }
rkyv = { version = "0.8", optional = true, default-features = false }

[dev-dependencies]
approx = "0.5"
glam = { version = "0.30", features = ["approx"] }
glam = { version = "0.32", features = ["approx"] }
21 changes: 18 additions & 3 deletions src/eigen3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
//!
//! Adapted from <https://github.com/Jondolf/barry/tree/main/src/math/eigen>

#![allow(clippy::manual_swap)] // Needed for spirv compatibility.

use glam::Vec3Swizzles;
use num_traits::float::FloatConst;

Expand Down Expand Up @@ -63,17 +65,30 @@ macro_rules! impl_symmetric_eigen3 {
if p1 == 0.0 {
// The matrix is diagonal.
let mut eigenvalues = [mat.x_axis.x, mat.y_axis.y, mat.z_axis.z];
eigenvalues.sort_by(|a, b| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal));
// Simple 3-element sorting network (no alloc needed).
// NOTE: manual swaps instead of .swap() to avoid ptr::swap which
// generates memcpy unsupported in SPIR-V.
if eigenvalues[0] > eigenvalues[1] { let t = eigenvalues[0]; eigenvalues[0] = eigenvalues[1]; eigenvalues[1] = t; }
if eigenvalues[1] > eigenvalues[2] { let t = eigenvalues[1]; eigenvalues[1] = eigenvalues[2]; eigenvalues[2] = t; }
if eigenvalues[0] > eigenvalues[1] { let t = eigenvalues[0]; eigenvalues[0] = eigenvalues[1]; eigenvalues[1] = t; }
<$Vec3>::from_array(eigenvalues)
} else {
let q = (mat.x_axis.x + mat.y_axis.y + mat.z_axis.z) / 3.0;
let p2 = (mat.x_axis.x - q).powi(2)
+ (mat.y_axis.y - q).powi(2)
+ (mat.z_axis.z - q).powi(2)
+ 2.0 * p1;

let p = (p2 / 6.0).sqrt();
let mat_b = 1.0 / p * (mat - q * <$Mat3>::IDENTITY);
let r = mat_b.determinant() / 2.0;

// NOTE: `p` shouldn’t be zero, but in some platforms (nvidia gpus apparently),
// denormals can be flushed resulting in a zero.
let r = if p != 0.0 {
let mat_b = 1.0 / p * (mat - q * <$Mat3>::IDENTITY);
mat_b.determinant() / 2.0
} else {
1.0 // Will result in phy == 0.0
};

// r should be in the [-1, 1] range for a symmetric matrix,
// but computation error can leave it slightly outside this range.
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@
#[cfg(feature = "std")]
extern crate std;

extern crate alloc;

// Re-export approx for convenience
#[cfg(feature = "approx")]
pub use approx;
Expand Down
4 changes: 3 additions & 1 deletion src/pose2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ macro_rules! impl_pose2 {
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
#[repr(C)]
$(#[$attr])*
pub struct $Pose2 {
/// The rotational part of the pose.
Expand Down Expand Up @@ -352,7 +353,8 @@ impl_pose2!(
glam::Vec2,
glam::Vec3,
glam::Mat2,
glam::Mat3
glam::Mat3,
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
);
impl_pose2!(
DPose2,
Expand Down
33 changes: 30 additions & 3 deletions src/pose3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,32 @@ use core::ops::{Mul, MulAssign};

/// Macro to generate a 3D pose type for a specific scalar type.
macro_rules! impl_pose3 {
($Pose3:ident, $Rot3:ident, $Real:ty, $Vec3:ty, $Mat4: ty $(, #[$attr:meta])*) => {
($Pose3:ident, $Rot3:ident, $Real:ty, $Vec3:ty, $Mat4: ty $(, $Padding: ty, $bytemuck: ident)?) => {
#[doc = concat!("A 3D pose (rotation + translation), representing a rigid body transformation (", stringify!($Real), " precision).")]
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
$(#[$attr])*
$(#[cfg_attr(feature = "bytemuck", derive($bytemuck::Pod, $bytemuck::Zeroable))])*
#[repr(C)]
pub struct $Pose3 {
/// The rotational part of the pose.
pub rotation: $Rot3,
/// The translational part of the pose.
pub translation: $Vec3,
$(
/// Explicit padding for compatibility with bytemuck and targets like spirv.
///
/// Can have any value as it is never read from or written to.
pub padding: $Padding,
)*
}

impl $Pose3 {
/// The identity pose (no rotation, no translation).
pub const IDENTITY: Self = Self {
rotation: $Rot3::IDENTITY,
translation: <$Vec3>::ZERO,
$(padding: 0 as $Padding,)*
};

/// Creates the identity pose.
Expand All @@ -37,6 +45,7 @@ macro_rules! impl_pose3 {
Self {
rotation: $Rot3::IDENTITY,
translation,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -52,6 +61,7 @@ macro_rules! impl_pose3 {
Self {
rotation,
translation: <$Vec3>::ZERO,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -61,6 +71,7 @@ macro_rules! impl_pose3 {
Self {
rotation,
translation,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -71,6 +82,7 @@ macro_rules! impl_pose3 {
Self {
rotation,
translation,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -80,6 +92,7 @@ macro_rules! impl_pose3 {
Self {
rotation: $Rot3::from_scaled_axis(axisangle.into()),
translation: <$Vec3>::ZERO,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -89,6 +102,7 @@ macro_rules! impl_pose3 {
Self {
rotation: self.rotation,
translation: self.translation + self.rotation * translation,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -98,6 +112,7 @@ macro_rules! impl_pose3 {
Self {
rotation: self.rotation,
translation: self.translation + translation,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -108,6 +123,7 @@ macro_rules! impl_pose3 {
Self {
rotation: inv_rot,
translation: inv_rot * (-self.translation),
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -119,6 +135,7 @@ macro_rules! impl_pose3 {
$Pose3 {
translation: inv_rot1 * tr_12,
rotation: inv_rot1 * rhs.rotation,
$(padding: 0 as $Padding,)*
}
}

Expand Down Expand Up @@ -158,6 +175,7 @@ macro_rules! impl_pose3 {
Self {
rotation: self.rotation.slerp(other.rotation, t),
translation: self.translation.lerp(other.translation, t),
$(padding: 0 as $Padding,)*
}
}

Expand Down Expand Up @@ -189,6 +207,7 @@ macro_rules! impl_pose3 {
Self {
rotation,
translation: translation.into(),
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -210,6 +229,7 @@ macro_rules! impl_pose3 {
$Pose3 {
rotation,
translation,
$(padding: 0 as $Padding,)*
}
}

Expand All @@ -228,6 +248,7 @@ macro_rules! impl_pose3 {
$Pose3 {
rotation: <$Rot3>::look_at_lh(eye.into(), target.into(), up.into()).inverse(),
translation: eye,
$(padding: 0 as $Padding,)*
}
}
}
Expand All @@ -241,6 +262,7 @@ macro_rules! impl_pose3 {
Self {
rotation: self.rotation * rhs.rotation,
translation: self.translation + self.rotation * rhs.translation,
$(padding: 0 as $Padding,)*
}
}
}
Expand Down Expand Up @@ -324,6 +346,7 @@ macro_rules! impl_pose3 {
$Pose3 {
translation: self * rhs.translation,
rotation: self * rhs.rotation,
$(padding: 0 as $Padding,)*
}
}
}
Expand All @@ -336,6 +359,7 @@ macro_rules! impl_pose3 {
$Pose3 {
translation: self.translation,
rotation: self.rotation * rhs,
$(padding: 0 as $Padding,)*
}
}
}
Expand Down Expand Up @@ -387,7 +411,7 @@ macro_rules! impl_pose3 {
};
}

impl_pose3!(Pose3, Rot3, f32, glam::Vec3, glam::Mat4);
impl_pose3!(Pose3, Rot3, f32, glam::Vec3, glam::Mat4, u32, bytemuck);
impl_pose3!(Pose3A, Rot3, f32, glam::Vec3A, glam::Mat4);
impl_pose3!(DPose3, DRot3, f64, glam::DVec3, glam::DMat4);

Expand All @@ -408,6 +432,7 @@ impl From<DPose3> for Pose3 {
Self {
rotation: p.rotation.as_quat(),
translation: p.translation.as_vec3(),
padding: 0,
}
}
}
Expand Down Expand Up @@ -449,6 +474,7 @@ impl From<Pose3A> for Pose3 {
Self {
rotation: p.rotation,
translation: p.translation.into(),
padding: 0,
}
}
}
Expand Down Expand Up @@ -481,6 +507,7 @@ mod nalgebra_conv {
iso.translation.y,
iso.translation.z,
),
padding: 0,
}
}
}
Expand Down
Loading