2020-03-21 19:16:46 +08:00
|
|
|
|
use num::{One, Zero};
|
2018-02-02 19:26:35 +08:00
|
|
|
|
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2020-03-22 06:22:55 +08:00
|
|
|
|
use simba::scalar::{ClosedAdd, ClosedMul};
|
|
|
|
|
use simba::simd::SimdRealField;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::base::allocator::Allocator;
|
2020-03-25 02:06:28 +08:00
|
|
|
|
use crate::base::dimension::{DimName, U1, U2, U3, U4};
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use crate::base::{DefaultAllocator, Scalar, VectorN};
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use crate::geometry::{
|
2020-03-25 02:06:28 +08:00
|
|
|
|
AbstractRotation, Isometry, Point, Rotation, Similarity, Translation, UnitComplex,
|
|
|
|
|
UnitQuaternion,
|
2020-03-21 19:16:46 +08:00
|
|
|
|
};
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: there are several cloning of rotations that we could probably get rid of (but we didn't
|
2016-12-05 05:44:42 +08:00
|
|
|
|
// yet because that would require to add a bound like `where for<'a, 'b> &'a R: Mul<&'b R, Output = R>`
|
|
|
|
|
// which is quite ugly.
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* In this file, we provide:
|
|
|
|
|
* =========================
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* (Operators)
|
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Similarity × Similarity
|
|
|
|
|
* Similarity × R
|
|
|
|
|
* Similarity × Isometry
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Isometry × Similarity
|
|
|
|
|
* Isometry ÷ Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Similarity ÷ Similarity
|
|
|
|
|
* Similarity ÷ R
|
|
|
|
|
* Similarity ÷ Isometry
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Similarity × Point
|
|
|
|
|
* Similarity × Vector
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Similarity × Translation
|
|
|
|
|
* Translation × Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* NOTE: The following are provided explicitly because we can't have R × Similarity.
|
|
|
|
|
* Rotation × Similarity<Rotation>
|
|
|
|
|
* UnitQuaternion × Similarity<UnitQuaternion>
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Rotation ÷ Similarity<Rotation>
|
|
|
|
|
* UnitQuaternion ÷ Similarity<UnitQuaternion>
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
* (Assignment Operators)
|
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Similarity ×= Translation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Similarity ×= Similarity
|
|
|
|
|
* Similarity ×= Isometry
|
|
|
|
|
* Similarity ×= R
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
2017-08-03 01:37:44 +08:00
|
|
|
|
* Similarity ÷= Similarity
|
|
|
|
|
* Similarity ÷= Isometry
|
|
|
|
|
* Similarity ÷= R
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// XXX: code duplication: those macros are the same as for the isometry.
|
|
|
|
|
macro_rules! similarity_binop_impl(
|
|
|
|
|
($Op: ident, $op: ident;
|
|
|
|
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
|
|
|
|
$action: expr; $($lives: tt),*) => {
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<$($lives ,)* N: SimdRealField, D: DimName, R> $Op<$Rhs> for $Lhs
|
|
|
|
|
where N::Element: SimdRealField,
|
|
|
|
|
R: AbstractRotation<N, D>,
|
2017-08-03 01:37:44 +08:00
|
|
|
|
DefaultAllocator: Allocator<N, D> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
type Output = $Output;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn $op($lhs, $rhs: $Rhs) -> Self::Output {
|
|
|
|
|
$action
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
macro_rules! similarity_binop_impl_all(
|
|
|
|
|
($Op: ident, $op: ident;
|
|
|
|
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
|
|
|
|
[val val] => $action_val_val: expr;
|
|
|
|
|
[ref val] => $action_ref_val: expr;
|
|
|
|
|
[val ref] => $action_val_ref: expr;
|
|
|
|
|
[ref ref] => $action_ref_ref: expr;) => {
|
|
|
|
|
similarity_binop_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
$lhs: $Lhs, $rhs: $Rhs, Output = $Output;
|
|
|
|
|
$action_val_val; );
|
|
|
|
|
|
|
|
|
|
similarity_binop_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
$lhs: &'a $Lhs, $rhs: $Rhs, Output = $Output;
|
|
|
|
|
$action_ref_val; 'a);
|
|
|
|
|
|
|
|
|
|
similarity_binop_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
$lhs: $Lhs, $rhs: &'b $Rhs, Output = $Output;
|
|
|
|
|
$action_val_ref; 'b);
|
|
|
|
|
|
|
|
|
|
similarity_binop_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
$lhs: &'a $Lhs, $rhs: &'b $Rhs, Output = $Output;
|
|
|
|
|
$action_ref_ref; 'a, 'b);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
macro_rules! similarity_binop_assign_impl_all(
|
|
|
|
|
($OpAssign: ident, $op_assign: ident;
|
|
|
|
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty;
|
|
|
|
|
[val] => $action_val: expr;
|
|
|
|
|
[ref] => $action_ref: expr;) => {
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<N: SimdRealField, D: DimName, R> $OpAssign<$Rhs> for $Lhs
|
|
|
|
|
where N::Element: SimdRealField,
|
|
|
|
|
R: AbstractRotation<N, D>,
|
2017-08-03 01:37:44 +08:00
|
|
|
|
DefaultAllocator: Allocator<N, D> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
fn $op_assign(&mut $lhs, $rhs: $Rhs) {
|
|
|
|
|
$action_val
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<'b, N: SimdRealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs
|
|
|
|
|
where N::Element: SimdRealField,
|
|
|
|
|
R: AbstractRotation<N, D>,
|
2017-08-03 01:37:44 +08:00
|
|
|
|
DefaultAllocator: Allocator<N, D> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) {
|
|
|
|
|
$action_ref
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity × Similarity
|
|
|
|
|
// Similarity ÷ Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Similarity<N, D, R>, Output = Similarity<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => &self * &rhs;
|
|
|
|
|
[ref val] => self * &rhs;
|
|
|
|
|
[val ref] => &self * rhs;
|
|
|
|
|
[ref ref] => {
|
|
|
|
|
let mut res = self * &rhs.isometry;
|
|
|
|
|
res.prepend_scaling_mut(rhs.scaling());
|
|
|
|
|
res
|
|
|
|
|
};
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Div, div;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Similarity<N, D, R>, Output = Similarity<N, D, R>;
|
2020-10-26 01:23:24 +08:00
|
|
|
|
[val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity ×= Translation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_assign_impl_all!(
|
|
|
|
|
MulAssign, mul_assign;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Translation<N, D>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val] => *self *= &rhs;
|
|
|
|
|
[ref] => {
|
|
|
|
|
let shift = self.isometry.rotation.transform_vector(&rhs.vector) * self.scaling();
|
|
|
|
|
self.isometry.translation.vector += shift;
|
|
|
|
|
};
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity ×= Similarity
|
|
|
|
|
// Similarity ÷= Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_assign_impl_all!(
|
|
|
|
|
MulAssign, mul_assign;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Similarity<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val] => *self *= &rhs;
|
|
|
|
|
[ref] => {
|
|
|
|
|
*self *= &rhs.isometry;
|
|
|
|
|
self.prepend_scaling_mut(rhs.scaling());
|
|
|
|
|
};
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
similarity_binop_assign_impl_all!(
|
|
|
|
|
DivAssign, div_assign;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Similarity<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val] => *self /= &rhs;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: don't invert explicitly.
|
2020-10-26 19:44:53 +08:00
|
|
|
|
[ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity ×= Isometry
|
|
|
|
|
// Similarity ÷= Isometry
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_assign_impl_all!(
|
|
|
|
|
MulAssign, mul_assign;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Isometry<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val] => *self *= &rhs;
|
|
|
|
|
[ref] => {
|
|
|
|
|
let shift = self.isometry.rotation.transform_vector(&rhs.translation.vector) * self.scaling();
|
|
|
|
|
self.isometry.translation.vector += shift;
|
|
|
|
|
self.isometry.rotation *= rhs.rotation.clone();
|
|
|
|
|
};
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
similarity_binop_assign_impl_all!(
|
|
|
|
|
DivAssign, div_assign;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Isometry<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val] => *self /= &rhs;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: don't invert explicitly.
|
2020-10-26 19:44:53 +08:00
|
|
|
|
[ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity ×= R
|
|
|
|
|
// Similarity ÷= R
|
2020-03-21 19:16:46 +08:00
|
|
|
|
md_assign_impl_all!(
|
2020-03-22 06:22:55 +08:00
|
|
|
|
MulAssign, mul_assign where N: SimdRealField for N::Element: SimdRealField;
|
2020-03-21 19:16:46 +08:00
|
|
|
|
(D, U1), (D, D) for D: DimName;
|
|
|
|
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val] => self.isometry.rotation *= rhs;
|
|
|
|
|
[ref] => self.isometry.rotation *= rhs.clone();
|
|
|
|
|
);
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
md_assign_impl_all!(
|
2020-03-22 06:22:55 +08:00
|
|
|
|
DivAssign, div_assign where N: SimdRealField for N::Element: SimdRealField;
|
2020-03-21 19:16:46 +08:00
|
|
|
|
(D, U1), (D, D) for D: DimName;
|
|
|
|
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: don't invert explicitly?
|
2020-10-26 19:44:53 +08:00
|
|
|
|
[val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
|
|
|
|
[ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
md_assign_impl_all!(
|
2020-03-22 06:22:55 +08:00
|
|
|
|
MulAssign, mul_assign where N: SimdRealField for N::Element: SimdRealField;
|
2020-03-21 19:16:46 +08:00
|
|
|
|
(U3, U3), (U3, U3) for;
|
|
|
|
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>;
|
|
|
|
|
[val] => self.isometry.rotation *= rhs;
|
2020-11-19 19:55:15 +08:00
|
|
|
|
[ref] => self.isometry.rotation *= *rhs;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
md_assign_impl_all!(
|
2020-03-22 06:22:55 +08:00
|
|
|
|
DivAssign, div_assign where N: SimdRealField for N::Element: SimdRealField;
|
2020-03-21 19:16:46 +08:00
|
|
|
|
(U3, U3), (U3, U3) for;
|
|
|
|
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: don't invert explicitly?
|
2020-10-26 19:44:53 +08:00
|
|
|
|
[val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
|
|
|
|
[ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2020-03-25 02:06:28 +08:00
|
|
|
|
md_assign_impl_all!(
|
|
|
|
|
MulAssign, mul_assign where N: SimdRealField for N::Element: SimdRealField;
|
|
|
|
|
(U2, U2), (U2, U2) for;
|
|
|
|
|
self: Similarity<N, U2, UnitComplex<N>>, rhs: UnitComplex<N>;
|
|
|
|
|
[val] => self.isometry.rotation *= rhs;
|
2020-11-19 19:55:15 +08:00
|
|
|
|
[ref] => self.isometry.rotation *= *rhs;
|
2020-03-25 02:06:28 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
md_assign_impl_all!(
|
|
|
|
|
DivAssign, div_assign where N: SimdRealField for N::Element: SimdRealField;
|
|
|
|
|
(U2, U2), (U2, U2) for;
|
|
|
|
|
self: Similarity<N, U2, UnitComplex<N>>, rhs: UnitComplex<N>;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: don't invert explicitly?
|
2020-10-26 19:44:53 +08:00
|
|
|
|
[val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
|
|
|
|
[ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
|
2020-03-25 02:06:28 +08:00
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity × Isometry
|
|
|
|
|
// Similarity ÷ Isometry
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Isometry<N, D, R>, Output = Similarity<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => &self * &rhs;
|
|
|
|
|
[ref val] => self * &rhs;
|
|
|
|
|
[val ref] => &self * rhs;
|
|
|
|
|
[ref ref] => {
|
|
|
|
|
let shift = self.isometry.rotation.transform_vector(&rhs.translation.vector) * self.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_parts(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
#[allow(clippy::suspicious_arithmetic_impl)]
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Translation::from(&self.isometry.translation.vector + shift),
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self.isometry.rotation.clone() * rhs.rotation.clone(),
|
|
|
|
|
self.scaling())
|
|
|
|
|
};
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Div, div;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, rhs: Isometry<N, D, R>, Output = Similarity<N, D, R>;
|
2020-10-26 01:23:24 +08:00
|
|
|
|
[val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Isometry × Similarity
|
|
|
|
|
// Isometry ÷ Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Isometry<N, D, R>, rhs: Similarity<N, D, R>, Output = Similarity<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = rhs.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_isometry(self * rhs.isometry, scaling)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
};
|
|
|
|
|
[ref val] => {
|
|
|
|
|
let scaling = rhs.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_isometry(self * rhs.isometry, scaling)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
};
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = rhs.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_isometry(self * &rhs.isometry, scaling)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
};
|
|
|
|
|
[ref ref] => {
|
|
|
|
|
let scaling = rhs.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_isometry(self * &rhs.isometry, scaling)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
};
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Div, div;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Isometry<N, D, R>, rhs: Similarity<N, D, R>, Output = Similarity<N, D, R>;
|
2020-10-26 01:23:24 +08:00
|
|
|
|
[val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
|
|
|
|
[ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity × Point
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, right: Point<N, D>, Output = Point<N, D>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
self.isometry.translation * (self.isometry.rotation.transform_point(&right) * scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref val] => &self.isometry.translation * (self.isometry.rotation.transform_point(&right) * self.scaling());
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
self.isometry.translation * (self.isometry.rotation.transform_point(right) * scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref ref] => &self.isometry.translation * (self.isometry.rotation.transform_point(right) * self.scaling());
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity × Vector
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, right: VectorN<N, D>, Output = VectorN<N, D>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => self.isometry.rotation.transform_vector(&right) * self.scaling();
|
|
|
|
|
[ref val] => self.isometry.rotation.transform_vector(&right) * self.scaling();
|
|
|
|
|
[val ref] => self.isometry.rotation.transform_vector(right) * self.scaling();
|
|
|
|
|
[ref ref] => self.isometry.rotation.transform_vector(right) * self.scaling();
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Similarity × Translation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Similarity<N, D, R>, right: Translation<N, D>, Output = Similarity<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => &self * &right;
|
|
|
|
|
[ref val] => self * &right;
|
|
|
|
|
[val ref] => &self * right;
|
|
|
|
|
[ref ref] => {
|
|
|
|
|
let shift = self.isometry.rotation.transform_vector(&right.vector) * self.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_parts(
|
2020-10-26 01:23:24 +08:00
|
|
|
|
#[allow(clippy::suspicious_arithmetic_impl)]
|
2018-10-28 14:33:39 +08:00
|
|
|
|
Translation::from(&self.isometry.translation.vector + shift),
|
2016-12-05 05:44:42 +08:00
|
|
|
|
self.isometry.rotation.clone(),
|
|
|
|
|
self.scaling())
|
|
|
|
|
};
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Translation × Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_binop_impl_all!(
|
|
|
|
|
Mul, mul;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Translation<N, D>, right: Similarity<N, D, R>, Output = Similarity<N, D, R>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = right.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_isometry(self * right.isometry, scaling)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
};
|
|
|
|
|
[ref val] => {
|
|
|
|
|
let scaling = right.scaling();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Similarity::from_isometry(self * right.isometry, scaling)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
};
|
2017-08-03 01:37:44 +08:00
|
|
|
|
[val ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
|
|
|
|
[ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
macro_rules! similarity_from_composition_impl(
|
|
|
|
|
($Op: ident, $op: ident;
|
|
|
|
|
($R1: ty, $C1: ty),($R2: ty, $C2: ty) $(for $Dims: ident: $DimsBound: ident),*;
|
|
|
|
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
|
|
|
|
$action: expr; $($lives: tt),*) => {
|
2020-03-22 06:22:55 +08:00
|
|
|
|
impl<$($lives ,)* N: SimdRealField $(, $Dims: $DimsBound)*> $Op<$Rhs> for $Lhs
|
|
|
|
|
where N::Element: SimdRealField,
|
|
|
|
|
DefaultAllocator: Allocator<N, $R1, $C1> +
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Allocator<N, $R2, $C2> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
type Output = $Output;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn $op($lhs, $rhs: $Rhs) -> Self::Output {
|
|
|
|
|
$action
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
macro_rules! similarity_from_composition_impl_all(
|
|
|
|
|
($Op: ident, $op: ident;
|
|
|
|
|
($R1: ty, $C1: ty),($R2: ty, $C2: ty) $(for $Dims: ident: $DimsBound: ident),*;
|
|
|
|
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
|
|
|
|
[val val] => $action_val_val: expr;
|
|
|
|
|
[ref val] => $action_ref_val: expr;
|
|
|
|
|
[val ref] => $action_val_ref: expr;
|
|
|
|
|
[ref ref] => $action_ref_ref: expr;) => {
|
|
|
|
|
|
|
|
|
|
similarity_from_composition_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
($R1, $C1),($R2, $C2) $(for $Dims: $DimsBound),*;
|
|
|
|
|
$lhs: $Lhs, $rhs: $Rhs, Output = $Output;
|
|
|
|
|
$action_val_val; );
|
|
|
|
|
|
|
|
|
|
similarity_from_composition_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
($R1, $C1),($R2, $C2) $(for $Dims: $DimsBound),*;
|
|
|
|
|
$lhs: &'a $Lhs, $rhs: $Rhs, Output = $Output;
|
|
|
|
|
$action_ref_val; 'a);
|
|
|
|
|
|
|
|
|
|
similarity_from_composition_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
($R1, $C1),($R2, $C2) $(for $Dims: $DimsBound),*;
|
|
|
|
|
$lhs: $Lhs, $rhs: &'b $Rhs, Output = $Output;
|
|
|
|
|
$action_val_ref; 'b);
|
|
|
|
|
|
|
|
|
|
similarity_from_composition_impl!(
|
|
|
|
|
$Op, $op;
|
|
|
|
|
($R1, $C1),($R2, $C2) $(for $Dims: $DimsBound),*;
|
|
|
|
|
$lhs: &'a $Lhs, $rhs: &'b $Rhs, Output = $Output;
|
|
|
|
|
$action_ref_ref; 'a, 'b);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
// Similarity × Rotation
|
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(D, D), (D, U1) for D: DimName;
|
|
|
|
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>,
|
|
|
|
|
Output = Similarity<N, D, Rotation<N, D>>;
|
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Rotation × Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(D, D), (D, U1) for D: DimName;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Rotation<N, D>, right: Similarity<N, D, Rotation<N, D>>,
|
|
|
|
|
Output = Similarity<N, D, Rotation<N, D>>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => &self * &right;
|
|
|
|
|
[ref val] => self * &right;
|
|
|
|
|
[val ref] => &self * right;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
[ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
// Similarity ÷ Rotation
|
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(D, D), (D, U1) for D: DimName;
|
|
|
|
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>,
|
|
|
|
|
Output = Similarity<N, D, Rotation<N, D>>;
|
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// Rotation ÷ Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(D, D), (D, U1) for D: DimName;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: Rotation<N, D>, right: Similarity<N, D, Rotation<N, D>>,
|
|
|
|
|
Output = Similarity<N, D, Rotation<N, D>>;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: don't call inverse explicitly?
|
2020-10-26 01:23:24 +08:00
|
|
|
|
[val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
|
|
|
|
[ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
|
|
|
|
[val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
|
|
|
|
[ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
// Similarity × UnitQuaternion
|
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1);
|
|
|
|
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>,
|
|
|
|
|
Output = Similarity<N, U3, UnitQuaternion<N>>;
|
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// UnitQuaternion × Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U4, U1), (U3, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, right: Similarity<N, U3, UnitQuaternion<N>>,
|
|
|
|
|
Output = Similarity<N, U3, UnitQuaternion<N>>;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
[val val] => &self * &right;
|
|
|
|
|
[ref val] => self * &right;
|
|
|
|
|
[val ref] => &self * right;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
[ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
2020-03-25 02:06:28 +08:00
|
|
|
|
// Similarity ÷ UnitQuaternion
|
2020-03-21 19:16:46 +08:00
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U3, U1);
|
|
|
|
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>,
|
|
|
|
|
Output = Similarity<N, U3, UnitQuaternion<N>>;
|
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
|
|
|
);
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// UnitQuaternion ÷ Similarity
|
2016-12-05 05:44:42 +08:00
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U4, U1), (U3, U1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self: UnitQuaternion<N>, right: Similarity<N, U3, UnitQuaternion<N>>,
|
|
|
|
|
Output = Similarity<N, U3, UnitQuaternion<N>>;
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: don't call inverse explicitly?
|
2020-10-26 01:23:24 +08:00
|
|
|
|
[val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
|
|
|
|
[ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
|
|
|
|
[val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
|
|
|
|
[ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
);
|
2020-03-25 02:06:28 +08:00
|
|
|
|
|
|
|
|
|
// Similarity × UnitComplex
|
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Mul, mul;
|
|
|
|
|
(U2, U1), (U2, U1);
|
|
|
|
|
self: Similarity<N, U2, UnitComplex<N>>, rhs: UnitComplex<N>,
|
|
|
|
|
Output = Similarity<N, U2, UnitComplex<N>>;
|
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Similarity ÷ UnitComplex
|
|
|
|
|
similarity_from_composition_impl_all!(
|
|
|
|
|
Div, div;
|
|
|
|
|
(U2, U1), (U2, U1);
|
|
|
|
|
self: Similarity<N, U2, UnitComplex<N>>, rhs: UnitComplex<N>,
|
|
|
|
|
Output = Similarity<N, U2, UnitComplex<N>>;
|
|
|
|
|
[val val] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
|
|
|
[val ref] => {
|
|
|
|
|
let scaling = self.scaling();
|
|
|
|
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
|
|
|
|
};
|
|
|
|
|
[ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
|
|
|
);
|