Add impl_approx! macro

This commit is contained in:
Brendan Zabarauskas 2013-07-12 11:22:14 +10:00
parent f30b79deb3
commit 3656068f5c
17 changed files with 81 additions and 182 deletions

View file

@ -30,6 +30,10 @@ pub mod ycbcr;
pub trait Color<T> {
pub fn clamp(&self, lo: T, hi: T) -> Self;
pub fn inverse(&self) -> Self;
// pub fn mix(&self, other: &Self, value: T) -> Self;
// pub fn saturation(&self, value: T) -> Self;
// pub fn exposure(&self, value: T) -> Self;
// pub fn brightness(&self, value: T) -> Self;
}
pub trait FloatColor<T>: Color<T> {

View file

@ -20,12 +20,11 @@ use color::{Color, FloatColor};
use color::{Channel, FloatChannel};
use color::{RGB, ToRGB, RGBA, ToRGBA};
#[path = "../num_macros.rs"]
mod num_macros;
#[deriving(Clone, Eq)]
pub struct HSV<T> { h: T, s: T, v: T }
impl_approx!(HSV { h, s, v })
impl<T:FloatChannel> HSV<T> {
pub fn new(h: T, s: T, v: T) -> HSV<T> {
HSV { h: h, s: s, v: v }
@ -123,6 +122,8 @@ impl<T:Clone + FloatChannel> ToRGB for HSV<T> {
#[deriving(Clone, Eq)]
pub struct HSVA<T> { h: T, s: T, v: T, a: T }
impl_approx!(HSVA { h, s, v, a })
impl<T:FloatChannel> HSVA<T> {
#[inline]
pub fn new(h: T, s: T, v: T, a: T) -> HSVA<T> {

View file

@ -20,12 +20,11 @@ use color::{Color, FloatColor};
use color::{Channel, FloatChannel};
use color::{HSV, ToHSV, HSVA, ToHSVA};
#[path = "../num_macros.rs"]
mod num_macros;
#[deriving(Clone, Eq)]
pub struct RGB<T> { r: T, g: T, b: T }
impl_approx!(RGB { r, g, b })
impl<T:Channel> RGB<T> {
#[inline]
pub fn new(r: T, g: T, b: T) -> RGB<T> {
@ -120,6 +119,8 @@ impl<T:Clone + Channel> ToHSV for RGB<T> {
#[deriving(Clone, Eq)]
pub struct RGBA<T> { r: T, g: T, b: T, a: T }
impl_approx!(RGBA { r, g, b, a })
impl<T:Channel> RGBA<T> {
#[inline]
pub fn new(r: T, g: T, b: T, a: T) -> RGBA<T> {

View file

@ -23,9 +23,13 @@ impl<T> SRGB<T> {
}
}
impl_approx!(SRGB { r, g, b })
#[deriving(Clone, Eq)]
pub struct SRGBA<T> { r: T, g: T, b: T, a: T }
impl_approx!(SRGBA { r, g, b, a })
impl<T> SRGBA<T> {
#[inline]
pub fn new(r: T, g: T, b: T, a: T) -> SRGBA<T> {

View file

@ -18,6 +18,8 @@
#[deriving(Clone, Eq)]
pub struct YCbCr<T> { y: T, cb: T, cr: T }
impl_approx!(YCbCr { y, cb, cr })
impl<T> YCbCr<T> {
#[inline]
pub fn new(y: T, cb: T, cr: T) -> YCbCr<T> {

View file

@ -17,9 +17,6 @@ use core::{Dimensional, Swap};
use core::{Quat, ToQuat};
use core::{Vec2, Vec3, Vec4};
#[path = "../num_macros.rs"]
mod num_macros;
macro_rules! impl_mat(
($Mat:ident, $Vec:ident) => (
impl<T> $Mat<T> {
@ -126,6 +123,7 @@ pub type Mat2f64 = Mat2<f64>;
impl_mat!(Mat2, Vec2)
impl_mat_swap!(Mat2, Vec2)
impl_approx!(Mat3 { x, y, z })
pub trait ToMat2<T> {
pub fn to_mat2(&self) -> Mat2<T>;
@ -330,24 +328,6 @@ impl<T:Clone + Real + ApproxEq<T>> Mat2<T> {
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Mat2<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Mat2<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Mat2<T>, epsilon: &T) -> bool {
self.col(0).approx_eq_eps(other.col(0), epsilon) &&
self.col(1).approx_eq_eps(other.col(1), epsilon)
}
}
#[cfg(test)]
mod mat2_tests{
use core::mat::*;
@ -554,6 +534,7 @@ pub type Mat3f64 = Mat3<f64>;
impl_mat!(Mat3, Vec3)
impl_mat_swap!(Mat3, Vec3)
impl_approx!(Mat2 { x, y })
pub trait ToMat3<T> {
pub fn to_mat3(&self) -> Mat3<T>;
@ -909,25 +890,6 @@ impl<T:Clone + Real + ApproxEq<T>> Mat3<T> {
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Mat3<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Mat3<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Mat3<T>, epsilon: &T) -> bool {
self.col(0).approx_eq_eps(other.col(0), epsilon) &&
self.col(1).approx_eq_eps(other.col(1), epsilon) &&
self.col(2).approx_eq_eps(other.col(2), epsilon)
}
}
#[cfg(test)]
mod mat3_tests{
use core::mat::*;
@ -1159,6 +1121,7 @@ pub type Mat4f64 = Mat4<f64>;
impl_mat!(Mat4, Vec4)
impl_mat_swap!(Mat4, Vec4)
impl_approx!(Mat4 { x, y, z, w })
pub trait ToMat4<T> {
pub fn to_mat4(&self) -> Mat4<T>;
@ -1454,26 +1417,6 @@ impl<T:Clone + Real + ApproxEq<T>> Mat4<T> {
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Mat4<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Mat4<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Mat4<T>, epsilon: &T) -> bool {
self.col(0).approx_eq_eps(other.col(0), epsilon) &&
self.col(1).approx_eq_eps(other.col(1), epsilon) &&
self.col(2).approx_eq_eps(other.col(2), epsilon) &&
self.col(3).approx_eq_eps(other.col(3), epsilon)
}
}
#[cfg(test)]
mod mat4_tests {
use core::mat::*;

View file

@ -17,9 +17,6 @@ use core::Dimensional;
use core::{Mat3, ToMat3};
use core::Vec3;
#[path = "../num_macros.rs"]
mod num_macros;
// GLSL-style type aliases
pub type quat = Quat<f32>;

View file

@ -20,9 +20,6 @@ use core::Dimensional;
#[cfg(geom)]
use geom::{Point2, Point3};
#[path = "../num_macros.rs"]
mod num_macros;
#[deriving(Clone, Eq)]
pub struct Vec2<T> { x: T, y: T }
@ -49,6 +46,8 @@ pub type Vec2u32 = Vec2<u32>;
pub type Vec2u64 = Vec2<u64>;
pub type Vec2b = Vec2<bool>;
impl_approx!(Vec2 { x, y })
impl<T> Vec2<T> {
#[inline]
pub fn new(x: T, y: T) -> Vec2<T> {
@ -586,6 +585,8 @@ pub type Vec3u32 = Vec3<u32>;
pub type Vec3u64 = Vec3<u64>;
pub type Vec3b = Vec3<bool>;
impl_approx!(Vec3 { x, y, z })
impl<T> Vec3<T> {
#[inline]
pub fn new(x: T, y: T, z: T) -> Vec3<T> {
@ -1188,6 +1189,8 @@ pub type Vec4u32 = Vec4<u32>;
pub type Vec4u64 = Vec4<u64>;
pub type Vec4b = Vec4<bool>;
impl_approx!(Vec4 { x, y, z, w })
impl<T> Vec4<T> {
#[inline]
pub fn new(x: T, y: T, z: T, w: T) -> Vec4<T> {

View file

@ -18,14 +18,13 @@
use core::{Vec2, Vec3};
use geom::{Point2, Point3};
#[path = "../num_macros.rs"]
mod num_macros;
pub struct AABB2<T> {
center: Point2<T>,
size: Vec2<T>,
}
impl_approx!(AABB2 { center, size })
impl<T> AABB2<T> {
#[inline]
pub fn new(center: Point2<T>, size: Vec2<T>) -> AABB2<T> {
@ -50,6 +49,8 @@ pub struct AABB3<T> {
size: Vec3<T>,
}
impl_approx!(AABB3 { center, size })
impl<T> AABB3<T> {
#[inline]
pub fn new(center: Point3<T>, size: Vec3<T>) -> AABB3<T> {

View file

@ -16,9 +16,6 @@
use core::Mat4;
use geom::{Plane3, Point3};
#[path = "../num_macros.rs"]
mod num_macros;
#[deriving(Clone, Eq)]
pub struct Frustum<T> {
left: Plane3<T>,
@ -29,6 +26,12 @@ pub struct Frustum<T> {
far: Plane3<T>,
}
impl_approx!(Frustum {
left, right,
top, bottom,
near, far
})
#[deriving(Clone, Eq)]
pub struct FrustumPoints<T> {
near_top_left: Point3<T>,
@ -41,6 +44,17 @@ pub struct FrustumPoints<T> {
far_bottom_right: Point3<T>,
}
impl_approx!(FrustumPoints {
near_top_left,
near_top_right,
near_bottom_left,
near_bottom_right,
far_top_left,
far_top_right,
far_bottom_left,
far_bottom_right
})
impl<T:Clone + Float> Frustum<T> {
/// Constructs a frustum
pub fn from_planes(left: Plane3<T>, right: Plane3<T>,
@ -96,25 +110,3 @@ impl<T:Clone + Float> Frustum<T> {
}
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Frustum<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Frustum<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Frustum<T>, epsilon: &T) -> bool {
self.left.approx_eq_eps(&other.left, epsilon) &&
self.right.approx_eq_eps(&other.right, epsilon) &&
self.bottom.approx_eq_eps(&other.bottom, epsilon) &&
self.top.approx_eq_eps(&other.top, epsilon) &&
self.near.approx_eq_eps(&other.near, epsilon) &&
self.far.approx_eq_eps(&other.far, epsilon)
}
}

View file

@ -16,9 +16,6 @@
use core::{Vec3, Vec4, Mat3};
use geom::{Point, Point3, Ray3};
#[path = "../num_macros.rs"]
mod num_macros;
/// A plane formed from the equation: `Ax + Bx + Cx + D = 0`
///
/// # Fields
@ -34,6 +31,8 @@ pub struct Plane3<T> {
distance: T,
}
impl_approx!(Plane3 { normal, distance })
impl<T:Clone + Float> Plane3<T> {
/// # Arguments
///
@ -143,24 +142,6 @@ impl<T:Clone + Float> Plane3<T> {
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Plane3<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Plane3<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Plane3<T>, epsilon: &T) -> bool {
self.normal.approx_eq_eps(&other.normal, epsilon) &&
self.distance.approx_eq_eps(&other.distance, epsilon)
}
}
impl<T> ToStr for Plane3<T> {
pub fn to_str(&self) -> ~str {
fmt!("%?x + %?y + %?z + %? = 0",

View file

@ -24,9 +24,6 @@ use std::cast;
use core::{Mat2, Mat3, Quat, Vec2, Vec3, Vec4};
#[path = "../num_macros.rs"]
mod num_macros;
/// A geometric point
pub trait Point<T, Vec>: Eq
+ Add<Vec, Self>
@ -48,6 +45,8 @@ pub trait Point<T, Vec>: Eq
#[deriving(Clone, Eq)]
pub struct Point2<T> { x: T, y: T }
impl_approx!(Point2 { x, y })
impl<T:Num> Point2<T> {
#[inline]
pub fn new(x: T, y: T) -> Point2<T> {
@ -149,24 +148,6 @@ impl<T:Num> Mul<Vec2<T>, Point2<T>> for Point2<T> {
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Point2<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Point2<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Point2<T>, epsilon: &T) -> bool {
self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon)
}
}
impl<T> ToStr for Point2<T> {
pub fn to_str(&self) -> ~str {
fmt!("[%?, %?]", self.x, self.y)
@ -187,6 +168,8 @@ mod test_point2 {
#[deriving(Clone, Eq)]
pub struct Point3<T> { x: T, y: T, z: T }
impl_approx!(Point3 { x, y, z })
impl<T:Num> Point3<T> {
#[inline]
pub fn new(x: T, y: T, z: T) -> Point3<T> {
@ -291,25 +274,6 @@ impl<T:Num> Mul<Vec3<T>, Point3<T>> for Point3<T> {
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Point3<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Point3<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Point3<T>, epsilon: &T) -> bool {
self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon) &&
self.z.approx_eq_eps(&other.z, epsilon)
}
}
impl<T> ToStr for Point3<T> {
pub fn to_str(&self) -> ~str {
fmt!("[%?, %?, %?]", self.x, self.y, self.z)

View file

@ -22,27 +22,11 @@ pub struct Ray3<T> {
direction: Vec3<T>,
}
impl_approx!(Ray3 { origin, direction })
impl<T> Ray3<T> {
#[inline]
pub fn new(origin: Point3<T>, direction: Vec3<T>) -> Ray3<T> {
Ray3 { origin: origin, direction: direction }
}
}
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Ray3<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &Ray3<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &Ray3<T>, epsilon: &T) -> bool {
self.origin.approx_eq_eps(&other.origin, epsilon) &&
self.direction.approx_eq_eps(&other.direction, epsilon)
}
}

View file

@ -22,6 +22,8 @@ pub struct Sphere<T> {
radius: T,
}
impl_approx!(Sphere { center, radius })
impl<T> Sphere<T> {
#[inline]
pub fn new(center: Point3<T>, radius: T) -> Sphere<T> {

View file

@ -23,6 +23,8 @@
#[license = "ASL2"];
#[crate_type = "lib"];
mod macros;
#[path = "core/core.rs"]
pub mod core;

View file

@ -32,3 +32,24 @@ macro_rules! one(
macro_rules! two(
($T:ty) => (one!(T) + one!(T));
)
macro_rules! impl_approx(
($T:ident { $($field:ident),+ }) => (
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for $T<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &$T<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &$T<T>, epsilon: &T) -> bool {
$( self.$field.approx_eq_eps(&other.$field, epsilon) )&&+
}
}
)
)

View file

@ -16,9 +16,6 @@
use core::Mat4;
use geom::{Plane3, Frustum};
#[path = "../num_macros.rs"]
mod num_macros;
///
/// Create a perspective projection matrix
///