-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathprojection.cpp
102 lines (85 loc) · 2.38 KB
/
projection.cpp
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <fstream>
#include <sstream>
#include "common.hpp"
// Transform
void Transform::from(const glm::vec3 &position_, const glm::vec3 &rotation_, const glm::vec3 &scale_)
{
position = position_;
rotation = rotation_;
scale = scale_;
}
glm::mat4 Transform::matrix() const
{
glm::mat4 pmat = glm::translate(glm::mat4(1.0f), position);
glm::mat4 rmat = glm::mat4_cast(glm::quat(glm::radians(rotation)));
glm::mat4 smat = glm::scale(glm::mat4(1.0f), scale);
return pmat * rmat * smat;
}
glm::vec3 Transform::right() const
{
glm::quat q = glm::quat(rotation);
return glm::normalize(glm::vec3(q * glm::vec4(1.0f, 0.0f, 0.0f, 0.0f)));
}
glm::vec3 Transform::up() const
{
glm::quat q = glm::quat(rotation);
return glm::normalize(glm::vec3(q * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f)));
}
glm::vec3 Transform::forward() const
{
glm::quat q = glm::quat(rotation);
return glm::normalize(glm::vec3(q * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f)));
}
std::tuple <glm::vec3, glm::vec3, glm::vec3> Transform::axes() const
{
glm::quat q = glm::quat(rotation);
return std::make_tuple(
glm::normalize(glm::vec3(q * glm::vec4(1.0f, 0.0f, 0.0f, 0.0f))),
glm::normalize(glm::vec3(q * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f))),
glm::normalize(glm::vec3(q * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f)))
);
}
// Camera
void Camera::from(float aspect_, float fov_, float near_, float far_)
{
aspect = aspect_;
fov = fov_;
near = near_;
far = far_;
}
glm::mat4 Camera::perspective_matrix() const
{
return glm::perspective(
glm::radians(fov),
aspect, near, far
);
}
RayFrame Camera::rayframe(const Transform &transform) const
{
auto [right, up, forward] = transform.axes();
// Convert FOV to radians
float vfov = glm::radians(fov);
float h = std::tan(vfov / 2);
float vheight = 2 * h;
float vwidth = vheight * aspect;
glm::vec3 w = glm::normalize(-forward);
glm::vec3 u = glm::normalize(cross(up, w));
glm::vec3 v = glm::cross(w, u);
glm::vec3 horizontal = u * vwidth;
glm::vec3 vertical = v * vheight;
return RayFrame {
.origin = transform.position,
.lower_left = transform.position - horizontal/2.0f - vertical/2.0f - w,
.horizontal = horizontal,
.vertical = vertical
};
}
glm::mat4 Camera::view_matrix(const Transform &transform)
{
auto [right, up, forward] = transform.axes();
return glm::lookAt(
transform.position,
transform.position + forward,
up
);
}