Skip to content

Commit

Permalink
[WIP] Camera projections (amethyst#1598)
Browse files Browse the repository at this point in the history
Tests PR to follow
* Started work on camera refine with adding tests etc.
* Add some ideas for tests.
* standard_2d should not use size parameters
* Change standard_2d back to take width and height.
A bunch of examples expect standard_2d to take two parameters.
For this to work we need to center our matrix. Godot does this similar.
* Fix upside down image when created by standard_2d
* Remove dummy tests
  • Loading branch information
valkum authored and jaynus committed May 16, 2019
1 parent 1eb84e1 commit ebc186e
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions amethyst_rendy/src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,38 @@ pub enum Projection {
impl Projection {
/// Creates an orthographic projection with the given left, right, bottom, and
/// top plane distances.
pub fn orthographic(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32,) -> Projection {

let mut proj = Orthographic3::new(left, right, bottom, top, 0.1, 2000.0).into_inner();
proj[(2, 2)] = 2.0 / (far - near);
proj[(2, 3)] = (far + near) / (far - near);

/// The projection matrix is right-handed and has a depth range of 0 to 1
pub fn orthographic(left: f32, right: f32, bottom: f32, top: f32, z_near: f32, z_far: f32,) -> Projection {
let mut proj = Matrix4::<f32>::identity();

proj[(0, 0)] = 2.0 / (right - left);
proj[(1, 1)] = 2.0 / (top - bottom);
proj[(2, 2)] = - 1.0 / (z_far - z_near);
proj[(0, 3)] = - (right + left) / (right - left);
proj[(1, 3)] = - (top + bottom) / (top - bottom);
proj[(2, 3)] = - z_near / (z_far - z_near);

// Important: nalgebra's methods on Orthographic3 are not safe for use with RH matrices
Projection::Orthographic(Orthographic3::from_matrix_unchecked(proj))
}

/// Creates a perspective projection with the given aspect ratio and
/// field-of-view. `fov` is specified in radians.
/// The projection matrix is right-handed and has a depth range of 0 to 1
pub fn perspective(aspect: f32, fov: f32, z_near: f32, z_far: f32) -> Projection {
let mut proj = Perspective3::new(aspect, fov, z_near, z_far).into_inner();
proj[(1, 1)] = -proj[(1, 1)];
let mut proj = Matrix4::<f32>::identity();

let tan_half_fovy = (fov / 2.0).tan();

proj[(0, 0)] = 1.0 / (aspect * tan_half_fovy);
proj[(1, 1)] = - 1.0 / tan_half_fovy;
proj[(2, 2)] = z_far / (z_near - z_far);
proj[(2, 3)] = (z_near * z_far) / (z_near - z_far);

proj[(2, 3)] = - (z_near * z_far) / (z_far - z_near);
proj[(3, 2)] = - 1.0;
proj[(3, 3)] = 0.0;

// Important: nalgebra's methods on Perspective3 are not safe for use with RH matrices
Projection::Perspective(Perspective3::from_matrix_unchecked(proj))
}
}
Expand All @@ -67,11 +81,11 @@ pub struct Camera {
impl Camera {
/// Create a normalized camera for 2D.
///
/// Will use an orthographic projection with lower left corner being (-1., -1.) and
/// upper right (1., 1.).
/// Will use an orthographic projection centered around (0, 0) of size (width, height)
/// Bottom left corner is (-width/2.0, -height/2.0)
/// View transformation will be multiplicative identity.
pub fn standard_2d(width: f32, height: f32) -> Self {
Self::from(Projection::orthographic(-1., width, -1., height, 0.1, 2000.0))
Self::from(Projection::orthographic(-width/2.0, width/2.0, height/2.0, - height/2.0, 0.1, 2000.0))
}

/// Create a standard camera for 3D.
Expand Down Expand Up @@ -257,4 +271,4 @@ mod serde_persp {
serializer,
)
}
}
}

0 comments on commit ebc186e

Please sign in to comment.