mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-04-10 06:14:07 +08:00
feat: add frustum culling
This commit is contained in:
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
src/input.cpp
|
src/input.cpp
|
||||||
src/map_table.cpp
|
src/map_table.cpp
|
||||||
src/texture_manager.cpp
|
src/texture_manager.cpp
|
||||||
|
src/tools/math_tools.cpp
|
||||||
src/tools/shader_tools.cpp
|
src/tools/shader_tools.cpp
|
||||||
src/tools/log.cpp
|
src/tools/log.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ private:
|
|||||||
BlockRenderData m_block_render_data;
|
BlockRenderData m_block_render_data;
|
||||||
std::unordered_map<ChunkPos , Chunk, ChunkPos::Hash> m_chunks;
|
std::unordered_map<ChunkPos , Chunk, ChunkPos::Hash> m_chunks;
|
||||||
std::unordered_map<std::size_t, Player> m_players;
|
std::unordered_map<std::size_t, Player> m_players;
|
||||||
|
std::vector<glm::vec4> m_planes;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
World();
|
World();
|
||||||
@@ -20,8 +21,10 @@ public:
|
|||||||
const std::optional<LookBlock>& get_look_block_pos(const std::string& name) const;
|
const std::optional<LookBlock>& get_look_block_pos(const std::string& name) const;
|
||||||
Player& get_player(const std::string& name);
|
Player& get_player(const std::string& name);
|
||||||
void init_world();
|
void init_world();
|
||||||
|
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents);
|
||||||
bool is_block(const glm::ivec3& block_pos) const;
|
bool is_block(const glm::ivec3& block_pos) const;
|
||||||
void render();
|
|
||||||
|
void render(const glm::mat4& mvp_matrix);
|
||||||
void set_block(const glm::ivec3& pos, unsigned id);
|
void set_block(const glm::ivec3& pos, unsigned id);
|
||||||
void update(float delta_time);
|
void update(float delta_time);
|
||||||
|
|
||||||
|
|||||||
5
include/Cubed/tools/math_tools.hpp
Normal file
5
include/Cubed/tools/math_tools.hpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
namespace Math {
|
||||||
|
void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector<glm::vec4>& planes);
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <Cubed/map_table.hpp>
|
#include <Cubed/map_table.hpp>
|
||||||
#include <Cubed/tools/cubed_assert.hpp>
|
#include <Cubed/tools/cubed_assert.hpp>
|
||||||
#include <Cubed/tools/cubed_hash.hpp>
|
#include <Cubed/tools/cubed_hash.hpp>
|
||||||
|
#include <Cubed/tools/math_tools.hpp>
|
||||||
World::World() {
|
World::World() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -123,26 +124,43 @@ void World::init_world() {
|
|||||||
m_players.emplace(HASH::str("TestPlayer"), Player(*this, "TestPlayer"));
|
m_players.emplace(HASH::str("TestPlayer"), Player(*this, "TestPlayer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::render() {
|
void World::render(const glm::mat4& mvp_matrix) {
|
||||||
|
Math::extract_frustum_planes(mvp_matrix, m_planes);
|
||||||
for (const auto& chunk_map : m_chunks) {
|
for (const auto& chunk_map : m_chunks) {
|
||||||
const auto& [pos, chunk] = chunk_map;
|
const auto& [pos, chunk] = chunk_map;
|
||||||
|
glm::vec3 center = glm::vec3(static_cast<float>(pos.x * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(pos.z * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2));
|
||||||
|
if (is_aabb_in_frustum(center, glm::vec3(static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2)))) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, chunk.get_vbo());
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, s));
|
||||||
|
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, layer));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, chunk.get_vertex_data().size() * 3);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, chunk.get_vbo());
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, s));
|
|
||||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, layer));
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glEnableVertexAttribArray(2);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, chunk.get_vertex_data().size() * 3);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
bool World::is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents) {
|
||||||
|
for (const auto& plane : m_planes) {
|
||||||
|
// distance
|
||||||
|
float d = glm::dot(glm::vec3(plane), center) + plane.w;
|
||||||
|
float r = half_extents.x * std::abs(plane.x) +
|
||||||
|
half_extents.y * std::abs(plane.y) +
|
||||||
|
half_extents.z * std::abs(plane.z);
|
||||||
|
if (d + r < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool World::is_block(const glm::ivec3& block_pos) const{
|
bool World::is_block(const glm::ivec3& block_pos) const{
|
||||||
int chunk_x, chunk_z;
|
int chunk_x, chunk_z;
|
||||||
int world_x, world_y, world_z;
|
int world_x, world_y, world_z;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ GLuint vao[NUM_VAO];
|
|||||||
GLuint mv_loc, proj_loc;
|
GLuint mv_loc, proj_loc;
|
||||||
int width ,height;
|
int width ,height;
|
||||||
float aspect;
|
float aspect;
|
||||||
glm::mat4 p_mat, v_mat, m_mat, mv_mat;
|
glm::mat4 p_mat, v_mat, m_mat, mv_mat, mvp_mat;
|
||||||
float inc = 0.01f;
|
float inc = 0.01f;
|
||||||
float tf = 0.0f;
|
float tf = 0.0f;
|
||||||
double last_time = glfwGetTime();
|
double last_time = glfwGetTime();
|
||||||
@@ -183,8 +183,8 @@ void display(GLFWwindow* window, double current_time) {
|
|||||||
mv_mat = v_mat * m_mat;
|
mv_mat = v_mat * m_mat;
|
||||||
glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat));
|
glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat));
|
||||||
glUniformMatrix4fv(proj_loc, 1 ,GL_FALSE, glm::value_ptr(p_mat));
|
glUniformMatrix4fv(proj_loc, 1 ,GL_FALSE, glm::value_ptr(p_mat));
|
||||||
|
mvp_mat = p_mat * mv_mat;
|
||||||
world.render();
|
world.render(mvp_mat);
|
||||||
|
|
||||||
render_outline();
|
render_outline();
|
||||||
|
|
||||||
|
|||||||
29
src/tools/math_tools.cpp
Normal file
29
src/tools/math_tools.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <Cubed/tools/math_tools.hpp>
|
||||||
|
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
namespace Math {
|
||||||
|
void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector<glm::vec4>& planes) {
|
||||||
|
if (planes.size() != 6) {
|
||||||
|
planes.resize(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float* m = glm::value_ptr(mvp_matrix);
|
||||||
|
|
||||||
|
// left plane
|
||||||
|
planes[0] = glm::vec4(m[3] + m[0], m[7] + m[4], m[11] + m[8], m[15] + m[12]);
|
||||||
|
// right plane
|
||||||
|
planes[1] = glm::vec4(m[3] - m[0], m[7] - m[4], m[11] - m[8], m[15] - m[12]);
|
||||||
|
// bottom plane
|
||||||
|
planes[2] = glm::vec4(m[3] + m[1], m[7] + m[5], m[11] + m[9], m[15] + m[13]);
|
||||||
|
// top plane
|
||||||
|
planes[3] = glm::vec4(m[3] - m[1], m[7] - m[5], m[11] - m[9], m[15] - m[13]);
|
||||||
|
// near plane
|
||||||
|
planes[4] = glm::vec4(m[3] + m[2], m[7] + m[6], m[11] + m[10], m[15] + m[14]);
|
||||||
|
// far plane
|
||||||
|
planes[5] = glm::vec4(m[3] - m[2], m[7] - m[6], m[11] - m[10], m[15] - m[14]);
|
||||||
|
|
||||||
|
for (auto& p : planes) {
|
||||||
|
p = glm::normalize(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user