2016-12-05 05:44:42 +08:00
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Computer-graphics specific implementations.
|
|
|
|
|
* Currently, it is mostly implemented for homogeneous matrices in 2- and 3-space.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use num::{One, Zero};
|
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::{DimName, DimNameDiff, DimNameSub, U1};
|
|
|
|
|
use crate::base::storage::{Storage, StorageMut};
|
|
|
|
|
use crate::base::{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
Const, DefaultAllocator, Matrix3, Matrix4, OMatrix, OVector, Scalar, SquareMatrix, Unit,
|
|
|
|
|
Vector, Vector2, Vector3,
|
2018-10-22 13:00:10 +08:00
|
|
|
|
};
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::geometry::{
|
2020-07-03 01:31:30 +08:00
|
|
|
|
Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point2, Point3, Rotation2,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
Rotation3,
|
2018-10-22 13:00:10 +08:00
|
|
|
|
};
|
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use simba::scalar::{ClosedAdd, ClosedMul, RealField};
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Translation and scaling in any dimension
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, D: DimName> OMatrix<T, D, D>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + Zero + One,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Creates a new homogeneous matrix that applies the same scaling factor on each dimension.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_scaling(scaling: T) -> Self {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = Self::from_diagonal_element(scaling);
|
2021-04-11 17:00:38 +08:00
|
|
|
|
res[(D::dim() - 1, D::dim() - 1)] = T::one();
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new homogeneous matrix that applies a distinct scaling factor for each dimension.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_nonuniform_scaling<SB>(scaling: &Vector<T, DimNameDiff<D, U1>, SB>) -> Self
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2020-03-21 19:16:46 +08:00
|
|
|
|
let mut res = Self::identity();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for i in 0..scaling.len() {
|
2019-12-06 06:54:17 +08:00
|
|
|
|
res[(i, i)] = scaling[i].inlined_clone();
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new homogeneous matrix that applies a pure translation.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_translation<SB>(translation: &Vector<T, DimNameDiff<D, U1>, SB>) -> Self
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2020-03-21 19:16:46 +08:00
|
|
|
|
let mut res = Self::identity();
|
2021-04-11 17:00:38 +08:00
|
|
|
|
res.generic_slice_mut(
|
|
|
|
|
(0, D::dim() - 1),
|
|
|
|
|
(DimNameDiff::<D, U1>::name(), Const::<1>),
|
|
|
|
|
)
|
|
|
|
|
.copy_from(translation);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # 2D transformations as a Matrix3
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: RealField> Matrix3<T> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Builds a 2 dimensional homogeneous rotation matrix from an angle in radian.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_rotation(angle: T) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Rotation2::new(angle).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
2020-07-03 01:16:18 +08:00
|
|
|
|
|
|
|
|
|
/// Creates a new homogeneous matrix that applies a scaling factor for each dimension with respect to point.
|
|
|
|
|
///
|
|
|
|
|
/// Can be used to implement "zoom_to" functionality.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_nonuniform_scaling_wrt_point(scaling: &Vector2<T>, pt: &Point2<T>) -> Self {
|
|
|
|
|
let zero = T::zero();
|
|
|
|
|
let one = T::one();
|
2020-07-06 04:29:08 +08:00
|
|
|
|
Matrix3::new(
|
|
|
|
|
scaling.x,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
pt.x - pt.x * scaling.x,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
scaling.y,
|
|
|
|
|
pt.y - pt.y * scaling.y,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
|
|
|
|
zero,
|
|
|
|
|
one,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
)
|
2020-07-03 01:16:18 +08:00
|
|
|
|
}
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # 3D transformations as a Matrix4
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: RealField> Matrix4<T> {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
|
2018-02-02 19:26:35 +08:00
|
|
|
|
///
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Returns the identity matrix if the given argument is zero.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_rotation(axisangle: Vector3<T>) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Rotation3::new(axisangle).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
|
2018-02-02 19:26:35 +08:00
|
|
|
|
///
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Returns the identity matrix if the given argument is zero.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_rotation_wrt_point(axisangle: Vector3<T>, pt: Point3<T>) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let rot = Rotation3::from_scaled_axis(axisangle);
|
|
|
|
|
Isometry::rotation_wrt_point(rot, pt).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-03 01:16:18 +08:00
|
|
|
|
/// Creates a new homogeneous matrix that applies a scaling factor for each dimension with respect to point.
|
|
|
|
|
///
|
|
|
|
|
/// Can be used to implement "zoom_to" functionality.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_nonuniform_scaling_wrt_point(scaling: &Vector3<T>, pt: &Point3<T>) -> Self {
|
|
|
|
|
let zero = T::zero();
|
|
|
|
|
let one = T::one();
|
2020-07-06 04:29:08 +08:00
|
|
|
|
Matrix4::new(
|
|
|
|
|
scaling.x,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
|
|
|
|
zero,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
pt.x - pt.x * scaling.x,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
scaling.y,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
pt.y - pt.y * scaling.y,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
|
|
|
|
zero,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
scaling.z,
|
|
|
|
|
pt.z - pt.z * scaling.z,
|
2020-10-26 20:37:11 +08:00
|
|
|
|
zero,
|
|
|
|
|
zero,
|
|
|
|
|
zero,
|
|
|
|
|
one,
|
2020-07-06 04:29:08 +08:00
|
|
|
|
)
|
2020-07-03 01:16:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
|
2018-02-02 19:26:35 +08:00
|
|
|
|
///
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Returns the identity matrix if the given argument is zero.
|
|
|
|
|
/// This is identical to `Self::new_rotation`.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_scaled_axis(axisangle: Vector3<T>) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Rotation3::from_scaled_axis(axisangle).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new rotation from Euler angles.
|
|
|
|
|
///
|
|
|
|
|
/// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw.
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_euler_angles(roll: T, pitch: T, yaw: T) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Rotation3::from_euler_angles(roll, pitch, yaw).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds a 3D homogeneous rotation matrix from an axis and a rotation angle.
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_axis_angle(axis: &Unit<Vector3<T>>, angle: T) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Rotation3::from_axis_angle(axis, angle).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new homogeneous matrix for an orthographic projection.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_orthographic(left: T, right: T, bottom: T, top: T, znear: T, zfar: T) -> Self {
|
2018-12-10 04:32:35 +08:00
|
|
|
|
Orthographic3::new(left, right, bottom, top, znear, zfar).into_inner()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new homogeneous matrix for a perspective projection.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_perspective(aspect: T, fovy: T, znear: T, zfar: T) -> Self {
|
2018-12-10 04:38:02 +08:00
|
|
|
|
Perspective3::new(aspect, fovy, znear, zfar).into_inner()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates an isometry that corresponds to the local frame of an observer standing at the
|
|
|
|
|
/// point `eye` and looking toward `target`.
|
|
|
|
|
///
|
|
|
|
|
/// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
|
|
|
|
|
/// `eye`.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn face_towards(eye: &Point3<T>, target: &Point3<T>, up: &Vector3<T>) -> Self {
|
2019-01-17 05:41:25 +08:00
|
|
|
|
IsometryMatrix3::face_towards(eye, target, up).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-17 17:17:00 +08:00
|
|
|
|
/// Deprecated: Use [Matrix4::face_towards] instead.
|
2020-03-21 19:16:46 +08:00
|
|
|
|
#[deprecated(note = "renamed to `face_towards`")]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new_observer_frame(eye: &Point3<T>, target: &Point3<T>, up: &Vector3<T>) -> Self {
|
2019-01-17 17:17:00 +08:00
|
|
|
|
Matrix4::face_towards(eye, target, up)
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Builds a right-handed look-at view matrix.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn look_at_rh(eye: &Point3<T>, target: &Point3<T>, up: &Vector3<T>) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
IsometryMatrix3::look_at_rh(eye, target, up).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds a left-handed look-at view matrix.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn look_at_lh(eye: &Point3<T>, target: &Point3<T>, up: &Vector3<T>) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
IsometryMatrix3::look_at_lh(eye, target, up).to_homogeneous()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Append/prepend translation and scaling
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: Scalar + Zero + One + ClosedMul + ClosedAdd, D: DimName, S: Storage<T, D, D>>
|
|
|
|
|
SquareMatrix<T, D, S>
|
2020-03-21 19:16:46 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Computes the transformation equal to `self` followed by an uniform scaling factor.
|
|
|
|
|
#[inline]
|
2019-06-06 05:04:04 +08:00
|
|
|
|
#[must_use = "Did you mean to use append_scaling_mut()?"]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn append_scaling(&self, scaling: T) -> OMatrix<T, D, D>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
|
|
|
|
res.append_scaling_mut(scaling);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the transformation equal to an uniform scaling factor followed by `self`.
|
|
|
|
|
#[inline]
|
2019-06-06 05:04:04 +08:00
|
|
|
|
#[must_use = "Did you mean to use prepend_scaling_mut()?"]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn prepend_scaling(&self, scaling: T) -> OMatrix<T, D, D>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
|
|
|
|
res.prepend_scaling_mut(scaling);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the transformation equal to `self` followed by a non-uniform scaling factor.
|
|
|
|
|
#[inline]
|
2019-06-06 05:04:04 +08:00
|
|
|
|
#[must_use = "Did you mean to use append_nonuniform_scaling_mut()?"]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub fn append_nonuniform_scaling<SB>(
|
|
|
|
|
&self,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
scaling: &Vector<T, DimNameDiff<D, U1>, SB>,
|
|
|
|
|
) -> OMatrix<T, D, D>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
|
|
|
|
res.append_nonuniform_scaling_mut(scaling);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the transformation equal to a non-uniform scaling factor followed by `self`.
|
|
|
|
|
#[inline]
|
2019-06-06 05:04:04 +08:00
|
|
|
|
#[must_use = "Did you mean to use prepend_nonuniform_scaling_mut()?"]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub fn prepend_nonuniform_scaling<SB>(
|
|
|
|
|
&self,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
scaling: &Vector<T, DimNameDiff<D, U1>, SB>,
|
|
|
|
|
) -> OMatrix<T, D, D>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
|
|
|
|
res.prepend_nonuniform_scaling_mut(scaling);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the transformation equal to `self` followed by a translation.
|
|
|
|
|
#[inline]
|
2019-06-06 05:04:04 +08:00
|
|
|
|
#[must_use = "Did you mean to use append_translation_mut()?"]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn append_translation<SB>(
|
|
|
|
|
&self,
|
|
|
|
|
shift: &Vector<T, DimNameDiff<D, U1>, SB>,
|
|
|
|
|
) -> OMatrix<T, D, D>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
|
|
|
|
res.append_translation_mut(shift);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the transformation equal to a translation followed by `self`.
|
|
|
|
|
#[inline]
|
2019-06-06 05:04:04 +08:00
|
|
|
|
#[must_use = "Did you mean to use prepend_translation_mut()?"]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub fn prepend_translation<SB>(
|
|
|
|
|
&self,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
shift: &Vector<T, DimNameDiff<D, U1>, SB>,
|
|
|
|
|
) -> OMatrix<T, D, D>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D> + Allocator<T, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
|
|
|
|
res.prepend_translation_mut(shift);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes in-place the transformation equal to `self` followed by an uniform scaling factor.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn append_scaling_mut(&mut self, scaling: T)
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: StorageMut<T, D, D>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
D: DimNameSub<U1>,
|
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let mut to_scale = self.rows_generic_mut(0, DimNameDiff::<D, U1>::name());
|
2016-12-05 05:44:42 +08:00
|
|
|
|
to_scale *= scaling;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes in-place the transformation equal to an uniform scaling factor followed by `self`.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn prepend_scaling_mut(&mut self, scaling: T)
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: StorageMut<T, D, D>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
D: DimNameSub<U1>,
|
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let mut to_scale = self.columns_generic_mut(0, DimNameDiff::<D, U1>::name());
|
2016-12-05 05:44:42 +08:00
|
|
|
|
to_scale *= scaling;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes in-place the transformation equal to `self` followed by a non-uniform scaling factor.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn append_nonuniform_scaling_mut<SB>(&mut self, scaling: &Vector<T, DimNameDiff<D, U1>, SB>)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: StorageMut<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
|
|
|
|
for i in 0..scaling.len() {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let mut to_scale = self.fixed_rows_mut::<1>(i);
|
2019-12-06 06:54:17 +08:00
|
|
|
|
to_scale *= scaling[i].inlined_clone();
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes in-place the transformation equal to a non-uniform scaling factor followed by `self`.
|
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub fn prepend_nonuniform_scaling_mut<SB>(
|
|
|
|
|
&mut self,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
scaling: &Vector<T, DimNameDiff<D, U1>, SB>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
) where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: StorageMut<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
|
|
|
|
for i in 0..scaling.len() {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let mut to_scale = self.fixed_columns_mut::<1>(i);
|
2019-12-06 06:54:17 +08:00
|
|
|
|
to_scale *= scaling[i].inlined_clone();
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the transformation equal to `self` followed by a translation.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn append_translation_mut<SB>(&mut self, shift: &Vector<T, DimNameDiff<D, U1>, SB>)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: StorageMut<T, D, D>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
|
|
|
|
for i in 0..D::dim() {
|
|
|
|
|
for j in 0..D::dim() - 1 {
|
2019-12-06 06:54:17 +08:00
|
|
|
|
let add = shift[j].inlined_clone() * self[(D::dim() - 1, i)].inlined_clone();
|
2019-03-12 16:00:23 +08:00
|
|
|
|
self[(j, i)] += add;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the transformation equal to a translation followed by `self`.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn prepend_translation_mut<SB>(&mut self, shift: &Vector<T, DimNameDiff<D, U1>, SB>)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: DimNameSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: StorageMut<T, D, D>,
|
|
|
|
|
SB: Storage<T, DimNameDiff<D, U1>>,
|
|
|
|
|
DefaultAllocator: Allocator<T, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2018-10-22 13:00:10 +08:00
|
|
|
|
let scale = self
|
2021-04-11 17:00:38 +08:00
|
|
|
|
.generic_slice(
|
|
|
|
|
(D::dim() - 1, 0),
|
|
|
|
|
(Const::<1>, DimNameDiff::<D, U1>::name()),
|
|
|
|
|
)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
.tr_dot(&shift);
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let post_translation = self.generic_slice(
|
|
|
|
|
(0, 0),
|
|
|
|
|
(DimNameDiff::<D, U1>::name(), DimNameDiff::<D, U1>::name()),
|
|
|
|
|
) * shift;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2017-02-13 01:17:09 +08:00
|
|
|
|
self[(D::dim() - 1, D::dim() - 1)] += scale;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let mut translation = self.generic_slice_mut(
|
|
|
|
|
(0, D::dim() - 1),
|
|
|
|
|
(DimNameDiff::<D, U1>::name(), Const::<1>),
|
|
|
|
|
);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
translation += post_translation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Transformation of vectors and points
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: RealField, D: DimNameSub<U1>, S: Storage<T, D, D>> SquareMatrix<T, D, S>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, D, D>
|
|
|
|
|
+ Allocator<T, DimNameDiff<D, U1>>
|
|
|
|
|
+ Allocator<T, DimNameDiff<D, U1>, DimNameDiff<D, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2018-10-29 19:50:27 +08:00
|
|
|
|
/// Transforms the given vector, assuming the matrix `self` uses homogeneous coordinates.
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2018-10-30 14:54:26 +08:00
|
|
|
|
pub fn transform_vector(
|
2018-02-02 19:26:35 +08:00
|
|
|
|
&self,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
v: &OVector<T, DimNameDiff<D, U1>>,
|
|
|
|
|
) -> OVector<T, DimNameDiff<D, U1>> {
|
|
|
|
|
let transform = self.generic_slice(
|
|
|
|
|
(0, 0),
|
|
|
|
|
(DimNameDiff::<D, U1>::name(), DimNameDiff::<D, U1>::name()),
|
|
|
|
|
);
|
|
|
|
|
let normalizer = self.generic_slice(
|
|
|
|
|
(D::dim() - 1, 0),
|
|
|
|
|
(Const::<1>, DimNameDiff::<D, U1>::name()),
|
|
|
|
|
);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let n = normalizer.tr_dot(&v);
|
|
|
|
|
|
|
|
|
|
if !n.is_zero() {
|
|
|
|
|
return transform * (v / n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
transform * v
|
|
|
|
|
}
|
2021-04-08 17:53:01 +08:00
|
|
|
|
}
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: RealField, S: Storage<T, Const<3>, Const<3>>> SquareMatrix<T, Const<3>, S> {
|
2018-10-29 19:48:53 +08:00
|
|
|
|
/// Transforms the given point, assuming the matrix `self` uses homogeneous coordinates.
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn transform_point(&self, pt: &Point<T, 2>) -> Point<T, 2> {
|
|
|
|
|
let transform = self.fixed_slice::<2, 2>(0, 0);
|
|
|
|
|
let translation = self.fixed_slice::<2, 1>(0, 2);
|
|
|
|
|
let normalizer = self.fixed_slice::<1, 2>(2, 0);
|
2021-04-08 17:53:01 +08:00
|
|
|
|
let n = normalizer.tr_dot(&pt.coords) + unsafe { *self.get_unchecked((2, 2)) };
|
|
|
|
|
|
|
|
|
|
if !n.is_zero() {
|
|
|
|
|
(transform * pt + translation) / n
|
|
|
|
|
} else {
|
|
|
|
|
transform * pt + translation
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: RealField, S: Storage<T, Const<4>, Const<4>>> SquareMatrix<T, Const<4>, S> {
|
2021-04-08 17:53:01 +08:00
|
|
|
|
/// Transforms the given point, assuming the matrix `self` uses homogeneous coordinates.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn transform_point(&self, pt: &Point<T, 3>) -> Point<T, 3> {
|
|
|
|
|
let transform = self.fixed_slice::<3, 3>(0, 0);
|
|
|
|
|
let translation = self.fixed_slice::<3, 1>(0, 3);
|
|
|
|
|
let normalizer = self.fixed_slice::<1, 3>(3, 0);
|
2021-04-08 17:53:01 +08:00
|
|
|
|
let n = normalizer.tr_dot(&pt.coords) + unsafe { *self.get_unchecked((3, 3)) };
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
if !n.is_zero() {
|
2019-08-27 20:30:20 +08:00
|
|
|
|
(transform * pt + translation) / n
|
|
|
|
|
} else {
|
|
|
|
|
transform * pt + translation
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|