commit
6ac2184397
5 changed files with 127 additions and 52 deletions
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
#![crate_type = "dylib"]
|
#![crate_type = "dylib"]
|
||||||
#![feature(old_impl_check, plugin, core, hash, std_misc)]
|
#![feature(old_impl_check, plugin, core, std_misc)]
|
||||||
#![plugin(rand_macros)]
|
#![plugin(rand_macros)]
|
||||||
|
|
||||||
//! Computer graphics-centric math.
|
//! Computer graphics-centric math.
|
||||||
|
@ -37,45 +37,30 @@ extern crate rand;
|
||||||
|
|
||||||
// Re-exports
|
// Re-exports
|
||||||
|
|
||||||
pub use array::{Array1, Array2, FixedArray};
|
pub use array::*;
|
||||||
|
pub use matrix::*;
|
||||||
|
pub use quaternion::*;
|
||||||
|
pub use vector::*;
|
||||||
|
|
||||||
pub use matrix::Matrix;
|
pub use angle::*;
|
||||||
pub use matrix::{Matrix2, Matrix3, Matrix4};
|
|
||||||
pub use matrix::{ToMatrix2, ToMatrix3, ToMatrix4};
|
|
||||||
pub use quaternion::{Quaternion, ToQuaternion};
|
|
||||||
pub use vector::{Vector, EuclideanVector};
|
|
||||||
pub use vector::{Vector2, Vector3, Vector4};
|
|
||||||
pub use vector::{dot, vec2, vec3, vec4};
|
|
||||||
|
|
||||||
pub use angle::{rad, deg};
|
|
||||||
pub use angle::{Angle, Rad, Deg};
|
|
||||||
pub use angle::{ToRad, ToDeg};
|
|
||||||
pub use angle::bisect;
|
|
||||||
pub use angle::{sin, cos, tan, sin_cos};
|
|
||||||
pub use angle::{cot, sec, csc};
|
|
||||||
pub use angle::{acos, asin, atan, atan2};
|
|
||||||
pub use plane::Plane;
|
pub use plane::Plane;
|
||||||
pub use point::{Point, Point2, Point3};
|
pub use point::*;
|
||||||
pub use line::{Line, Line2, Line3};
|
pub use line::*;
|
||||||
pub use ray::{Ray, Ray2, Ray3};
|
pub use ray::*;
|
||||||
pub use rotation::{Rotation, Rotation2, Rotation3};
|
pub use rotation::*;
|
||||||
pub use rotation::{Basis3, Basis2};
|
pub use transform::*;
|
||||||
pub use rotation::{ToBasis2, ToBasis3};
|
|
||||||
pub use transform::{Transform, Transform3};
|
|
||||||
pub use transform::{Decomposed, AffineMatrix3};
|
|
||||||
|
|
||||||
pub use projection::{perspective, frustum, ortho};
|
pub use projection::*;
|
||||||
pub use projection::{Projection, PerspectiveFov, Perspective, Ortho};
|
|
||||||
|
|
||||||
pub use aabb::{Aabb, Aabb2, Aabb3};
|
pub use aabb::*;
|
||||||
pub use cylinder::Cylinder;
|
pub use cylinder::Cylinder;
|
||||||
pub use frustum::{Frustum, FrustumPoints};
|
pub use frustum::{Frustum, FrustumPoints};
|
||||||
pub use intersect::Intersect;
|
pub use intersect::Intersect;
|
||||||
pub use obb::{Obb2, Obb3};
|
pub use obb::*;
|
||||||
pub use sphere::Sphere;
|
pub use sphere::Sphere;
|
||||||
|
|
||||||
pub use approx::ApproxEq;
|
pub use approx::ApproxEq;
|
||||||
pub use num::{PartialOrd, BaseNum, BaseInt, BaseFloat, One, one, Zero, zero};
|
pub use num::*;
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use approx::ApproxEq;
|
use approx::ApproxEq;
|
||||||
use matrix::{Matrix, Matrix4, ToMatrix4};
|
use matrix::*;
|
||||||
use num::{BaseNum, BaseFloat, zero, one};
|
use num::{BaseNum, BaseFloat, zero, one};
|
||||||
use point::{Point, Point3};
|
use point::{Point, Point3};
|
||||||
|
use quaternion::*;
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use rotation::{Rotation, Rotation3};
|
use rotation::{Rotation, Rotation3};
|
||||||
use std::marker::PhantomFn;
|
use std::marker::PhantomFn;
|
||||||
|
@ -84,7 +85,12 @@ pub struct Decomposed<S, V, R> {
|
||||||
pub disp: V,
|
pub disp: V,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform<S, V, P> for Decomposed<S, V, R> {
|
impl<
|
||||||
|
S: BaseFloat,
|
||||||
|
V: Vector<S>,
|
||||||
|
P: Point<S, V>,
|
||||||
|
R: Rotation<S, V, P>
|
||||||
|
> Transform<S, V, P> for Decomposed<S, V, R> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn identity() -> Decomposed<S, V, R> {
|
fn identity() -> Decomposed<S, V, R> {
|
||||||
Decomposed {
|
Decomposed {
|
||||||
|
@ -142,7 +148,10 @@ impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform
|
||||||
|
|
||||||
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + ToMatrix4<S> {}
|
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + ToMatrix4<S> {}
|
||||||
|
|
||||||
impl<S: BaseFloat + 'static, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
|
impl<
|
||||||
|
S: BaseFloat + 'static,
|
||||||
|
R: Rotation3<S>
|
||||||
|
> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
|
||||||
fn to_matrix4(&self) -> Matrix4<S> {
|
fn to_matrix4(&self) -> Matrix4<S> {
|
||||||
let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4();
|
let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4();
|
||||||
m.w = self.disp.extend(one());
|
m.w = self.disp.extend(one());
|
||||||
|
@ -150,9 +159,15 @@ impl<S: BaseFloat + 'static, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat, R: Rotation3<S>> Transform3<S> for Decomposed<S,Vector3<S>,R> where S: 'static {}
|
impl<
|
||||||
|
S: BaseFloat + 'static,
|
||||||
|
R: Rotation3<S>
|
||||||
|
> Transform3<S> for Decomposed<S, 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<S, 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)
|
||||||
|
@ -202,3 +217,71 @@ impl<S: BaseNum> ToMatrix4<S> for AffineMatrix3<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> where S: 'static {}
|
impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> where S: 'static {}
|
||||||
|
|
||||||
|
/// A trait that allows extracting components (rotation, translation, scale)
|
||||||
|
/// from an arbitrary transformation/
|
||||||
|
pub trait ToComponents<S, V: Vector<S>, P: Point<S, V>> {
|
||||||
|
/// Associated rotation type
|
||||||
|
type Rotation;
|
||||||
|
/// Extract translation component
|
||||||
|
fn to_translation(&self) -> V;
|
||||||
|
/// Extract rotation component
|
||||||
|
fn to_rotation(&self) -> Self::Rotation;
|
||||||
|
/// Extract scale component
|
||||||
|
fn to_scale(&self) -> V;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ToComponents3<S>: ToComponents<S, Vector3<S>, Point3<S>>
|
||||||
|
where Self::Rotation: ToMatrix3<S> {}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
S: BaseFloat,
|
||||||
|
V: Vector<S> + Clone,
|
||||||
|
P: Point<S, V>,
|
||||||
|
R: Rotation<S, V, P> + Clone,
|
||||||
|
> ToComponents<S, V, P> for Decomposed<S, V, R> {
|
||||||
|
type Rotation = R;
|
||||||
|
|
||||||
|
fn to_translation(&self) -> V {
|
||||||
|
self.disp.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_rotation(&self) -> R {
|
||||||
|
self.rot.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_scale(&self) -> V {
|
||||||
|
Vector::from_value(self.scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
S: BaseFloat,
|
||||||
|
R: Rotation<S, Vector3<S>, Point3<S>> + Clone + ToMatrix3<S>,
|
||||||
|
> ToComponents3<S> for Decomposed<S, Vector3<S>, R> {}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
S: BaseFloat + 'static,
|
||||||
|
> ToComponents<S, Vector3<S>, Point3<S>> for AffineMatrix3<S> {
|
||||||
|
type Rotation = Quaternion<S>;
|
||||||
|
|
||||||
|
fn to_translation(&self) -> Vector3<S> {
|
||||||
|
Vector3::new(self.mat.w.x, self.mat.w.y, self.mat.w.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_rotation(&self) -> Quaternion<S> {
|
||||||
|
Matrix3::new(
|
||||||
|
self.mat.x.x, self.mat.x.y, self.mat.x.z,
|
||||||
|
self.mat.y.x, self.mat.y.y, self.mat.y.z,
|
||||||
|
self.mat.z.x, self.mat.z.y, self.mat.z.z,
|
||||||
|
).to_quaternion()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_scale(&self) -> Vector3<S> {
|
||||||
|
Vector3::new(self.mat.x.x, self.mat.y.y, self.mat.z.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
S: BaseFloat + 'static,
|
||||||
|
> ToComponents3<S> for AffineMatrix3<S> {}
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
//! vector are also provided:
|
//! vector are also provided:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use cgmath::{Vector2, Vector3, Vector4, one, zero, vec3};
|
//! use cgmath::{Vector, Vector2, Vector3, Vector4, zero, vec2, vec3};
|
||||||
//!
|
//!
|
||||||
//! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x());
|
//! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x());
|
||||||
//! assert_eq!(vec3(0.0f64, 0.0f64, 0.0f64), zero());
|
//! assert_eq!(vec3(0.0f64, 0.0f64, 0.0f64), zero());
|
||||||
//! assert_eq!(Vector4::from_value(1.0f64), one());
|
//! assert_eq!(Vector::from_value(1.0f64), vec2(1.0, 1.0));
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Vectors can be manipulated with typical mathematical operations (addition,
|
//! Vectors can be manipulated with typical mathematical operations (addition,
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
//!
|
//!
|
||||||
//! // Scalar multiplication can return a new object, or be done in place
|
//! // Scalar multiplication can return a new object, or be done in place
|
||||||
//! // to avoid an allocation:
|
//! // to avoid an allocation:
|
||||||
//! let mut c: Vector4<f64> = Vector4::from_value(3.0);
|
//! let mut c: Vector4<f64> = Vector::from_value(3.0);
|
||||||
//! let d: Vector4<f64> = c.mul_s(2.0);
|
//! let d: Vector4<f64> = c.mul_s(2.0);
|
||||||
//! c.mul_self_s(2.0);
|
//! c.mul_self_s(2.0);
|
||||||
//! assert_eq!(c, d);
|
//! assert_eq!(c, d);
|
||||||
|
@ -110,6 +110,8 @@ use num::{BaseNum, BaseFloat, Zero, One, zero, one};
|
||||||
/// of these make sense from a linear algebra point of view, but are included
|
/// of these make sense from a linear algebra point of view, but are included
|
||||||
/// for pragmatic reasons.
|
/// for pragmatic reasons.
|
||||||
pub trait Vector<S: BaseNum>: Array1<S> + Zero + One + Neg<Output=Self> {
|
pub trait Vector<S: BaseNum>: Array1<S> + Zero + One + Neg<Output=Self> {
|
||||||
|
/// Construct a vector from a single value, replicating it.
|
||||||
|
fn from_value(s: S) -> Self;
|
||||||
/// Add a scalar to this vector, returning a new vector.
|
/// Add a scalar to this vector, returning a new vector.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn add_s(&self, s: S) -> Self;
|
fn add_s(&self, s: S) -> Self;
|
||||||
|
@ -206,14 +208,6 @@ macro_rules! vec(
|
||||||
$Self_::new($($field),+)
|
$Self_::new($($field),+)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$S: Copy> $Self_<$S> {
|
|
||||||
/// Construct a vector from a single value, replicating it.
|
|
||||||
#[inline]
|
|
||||||
pub fn from_value(value: $S) -> $Self_<$S> {
|
|
||||||
$Self_ { $($field: value),+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<$S: Zero> Zero for $Self_<$S> {
|
impl<$S: Zero> Zero for $Self_<$S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> $Self_<S> { $Self_ { $($field: zero()),+ } }
|
fn zero() -> $Self_<S> { $Self_ { $($field: zero()),+ } }
|
||||||
|
@ -292,6 +286,7 @@ macro_rules! vec(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseNum> Vector<S> for $Self_<S> {
|
impl<S: BaseNum> Vector<S> for $Self_<S> {
|
||||||
|
#[inline] fn from_value(s: S) -> $Self_<S> { $Self_ { $($field: s),+ } }
|
||||||
#[inline] fn add_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field + s),+) }
|
#[inline] fn add_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field + s),+) }
|
||||||
#[inline] fn sub_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field - s),+) }
|
#[inline] fn sub_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field - s),+) }
|
||||||
#[inline] fn mul_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field * s),+) }
|
#[inline] fn mul_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field * s),+) }
|
||||||
|
|
|
@ -41,3 +41,15 @@ fn test_look_at() {
|
||||||
let view_point = Point3::new(0.0f64, 1.0f64, 5.0f64);
|
let view_point = Point3::new(0.0f64, 1.0f64, 5.0f64);
|
||||||
assert!( t.transform_point(&point).approx_eq(&view_point) );
|
assert!( t.transform_point(&point).approx_eq(&view_point) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_components() {
|
||||||
|
let t = Decomposed {
|
||||||
|
scale: 1.5f64,
|
||||||
|
rot: Quaternion::new(0.5f64,0.5,0.5,0.5),
|
||||||
|
disp: Vector3::new(6.0f64,-7.0f64,8.0)
|
||||||
|
};
|
||||||
|
assert_eq!(t.to_translation(), t.disp);
|
||||||
|
assert_eq!(t.to_rotation(), t.rot);
|
||||||
|
assert_eq!(t.to_scale(), Vector::from_value(t.scale));
|
||||||
|
}
|
||||||
|
|
|
@ -31,9 +31,9 @@ fn test_constructor() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_value() {
|
fn test_from_value() {
|
||||||
assert_eq!(Vector2::from_value(102is), Vector2::new(102is, 102is));
|
assert_eq!(Vector::from_value(102is), Vector2::new(102is, 102is));
|
||||||
assert_eq!(Vector3::from_value(22is), Vector3::new(22is, 22is, 22is));
|
assert_eq!(Vector::from_value(22is), Vector3::new(22is, 22is, 22is));
|
||||||
assert_eq!(Vector4::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64));
|
assert_eq!(Vector::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue