use geom::{Vector, Rectangle, Transform};
#[derive(Clone, Copy, Debug)]
pub struct View {
pub(crate) normalize: Transform,
pub(crate) opengl: Transform
}
impl View {
pub fn new(world: Rectangle) -> View {
View::new_transformed(world, Transform::identity())
}
pub fn new_transformed(world: Rectangle, transform: Transform) -> View {
let normalize = Transform::scale(world.size().recip())
* Transform::translate(world.size() / 2)
* transform
* Transform::translate(-world.top_left() - world.size() / 2);
let opengl = Transform::scale(Vector::new(2, -2))
* Transform::translate(-Vector::one() / 2)
* normalize;
View { normalize, opengl }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn opengl_projection() {
let view = View::new(Rectangle::new_sized(50, 50));
let world_bottom = Vector::y() * 50;
assert_eq!(view.opengl * world_bottom, -Vector::one());
let view = View::new(Rectangle::new(50, 50, 50, 50));
let world_top = Vector::one() * 50;
let expected = -Vector::x() + Vector::y();
assert_eq!(view.opengl * world_top, expected);
}
#[test]
fn projection() {
let view = View::new(Rectangle::new_sized(50, 50));
let screen_size = Vector::new(100, 100);
let unproject = Transform::scale(screen_size) * view.normalize;
let project = unproject.inverse();
let screen_bottom = Vector::y() * 100;
let world_bottom = Vector::y() * 50;
assert_eq!(project * screen_bottom, world_bottom);
assert_eq!(unproject * world_bottom, screen_bottom);
}
}