commit 981f0f9c0b582d41d40809e00d9a4e22322e4b1f
parent 6dad92883cdbc38f8a51c0a4c5d22abff95b0f33
Author: Christian Ermann <christianermann@gmail.com>
Date: Sun, 29 May 2022 16:11:06 -0700
Prototyped frustum culling system.
Diffstat:
5 files changed, 218 insertions(+), 6 deletions(-)
diff --git a/include/camera.h b/include/camera.h
@@ -5,6 +5,11 @@
#include "vec.h"
typedef struct {
+ Vec3 n;
+ Vec3 p;
+} Plane;
+
+typedef struct {
Vec3 position;
float yaw;
float pitch;
@@ -22,6 +27,13 @@ typedef struct {
Vec3 right;
Mat4 matrix;
+
+ float near_h;
+ float near_w;
+ float far_h;
+ float far_w;
+ Plane frustum[6];
+
} Camera;
Camera *Camera_make(float x, float y, float z, float yaw, float pitch);
@@ -41,4 +53,7 @@ void Camera_updateMatrix(Camera* camera);
// Process user input to adjust camera's position and orientation
void Camera_move(Camera *camera, UserInput *input);
+void Camera_updateFrustum(Camera *camera);
+int Camera_sphereInFrustum(const Camera *camera, Vec3 p, float r);
+
#endif
diff --git a/include/chunk_manager.h b/include/chunk_manager.h
@@ -1,6 +1,7 @@
#ifndef CHUNK_MANAGER_H
#define CHUNK_MANAGER_H
+#include "camera.h"
#include "chunk.h"
#include "threadpool.h"
@@ -29,6 +30,6 @@ void ChunkManager_free(ChunkManager *cm);
void ChunkManager_recenter(ChunkManager *cm, const Vec3 target);
-void ChunkManager_drawChunks(const ChunkManager *cm);
+void ChunkManager_drawChunks(const ChunkManager *cm, const Camera *camera);
#endif
diff --git a/src/camera.c b/src/camera.c
@@ -36,6 +36,12 @@ void Camera_defaultSettings(Camera* camera)
camera->far = 200.0f;
camera->speed = 0.1f;
camera->sensitivity = 0.3f;
+
+ camera->near_h = 2 * tan(camera->fovy / 2) * camera->near;
+ camera->near_w = camera->near_h * camera->aspect;
+
+ camera->far_h = 2 * tan(camera->fovy / 2) * camera->far;
+ camera->far_w = camera->far_h * camera->aspect;
}
void Camera_updateRotation(Camera* camera, float dx, float dy)
@@ -103,4 +109,176 @@ void Camera_move(Camera *camera, UserInput *input)
Camera_updatePosition(camera, input->move_dx, input->move_dy, input->move_dz);
Camera_updateVectors(camera);
Camera_updateMatrix(camera);
+ Camera_updateFrustum(camera);
+}
+
+void Camera_updateFrustum(Camera *camera)
+{
+ // Near plane
+ camera->frustum[0].n[0] = camera->front[0];
+ camera->frustum[0].n[1] = camera->front[1];
+ camera->frustum[0].n[2] = camera->front[2];
+ Vec3_scale(
+ camera->front,
+ camera->near,
+ camera->frustum[0].p
+ );
+ Vec3_add(
+ camera->position,
+ camera->frustum[0].p,
+ camera->frustum[0].p
+ );
+
+ // Far plane
+ camera->frustum[1].n[0] = -camera->front[0];
+ camera->frustum[1].n[1] = -camera->front[1];
+ camera->frustum[1].n[2] = -camera->front[2];
+ Vec3_scale(
+ camera->front,
+ camera->far,
+ camera->frustum[1].p
+ );
+ Vec3_add(
+ camera->position,
+ camera->frustum[1].p,
+ camera->frustum[1].p
+ );
+
+ // Used to store vector in plane
+ Vec3 a;
+
+ // Top plane
+ Vec3_scale(
+ camera->up,
+ camera->near_h / 2,
+ camera->frustum[2].p
+ );
+ Vec3_add(
+ camera->frustum[0].p,
+ camera->frustum[2].p,
+ camera->frustum[2].p
+ );
+
+ Vec3_sub(
+ camera->frustum[2].p,
+ camera->position,
+ a
+ );
+
+ Vec3_mul(
+ a,
+ camera->right,
+ camera->frustum[2].n
+ );
+ Vec3_normalize(
+ camera->frustum[2].n,
+ camera->frustum[2].n
+ );
+
+ // Bottom plane
+ Vec3_scale(
+ camera->up,
+ camera->near_h / 2,
+ camera->frustum[3].p
+ );
+ Vec3_sub(
+ camera->frustum[0].p,
+ camera->frustum[3].p,
+ camera->frustum[3].p
+ );
+
+ Vec3_sub(
+ camera->frustum[3].p,
+ camera->position,
+ a
+ );
+
+ Vec3_mul(
+ camera->right,
+ a,
+ camera->frustum[3].n
+ );
+ Vec3_normalize(
+ camera->frustum[3].n,
+ camera->frustum[3].n
+ );
+
+ // Left plane
+ Vec3_scale(
+ camera->right,
+ camera->near_w / 2,
+ camera->frustum[4].p
+ );
+ Vec3_sub(
+ camera->frustum[0].p,
+ camera->frustum[4].p,
+ camera->frustum[4].p
+ );
+
+ Vec3_sub(
+ camera->frustum[4].p,
+ camera->position,
+ a
+ );
+
+ Vec3_mul(
+ a,
+ camera->up,
+ camera->frustum[4].n
+ );
+ Vec3_normalize(
+ camera->frustum[4].n,
+ camera->frustum[4].n
+ );
+
+ // Right plane
+ Vec3_scale(
+ camera->right,
+ camera->near_w / 2,
+ camera->frustum[5].p
+ );
+ Vec3_add(
+ camera->frustum[0].p,
+ camera->frustum[5].p,
+ camera->frustum[5].p
+ );
+
+ Vec3_sub(
+ camera->frustum[5].p,
+ camera->position,
+ a
+ );
+
+ Vec3_mul(
+ camera->up,
+ a,
+ camera->frustum[5].n
+ );
+ Vec3_normalize(
+ camera->frustum[5].n,
+ camera->frustum[5].n
+ );
+
+}
+
+static float planeSDF(const Plane *p, const Vec3 r)
+{
+ return Vec3_dot(p->n, r) - Vec3_dot(p->n, p->p);
+}
+
+int Camera_sphereInFrustum(const Camera *camera, Vec3 p, float r)
+{
+ for (int i = 0; i < 6; i++)
+ {
+ float distance = planeSDF(&camera->frustum[i], p);
+ if (distance < -r)
+ {
+ return 0;
+ }
+ else if (distance < r)
+ {
+ return 1;
+ }
+ }
+ return 1;
}
diff --git a/src/chunk_manager.c b/src/chunk_manager.c
@@ -124,6 +124,13 @@ static void ChunkManager_worldToChunk(const Vec3 src, IVec3 dst)
dst[2] = (int)floorf(src[2] / CHUNK_WIDTH);
}
+static void ChunkManager_chunkToWorld(const IVec3 src, Vec3 dst)
+{
+ dst[0] = src[0] * CHUNK_WIDTH;
+ dst[1] = src[1] * CHUNK_WIDTH;
+ dst[2] = src[2] * CHUNK_WIDTH;
+}
+
ChunkManager ChunkManager_create(const Vec3 target, int radius, SDF f,
float isolevel)
{
@@ -178,10 +185,21 @@ void ChunkManager_recenter(ChunkManager *cm, const Vec3 target)
}
}
-void ChunkManager_drawChunks(const ChunkManager *cm)
+void ChunkManager_drawChunks(const ChunkManager *cm, const Camera *camera)
{
for (int i = 0; i < cm->chunk_count; i++)
{
- Chunk_drawMesh(&cm->chunks[i]);
+ Vec3 chunk_center;
+ ChunkManager_chunkToWorld(cm->chunks[i].origin, chunk_center);
+ chunk_center[0] += CHUNK_WIDTH / 2;
+ chunk_center[1] += CHUNK_WIDTH / 2;
+ chunk_center[2] += CHUNK_WIDTH / 2;
+
+ float chunk_radius = CHUNK_WIDTH * 0.866025f;
+
+ if (Camera_sphereInFrustum(camera, chunk_center, chunk_radius))
+ {
+ Chunk_drawMesh(&cm->chunks[i]);
+ }
}
}
diff --git a/src/main.c b/src/main.c
@@ -78,11 +78,11 @@ int main(int argc, char** argv)
ChunkManager chunk_manager = ChunkManager_create(
camera->position,
- 3,
+ 5,
terrainSDF,
0.0f
);
- ChunkManager_drawChunks(&chunk_manager);
+ ChunkManager_drawChunks(&chunk_manager, camera);
Shader *shader = Shader_make("shaders/basic.vs", "shaders/basic.fs");
Shader_use(shader);
@@ -114,7 +114,7 @@ int main(int argc, char** argv)
Shader_setVec3(shader, "pointlight_pos", camera->position);
ChunkManager_recenter(&chunk_manager, camera->position);
- ChunkManager_drawChunks(&chunk_manager);
+ ChunkManager_drawChunks(&chunk_manager, camera);
glfwSwapBuffers(app->window);
glfwPollEvents();