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
52
53
54
55
56
57
58
|
use cgmath::prelude::*;
use cgmath::{Matrix3, Vector3};
use crate::screen::ScreenIterator;
type Vector = Vector3<f32>;
// The physical screen that camera projects onto
#[derive(Debug, Copy, Clone)]
pub struct Screen {
pub width: f32,
pub height: f32,
}
#[derive(Debug, Copy, Clone)]
pub struct Camera {
pub position: Vector,
pub direction: Vector,
pub up: Vector,
pub distance: f32,
pub speed: f32,
pub turn_rate: f32,
pub screen: Screen,
}
const ASPECT_RATIO: f32 = 2.0 / 3.0;
impl Camera {
pub fn new(position: Vector, look_at: Vector, angle: f32, distance: f32) -> Self {
let width = distance * 2.0 * (angle / 2.0).tan();
let height = width * ASPECT_RATIO;
Self {
position,
direction: (look_at - position).normalize(),
up: Vector::unit_z(),
distance,
screen: Screen { width, height },
speed: 0.5,
turn_rate: 60.0,
}
}
pub fn get_screen_iterator(self) -> ScreenIterator {
// Linear transormation operator for calculating screen position
// Assumes "initial" screen is perpendicular to OX
// and it's bottom edge is parallel to OY
let operator = Matrix3::from_cols(
self.direction * self.distance,
self.direction.cross(self.up) * self.screen.width,
-self.up * self.screen.height,
);
ScreenIterator::from_screen_position(
operator * Vector::new(1.0, -0.5, -0.5),
operator * Vector::unit_z(),
operator * Vector::unit_y(),
)
}
}
|