Make scalar type parametrs out of transform and rotation traits
This commit is contained in:
parent
25aea84e0d
commit
669e43ab59
6 changed files with 114 additions and 109 deletions
88
src/point.rs
88
src/point.rs
|
@ -66,7 +66,7 @@ impl<S: BaseNum> Point3<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specifies the numeric operations for point types.
|
/// Specifies the numeric operations for point types.
|
||||||
pub trait Point<S: BaseNum>: Array1<Element = S> + Clone // where
|
pub trait Point: Array1<Element = <<Self as Point>::Vector as Vector>::Scalar> + Clone // where
|
||||||
// FIXME: blocked by rust-lang/rust#20671
|
// FIXME: blocked by rust-lang/rust#20671
|
||||||
//
|
//
|
||||||
// for<'a, 'b> &'a Self: Add<&'b V, Output = Self>,
|
// for<'a, 'b> &'a Self: Add<&'b V, Output = Self>,
|
||||||
|
@ -77,7 +77,7 @@ pub trait Point<S: BaseNum>: Array1<Element = S> + Clone // where
|
||||||
// for<'a> &'a Self: Rem<S, Output = Self>,
|
// for<'a> &'a Self: Rem<S, Output = Self>,
|
||||||
{
|
{
|
||||||
/// The associated displacement vector.
|
/// The associated displacement vector.
|
||||||
type Vector: Vector<Scalar = S>;
|
type Vector: Vector;
|
||||||
|
|
||||||
/// Create a point at the origin.
|
/// Create a point at the origin.
|
||||||
fn origin() -> Self;
|
fn origin() -> Self;
|
||||||
|
@ -89,13 +89,13 @@ pub trait Point<S: BaseNum>: Array1<Element = S> + Clone // where
|
||||||
|
|
||||||
/// Multiply each component by a scalar, returning the new point.
|
/// Multiply each component by a scalar, returning the new point.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn mul_s(&self, s: S) -> Self;
|
fn mul_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Self;
|
||||||
/// Divide each component by a scalar, returning the new point.
|
/// Divide each component by a scalar, returning the new point.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn div_s(&self, s: S) -> Self;
|
fn div_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Self;
|
||||||
/// Subtract a scalar from each component, returning the new point.
|
/// Subtract a scalar from each component, returning the new point.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn rem_s(&self, s: S) -> Self;
|
fn rem_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Self;
|
||||||
|
|
||||||
/// Add a vector to this point, returning the new point.
|
/// Add a vector to this point, returning the new point.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -104,17 +104,17 @@ pub trait Point<S: BaseNum>: Array1<Element = S> + Clone // where
|
||||||
fn sub_p(&self, p: &Self) -> Self::Vector;
|
fn sub_p(&self, p: &Self) -> Self::Vector;
|
||||||
|
|
||||||
/// Multiply each component by a scalar, in-place.
|
/// Multiply each component by a scalar, in-place.
|
||||||
fn mul_self_s(&mut self, s: S);
|
fn mul_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar);
|
||||||
/// Divide each component by a scalar, in-place.
|
/// Divide each component by a scalar, in-place.
|
||||||
fn div_self_s(&mut self, s: S);
|
fn div_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar);
|
||||||
/// Take the remainder of each component by a scalar, in-place.
|
/// Take the remainder of each component by a scalar, in-place.
|
||||||
fn rem_self_s(&mut self, s: S);
|
fn rem_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar);
|
||||||
|
|
||||||
/// Add a vector to this point, in-place.
|
/// Add a vector to this point, in-place.
|
||||||
fn add_self_v(&mut self, v: &Self::Vector);
|
fn add_self_v(&mut self, v: &Self::Vector);
|
||||||
|
|
||||||
/// This is a weird one, but its useful for plane calculations.
|
/// This is a weird one, but its useful for plane calculations.
|
||||||
fn dot(&self, v: &Self::Vector) -> S;
|
fn dot(&self, v: &Self::Vector) -> <<Self as Point>::Vector as Vector>::Scalar;
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn min(&self, p: &Self) -> Self;
|
fn min(&self, p: &Self) -> Self;
|
||||||
|
@ -127,7 +127,7 @@ impl<S: BaseNum> Array1 for Point2<S> {
|
||||||
type Element = S;
|
type Element = S;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseNum> Point<S> for Point2<S> {
|
impl<S: BaseNum> Point for Point2<S> {
|
||||||
type Vector = Vector2<S>;
|
type Vector = Vector2<S>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -145,28 +145,28 @@ impl<S: BaseNum> Point<S> for Point2<S> {
|
||||||
Vector2::new(self.x, self.y)
|
Vector2::new(self.x, self.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline] fn mul_s(&self, s: S) -> Point2<S> { self * s }
|
#[inline] fn mul_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Point2<S> { self * scalar }
|
||||||
#[inline] fn div_s(&self, s: S) -> Point2<S> { self / s }
|
#[inline] fn div_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Point2<S> { self / scalar }
|
||||||
#[inline] fn rem_s(&self, s: S) -> Point2<S> { self % s }
|
#[inline] fn rem_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Point2<S> { self % scalar }
|
||||||
#[inline] fn add_v(&self, v: &Vector2<S>) -> Point2<S> { self + v }
|
#[inline] fn add_v(&self, v: &Vector2<S>) -> Point2<S> { self + v }
|
||||||
#[inline] fn sub_p(&self, p: &Point2<S>) -> Vector2<S> { self - p }
|
#[inline] fn sub_p(&self, p: &Point2<S>) -> Vector2<S> { self - p }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_self_s(&mut self, s: S) {
|
fn mul_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar) {
|
||||||
self.x = self.x * s;
|
self.x = self.x * scalar;
|
||||||
self.y = self.y * s;
|
self.y = self.y * scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div_self_s(&mut self, s: S) {
|
fn div_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar) {
|
||||||
self.x = self.x / s;
|
self.x = self.x / scalar;
|
||||||
self.y = self.y / s;
|
self.y = self.y / scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem_self_s(&mut self, s: S) {
|
fn rem_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar) {
|
||||||
self.x = self.x % s;
|
self.x = self.x % scalar;
|
||||||
self.y = self.y % s;
|
self.y = self.y % scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -206,7 +206,7 @@ impl<S: BaseNum> Array1 for Point3<S> {
|
||||||
type Element = S;
|
type Element = S;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseNum> Point<S> for Point3<S> {
|
impl<S: BaseNum> Point for Point3<S> {
|
||||||
type Vector = Vector3<S>;
|
type Vector = Vector3<S>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -224,31 +224,31 @@ impl<S: BaseNum> Point<S> for Point3<S> {
|
||||||
Vector3::new(self.x, self.y, self.z)
|
Vector3::new(self.x, self.y, self.z)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline] fn mul_s(&self, s: S) -> Point3<S> { self * s }
|
#[inline] fn mul_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Point3<S> { self * scalar }
|
||||||
#[inline] fn div_s(&self, s: S) -> Point3<S> { self / s }
|
#[inline] fn div_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Point3<S> { self / scalar }
|
||||||
#[inline] fn rem_s(&self, s: S) -> Point3<S> { self % s }
|
#[inline] fn rem_s(&self, scalar: <<Self as Point>::Vector as Vector>::Scalar) -> Point3<S> { self % scalar }
|
||||||
#[inline] fn add_v(&self, v: &Vector3<S>) -> Point3<S> { self + v }
|
#[inline] fn add_v(&self, v: &Vector3<S>) -> Point3<S> { self + v }
|
||||||
#[inline] fn sub_p(&self, p: &Point3<S>) -> Vector3<S> { self - p }
|
#[inline] fn sub_p(&self, p: &Point3<S>) -> Vector3<S> { self - p }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_self_s(&mut self, s: S) {
|
fn mul_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar) {
|
||||||
self.x = self.x * s;
|
self.x = self.x * scalar;
|
||||||
self.y = self.y * s;
|
self.y = self.y * scalar;
|
||||||
self.z = self.z * s;
|
self.z = self.z * scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div_self_s(&mut self, s: S) {
|
fn div_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar) {
|
||||||
self.x = self.x / s;
|
self.x = self.x / scalar;
|
||||||
self.y = self.y / s;
|
self.y = self.y / scalar;
|
||||||
self.z = self.z / s;
|
self.z = self.z / scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem_self_s(&mut self, s: S) {
|
fn rem_self_s(&mut self, scalar: <<Self as Point>::Vector as Vector>::Scalar) {
|
||||||
self.x = self.x % s;
|
self.x = self.x % scalar;
|
||||||
self.y = self.y % s;
|
self.y = self.y % scalar;
|
||||||
self.z = self.z % s;
|
self.z = self.z % scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -294,8 +294,8 @@ macro_rules! impl_operators {
|
||||||
type Output = $PointN<S>;
|
type Output = $PointN<S>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(self, s: S) -> $PointN<S> {
|
fn mul(self, scalar: S) -> $PointN<S> {
|
||||||
$PointN::new($(self.$field * s),+)
|
$PointN::new($(self.$field * scalar),+)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,8 +303,8 @@ macro_rules! impl_operators {
|
||||||
type Output = $PointN<S>;
|
type Output = $PointN<S>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self, s: S) -> $PointN<S> {
|
fn div(self, scalar: S) -> $PointN<S> {
|
||||||
$PointN::new($(self.$field / s),+)
|
$PointN::new($(self.$field / scalar),+)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,8 +312,8 @@ macro_rules! impl_operators {
|
||||||
type Output = $PointN<S>;
|
type Output = $PointN<S>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem(self, s: S) -> $PointN<S> {
|
fn rem(self, scalar: S) -> $PointN<S> {
|
||||||
$PointN::new($(self.$field % s),+)
|
$PointN::new($(self.$field % scalar),+)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -343,7 +343,7 @@ impl<S: BaseFloat> From<Quaternion<S>> for Basis3<S> {
|
||||||
fn from(quat: Quaternion<S>) -> Basis3<S> { Basis3::from_quaternion(&quat) }
|
fn from(quat: Quaternion<S>) -> Basis3<S> { Basis3::from_quaternion(&quat) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat + 'static> Rotation<S, Point3<S>> for Quaternion<S> {
|
impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Quaternion<S> { Quaternion::one() }
|
fn one() -> Quaternion<S> { Quaternion::one() }
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,9 @@ use vector::{Vector, Vector2, Vector3};
|
||||||
|
|
||||||
/// A trait for a generic rotation. A rotation is a transformation that
|
/// A trait for a generic rotation. A rotation is a transformation that
|
||||||
/// creates a circular motion, and preserves at least one point in the space.
|
/// creates a circular motion, and preserves at least one point in the space.
|
||||||
pub trait Rotation<S: BaseFloat, P: Point<S>>: PartialEq + ApproxEq<Epsilon = S> + Sized {
|
pub trait Rotation<P: Point>: PartialEq + ApproxEq<Epsilon = <<P as Point>::Vector as Vector>::Scalar> + Sized where
|
||||||
|
<<P as Point>::Vector as Vector>::Scalar: BaseFloat,
|
||||||
|
{
|
||||||
/// Create the identity transform (causes no transformation).
|
/// Create the identity transform (causes no transformation).
|
||||||
fn one() -> Self;
|
fn one() -> Self;
|
||||||
|
|
||||||
|
@ -67,7 +69,7 @@ pub trait Rotation<S: BaseFloat, P: Point<S>>: PartialEq + ApproxEq<Epsilon = S>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A two-dimensional rotation.
|
/// A two-dimensional rotation.
|
||||||
pub trait Rotation2<S: BaseFloat>: Rotation<S, Point2<S>>
|
pub trait Rotation2<S: BaseFloat>: Rotation<Point2<S>>
|
||||||
+ Into<Matrix2<S>>
|
+ Into<Matrix2<S>>
|
||||||
+ Into<Basis2<S>> {
|
+ Into<Basis2<S>> {
|
||||||
/// Create a rotation by a given angle. Thus is a redundant case of both
|
/// Create a rotation by a given angle. Thus is a redundant case of both
|
||||||
|
@ -76,7 +78,7 @@ pub trait Rotation2<S: BaseFloat>: Rotation<S, Point2<S>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A three-dimensional rotation.
|
/// A three-dimensional rotation.
|
||||||
pub trait Rotation3<S: BaseFloat>: Rotation<S, Point3<S>>
|
pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
|
||||||
+ Into<Matrix3<S>>
|
+ Into<Matrix3<S>>
|
||||||
+ Into<Basis3<S>>
|
+ Into<Basis3<S>>
|
||||||
+ Into<Quaternion<S>> {
|
+ Into<Quaternion<S>> {
|
||||||
|
@ -172,7 +174,7 @@ impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
|
||||||
fn from(b: Basis2<S>) -> Matrix2<S> { b.mat }
|
fn from(b: Basis2<S>) -> Matrix2<S> { b.mat }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Rotation<S, Point2<S>> for Basis2<S> {
|
impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Basis2<S> { Basis2 { mat: Matrix2::one() } }
|
fn one() -> Basis2<S> { Basis2 { mat: Matrix2::one() } }
|
||||||
|
|
||||||
|
@ -255,7 +257,7 @@ impl<S: BaseFloat> From<Basis3<S>> for Quaternion<S> {
|
||||||
fn from(b: Basis3<S>) -> Quaternion<S> { b.mat.into() }
|
fn from(b: Basis3<S>) -> Quaternion<S> { b.mat.into() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Rotation<S, Point3<S>> for Basis3<S> {
|
impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Basis3<S> { Basis3 { mat: Matrix3::one() } }
|
fn one() -> Basis3<S> { Basis3 { mat: Matrix3::one() } }
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ use vector::*;
|
||||||
/// A trait representing an [affine
|
/// A trait representing an [affine
|
||||||
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
|
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
|
||||||
/// can be applied to points or vectors. An affine transformation is one which
|
/// can be applied to points or vectors. An affine transformation is one which
|
||||||
pub trait Transform<S: BaseNum, P: Point<S>>: Sized {
|
pub trait Transform<P: Point>: Sized {
|
||||||
/// Create an identity transformation. That is, a transformation which
|
/// Create an identity transformation. That is, a transformation which
|
||||||
/// does nothing.
|
/// does nothing.
|
||||||
fn one() -> Self;
|
fn one() -> Self;
|
||||||
|
@ -72,28 +72,30 @@ pub trait Transform<S: BaseNum, P: Point<S>>: Sized {
|
||||||
/// A generic transformation consisting of a rotation,
|
/// A generic transformation consisting of a rotation,
|
||||||
/// displacement vector and scale amount.
|
/// displacement vector and scale amount.
|
||||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Decomposed<S, V, R> {
|
pub struct Decomposed<V: Vector, R> {
|
||||||
pub scale: S,
|
pub scale: V::Scalar,
|
||||||
pub rot: R,
|
pub rot: R,
|
||||||
pub disp: V,
|
pub disp: V,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat, P: Point<S>, R: Rotation<S, P>> Transform<S, P> for Decomposed<S, P::Vector, R> {
|
impl<P: Point, R: Rotation<P>> Transform<P> for Decomposed<P::Vector, R> where
|
||||||
|
<<P as Point>::Vector as Vector>::Scalar: BaseFloat,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Decomposed<S, P::Vector, R> {
|
fn one() -> Decomposed<P::Vector, R> {
|
||||||
Decomposed {
|
Decomposed {
|
||||||
scale: S::one(),
|
scale: <<P as Point>::Vector as Vector>::Scalar::one(),
|
||||||
rot: R::one(),
|
rot: R::one(),
|
||||||
disp: P::Vector::zero(),
|
disp: P::Vector::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn look_at(eye: &P, center: &P, up: &P::Vector) -> Decomposed<S, P::Vector, R> {
|
fn look_at(eye: &P, center: &P, up: &P::Vector) -> Decomposed<P::Vector, R> {
|
||||||
let rot = R::look_at(¢er.sub_p(eye), up);
|
let rot = R::look_at(¢er.sub_p(eye), up);
|
||||||
let disp = rot.rotate_vector(&P::origin().sub_p(eye));
|
let disp = rot.rotate_vector(&P::origin().sub_p(eye));
|
||||||
Decomposed {
|
Decomposed {
|
||||||
scale: S::one(),
|
scale: <<P as Point>::Vector as Vector>::Scalar::one(),
|
||||||
rot: rot,
|
rot: rot,
|
||||||
disp: disp,
|
disp: disp,
|
||||||
}
|
}
|
||||||
|
@ -109,7 +111,7 @@ impl<S: BaseFloat, P: Point<S>, R: Rotation<S, P>> Transform<S, P> for Decompose
|
||||||
self.rot.rotate_point(&point.mul_s(self.scale.clone())).add_v(&self.disp)
|
self.rot.rotate_point(&point.mul_s(self.scale.clone())).add_v(&self.disp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn concat(&self, other: &Decomposed<S, P::Vector, R>) -> Decomposed<S, P::Vector, R> {
|
fn concat(&self, other: &Decomposed<P::Vector, R>) -> Decomposed<P::Vector, R> {
|
||||||
Decomposed {
|
Decomposed {
|
||||||
scale: self.scale * other.scale,
|
scale: self.scale * other.scale,
|
||||||
rot: self.rot.concat(&other.rot),
|
rot: self.rot.concat(&other.rot),
|
||||||
|
@ -117,11 +119,11 @@ impl<S: BaseFloat, P: Point<S>, R: Rotation<S, P>> Transform<S, P> for Decompose
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invert(&self) -> Option<Decomposed<S, P::Vector, R>> {
|
fn invert(&self) -> Option<Decomposed<P::Vector, R>> {
|
||||||
if self.scale.approx_eq(&S::zero()) {
|
if self.scale.approx_eq(&<<P as Point>::Vector as Vector>::Scalar::zero()) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let s = S::one() / self.scale;
|
let s = <<P as Point>::Vector as Vector>::Scalar::one() / self.scale;
|
||||||
let r = self.rot.invert();
|
let r = self.rot.invert();
|
||||||
let d = r.rotate_vector(&self.disp).mul_s(-s);
|
let d = r.rotate_vector(&self.disp).mul_s(-s);
|
||||||
Some(Decomposed {
|
Some(Decomposed {
|
||||||
|
@ -133,11 +135,11 @@ impl<S: BaseFloat, P: Point<S>, R: Rotation<S, P>> Transform<S, P> for Decompose
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Transform2<S: BaseNum>: Transform<S, Point2<S>> + Into<Matrix3<S>> {}
|
pub trait Transform2<S: BaseNum>: Transform<Point2<S>> + Into<Matrix3<S>> {}
|
||||||
pub trait Transform3<S: BaseNum>: Transform<S, Point3<S>> + Into<Matrix4<S>> {}
|
pub trait Transform3<S: BaseNum>: Transform<Point3<S>> + Into<Matrix4<S>> {}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: Rotation2<S>> From<Decomposed<S, Vector2<S>, R>> for Matrix3<S> {
|
impl<S: BaseFloat, R: Rotation2<S>> From<Decomposed<Vector2<S>, R>> for Matrix3<S> {
|
||||||
fn from(dec: Decomposed<S, Vector2<S>, R>) -> Matrix3<S> {
|
fn from(dec: Decomposed<Vector2<S>, R>) -> Matrix3<S> {
|
||||||
let m: Matrix2<_> = dec.rot.into();
|
let m: Matrix2<_> = dec.rot.into();
|
||||||
let mut m: Matrix3<_> = m.mul_s(dec.scale).into();
|
let mut m: Matrix3<_> = m.mul_s(dec.scale).into();
|
||||||
m.z = dec.disp.extend(S::one());
|
m.z = dec.disp.extend(S::one());
|
||||||
|
@ -145,8 +147,8 @@ impl<S: BaseFloat, R: Rotation2<S>> From<Decomposed<S, Vector2<S>, R>> for Matri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: Rotation3<S>> From<Decomposed<S, Vector3<S>, R>> for Matrix4<S> {
|
impl<S: BaseFloat, R: Rotation3<S>> From<Decomposed<Vector3<S>, R>> for Matrix4<S> {
|
||||||
fn from(dec: Decomposed<S, Vector3<S>, R>) -> Matrix4<S> {
|
fn from(dec: Decomposed<Vector3<S>, R>) -> Matrix4<S> {
|
||||||
let m: Matrix3<_> = dec.rot.into();
|
let m: Matrix3<_> = dec.rot.into();
|
||||||
let mut m: Matrix4<_> = m.mul_s(dec.scale).into();
|
let mut m: Matrix4<_> = m.mul_s(dec.scale).into();
|
||||||
m.w = dec.disp.extend(S::one());
|
m.w = dec.disp.extend(S::one());
|
||||||
|
@ -154,11 +156,11 @@ impl<S: BaseFloat, R: Rotation3<S>> From<Decomposed<S, Vector3<S>, R>> for Matri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: Rotation2<S>> Transform2<S> for Decomposed<S, Vector2<S>, R> {}
|
impl<S: BaseFloat, R: Rotation2<S>> Transform2<S> for Decomposed<Vector2<S>, R> {}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: Rotation3<S>> Transform3<S> for Decomposed<S, Vector3<S>, R> {}
|
impl<S: BaseFloat, R: Rotation3<S>> Transform3<S> for Decomposed<Vector3<S>, R> {}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: fmt::Debug + Rotation3<S>> fmt::Debug for Decomposed<S, Vector3<S>, R> {
|
impl<S: BaseFloat, R: fmt::Debug + Rotation3<S>> fmt::Debug for Decomposed<Vector3<S>, R> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "(scale({:?}), rot({:?}), disp{:?})",
|
write!(f, "(scale({:?}), rot({:?}), disp{:?})",
|
||||||
self.scale, self.rot, self.disp)
|
self.scale, self.rot, self.disp)
|
||||||
|
@ -171,7 +173,7 @@ pub struct AffineMatrix3<S> {
|
||||||
pub mat: Matrix4<S>,
|
pub mat: Matrix4<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Transform<S, Point3<S>> for AffineMatrix3<S> {
|
impl<S: BaseFloat> Transform<Point3<S>> for AffineMatrix3<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> AffineMatrix3<S> {
|
fn one() -> AffineMatrix3<S> {
|
||||||
AffineMatrix3 { mat: Matrix4::one() }
|
AffineMatrix3 { mat: Matrix4::one() }
|
||||||
|
@ -211,35 +213,33 @@ impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> {}
|
||||||
|
|
||||||
/// A trait that allows extracting components (rotation, translation, scale)
|
/// A trait that allows extracting components (rotation, translation, scale)
|
||||||
/// from an arbitrary transformations
|
/// from an arbitrary transformations
|
||||||
pub trait ToComponents<S: BaseFloat, P: Point<S>, R: Rotation<S, P>> {
|
pub trait ToComponents<P: Point, R: Rotation<P>> where
|
||||||
|
<<P as Point>::Vector as Vector>::Scalar: BaseFloat,
|
||||||
|
{
|
||||||
/// Extract the (scale, rotation, translation) triple
|
/// Extract the (scale, rotation, translation) triple
|
||||||
fn decompose(&self) -> (P::Vector, R, P::Vector);
|
fn decompose(&self) -> (P::Vector, R, P::Vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToComponents2<S: BaseFloat, R: Rotation2<S>>:
|
pub trait ToComponents2<S: BaseFloat, R: Rotation2<S>>: ToComponents<Point2<S>, R> {}
|
||||||
ToComponents<S, Point2<S>, R> {}
|
pub trait ToComponents3<S: BaseFloat, R: Rotation3<S>>: ToComponents<Point3<S>, R> {}
|
||||||
pub trait ToComponents3<S: BaseFloat, R: Rotation3<S>>:
|
|
||||||
ToComponents<S, Point3<S>, R> {}
|
|
||||||
|
|
||||||
pub trait CompositeTransform<S: BaseFloat, P: Point<S>, R: Rotation<S, P>>:
|
pub trait CompositeTransform<P: Point, R: Rotation<P>>: Transform<P> + ToComponents<P, R> where
|
||||||
Transform<S, P> + ToComponents<S, P, R> {}
|
<<P as Point>::Vector as Vector>::Scalar: BaseFloat,
|
||||||
pub trait CompositeTransform2<S: BaseFloat, R: Rotation2<S>>:
|
{}
|
||||||
Transform2<S> + ToComponents2<S, R> {}
|
|
||||||
pub trait CompositeTransform3<S: BaseFloat, R: Rotation3<S>>:
|
|
||||||
Transform3<S> + ToComponents3<S, R> {}
|
|
||||||
|
|
||||||
impl<
|
pub trait CompositeTransform2<S: BaseFloat, R: Rotation2<S>>: Transform2<S> + ToComponents2<S, R> {}
|
||||||
S: BaseFloat,
|
pub trait CompositeTransform3<S: BaseFloat, R: Rotation3<S>>: Transform3<S> + ToComponents3<S, R> {}
|
||||||
P: Point<S>,
|
|
||||||
R: Rotation<S, P> + Clone,
|
impl<P: Point, R: Rotation<P> + Clone> ToComponents<P, R> for Decomposed<P::Vector, R> where
|
||||||
> ToComponents<S, P, R> for Decomposed<S, P::Vector, R> {
|
<<P as Point>::Vector as Vector>::Scalar: BaseFloat,
|
||||||
|
{
|
||||||
fn decompose(&self) -> (P::Vector, R, P::Vector) {
|
fn decompose(&self) -> (P::Vector, R, P::Vector) {
|
||||||
(P::Vector::one().mul_s(self.scale), self.rot.clone(), self.disp.clone())
|
(P::Vector::one().mul_s(self.scale), self.rot.clone(), self.disp.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: Rotation2<S> + Clone> ToComponents2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
impl<S: BaseFloat, R: Rotation2<S> + Clone> ToComponents2<S, R> for Decomposed<Vector2<S>, R> {}
|
||||||
impl<S: BaseFloat, R: Rotation3<S> + Clone> ToComponents3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
impl<S: BaseFloat, R: Rotation3<S> + Clone> ToComponents3<S, R> for Decomposed<Vector3<S>, R> {}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: Rotation2<S> + Clone> CompositeTransform2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
impl<S: BaseFloat, R: Rotation2<S> + Clone> CompositeTransform2<S, R> for Decomposed<Vector2<S>, R> {}
|
||||||
impl<S: BaseFloat, R: Rotation3<S> + Clone> CompositeTransform3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
impl<S: BaseFloat, R: Rotation3<S> + Clone> CompositeTransform3<S, R> for Decomposed<Vector3<S>, R> {}
|
||||||
|
|
|
@ -127,7 +127,7 @@ pub trait Vector: Array1<Element = <Self as Vector>::Scalar> + Clone // where
|
||||||
// for<'a> &'a Self: Div<S, Output = Self>,
|
// for<'a> &'a Self: Div<S, Output = Self>,
|
||||||
// for<'a> &'a Self: Rem<S, Output = Self>,
|
// for<'a> &'a Self: Rem<S, Output = Self>,
|
||||||
{
|
{
|
||||||
// The associated scalar
|
/// The associated scalar.
|
||||||
type Scalar: BaseNum;
|
type Scalar: BaseNum;
|
||||||
|
|
||||||
/// Construct a vector from a single value, replicating it.
|
/// Construct a vector from a single value, replicating it.
|
||||||
|
@ -626,42 +626,45 @@ impl<S: BaseNum> Vector4<S> {
|
||||||
|
|
||||||
/// Specifies geometric operations for vectors. This is only implemented for
|
/// Specifies geometric operations for vectors. This is only implemented for
|
||||||
/// 2-dimensional and 3-dimensional vectors.
|
/// 2-dimensional and 3-dimensional vectors.
|
||||||
pub trait EuclideanVector<S: BaseFloat>: Vector<Scalar = S> + ApproxEq<Epsilon = <Self as Vector>::Scalar> + Sized {
|
pub trait EuclideanVector: Vector + Sized where
|
||||||
|
<Self as Vector>::Scalar: BaseFloat,
|
||||||
|
Self: ApproxEq<Epsilon = <Self as Vector>::Scalar>,
|
||||||
|
{
|
||||||
/// Returns `true` if the vector is perpendicular (at right angles) to the
|
/// Returns `true` if the vector is perpendicular (at right angles) to the
|
||||||
/// other vector.
|
/// other vector.
|
||||||
fn is_perpendicular(&self, other: &Self) -> bool {
|
fn is_perpendicular(&self, other: &Self) -> bool {
|
||||||
self.dot(other).approx_eq(&S::zero())
|
self.dot(other).approx_eq(&Self::Scalar::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the squared length of the vector. This does not perform an
|
/// Returns the squared length of the vector. This does not perform an
|
||||||
/// expensive square root operation like in the `length` method and can
|
/// expensive square root operation like in the `length` method and can
|
||||||
/// therefore be more efficient for comparing the lengths of two vectors.
|
/// therefore be more efficient for comparing the lengths of two vectors.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn length2(&self) -> S {
|
fn length2(&self) -> Self::Scalar {
|
||||||
self.dot(self)
|
self.dot(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The norm of the vector.
|
/// The norm of the vector.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn length(&self) -> S {
|
fn length(&self) -> Self::Scalar {
|
||||||
self.dot(self).sqrt()
|
<<Self as Vector>::Scalar as ::rust_num::Float>::sqrt(self.dot(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The angle between the vector and `other`, in radians.
|
/// The angle between the vector and `other`, in radians.
|
||||||
fn angle(&self, other: &Self) -> Rad<S>;
|
fn angle(&self, other: &Self) -> Rad<Self::Scalar>;
|
||||||
|
|
||||||
/// Returns a vector with the same direction, but with a `length` (or
|
/// Returns a vector with the same direction, but with a `length` (or
|
||||||
/// `norm`) of `1`.
|
/// `norm`) of `1`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn normalize(&self) -> Self {
|
fn normalize(&self) -> Self {
|
||||||
self.normalize_to(S::one())
|
self.normalize_to(Self::Scalar::one())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector with the same direction and a given `length`.
|
/// Returns a vector with the same direction and a given `length`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn normalize_to(&self, length: S) -> Self {
|
fn normalize_to(&self, length: Self::Scalar) -> Self {
|
||||||
self.mul_s(length / self.length())
|
self.mul_s(length / self.length())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,47 +672,47 @@ pub trait EuclideanVector<S: BaseFloat>: Vector<Scalar = S> + ApproxEq<Epsilon =
|
||||||
/// towards the length of `other` by the specified amount.
|
/// towards the length of `other` by the specified amount.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn lerp(&self, other: &Self, amount: S) -> Self {
|
fn lerp(&self, other: &Self, amount: Self::Scalar) -> Self {
|
||||||
self.add_v(&other.sub_v(self).mul_s(amount))
|
self.add_v(&other.sub_v(self).mul_s(amount))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalises the vector to a length of `1`.
|
/// Normalises the vector to a length of `1`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn normalize_self(&mut self) {
|
fn normalize_self(&mut self) {
|
||||||
let rlen = self.length().recip();
|
let rlen = <<Self as Vector>::Scalar as ::rust_num::Float>::recip(self.length());
|
||||||
self.mul_self_s(rlen);
|
self.mul_self_s(rlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalizes the vector to `length`.
|
/// Normalizes the vector to `length`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn normalize_self_to(&mut self, length: S) {
|
fn normalize_self_to(&mut self, length: Self::Scalar) {
|
||||||
let n = length / self.length();
|
let n = length / self.length();
|
||||||
self.mul_self_s(n);
|
self.mul_self_s(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Linearly interpolates the length of the vector towards the length of
|
/// Linearly interpolates the length of the vector towards the length of
|
||||||
/// `other` by the specified amount.
|
/// `other` by the specified amount.
|
||||||
fn lerp_self(&mut self, other: &Self, amount: S) {
|
fn lerp_self(&mut self, other: &Self, amount: Self::Scalar) {
|
||||||
let v = other.sub_v(self).mul_s(amount);
|
let v = other.sub_v(self).mul_s(amount);
|
||||||
self.add_self_v(&v);
|
self.add_self_v(&v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> EuclideanVector<S> for Vector2<S> {
|
impl<S: BaseFloat> EuclideanVector for Vector2<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn angle(&self, other: &Vector2<S>) -> Rad<S> {
|
fn angle(&self, other: &Vector2<S>) -> Rad<S> {
|
||||||
atan2(self.perp_dot(other), self.dot(other))
|
atan2(self.perp_dot(other), self.dot(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> EuclideanVector<S> for Vector3<S> {
|
impl<S: BaseFloat> EuclideanVector for Vector3<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn angle(&self, other: &Vector3<S>) -> Rad<S> {
|
fn angle(&self, other: &Vector3<S>) -> Rad<S> {
|
||||||
atan2(self.cross(other).length(), self.dot(other))
|
atan2(self.cross(other).length(), self.dot(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> EuclideanVector<S> for Vector4<S> {
|
impl<S: BaseFloat> EuclideanVector for Vector4<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn angle(&self, other: &Vector4<S>) -> Rad<S> {
|
fn angle(&self, other: &Vector4<S>) -> Rad<S> {
|
||||||
acos(self.dot(other) / (self.length() * other.length()))
|
acos(self.dot(other) / (self.length() * other.length()))
|
||||||
|
|
|
@ -36,7 +36,7 @@ fn test_look_at() {
|
||||||
let eye = Point3::new(0.0f64, 0.0, -5.0);
|
let eye = Point3::new(0.0f64, 0.0, -5.0);
|
||||||
let center = Point3::new(0.0f64, 0.0, 0.0);
|
let center = Point3::new(0.0f64, 0.0, 0.0);
|
||||||
let up = Vector3::new(1.0f64, 0.0, 0.0);
|
let up = Vector3::new(1.0f64, 0.0, 0.0);
|
||||||
let t: Decomposed<f64,Vector3<f64>,Quaternion<f64>> = Transform::look_at(&eye, ¢er, &up);
|
let t: Decomposed<Vector3<f64>, Quaternion<f64>> = Transform::look_at(&eye, ¢er, &up);
|
||||||
let point = Point3::new(1.0f64, 0.0, 0.0);
|
let point = Point3::new(1.0f64, 0.0, 0.0);
|
||||||
let view_point = Point3::new(0.0f64, 1.0, 5.0);
|
let view_point = Point3::new(0.0f64, 1.0, 5.0);
|
||||||
assert!( t.transform_point(&point).approx_eq(&view_point) );
|
assert!( t.transform_point(&point).approx_eq(&view_point) );
|
||||||
|
|
Loading…
Reference in a new issue