2016-12-05 05:44:42 +08:00
|
|
|
|
/*
|
|
|
|
|
* This file provides:
|
|
|
|
|
* ===================
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* (Quaternion)
|
|
|
|
|
*
|
|
|
|
|
* Index<usize>
|
|
|
|
|
* IndexMut<usize>
|
|
|
|
|
* Quaternion × Quaternion
|
|
|
|
|
* Quaternion + Quaternion
|
|
|
|
|
* Quaternion - Quaternion
|
|
|
|
|
* -Quaternion
|
|
|
|
|
* Quaternion × Scalar
|
|
|
|
|
* Quaternion ÷ Scalar
|
|
|
|
|
* Scalar × Quaternion
|
|
|
|
|
*
|
|
|
|
|
* (Unit Quaternion)
|
|
|
|
|
* UnitQuaternion × UnitQuaternion
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* UnitQuaternion × Rotation -> UnitQuaternion
|
|
|
|
|
* Rotation × UnitQuaternion -> UnitQuaternion
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
* UnitQuaternion ÷ UnitQuaternion
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* UnitQuaternion ÷ Rotation -> UnitQuaternion
|
|
|
|
|
* Rotation ÷ UnitQuaternion -> UnitQuaternion
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* UnitQuaternion × Point
|
|
|
|
|
* UnitQuaternion × Vector
|
|
|
|
|
* UnitQuaternion × Unit<Vector>
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
* NOTE: -UnitQuaternion is already provided by `Unit<T>`.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* (Assignment Operators)
|
|
|
|
|
*
|
|
|
|
|
* Quaternion ×= Scalar
|
|
|
|
|
* Quaternion ×= Quaternion
|
|
|
|
|
* Quaternion += Quaternion
|
|
|
|
|
* Quaternion -= Quaternion
|
|
|
|
|
*
|
|
|
|
|
* UnitQuaternion ×= UnitQuaternion
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* UnitQuaternion ×= Rotation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
* UnitQuaternion ÷= UnitQuaternion
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* UnitQuaternion ÷= Rotation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
2020-11-15 23:57:49 +08:00
|
|
|
|
* TODO: Rotation ×= UnitQuaternion
|
|
|
|
|
* TODO: Rotation ÷= UnitQuaternion
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2018-10-22 13:00:10 +08:00
|
|
|
|
use std::ops::{
|
|
|
|
|
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
|
|
|
|
};
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::base::allocator::Allocator;
|
|
|
|
|
use crate::base::dimension::{U1, U3, U4};
|
|
|
|
|
use crate::base::storage::Storage;
|
2020-12-18 19:06:27 +08:00
|
|
|
|
use crate::base::{DefaultAllocator, Scalar, Unit, Vector, Vector3};
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use crate::SimdRealField;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion};
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2020-12-18 19:06:27 +08:00
|
|
|
|
impl<N: Scalar> Index<usize> for Quaternion<N> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
type Output = N;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2019-02-17 05:29:41 +08:00
|
|
|
|
fn index(&self, i: usize) -> &Self::Output {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
&self.coords[i]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-18 19:06:27 +08:00
|
|
|
|
impl<N: Scalar> IndexMut<usize> for Quaternion<N> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
fn index_mut(&mut self, i: usize) -> &mut N {
|
|
|
|
|
&mut self.coords[i]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! quaternion_op_impl(
|
|
|
|
|
($Op: ident, $op: ident;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
($LhsRDim: ident, $LhsCDim: ident), ($RhsRDim: ident, $RhsCDim: ident)
|
|
|
|
|
$(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty $(=> $VDimA: ty, $VDimB: ty)*;
|
|
|
|
|
$action: expr; $($lives: tt),*) => {
|
2020-03-21 19:16:46 +08:00
|
|
|
|
impl<$($lives ,)* N: SimdRealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs
|
2020-03-22 06:22:55 +08:00
|
|
|
|
where N::Element: SimdRealField,
|
|
|
|
|
DefaultAllocator: Allocator<N, $LhsRDim, $LhsCDim> +
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Allocator<N, $RhsRDim, $RhsCDim> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
type Output = $Result;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn $op($lhs, $rhs: $Rhs) -> Self::Output {
|
|
|
|
|
$action
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Quaternion + Quaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Add, add;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Quaternion<N>, rhs: &'b Quaternion<N>, Output = Quaternion<N>;
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(&self.coords + &rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Add, add;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(&self.coords + rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Add, add;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: &'b Quaternion<N>, Output = Quaternion<N>;
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(self.coords + &rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Add, add;
|
|
|
|
|
(U4, U1), (U4, U1);
|
|
|
|
|
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
|
|
|
|
Quaternion::from(self.coords + rhs.coords); );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
// Quaternion - Quaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Sub, sub;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Quaternion<N>, rhs: &'b Quaternion<N>, Output = Quaternion<N>;
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(&self.coords - &rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Sub, sub;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(&self.coords - rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Sub, sub;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: &'b Quaternion<N>, Output = Quaternion<N>;
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(self.coords - &rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Sub, sub;
|
|
|
|
|
(U4, U1), (U4, U1);
|
|
|
|
|
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
|
|
|
|
Quaternion::from(self.coords - rhs.coords); );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
// Quaternion × Quaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Quaternion<N>, rhs: &'b Quaternion<N>, Output = Quaternion<N>;
|
|
|
|
|
Quaternion::new(
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self[3] * rhs[3] - self[0] * rhs[0] - self[1] * rhs[1] - self[2] * rhs[2],
|
|
|
|
|
self[3] * rhs[0] + self[0] * rhs[3] + self[1] * rhs[2] - self[2] * rhs[1],
|
|
|
|
|
self[3] * rhs[1] - self[0] * rhs[2] + self[1] * rhs[3] + self[2] * rhs[0],
|
|
|
|
|
self[3] * rhs[2] + self[0] * rhs[1] - self[1] * rhs[0] + self[2] * rhs[3]);
|
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self * &rhs;
|
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: &'b Quaternion<N>, Output = Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
&self * rhs;
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
|
|
|
|
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
|
|
|
|
&self * &rhs; );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
// UnitQuaternion × UnitQuaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: &'b UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
|
|
|
|
UnitQuaternion::new_unchecked(self.quaternion() * rhs.quaternion());
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self * &rhs;
|
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
&self * rhs;
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U4, U1);
|
|
|
|
|
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
|
|
|
|
&self * &rhs; );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
// UnitQuaternion ÷ UnitQuaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: &'b UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
2020-10-26 01:23:24 +08:00
|
|
|
|
#[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self / &rhs;
|
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
&self / rhs;
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U4, U1);
|
|
|
|
|
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
|
|
|
|
&self / &rhs; );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// UnitQuaternion × Rotation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: &'b Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: can we avoid the conversion from a rotation matrix?
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self * UnitQuaternion::<N>::from_rotation_matrix(rhs);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
self * UnitQuaternion::<N>::from_rotation_matrix(&rhs);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
self * UnitQuaternion::<N>::from_rotation_matrix(rhs);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U3);
|
|
|
|
|
self: UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
self * UnitQuaternion::<N>::from_rotation_matrix(&rhs); );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// UnitQuaternion ÷ Rotation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: &'b Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: can we avoid the conversion to a rotation matrix?
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self / UnitQuaternion::<N>::from_rotation_matrix(rhs);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
self / UnitQuaternion::<N>::from_rotation_matrix(&rhs);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
self / UnitQuaternion::<N>::from_rotation_matrix(rhs);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U3, U3);
|
|
|
|
|
self: UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
self / UnitQuaternion::<N>::from_rotation_matrix(&rhs); );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Rotation × UnitQuaternion
|
2016-12-05 05:44:42 +08:00
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U3, U3), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Rotation<N, U3>, rhs: &'b UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: can we avoid the conversion from a rotation matrix?
|
2017-08-03 01:37:44 +08:00
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(self) * rhs;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U3, U3), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(self) * rhs;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U3, U3), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Rotation<N, U3>, rhs: &'b UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(&self) * rhs;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Mul, mul;
|
|
|
|
|
(U3, U3), (U4, U1);
|
|
|
|
|
self: Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(&self) * rhs; );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Rotation ÷ UnitQuaternion
|
2016-12-05 05:44:42 +08:00
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U3, U3), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Rotation<N, U3>, rhs: &'b UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: can we avoid the conversion from a rotation matrix?
|
2017-08-03 01:37:44 +08:00
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(self) / rhs;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U3, U3), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(self) / rhs;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U3, U3), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Rotation<N, U3>, rhs: &'b UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(&self) / rhs;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Div, div;
|
|
|
|
|
(U3, U3), (U4, U1);
|
|
|
|
|
self: Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
|
|
|
|
Output = UnitQuaternion<N> => U3, U3;
|
|
|
|
|
UnitQuaternion::<N>::from_rotation_matrix(&self) / rhs; );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
// UnitQuaternion × Vector
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: &'b Vector<N, U3, SB>,
|
|
|
|
|
Output = Vector3<N> => U3, U4;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
{
|
2019-03-23 21:29:07 +08:00
|
|
|
|
let two: N = crate::convert(2.0f64);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let t = self.as_ref().vector().cross(rhs) * two;
|
|
|
|
|
let cross = self.as_ref().vector().cross(&t);
|
|
|
|
|
|
|
|
|
|
t * self.as_ref().scalar() + cross + rhs
|
|
|
|
|
};
|
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: Vector<N, U3, SB>,
|
|
|
|
|
Output = Vector3<N> => U3, U4;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self * &rhs;
|
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b Vector<N, U3, SB>,
|
|
|
|
|
Output = Vector3<N> => U3, U4;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
&self * rhs;
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: UnitQuaternion<N>, rhs: Vector<N, U3, SB>,
|
|
|
|
|
Output = Vector3<N> => U3, U4;
|
|
|
|
|
&self * &rhs; );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// UnitQuaternion × Point
|
2016-12-05 05:44:42 +08:00
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: &'b Point3<N>,
|
|
|
|
|
Output = Point3<N> => U3, U4;
|
2018-10-24 02:47:42 +08:00
|
|
|
|
Point3::from(self * &rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: Point3<N>,
|
|
|
|
|
Output = Point3<N> => U3, U4;
|
2018-10-24 02:47:42 +08:00
|
|
|
|
Point3::from(self * rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b Point3<N>,
|
|
|
|
|
Output = Point3<N> => U3, U4;
|
2018-10-24 02:47:42 +08:00
|
|
|
|
Point3::from(self * &rhs.coords);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1);
|
|
|
|
|
self: UnitQuaternion<N>, rhs: Point3<N>,
|
|
|
|
|
Output = Point3<N> => U3, U4;
|
|
|
|
|
Point3::from(self * rhs.coords); );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
// UnitQuaternion × Unit<Vector>
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: &'b Unit<Vector<N, U3, SB>>,
|
|
|
|
|
Output = Unit<Vector3<N>> => U3, U4;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Unit::new_unchecked(self * rhs.as_ref());
|
|
|
|
|
'a, 'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: &'a UnitQuaternion<N>, rhs: Unit<Vector<N, U3, SB>>,
|
|
|
|
|
Output = Unit<Vector3<N>> => U3, U4;
|
2018-12-10 04:08:14 +08:00
|
|
|
|
Unit::new_unchecked(self * rhs.into_inner());
|
2016-12-05 05:44:42 +08:00
|
|
|
|
'a);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b Unit<Vector<N, U3, SB>>,
|
|
|
|
|
Output = Unit<Vector3<N>> => U3, U4;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Unit::new_unchecked(self * rhs.as_ref());
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
|
|
|
|
self: UnitQuaternion<N>, rhs: Unit<Vector<N, U3, SB>>,
|
|
|
|
|
Output = Unit<Vector3<N>> => U3, U4;
|
|
|
|
|
Unit::new_unchecked(self * rhs.into_inner()); );
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
macro_rules! scalar_op_impl(
|
|
|
|
|
($($Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident);* $(;)*) => {$(
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<N: SimdRealField> $Op<N> for Quaternion<N>
|
|
|
|
|
where N::Element: SimdRealField {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
type Output = Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn $op(self, n: N) -> Self::Output {
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(self.coords.$op(n))
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<'a, N: SimdRealField> $Op<N> for &'a Quaternion<N>
|
|
|
|
|
where N::Element: SimdRealField {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
type Output = Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn $op(self, n: N) -> Self::Output {
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from((&self.coords).$op(n))
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<N: SimdRealField> $OpAssign<N> for Quaternion<N>
|
|
|
|
|
where N::Element: SimdRealField {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn $op_assign(&mut self, n: N) {
|
|
|
|
|
self.coords.$op_assign(n)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)*}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
scalar_op_impl!(
|
|
|
|
|
Mul, mul, MulAssign, mul_assign;
|
|
|
|
|
Div, div, DivAssign, div_assign;
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
macro_rules! left_scalar_mul_impl(
|
|
|
|
|
($($T: ty),* $(,)*) => {$(
|
2017-08-03 01:37:44 +08:00
|
|
|
|
impl Mul<Quaternion<$T>> for $T {
|
|
|
|
|
type Output = Quaternion<$T>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
|
fn mul(self, right: Quaternion<$T>) -> Self::Output {
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(self * right.coords)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
impl<'b> Mul<&'b Quaternion<$T>> for $T {
|
|
|
|
|
type Output = Quaternion<$T>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
|
fn mul(self, right: &'b Quaternion<$T>) -> Self::Output {
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Quaternion::from(self * &right.coords)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)*}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
left_scalar_mul_impl!(f32, f64);
|
|
|
|
|
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<N: SimdRealField> Neg for Quaternion<N>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
|
|
|
|
N::Element: SimdRealField,
|
2020-03-22 06:22:55 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
type Output = Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn neg(self) -> Self::Output {
|
2019-03-18 16:08:42 +08:00
|
|
|
|
Self::Output::from(-self.coords)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<'a, N: SimdRealField> Neg for &'a Quaternion<N>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
|
|
|
|
N::Element: SimdRealField,
|
2020-03-22 06:22:55 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
type Output = Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn neg(self) -> Self::Output {
|
2019-03-18 16:08:42 +08:00
|
|
|
|
Self::Output::from(-&self.coords)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! quaternion_op_impl(
|
|
|
|
|
($OpAssign: ident, $op_assign: ident;
|
|
|
|
|
($LhsRDim: ident, $LhsCDim: ident), ($RhsRDim: ident, $RhsCDim: ident);
|
|
|
|
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty $(=> $VDimA: ty, $VDimB: ty)*;
|
|
|
|
|
$action: expr; $($lives: tt),*) => {
|
2020-03-21 19:16:46 +08:00
|
|
|
|
impl<$($lives ,)* N: SimdRealField> $OpAssign<$Rhs> for $Lhs
|
2020-03-22 06:22:55 +08:00
|
|
|
|
where N::Element: SimdRealField,
|
|
|
|
|
DefaultAllocator: Allocator<N, $LhsRDim, $LhsCDim> +
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Allocator<N, $RhsRDim, $RhsCDim> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn $op_assign(&mut $lhs, $rhs: $Rhs) {
|
|
|
|
|
$action
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Quaternion += Quaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
AddAssign, add_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: &'b Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self.coords += &rhs.coords;
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
AddAssign, add_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self.coords += rhs.coords; );
|
|
|
|
|
|
|
|
|
|
// Quaternion -= Quaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
SubAssign, sub_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: &'b Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self.coords -= &rhs.coords;
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
SubAssign, sub_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self.coords -= rhs.coords; );
|
|
|
|
|
|
|
|
|
|
// Quaternion ×= Quaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
MulAssign, mul_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: &'b Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
{
|
|
|
|
|
let res = &*self * rhs;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: will this be optimized away?
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self.coords.copy_from(&res.coords);
|
|
|
|
|
};
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
MulAssign, mul_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Quaternion<N>, rhs: Quaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*self *= &rhs; );
|
|
|
|
|
|
|
|
|
|
// UnitQuaternion ×= UnitQuaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
MulAssign, mul_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
{
|
|
|
|
|
let res = &*self * rhs;
|
|
|
|
|
self.as_mut_unchecked().coords.copy_from(&res.as_ref().coords);
|
|
|
|
|
};
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
MulAssign, mul_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*self *= &rhs; );
|
|
|
|
|
|
|
|
|
|
// UnitQuaternion ÷= UnitQuaternion
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
DivAssign, div_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
{
|
|
|
|
|
let res = &*self / rhs;
|
|
|
|
|
self.as_mut_unchecked().coords.copy_from(&res.as_ref().coords);
|
|
|
|
|
};
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
DivAssign, div_assign;
|
|
|
|
|
(U4, U1), (U4, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*self /= &rhs; );
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// UnitQuaternion ×= Rotation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
MulAssign, mul_assign;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b Rotation<N, U3> => U3, U3;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
{
|
|
|
|
|
let res = &*self * rhs;
|
|
|
|
|
self.as_mut_unchecked().coords.copy_from(&res.as_ref().coords);
|
|
|
|
|
};
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
MulAssign, mul_assign;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: Rotation<N, U3> => U3, U3;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*self *= &rhs; );
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// UnitQuaternion ÷= Rotation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
DivAssign, div_assign;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: &'b Rotation<N, U3> => U3, U3;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
{
|
|
|
|
|
let res = &*self / rhs;
|
|
|
|
|
self.as_mut_unchecked().coords.copy_from(&res.as_ref().coords);
|
|
|
|
|
};
|
|
|
|
|
'b);
|
|
|
|
|
|
|
|
|
|
quaternion_op_impl!(
|
|
|
|
|
DivAssign, div_assign;
|
|
|
|
|
(U4, U1), (U3, U3);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, rhs: Rotation<N, U3> => U3, U3;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*self /= &rhs; );
|