2018-04-10 15:25:01 +02:00
|
|
|
//! This module contains everything to deal with cameras.
|
|
|
|
|
2018-02-27 11:42:35 +01:00
|
|
|
use math::vector::Vector3;
|
|
|
|
|
2018-04-10 15:25:01 +02:00
|
|
|
/// The trait that a render camera should implement.
|
|
|
|
///
|
|
|
|
/// It allows the renderer to use it.
|
2018-04-10 15:13:35 +02:00
|
|
|
pub trait RenderCamera {
|
2018-04-10 15:25:01 +02:00
|
|
|
|
|
|
|
/// Returns the view matrix of the camera.
|
2018-02-27 11:42:35 +01:00
|
|
|
fn get_view_matrix(&self) -> [[f32; 4]; 4];
|
2018-04-10 15:25:01 +02:00
|
|
|
|
|
|
|
/// Returns the perspective matrix of the camera.
|
2018-04-11 17:03:32 +02:00
|
|
|
fn get_perspective_matrix(&self) -> [[f32; 4]; 4] ;
|
|
|
|
|
2018-02-27 11:42:35 +01:00
|
|
|
}
|
|
|
|
|
2018-04-10 15:25:01 +02:00
|
|
|
/// Creates a look at matrix from the center, the target pointed by the camera and the up vector.
|
2018-02-27 11:42:35 +01:00
|
|
|
pub fn look_at_matrix(position: [f32; 3], target: [f32; 3], up: [f32; 3]) -> [[f32; 4]; 4] {
|
|
|
|
let f = {
|
|
|
|
let f = [
|
|
|
|
target[0] - position[0],
|
|
|
|
target[1] - position[1],
|
|
|
|
target[2] - position[2],
|
|
|
|
];
|
|
|
|
let len = f[0] * f[0] + f[1] * f[1] + f[2] * f[2];
|
|
|
|
let len = len.sqrt();
|
|
|
|
[f[0] / len, f[1] / len, f[2] / len]
|
|
|
|
};
|
|
|
|
|
|
|
|
let s = [up[1] * f[2] - up[2] * f[1],
|
|
|
|
up[2] * f[0] - up[0] * f[2],
|
|
|
|
up[0] * f[1] - up[1] * f[0]];
|
|
|
|
|
|
|
|
let s_norm = {
|
|
|
|
let len = s[0] * s[0] + s[1] * s[1] + s[2] * s[2];
|
|
|
|
let len = len.sqrt();
|
|
|
|
[s[0] / len, s[1] / len, s[2] / len]
|
|
|
|
};
|
|
|
|
|
|
|
|
let u = [f[1] * s_norm[2] - f[2] * s_norm[1],
|
|
|
|
f[2] * s_norm[0] - f[0] * s_norm[2],
|
|
|
|
f[0] * s_norm[1] - f[1] * s_norm[0]];
|
|
|
|
|
|
|
|
let p = [-position[0] * s_norm[0] - position[1] * s_norm[1] - position[2] * s_norm[2],
|
|
|
|
-position[0] * u[0] - position[1] * u[1] - position[2] * u[2],
|
|
|
|
-position[0] * f[0] - position[1] * f[1] - position[2] * f[2]];
|
|
|
|
|
|
|
|
[
|
|
|
|
[-s_norm[0], u[0], f[0], 0.0],
|
|
|
|
[-s_norm[1], u[1], f[1], 0.0],
|
|
|
|
[-s_norm[2], u[2], f[2], 0.0],
|
|
|
|
[-p[0], p[1], p[2], 1.0],
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-04-11 17:03:32 +02:00
|
|
|
/// Creates a perspective matrix of a camera.
|
|
|
|
pub fn perspective_matrix(aspect_ratio: f32, z_near: f32, z_far: f32) -> [[f32; 4]; 4] {
|
|
|
|
let fov = 3.141592 / 3.0;
|
|
|
|
|
|
|
|
use num::Float;
|
|
|
|
let f = 1.0 / (fov / 2.0).tan();
|
|
|
|
|
|
|
|
[
|
|
|
|
[f / aspect_ratio , 0.0, 0.0 , 0.0],
|
|
|
|
[ 0.0 , f , 0.0 , 0.0],
|
|
|
|
[ 0.0 , 0.0, (z_far+z_near)/(z_far-z_near) , 1.0],
|
|
|
|
[ 0.0 , 0.0, -(2.0*z_far*z_near)/(z_far-z_near), 0.0],
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2018-04-10 15:25:01 +02:00
|
|
|
/// A simple camera with its position, target and up vector.
|
2018-04-10 15:13:35 +02:00
|
|
|
pub struct Camera {
|
2018-04-10 15:25:01 +02:00
|
|
|
/// The position of the center of the camera.
|
2018-04-10 15:13:35 +02:00
|
|
|
pub position: Vector3<f32>,
|
2018-04-10 15:25:01 +02:00
|
|
|
|
|
|
|
/// The 3D point the camera is targetting.
|
2018-04-10 15:13:35 +02:00
|
|
|
pub target: Vector3<f32>,
|
2018-04-10 15:25:01 +02:00
|
|
|
|
|
|
|
/// The up vector of the camera.
|
2018-04-10 15:13:35 +02:00
|
|
|
pub up: Vector3<f32>,
|
2018-04-11 17:03:32 +02:00
|
|
|
|
|
|
|
/// The minimum depth for visible things.
|
|
|
|
pub z_near: f32,
|
|
|
|
|
|
|
|
/// The maximum depth for visible things.
|
|
|
|
pub z_far: f32,
|
|
|
|
|
|
|
|
/// The aspect ratio of the camera.
|
|
|
|
pub aspect_ratio: f32,
|
|
|
|
|
2018-02-27 11:42:35 +01:00
|
|
|
}
|
|
|
|
|
2018-04-10 15:13:35 +02:00
|
|
|
impl Camera {
|
2018-04-10 15:25:01 +02:00
|
|
|
/// Creates a new camera from its attributes.
|
2018-04-10 15:13:35 +02:00
|
|
|
pub fn new(position: Vector3<f32>, target: Vector3<f32>, up: Vector3<f32>) -> Camera {
|
|
|
|
Camera {
|
2018-02-27 11:42:35 +01:00
|
|
|
position: position,
|
|
|
|
target: target,
|
|
|
|
up: up,
|
2018-04-11 17:03:32 +02:00
|
|
|
z_near: 0.01,
|
|
|
|
z_far: 1000.0,
|
|
|
|
aspect_ratio: 16.0 / 9.0
|
2018-02-27 11:42:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 15:13:35 +02:00
|
|
|
impl RenderCamera for Camera {
|
2018-02-27 11:42:35 +01:00
|
|
|
fn get_view_matrix(&self) -> [[f32; 4]; 4] {
|
|
|
|
look_at_matrix(self.position.into(), self.target.into(), self.up.into())
|
|
|
|
}
|
2018-04-11 17:03:32 +02:00
|
|
|
|
|
|
|
fn get_perspective_matrix(&self) -> [[f32; 4]; 4] {
|
|
|
|
perspective_matrix(self.aspect_ratio, self.z_near, self.z_far)
|
|
|
|
}
|
2018-02-27 11:42:35 +01:00
|
|
|
}
|
|
|
|
|