use traits::structure::{BaseFloat, Cast};
use structs::{Pnt3, Vec3, Mat4};
#[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen};
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
pub struct Ortho3<N> {
width: N,
height: N,
znear: N,
zfar: N
}
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
pub struct OrthoMat3<N> {
mat: Mat4<N>
}
impl<N: BaseFloat> Ortho3<N> {
pub fn new(width: N, height: N, znear: N, zfar: N) -> Ortho3<N> {
assert!(!::is_zero(&(zfar - znear)));
assert!(!::is_zero(&width));
assert!(!::is_zero(&height));
Ortho3 {
width: width,
height: height,
znear: znear,
zfar: zfar
}
}
pub fn to_mat(&self) -> Mat4<N> {
self.to_persp_mat().mat
}
pub fn to_persp_mat(&self) -> OrthoMat3<N> {
OrthoMat3::new(self.width, self.height, self.znear, self.zfar)
}
}
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for Ortho3<N> {
fn arbitrary<G: Gen>(g: &mut G) -> Ortho3<N> {
let width = reject(g, |x| !::is_zero(x));
let height = reject(g, |x| !::is_zero(x));
let znear = Arbitrary::arbitrary(g);
let zfar = reject(g, |&x: &N| !::is_zero(&(x - znear)));
Ortho3::new(width, height, znear, zfar)
}
}
impl<N: BaseFloat + Clone> Ortho3<N> {
#[inline]
pub fn width(&self) -> N {
self.width.clone()
}
#[inline]
pub fn height(&self) -> N {
self.height.clone()
}
#[inline]
pub fn znear(&self) -> N {
self.znear.clone()
}
#[inline]
pub fn zfar(&self) -> N {
self.zfar.clone()
}
#[inline]
pub fn set_width(&mut self, width: N) {
self.width = width
}
#[inline]
pub fn set_height(&mut self, height: N) {
self.height = height
}
#[inline]
pub fn set_znear(&mut self, znear: N) {
self.znear = znear
}
#[inline]
pub fn set_zfar(&mut self, zfar: N) {
self.zfar = zfar
}
#[inline]
pub fn project_pnt(&self, p: &Pnt3<N>) -> Pnt3<N> {
self.to_persp_mat().project_pnt(p)
}
#[inline]
pub fn project_vec(&self, p: &Vec3<N>) -> Vec3<N> {
self.to_persp_mat().project_vec(p)
}
}
impl<N: BaseFloat> OrthoMat3<N> {
pub fn new(width: N, height: N, znear: N, zfar: N) -> OrthoMat3<N> {
assert!(!::is_zero(&(zfar - znear)));
assert!(!::is_zero(&width));
assert!(!::is_zero(&height));
let mat: Mat4<N> = ::one();
let mut res = OrthoMat3 { mat: mat };
res.set_width(width);
res.set_height(height);
res.set_znear_and_zfar(znear, zfar);
res
}
#[inline]
pub unsafe fn new_with_mat(mat: Mat4<N>) -> OrthoMat3<N> {
OrthoMat3 {
mat: mat
}
}
#[inline]
pub fn as_mat<'a>(&'a self) -> &'a Mat4<N> {
&self.mat
}
#[inline]
pub fn width(&self) -> N {
<N as Cast<f64>>::from(2.0) / self.mat.m11
}
#[inline]
pub fn height(&self) -> N {
<N as Cast<f64>>::from(2.0) / self.mat.m22
}
#[inline]
pub fn znear(&self) -> N {
(self.mat.m34 + ::one()) / self.mat.m33
}
#[inline]
pub fn zfar(&self) -> N {
(self.mat.m34 - ::one()) / self.mat.m33
}
#[inline]
pub fn set_width(&mut self, width: N) {
assert!(!::is_zero(&width));
self.mat.m11 = <N as Cast<f64>>::from(2.0) / width;
}
#[inline]
pub fn set_height(&mut self, height: N) {
assert!(!::is_zero(&height));
self.mat.m22 = <N as Cast<f64>>::from(2.0) / height;
}
#[inline]
pub fn set_znear(&mut self, znear: N) {
let zfar = self.zfar();
self.set_znear_and_zfar(znear, zfar);
}
#[inline]
pub fn set_zfar(&mut self, zfar: N) {
let znear = self.znear();
self.set_znear_and_zfar(znear, zfar);
}
#[inline]
pub fn set_znear_and_zfar(&mut self, znear: N, zfar: N) {
assert!(!::is_zero(&(zfar - znear)));
self.mat.m33 = -<N as Cast<f64>>::from(2.0) / (zfar - znear);
self.mat.m34 = -(zfar + znear) / (zfar - znear);
}
#[inline]
pub fn project_pnt(&self, p: &Pnt3<N>) -> Pnt3<N> {
Pnt3::new(
self.mat.m11 * p.x,
self.mat.m22 * p.y,
self.mat.m33 * p.z + self.mat.m34
)
}
#[inline]
pub fn project_vec(&self, p: &Vec3<N>) -> Vec3<N> {
Vec3::new(
self.mat.m11 * p.x,
self.mat.m22 * p.y,
self.mat.m33 * p.z
)
}
}
impl<N: BaseFloat + Clone> OrthoMat3<N> {
#[inline]
pub fn to_mat<'a>(&'a self) -> Mat4<N> {
self.mat.clone()
}
}
#[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for OrthoMat3<N> {
fn arbitrary<G: Gen>(g: &mut G) -> OrthoMat3<N> {
let x: Ortho3<N> = Arbitrary::arbitrary(g);
x.to_persp_mat()
}
}
#[cfg(feature="arbitrary")]
#[inline]
pub fn reject<G: Gen, F: FnMut(&T) -> bool, T: Arbitrary>(g: &mut G, f: F) -> T {
use std::iter::repeat;
repeat(()).map(|_| Arbitrary::arbitrary(g)).filter(f).next().unwrap()
}