frustum culling added...?
This commit is contained in:
parent
561df24953
commit
f731ccf968
78
src/Camera.h
78
src/Camera.h
@ -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
71
src/Frustum.h
Normal 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
|
||||||
26
src/main.cpp
26
src/main.cpp
@ -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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user