Skip to content

Commit 6522a7d

Browse files
committed
renderer: Construct frustum with parameters.
1 parent 8d5fd3e commit 6522a7d

File tree

8 files changed

+155
-77
lines changed

8 files changed

+155
-77
lines changed

libopenage/renderer/camera/camera.cpp

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,18 @@ Camera::Camera(const std::shared_ptr<Renderer> &renderer,
2525
moved{true},
2626
zoom_changed{true},
2727
view{Eigen::Matrix4f::Identity()},
28-
proj{Eigen::Matrix4f::Identity()} {
28+
proj{Eigen::Matrix4f::Identity()},
29+
frustum{this->viewport_size,
30+
DEFAULT_NEAR_DISTANCE,
31+
DEFAULT_FAR_DISTANCE,
32+
this->scene_pos,
33+
CAM_DIRECTION,
34+
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
35+
this->get_zoom_factor()} {
2936
this->look_at_scene(Eigen::Vector3f(0.0f, 0.0f, 0.0f));
3037

3138
this->init_uniform_buffer(renderer);
3239

33-
// Make the frustum slightly bigger than the camera's view to ensure objects on the boundary get rendered
34-
float real_zoom = get_zoom_factor();
35-
frustum.update(this->viewport_size,
36-
DEFAULT_NEAR_DISTANCE,
37-
DEFAULT_FAR_DISTANCE,
38-
this->scene_pos,
39-
CAM_DIRECTION,
40-
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
41-
real_zoom);
42-
4340
log::log(INFO << "Created new camera at position "
4441
<< "(" << this->scene_pos[0]
4542
<< ", " << this->scene_pos[1]
@@ -61,19 +58,16 @@ Camera::Camera(const std::shared_ptr<Renderer> &renderer,
6158
zoom_changed{true},
6259
viewport_changed{true},
6360
view{Eigen::Matrix4f::Identity()},
64-
proj{Eigen::Matrix4f::Identity()} {
61+
proj{Eigen::Matrix4f::Identity()},
62+
frustum{this->viewport_size,
63+
DEFAULT_NEAR_DISTANCE,
64+
DEFAULT_FAR_DISTANCE,
65+
this->scene_pos,
66+
CAM_DIRECTION,
67+
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
68+
this->get_zoom_factor()} {
6569
this->init_uniform_buffer(renderer);
6670

67-
// Make the frustum slightly bigger than the camera's view to ensure objects on the boundary get rendered
68-
float real_zoom = this->get_zoom_factor();
69-
frustum.update(this->viewport_size,
70-
DEFAULT_NEAR_DISTANCE,
71-
DEFAULT_FAR_DISTANCE,
72-
this->scene_pos,
73-
CAM_DIRECTION,
74-
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
75-
real_zoom);
76-
7771
log::log(INFO << "Created new camera at position "
7872
<< "(" << this->scene_pos[0]
7973
<< ", " << this->scene_pos[1]
@@ -128,15 +122,14 @@ void Camera::move_to(Eigen::Vector3f scene_pos) {
128122
this->scene_pos = scene_pos;
129123
this->moved = true;
130124

131-
// Make the frustum slightly bigger than the camera's view to ensure objects on the boundary get rendered
132-
float real_zoom = this->get_zoom_factor();
125+
// Update frustum
133126
frustum.update(viewport_size,
134127
DEFAULT_NEAR_DISTANCE,
135128
DEFAULT_FAR_DISTANCE,
136129
scene_pos,
137130
CAM_DIRECTION,
138131
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
139-
real_zoom);
132+
this->get_zoom_factor());
140133
}
141134

142135
void Camera::move_rel(Eigen::Vector3f direction, float delta) {
@@ -183,7 +176,7 @@ const Eigen::Matrix4f &Camera::get_view_matrix() {
183176

184177
Eigen::Vector3f eye = this->scene_pos;
185178
Eigen::Vector3f center = this->scene_pos + direction; // look in the direction of the camera
186-
Eigen::Vector3f up = Eigen::Vector3f(0.0f, 1.0f, 0.0f);
179+
Eigen::Vector3f up = CAM_UP;
187180

188181
Eigen::Vector3f f = center - eye;
189182
f.normalize();
@@ -265,7 +258,7 @@ Eigen::Vector3f Camera::get_input_pos(const coord::input &coord) const {
265258
auto direction = CAM_DIRECTION.normalized();
266259
Eigen::Vector3f eye = this->scene_pos;
267260
Eigen::Vector3f center = this->scene_pos + direction;
268-
Eigen::Vector3f up = Eigen::Vector3f(0.0f, 1.0f, 0.0f);
261+
Eigen::Vector3f up = CAM_UP;
269262

270263
Eigen::Vector3f f = center - eye;
271264
f.normalize();
@@ -294,7 +287,7 @@ const std::shared_ptr<renderer::UniformBuffer> &Camera::get_uniform_buffer() con
294287
return this->uniform_buffer;
295288
}
296289

297-
Frustum Camera::get_frustum() const {
290+
const Frustum &Camera::get_frustum() const {
298291
return this->frustum;
299292
}
300293

libopenage/renderer/camera/camera.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ namespace camera {
2424
/**
2525
* Camera for selecting what part of the ingame world is displayed.
2626
*
27+
* The camera uses orthographic projection as it is primarily used for
28+
* 2D rendering.
29+
*
2730
* TODO: Vulkan version.
2831
*/
2932
class Camera {
@@ -184,7 +187,7 @@ class Camera {
184187
*
185188
* @return Frustum object.
186189
*/
187-
Frustum get_frustum() const;
190+
const Frustum &get_frustum() const;
188191

189192
private:
190193
/**
@@ -292,8 +295,7 @@ class Camera {
292295
std::shared_ptr<renderer::UniformBuffer> uniform_buffer;
293296

294297
/**
295-
* The frustum used to cull objects
296-
* Will be recalculated regardless of whether frustum culling is enabled
298+
* Frustum (viewing volume) for culling rendering objects.
297299
*/
298300
Frustum frustum;
299301
};

libopenage/renderer/camera/definitions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ static const Eigen::Vector3f CAM_DIRECTION{
1919
-1 * (std::sqrt(6.f) / 4),
2020
};
2121

22+
/**
23+
* Camera up vector.
24+
*/
25+
static const Eigen::Vector3f CAM_UP{0.0f, 1.0f, 0.0f};
26+
2227
/**
2328
* Default near distance of the camera.
2429
*

libopenage/renderer/camera/frustum.cpp

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,40 @@
1414

1515
namespace openage::renderer::camera {
1616

17-
Frustum::Frustum() :
18-
top_face_distance{0.0f},
19-
bottom_face_distance{0.0f},
20-
right_face_distance{0.0f},
21-
left_face_distance{0.0f},
22-
far_face_distance{0.0f},
23-
near_face_distance{0.0f},
24-
top_face_normal{Eigen::Vector3f(0.0f, 0.0f, 0.0f)},
25-
bottom_face_normal{Eigen::Vector3f(0.0f, 0.0f, 0.0f)},
26-
right_face_normal{Eigen::Vector3f(0.0f, 0.0f, 0.0f)},
27-
left_face_normal{Eigen::Vector3f(0.0f, 0.0f, 0.0f)},
28-
far_face_normal{Eigen::Vector3f(0.0f, 0.0f, 0.0f)},
29-
near_face_normal{Eigen::Vector3f(0.0f, 0.0f, 0.0f)} {
17+
Frustum::Frustum(const util::Vector2s &viewport_size,
18+
const float near_distance,
19+
const float far_distance,
20+
const Eigen::Vector3f &camera_pos,
21+
const Eigen::Vector3f &cam_direction,
22+
const Eigen::Vector3f &up_direction,
23+
const float zoom_factor) {
24+
this->update(viewport_size,
25+
near_distance,
26+
far_distance,
27+
camera_pos,
28+
cam_direction,
29+
up_direction,
30+
zoom_factor);
3031
}
3132

32-
void Frustum::update(util::Vector2s &viewport_size,
33-
float near_distance,
34-
float far_distance,
35-
Eigen::Vector3f &scene_pos,
36-
Eigen::Vector3f cam_direction,
37-
Eigen::Vector3f up_direction,
38-
float real_zoom) {
33+
void Frustum::update(const util::Vector2s &viewport_size,
34+
const float near_distance,
35+
const float far_distance,
36+
const Eigen::Vector3f &camera_pos,
37+
const Eigen::Vector3f &cam_direction,
38+
const Eigen::Vector3f &up_direction,
39+
const float zoom_factor) {
3940
// offsets are adjusted by zoom
4041
// this is the same calculation as for the projection matrix
4142
float halfscreenwidth = viewport_size[0] / 2;
4243
float halfscreenheight = viewport_size[1] / 2;
4344

44-
float halfwidth = halfscreenwidth * real_zoom;
45-
float halfheight = halfscreenheight * real_zoom;
45+
float halfwidth = halfscreenwidth * zoom_factor;
46+
float halfheight = halfscreenheight * zoom_factor;
4647

4748
Eigen::Vector3f direction = cam_direction.normalized();
48-
Eigen::Vector3f eye = scene_pos;
49-
Eigen::Vector3f center = scene_pos + direction;
49+
Eigen::Vector3f eye = camera_pos;
50+
Eigen::Vector3f center = camera_pos + direction;
5051

5152
// calculate up (u) and right (s) vectors for camera
5253
// these define the camera plane in 3D space that the input
@@ -57,8 +58,9 @@ void Frustum::update(util::Vector2s &viewport_size,
5758
Eigen::Vector3f u = s.cross(f);
5859
u.normalize();
5960

60-
Eigen::Vector3f near_position = scene_pos + direction * near_distance;
61-
Eigen::Vector3f far_position = scene_pos + direction * far_distance;
61+
// calculate distance of the camera position to the near and far plane
62+
Eigen::Vector3f near_position = camera_pos + direction * near_distance;
63+
Eigen::Vector3f far_position = camera_pos + direction * far_distance;
6264

6365
// The frustum is a cuboid box with 8 points defining it (4 on the near plane, 4 on the far plane)
6466
Eigen::Vector3f near_top_left = near_position - s * halfwidth + u * halfheight;
@@ -67,14 +69,15 @@ void Frustum::update(util::Vector2s &viewport_size,
6769
Eigen::Vector3f near_bottom_right = near_position + s * halfwidth - u * halfheight;
6870

6971
Eigen::Vector3f far_top_left = far_position - s * halfwidth + u * halfheight;
70-
Eigen::Vector3f far_top_right = far_position + s * halfwidth + u * halfheight;
72+
// Eigen::Vector3f far_top_right = far_position + s * halfwidth + u * halfheight; // unused
7173
Eigen::Vector3f far_bottom_left = far_position - s * halfwidth - u * halfheight;
7274
Eigen::Vector3f far_bottom_right = far_position + s * halfwidth - u * halfheight;
7375

7476
// The near and far planes are easiest to compute, as they should be in the direction of the camera
7577
this->near_face_normal = cam_direction.normalized();
7678
this->far_face_normal = -1.0f * cam_direction.normalized();
7779

80+
// The distance of the plane from the origin is the dot product of the normal and a point on the plane
7881
this->near_face_distance = this->near_face_normal.dot(near_position);
7982
this->far_face_distance = this->far_face_normal.dot(far_position);
8083

@@ -84,11 +87,14 @@ void Frustum::update(util::Vector2s &viewport_size,
8487
this->top_face_normal = (near_top_right - near_top_left).cross(near_top_left - far_top_left);
8588
this->bottom_face_normal = (near_bottom_left - far_bottom_left).cross(near_bottom_right - near_bottom_left);
8689

90+
// for orthographic projection, the normal of left/right should equal -s/s
91+
// and the normal of top/bottom should equal u/-u
8792
this->left_face_normal.normalize();
8893
this->right_face_normal.normalize();
8994
this->top_face_normal.normalize();
9095
this->bottom_face_normal.normalize();
9196

97+
// calculate the distance of the planes to the origin
9298
this->left_face_distance = this->left_face_normal.dot(near_bottom_left);
9399
this->right_face_distance = this->right_face_normal.dot(far_bottom_right);
94100
this->top_face_distance = this->top_face_normal.dot(near_top_right);

libopenage/renderer/camera/frustum.h

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,54 @@
1515
namespace openage::renderer::camera {
1616

1717
/**
18-
* Frustum for a camera.
18+
* Frustum for a camera. The frustum is defined by 6 planes (top, bottom, right, left, far, near) that
19+
* define the viewing volume of the camera.
1920
*
2021
* Used for frustum culling (https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling)
2122
* in the renderer.
23+
*
24+
* As the openage camera uses orthographic projection, the frustum is a box, i.e. plane opposite
25+
* to each other are parallel.
2226
*/
2327
class Frustum {
2428
public:
2529
/**
2630
* Create a new frustum.
31+
*
32+
* @param viewport_size Size of the viewport (width x height).
33+
* @param near_distance Near distance of the frustum.
34+
* @param far_distance Far distance of the frustum.
35+
* @param camera_pos Scene position of the camera.
36+
* @param cam_direction Direction the camera is looking at.
37+
* @param up_direction Up direction of the camera.
38+
* @param zoom_factor Zoom factor of the camera.
2739
*/
28-
Frustum();
40+
Frustum(const util::Vector2s &viewport_size,
41+
const float near_distance,
42+
const float far_distance,
43+
const Eigen::Vector3f &camera_pos,
44+
const Eigen::Vector3f &cam_direction,
45+
const Eigen::Vector3f &up_direction,
46+
const float zoom_factor);
2947

3048
/**
3149
* Update this frustum with the new camera parameters.
3250
*
3351
* @param viewport_size Size of the viewport (width x height).
3452
* @param near_distance Near distance of the frustum.
3553
* @param far_distance Far distance of the frustum.
36-
* @param scene_pos Scene position of the camera.
54+
* @param camera_pos Scene position of the camera.
3755
* @param cam_direction Direction the camera is looking at.
3856
* @param up_direction Up direction of the camera.
39-
* @param real_zoom Zoom factor of the camera.
57+
* @param zoom_factor Zoom factor of the camera.
4058
*/
41-
void update(util::Vector2s &viewport_size,
42-
float near_distance,
43-
float far_distance,
44-
Eigen::Vector3f &scene_pos,
45-
Eigen::Vector3f cam_direction,
46-
Eigen::Vector3f up_direction,
47-
float real_zoom);
59+
void update(const util::Vector2s &viewport_size,
60+
const float near_distance,
61+
const float far_distance,
62+
const Eigen::Vector3f &camera_pos,
63+
const Eigen::Vector3f &cam_direction,
64+
const Eigen::Vector3f &up_direction,
65+
const float zoom_factor);
4866

4967
/**
5068
* Check whether a point in the scene is inside the frustum.
@@ -56,18 +74,64 @@ class Frustum {
5674
bool in_frustum(Eigen::Vector3f &scene_pos) const;
5775

5876
private:
77+
/**
78+
* Normal vector of the top face.
79+
*/
5980
Eigen::Vector3f top_face_normal;
81+
82+
/**
83+
* Normal vector of the bottom face.
84+
*/
6085
Eigen::Vector3f bottom_face_normal;
86+
87+
/**
88+
* Normal vector of the right face.
89+
*/
6190
Eigen::Vector3f right_face_normal;
91+
92+
/**
93+
* Normal vector of the left face.
94+
*/
6295
Eigen::Vector3f left_face_normal;
96+
97+
/**
98+
* Normal vector of the far face.
99+
*/
63100
Eigen::Vector3f far_face_normal;
101+
102+
/**
103+
* Normal vector of the near face.
104+
*/
64105
Eigen::Vector3f near_face_normal;
65106

107+
/**
108+
* Shortest distance from the top face to the scene origin.
109+
*/
66110
float top_face_distance;
111+
112+
/**
113+
* Shortest distance from the bottom face to the scene origin.
114+
*/
67115
float bottom_face_distance;
116+
117+
/**
118+
* Shortest distance from the right face to the scene origin.
119+
*/
68120
float right_face_distance;
121+
122+
/**
123+
* Shortest distance from the left face to the scene origin.
124+
*/
69125
float left_face_distance;
126+
127+
/**
128+
* Shortest distance from the far face to the scene origin.
129+
*/
70130
float far_face_distance;
131+
132+
/**
133+
* Shortest distance from the near face to the scene origin.
134+
*/
71135
float near_face_distance;
72136
};
73137
} // namespace openage::renderer::camera

0 commit comments

Comments
 (0)