diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 9c5ad27c..ce49244f 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -5,7 +5,7 @@ use crate::{Quaternion, SimdRealField}; /// # Indexing /// /// DualQuaternions are stored as \[..real, ..dual\]. -/// Both of the quaternion components are laid out in `w, i, j, k` order. +/// Both of the quaternion components are laid out in `i, j, k, w` order. /// /// ``` /// # use nalgebra::{DualQuaternion, Quaternion}; @@ -14,9 +14,11 @@ use crate::{Quaternion, SimdRealField}; /// let dual = Quaternion::new(5.0, 6.0, 7.0, 8.0); /// /// let dq = DualQuaternion::from_real_and_dual(real, dual); -/// assert_eq!(dq[0], 1.0); -/// assert_eq!(dq[4], 5.0); -/// assert_eq!(dq[6], 7.0); +/// assert_eq!(dq[0], 2.0); +/// assert_eq!(dq[1], 3.0); +/// +/// assert_eq!(dq[4], 6.0); +/// assert_eq!(dq[7], 5.0); /// ``` /// /// NOTE: @@ -27,46 +29,10 @@ use crate::{Quaternion, SimdRealField}; #[derive(Debug, Default, Eq, PartialEq, Copy, Clone)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct DualQuaternion { - // [real(w, i, j, k), dual(w, i, j, k)] - pub(crate) dq: [N; 8], -} - -impl DualQuaternion { - /// Get the first quaternion component. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate approx; - /// # use nalgebra::{DualQuaternion, Quaternion}; - /// - /// let real = Quaternion::new(1.0, 2.0, 3.0, 4.0); - /// let dual = Quaternion::new(5.0, 6.0, 7.0, 8.0); - /// - /// let dq = DualQuaternion::from_real_and_dual(real, dual); - /// relative_eq!(dq.real(), real); - /// ``` - #[inline] - pub fn real(&self) -> Quaternion { - Quaternion::new(self[0], self[1], self[2], self[3]) - } - - /// Get the second quaternion component. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate approx; - /// # use nalgebra::{DualQuaternion, Quaternion}; - /// - /// let real = Quaternion::new(1.0, 2.0, 3.0, 4.0); - /// let dual = Quaternion::new(5.0, 6.0, 7.0, 8.0); - /// - /// let dq = DualQuaternion::from_real_and_dual(real, dual); - /// relative_eq!(dq.dual(), dual); - /// ``` - #[inline] - pub fn dual(&self) -> Quaternion { - Quaternion::new(self[4], self[5], self[6], self[7]) - } + /// The real component of the quaternion + pub real: Quaternion, + /// The dual component of the quaternion + pub dual: Quaternion, } impl DualQuaternion @@ -85,14 +51,14 @@ where /// /// let dq_normalized = dq.normalize(); /// - /// relative_eq!(dq_normalized.real().norm(), 1.0); + /// relative_eq!(dq_normalized.real.norm(), 1.0); /// ``` #[inline] #[must_use = "Did you mean to use normalize_mut()?"] pub fn normalize(&self) -> Self { - let real_norm = self.real().norm(); + let real_norm = self.real.norm(); - Self::from_real_and_dual(self.real() / real_norm, self.dual() / real_norm) + Self::from_real_and_dual(self.real / real_norm, self.dual / real_norm) } /// Normalizes this quaternion. @@ -107,7 +73,7 @@ where /// /// dq.normalize_mut(); /// - /// relative_eq!(dq.real().norm(), 1.0); + /// relative_eq!(dq.real.norm(), 1.0); /// ``` #[inline] pub fn normalize_mut(&mut self) { diff --git a/src/geometry/dual_quaternion_construction.rs b/src/geometry/dual_quaternion_construction.rs index beb398ad..aece0a87 100644 --- a/src/geometry/dual_quaternion_construction.rs +++ b/src/geometry/dual_quaternion_construction.rs @@ -10,15 +10,11 @@ impl DualQuaternion { /// let trans = Quaternion::new(5.0, 6.0, 7.0, 8.0); /// /// let dq = DualQuaternion::from_real_and_dual(rot, trans); - /// assert_eq!(dq.real().w, 1.0); + /// assert_eq!(dq.real.w, 1.0); /// ``` #[inline] pub fn from_real_and_dual(real: Quaternion, dual: Quaternion) -> Self { - Self { - dq: [ - real.w, real.i, real.j, real.k, dual.w, dual.i, dual.j, dual.k, - ], - } + Self { real, dual } } } diff --git a/src/geometry/dual_quaternion_ops.rs b/src/geometry/dual_quaternion_ops.rs index dc46faf2..869ee7bf 100644 --- a/src/geometry/dual_quaternion_ops.rs +++ b/src/geometry/dual_quaternion_ops.rs @@ -25,21 +25,36 @@ use crate::base::allocator::Allocator; use crate::{DefaultAllocator, DualQuaternion, SimdRealField, U1, U4}; use simba::simd::SimdValue; +use std::mem; use std::ops::{Add, Index, IndexMut, Mul, Sub}; +impl AsRef<[N; 8]> for DualQuaternion { + #[inline] + fn as_ref(&self) -> &[N; 8] { + unsafe { mem::transmute(self) } + } +} + +impl AsMut<[N; 8]> for DualQuaternion { + #[inline] + fn as_mut(&mut self) -> &mut [N; 8] { + unsafe { mem::transmute(self) } + } +} + impl Index for DualQuaternion { type Output = N; #[inline] fn index(&self, i: usize) -> &Self::Output { - &self.dq[i] + &self.as_ref()[i] } } impl IndexMut for DualQuaternion { #[inline] fn index_mut(&mut self, i: usize) -> &mut N { - &mut self.dq[i] + &mut self.as_mut()[i] } } @@ -52,8 +67,8 @@ where fn mul(self, rhs: Self) -> Self::Output { Self::from_real_and_dual( - self.real() * rhs.real(), - self.real() * rhs.dual() + self.dual() * rhs.real(), + self.real * rhs.real, + self.real * rhs.dual + self.dual * rhs.real, ) } } @@ -66,7 +81,7 @@ where type Output = DualQuaternion; fn mul(self, rhs: N) -> Self::Output { - Self::from_real_and_dual(self.real() * rhs, self.dual() * rhs) + Self::from_real_and_dual(self.real * rhs, self.dual * rhs) } } @@ -78,7 +93,7 @@ where type Output = DualQuaternion; fn add(self, rhs: DualQuaternion) -> Self::Output { - Self::from_real_and_dual(self.real() + rhs.real(), self.dual() + rhs.dual()) + Self::from_real_and_dual(self.real + rhs.real, self.dual + rhs.dual) } } @@ -90,6 +105,6 @@ where type Output = DualQuaternion; fn sub(self, rhs: DualQuaternion) -> Self::Output { - Self::from_real_and_dual(self.real() - rhs.real(), self.dual() - rhs.dual()) + Self::from_real_and_dual(self.real - rhs.real, self.dual - rhs.dual) } }