refactor(gameplay): encapsulate per-type vertex data into VertexData struct

This commit is contained in:
2026-06-05 11:25:05 +08:00
parent 0d209d5b9c
commit aa3805448f
5 changed files with 104 additions and 91 deletions

View File

@@ -123,6 +123,7 @@ add_executable(${PROJECT_NAME}
src/gameplay/river_worm.cpp src/gameplay/river_worm.cpp
src/gameplay/river_path.cpp src/gameplay/river_path.cpp
src/block.cpp src/block.cpp
src/gameplay/vertex_data.cpp
) )
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")

View File

@@ -4,7 +4,7 @@
#include "Cubed/gameplay/block.hpp" #include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_generator.hpp" #include "Cubed/gameplay/chunk_generator.hpp"
#include "Cubed/gameplay/chunk_pos.hpp" #include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/primitive_data.hpp" #include "Cubed/gameplay/vertex_data.hpp"
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
@@ -21,9 +21,6 @@ private:
std::atomic<bool> m_dirty{false}; std::atomic<bool> m_dirty{false};
std::atomic<bool> m_need_upload{true}; std::atomic<bool> m_need_upload{true};
std::atomic<bool> m_is_on_gen_vertex_data{false}; std::atomic<bool> m_is_on_gen_vertex_data{false};
std::atomic<size_t> m_normal_vertices_sum = 0;
std::atomic<size_t> m_cross_vertices_sum = 0;
std::atomic<size_t> m_transparent_vertices_sum = 0;
std::atomic<BiomeType> m_biome = BiomeType::PLAIN; std::atomic<BiomeType> m_biome = BiomeType::PLAIN;
std::mutex m_vertexs_data_mutex; std::mutex m_vertexs_data_mutex;
@@ -34,12 +31,13 @@ private:
HeightMapArray m_heightmap; HeightMapArray m_heightmap;
// the index is a array of block id // the index is a array of block id
std::vector<BlockType> m_blocks; std::vector<BlockType> m_blocks;
GLuint m_normal_vbo = 0;
GLuint m_cross_plane_vbo = 0; /*
GLuint m_transparent_normal_vbo = 0; 0 - normal
std::vector<Vertex> m_normal_vertices; 1 - cross_plane
std::vector<Vertex> m_cross_plane_vertices; 2 - transparent
std::vector<Vertex> m_transparent_normal_vertices; */
std::vector<VertexData> m_vertex_data;
float frequency = 0.01f; float frequency = 0.01f;
float height = 80; float height = 80;
unsigned m_seed = 0; unsigned m_seed = 0;

View File

@@ -0,0 +1,24 @@
#pragma once
#include "Cubed/primitive_data.hpp"
#include <atomic>
#include <glad/glad.h>
#include <vector>
namespace Cubed {
class World;
struct VertexData {
std::vector<Vertex> m_vertices;
GLuint m_vbo = 0;
std::atomic<std::size_t> m_sum{0};
World& m_world;
VertexData(World& world);
~VertexData();
VertexData(const VertexData&) = delete;
VertexData(VertexData&&) noexcept;
VertexData& operator=(const VertexData&) = delete;
VertexData& operator=(VertexData&&) noexcept;
void upload();
void update_sum();
};
} // namespace Cubed

View File

@@ -9,65 +9,36 @@
namespace Cubed { namespace Cubed {
Chunk::Chunk(World& world, ChunkPos chunk_pos) Chunk::Chunk(World& world, ChunkPos chunk_pos)
: m_chunk_pos(chunk_pos), m_world(world) {} : m_chunk_pos(chunk_pos), m_world(world) {
for (int i = 0; i < 3; i++) {
Chunk::~Chunk() { m_vertex_data.emplace_back(m_world);
if (m_normal_vbo != 0) {
m_world.push_delete_vbo(m_normal_vbo);
}
if (m_cross_plane_vbo != 0) {
m_world.push_delete_vbo(m_cross_plane_vbo);
}
if (m_transparent_normal_vbo != 0) {
m_world.push_delete_vbo(m_transparent_normal_vbo);
} }
} }
Chunk::~Chunk() {}
Chunk::Chunk(Chunk&& other) noexcept Chunk::Chunk(Chunk&& other) noexcept
: m_dirty(other.is_dirty()), m_need_upload(other.m_need_upload.load()), : m_dirty(other.is_dirty()), m_need_upload(other.m_need_upload.load()),
m_is_on_gen_vertex_data(other.m_is_on_gen_vertex_data.load()), m_is_on_gen_vertex_data(other.m_is_on_gen_vertex_data.load()),
m_normal_vertices_sum(other.m_normal_vertices_sum.load()),
m_cross_vertices_sum(other.m_cross_vertices_sum.load()),
m_transparent_vertices_sum(other.m_transparent_vertices_sum.load()),
m_biome(other.m_biome.load()), m_chunk_pos(std::move(other.m_chunk_pos)), m_biome(other.m_biome.load()), m_chunk_pos(std::move(other.m_chunk_pos)),
m_world(other.m_world), m_heightmap(std::move(other.m_heightmap)), m_world(other.m_world), m_heightmap(std::move(other.m_heightmap)),
m_blocks(std::move(other.m_blocks)), m_normal_vbo(other.m_normal_vbo), m_blocks(std::move(other.m_blocks)),
m_cross_plane_vbo(other.m_cross_plane_vbo), m_vertex_data(std::move(other.m_vertex_data)), m_seed(other.m_seed),
m_transparent_normal_vbo(other.m_transparent_normal_vbo), m_conditions(other.m_conditions) {}
m_normal_vertices(std::move(other.m_normal_vertices)),
m_cross_plane_vertices(std::move(other.m_cross_plane_vertices)),
m_transparent_normal_vertices(
std::move(other.m_transparent_normal_vertices)),
m_seed(other.m_seed), m_conditions(other.m_conditions) {
other.m_normal_vbo = 0;
other.m_cross_plane_vbo = 0;
other.m_transparent_normal_vbo = 0;
}
Chunk& Chunk::operator=(Chunk&& other) noexcept { Chunk& Chunk::operator=(Chunk&& other) noexcept {
// Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&& // Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&&
// other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z, // other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z,
// static_cast<const void*>(&other)); // static_cast<const void*>(&other));
m_normal_vbo = other.m_normal_vbo;
other.m_normal_vbo = 0;
m_cross_plane_vbo = other.m_cross_plane_vbo;
m_transparent_normal_vbo = other.m_transparent_normal_vbo;
other.m_transparent_normal_vbo = 0;
other.m_cross_plane_vbo = 0;
m_chunk_pos = std::move(other.m_chunk_pos); m_chunk_pos = std::move(other.m_chunk_pos);
m_heightmap = std::move(other.m_heightmap); m_heightmap = std::move(other.m_heightmap);
m_blocks = std::move(other.m_blocks); m_blocks = std::move(other.m_blocks);
m_dirty = other.is_dirty(); m_dirty = other.is_dirty();
m_normal_vertices = std::move(other.m_normal_vertices); m_vertex_data = std::move(other.m_vertex_data);
m_cross_plane_vertices = std::move(other.m_cross_plane_vertices);
m_transparent_normal_vertices =
std::move(other.m_transparent_normal_vertices);
m_biome = other.m_biome.load(); m_biome = other.m_biome.load();
m_is_on_gen_vertex_data = other.m_is_on_gen_vertex_data.load(); m_is_on_gen_vertex_data = other.m_is_on_gen_vertex_data.load();
m_need_upload = other.m_need_upload.load(); m_need_upload = other.m_need_upload.load();
m_normal_vertices_sum = other.m_normal_vertices_sum.load();
m_cross_vertices_sum = other.m_cross_vertices_sum.load();
m_transparent_vertices_sum = other.m_transparent_vertices_sum.load();
m_seed = other.m_seed; m_seed = other.m_seed;
m_conditions = other.m_conditions; m_conditions = other.m_conditions;
return *this; return *this;
@@ -139,29 +110,37 @@ void Chunk::gen_vertex_data(
} }
m_is_on_gen_vertex_data = true; m_is_on_gen_vertex_data = true;
std::lock_guard lk(m_vertexs_data_mutex); std::lock_guard lk(m_vertexs_data_mutex);
for (auto& data : m_vertex_data) {
data.m_vertices.clear();
}
gen_normal_vertices(neighbor_block); gen_normal_vertices(neighbor_block);
gen_cross_plane_vertices(); gen_cross_plane_vertices();
for (auto& data : m_vertex_data) {
data.update_sum();
}
m_need_upload = true; m_need_upload = true;
m_is_on_gen_vertex_data = false; m_is_on_gen_vertex_data = false;
} }
GLuint Chunk::get_normal_vbo() const { return m_normal_vbo; } GLuint Chunk::get_normal_vbo() const { return m_vertex_data[0].m_vbo; }
size_t Chunk::get_normal_vertices_sum() const { size_t Chunk::get_normal_vertices_sum() const {
if (m_normal_vertices_sum == 0) { if (m_vertex_data[0].m_sum == 0) {
Logger::warn("m_normal_vertices_sum is 0"); Logger::warn("m_normal_vertices_sum is 0");
} }
return m_normal_vertices_sum.load(); return m_vertex_data[0].m_sum.load();
} }
GLuint Chunk::get_cross_vbo() const { return m_cross_plane_vbo; } GLuint Chunk::get_cross_vbo() const { return m_vertex_data[1].m_vbo; }
size_t Chunk::get_cross_vertices_sum() const { size_t Chunk::get_cross_vertices_sum() const {
return m_cross_vertices_sum.load(); return m_vertex_data[1].m_sum.load();
} }
GLuint Chunk::get_transparent_vbo() const { return m_transparent_normal_vbo; } GLuint Chunk::get_transparent_vbo() const { return m_vertex_data[2].m_vbo; }
size_t Chunk::get_transparent_vertices_sum() const { size_t Chunk::get_transparent_vertices_sum() const {
return m_transparent_vertices_sum.load(); return m_vertex_data[2].m_sum.load();
} }
void Chunk::gen_phase_one() { void Chunk::gen_phase_one() {
@@ -235,33 +214,12 @@ void Chunk::upload_to_gpu() {
ASSERT(is_need_upload()); ASSERT(is_need_upload());
if (m_normal_vbo == 0) { std::lock_guard lk(m_vertexs_data_mutex);
glGenBuffers(1, &m_normal_vbo);
for (auto& data : m_vertex_data) {
data.upload();
} }
std::lock_guard lk(m_vertexs_data_mutex);
glBindBuffer(GL_ARRAY_BUFFER, m_normal_vbo);
glBufferData(GL_ARRAY_BUFFER, m_normal_vertices.size() * sizeof(Vertex),
m_normal_vertices.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (m_cross_plane_vertices.size() != 0) {
if (m_cross_plane_vbo == 0) {
glGenBuffers(1, &m_cross_plane_vbo);
}
glBindBuffer(GL_ARRAY_BUFFER, m_cross_plane_vbo);
glBufferData(GL_ARRAY_BUFFER,
m_cross_plane_vertices.size() * sizeof(Vertex),
m_cross_plane_vertices.data(), GL_DYNAMIC_DRAW);
}
if (m_transparent_normal_vertices.size() != 0) {
if (m_transparent_normal_vbo == 0) {
glGenBuffers(1, &m_transparent_normal_vbo);
}
glBindBuffer(GL_ARRAY_BUFFER, m_transparent_normal_vbo);
glBufferData(GL_ARRAY_BUFFER,
m_transparent_normal_vertices.size() * sizeof(Vertex),
m_transparent_normal_vertices.data(), GL_DYNAMIC_DRAW);
}
// after fininshed it, can use // after fininshed it, can use
clear_dirty(); clear_dirty();
m_need_upload = false; m_need_upload = false;
@@ -302,8 +260,6 @@ BiomeConditions& Chunk::conditions() { return m_conditions; }
void Chunk::gen_normal_vertices( void Chunk::gen_normal_vertices(
const std::array<const std::vector<BlockType>*, 4>& neighbor_block) { const std::array<const std::vector<BlockType>*, 4>& neighbor_block) {
m_normal_vertices.clear();
m_transparent_normal_vertices.clear();
static const glm::ivec3 DIR[6] = {{0, 0, 1}, {1, 0, 0}, {0, 0, -1}, static const glm::ivec3 DIR[6] = {{0, 0, 1}, {1, 0, 0}, {0, 0, -1},
{-1, 0, 0}, {0, 1, 0}, {0, -1, 0}}; {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}};
@@ -410,22 +366,18 @@ void Chunk::gen_normal_vertices(
}; };
if (BlockManager::is_transparent(cur_id)) { if (BlockManager::is_transparent(cur_id)) {
m_transparent_normal_vertices.emplace_back(vex); m_vertex_data[2].m_vertices.emplace_back(vex);
} else { } else {
m_normal_vertices.emplace_back(vex); m_vertex_data[0].m_vertices.emplace_back(vex);
} }
} }
} }
} }
} }
} }
m_normal_vertices_sum = m_normal_vertices.size();
m_transparent_vertices_sum = m_transparent_normal_vertices.size();
} }
void Chunk::gen_cross_plane_vertices() { void Chunk::gen_cross_plane_vertices() {
m_cross_plane_vertices.clear();
for (int x = 0; x < SIZE_X; x++) { for (int x = 0; x < SIZE_X; x++) {
for (int y = 0; y < SIZE_Y; y++) { for (int y = 0; y < SIZE_Y; y++) {
for (int z = 0; z < SIZE_Z; z++) { for (int z = 0; z < SIZE_Z; z++) {
@@ -451,13 +403,12 @@ void Chunk::gen_cross_plane_vertices() {
BlockManager::cross_plane_index(id)) BlockManager::cross_plane_index(id))
}; };
m_cross_plane_vertices.emplace_back(vex); m_vertex_data[1].m_vertices.emplace_back(vex);
} }
} }
} }
} }
} }
m_cross_vertices_sum = m_cross_plane_vertices.size();
// Logger::info("Cross Sum {}", m_cross_vertices_sum.load()); // Logger::info("Cross Sum {}", m_cross_vertices_sum.load());
} }

View File

@@ -0,0 +1,39 @@
#include "Cubed/gameplay/vertex_data.hpp"
#include "Cubed/gameplay/world.hpp"
namespace Cubed {
VertexData::VertexData(World& world) : m_world(world) {}
VertexData::~VertexData() {
if (m_vbo != 0) {
m_world.push_delete_vbo(m_vbo);
}
}
VertexData::VertexData(VertexData&& o) noexcept
: m_vertices(std::move(o.m_vertices)), m_vbo(o.m_vbo),
m_sum(o.m_sum.load()), m_world(o.m_world) {
o.m_vbo = 0;
o.m_sum = 0;
}
VertexData& VertexData::operator=(VertexData&& o) noexcept {
m_vbo = o.m_vbo;
o.m_vbo = 0;
m_sum = o.m_sum.load();
o.m_sum = 0;
m_vertices = std::move(o.m_vertices);
return *this;
}
void VertexData::upload() {
if (m_vertices.size() == 0) {
return;
}
if (m_vbo == 0) {
glGenBuffers(1, &m_vbo);
}
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex),
m_vertices.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void VertexData::update_sum() { m_sum = m_vertices.size(); }
} // namespace Cubed