frustum culling added...?

This commit is contained in:
JISAUAY 2025-11-24 14:29:42 -06:00
parent 561df24953
commit f731ccf968
3 changed files with 172 additions and 3 deletions

View File

@ -1,10 +1,14 @@
#ifndef CAMERA_H #ifndef CAMERA_H
#define CAMERA_H #define CAMERA_H
#include <math.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include "Player.h" #include "Player.h"
#include "Frustum.h"
class Camera class Camera
{ {
@ -41,9 +45,77 @@ class Camera
glm::vec3 getEyePosition() const { glm::vec3 getEyePosition() const {
return player->getEyePosition(); return player->getEyePosition();
} }
// Build frustum from view-projection matrix (more reliable method)
Frustum createFrustumFromMatrix(const glm::mat4& viewProj) {
Frustum frustum;
// Extract planes from view-projection matrix
// Left plane
frustum.leftFace.normal.x = viewProj[0][3] + viewProj[0][0];
frustum.leftFace.normal.y = viewProj[1][3] + viewProj[1][0];
frustum.leftFace.normal.z = viewProj[2][3] + viewProj[2][0];
frustum.leftFace.distance = viewProj[3][3] + viewProj[3][0];
// Right plane
frustum.rightFace.normal.x = viewProj[0][3] - viewProj[0][0];
frustum.rightFace.normal.y = viewProj[1][3] - viewProj[1][0];
frustum.rightFace.normal.z = viewProj[2][3] - viewProj[2][0];
frustum.rightFace.distance = viewProj[3][3] - viewProj[3][0];
// Bottom plane
frustum.bottomFace.normal.x = viewProj[0][3] + viewProj[0][1];
frustum.bottomFace.normal.y = viewProj[1][3] + viewProj[1][1];
frustum.bottomFace.normal.z = viewProj[2][3] + viewProj[2][1];
frustum.bottomFace.distance = viewProj[3][3] + viewProj[3][1];
// Top plane
frustum.topFace.normal.x = viewProj[0][3] - viewProj[0][1];
frustum.topFace.normal.y = viewProj[1][3] - viewProj[1][1];
frustum.topFace.normal.z = viewProj[2][3] - viewProj[2][1];
frustum.topFace.distance = viewProj[3][3] - viewProj[3][1];
// Near plane
frustum.nearFace.normal.x = viewProj[0][3] + viewProj[0][2];
frustum.nearFace.normal.y = viewProj[1][3] + viewProj[1][2];
frustum.nearFace.normal.z = viewProj[2][3] + viewProj[2][2];
frustum.nearFace.distance = viewProj[3][3] + viewProj[3][2];
// Far plane
frustum.farFace.normal.x = viewProj[0][3] - viewProj[0][2];
frustum.farFace.normal.y = viewProj[1][3] - viewProj[1][2];
frustum.farFace.normal.z = viewProj[2][3] - viewProj[2][2];
frustum.farFace.distance = viewProj[3][3] - viewProj[3][2];
// Normalize all planes
float length;
length = glm::length(frustum.leftFace.normal);
frustum.leftFace.normal /= length;
frustum.leftFace.distance /= length;
length = glm::length(frustum.rightFace.normal);
frustum.rightFace.normal /= length;
frustum.rightFace.distance /= length;
length = glm::length(frustum.bottomFace.normal);
frustum.bottomFace.normal /= length;
frustum.bottomFace.distance /= length;
length = glm::length(frustum.topFace.normal);
frustum.topFace.normal /= length;
frustum.topFace.distance /= length;
length = glm::length(frustum.nearFace.normal);
frustum.nearFace.normal /= length;
frustum.nearFace.distance /= length;
length = glm::length(frustum.farFace.normal);
frustum.farFace.normal /= length;
frustum.farFace.distance /= length;
return frustum;
}
}; };
#endif #endif

71
src/Frustum.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef FRUSTUM_H
#define FRUSTUM_H
#include <glm/glm.hpp>
struct Plane {
glm::vec3 normal = { 0.0f, 1.0f, 0.0f };
float distance = 0.0f;
// Distance from point to plane (positive = in front, negative = behind)
float distanceToPoint(const glm::vec3& point) const {
return glm::dot(normal, point) + distance;
}
};
struct AABB {
glm::vec3 min;
glm::vec3 max;
// Get center point
glm::vec3 getCenter() const {
return (min + max) * 0.5f;
}
// Get positive extents (half-size)
glm::vec3 getExtents() const {
return (max - min) * 0.5f;
}
};
struct Frustum {
Plane topFace;
Plane bottomFace;
Plane rightFace;
Plane leftFace;
Plane farFace;
Plane nearFace;
// Test if AABB is in frustum (returns true if visible)
bool isAABBVisible(const AABB& aabb) const {
// For each plane, check if the AABB is completely behind it
// If it's behind any plane, it's outside the frustum
return isOnOrForwardPlane(topFace, aabb) &&
isOnOrForwardPlane(bottomFace, aabb) &&
isOnOrForwardPlane(rightFace, aabb) &&
isOnOrForwardPlane(leftFace, aabb) &&
isOnOrForwardPlane(farFace, aabb) &&
isOnOrForwardPlane(nearFace, aabb);
}
private:
// Check if AABB is on or in front of plane
bool isOnOrForwardPlane(const Plane& plane, const AABB& aabb) const {
// Get the positive vertex (furthest point in direction of normal)
const glm::vec3 center = aabb.getCenter();
const glm::vec3 extents = aabb.getExtents();
// Project extents onto plane normal to get the effective radius
const float radius = extents.x * std::abs(plane.normal.x) +
extents.y * std::abs(plane.normal.y) +
extents.z * std::abs(plane.normal.z);
// Distance from center to plane
const float dist = plane.distanceToPoint(center);
// AABB is visible if center is within radius distance from plane
return dist >= -radius;
}
};
#endif

View File

@ -430,6 +430,10 @@ int main() {
std::floor(player.position.z / CHUNK_SIZE) std::floor(player.position.z / CHUNK_SIZE)
); );
// Create frustum for culling from view-projection matrix
glm::mat4 viewProj = projection * view;
Frustum frustum = camera.createFrustumFromMatrix(viewProj);
// ---- PASS 1: Draw solid grey cubes ---- // ---- PASS 1: Draw solid grey cubes ----
glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0); // Push solid faces "back" glPolygonOffset(1.0, 1.0); // Push solid faces "back"
@ -442,6 +446,17 @@ int main() {
glm::ivec3 chunk_offset = glm::ivec3(x, y, z); glm::ivec3 chunk_offset = glm::ivec3(x, y, z);
glm::ivec3 chunk_pos = camera_chunk + chunk_offset; glm::ivec3 chunk_pos = camera_chunk + chunk_offset;
// Create AABB for this chunk
glm::vec3 chunkWorldPos = glm::vec3(chunk_pos * CHUNK_SIZE);
AABB chunkAABB;
chunkAABB.min = chunkWorldPos;
chunkAABB.max = chunkWorldPos + glm::vec3(CHUNK_SIZE);
// Frustum culling - skip if chunk is not visible
if (!frustum.isAABBVisible(chunkAABB)) {
continue;
}
glm::mat4 model = glm::mat4(1.0f); glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(chunk_pos * CHUNK_SIZE)); model = glm::translate(model, glm::vec3(chunk_pos * CHUNK_SIZE));
glm::mat4 mvp = projection * view * model; glm::mat4 mvp = projection * view * model;
@ -472,6 +487,17 @@ int main() {
glm::ivec3 chunk_offset = glm::ivec3(x, y, z); glm::ivec3 chunk_offset = glm::ivec3(x, y, z);
glm::ivec3 chunk_pos = camera_chunk + chunk_offset; glm::ivec3 chunk_pos = camera_chunk + chunk_offset;
// Create AABB for this chunk
glm::vec3 chunkWorldPos = glm::vec3(chunk_pos * CHUNK_SIZE);
AABB chunkAABB;
chunkAABB.min = chunkWorldPos;
chunkAABB.max = chunkWorldPos + glm::vec3(CHUNK_SIZE);
// Frustum culling - skip if chunk is not visible
if (!frustum.isAABBVisible(chunkAABB)) {
continue;
}
glm::mat4 model = glm::mat4(1.0f); glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(chunk_pos * CHUNK_SIZE)); model = glm::translate(model, glm::vec3(chunk_pos * CHUNK_SIZE));
glm::mat4 mvp = projection * view * model; glm::mat4 mvp = projection * view * model;