1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use crate::{
Ray, ray,
Vec3, cross, normalize
};
/// This struct allows to position viewer in the scene.
pub struct Camera {
// Camera's position
position: Vec3,
// Lower left corner of the canvas
corner: Vec3,
// Horizontal scale
horizontal: Vec3,
// Vertical scale
vertical: Vec3
}
impl Camera {
/// Camera's constructor.
///
/// * `look_from` - Camera's position.
/// * `look_at` - The point camera is focusing on.
/// * `up` - `Vec3` that describes "up" direction in the world. Generally (0, 1, 0).
/// * `fov` - Vertical field of view in degrees.
/// * `aspect_ratio` - Aspect ratio of image's dimensions: `width / height`.
pub fn new(look_from: Vec3, look_at: Vec3, up: Vec3, fov: f32, aspect_ratio: f32) -> Camera {
let half_height = (fov.to_radians() / 2f32).tan();
let half_width = aspect_ratio * half_height;
let w = normalize!(look_from - look_at);
let u = normalize!(cross!(up, w));
let v = cross!(w, u);
Camera {
position: look_from,
corner: look_from - half_width * u - half_height * v - w,
horizontal: 2f32 * half_width * u,
vertical: 2f32 * half_height * v
}
}
/// Emits a Ray for given pixel on virtual camera's canvas.
///
/// * `s` - Horizontal coordinate on canvas. Must be a value in range `[0; 1]`.
/// * `t` - Vertical coordinate on canvas. Must be a value in range `[0; 1]`.
pub fn ray(&self, s: f32, t: f32) -> Ray {
ray!(self.position, self.corner + s * self.horizontal + t * self.vertical - self.position)
}
}