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_path.cpp
src/block.cpp
src/gameplay/vertex_data.cpp
)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")

View File

@@ -4,7 +4,7 @@
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_generator.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/primitive_data.hpp"
#include "Cubed/gameplay/vertex_data.hpp"
#include <atomic>
#include <mutex>
@@ -21,9 +21,6 @@ private:
std::atomic<bool> m_dirty{false};
std::atomic<bool> m_need_upload{true};
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::mutex m_vertexs_data_mutex;
@@ -34,12 +31,13 @@ private:
HeightMapArray m_heightmap;
// the index is a array of block id
std::vector<BlockType> m_blocks;
GLuint m_normal_vbo = 0;
GLuint m_cross_plane_vbo = 0;
GLuint m_transparent_normal_vbo = 0;
std::vector<Vertex> m_normal_vertices;
std::vector<Vertex> m_cross_plane_vertices;
std::vector<Vertex> m_transparent_normal_vertices;
/*
0 - normal
1 - cross_plane
2 - transparent
*/
std::vector<VertexData> m_vertex_data;
float frequency = 0.01f;
float height = 80;
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 {
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++) {
m_vertex_data.emplace_back(m_world);
}
}
Chunk::~Chunk() {
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
: 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_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_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_cross_plane_vbo(other.m_cross_plane_vbo),
m_transparent_normal_vbo(other.m_transparent_normal_vbo),
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;
}
m_blocks(std::move(other.m_blocks)),
m_vertex_data(std::move(other.m_vertex_data)), m_seed(other.m_seed),
m_conditions(other.m_conditions) {}
Chunk& Chunk::operator=(Chunk&& other) noexcept {
// Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&&
// other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z,
// 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_heightmap = std::move(other.m_heightmap);
m_blocks = std::move(other.m_blocks);
m_dirty = other.is_dirty();
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_vertex_data = std::move(other.m_vertex_data);
m_biome = other.m_biome.load();
m_is_on_gen_vertex_data = other.m_is_on_gen_vertex_data.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_conditions = other.m_conditions;
return *this;
@@ -139,29 +110,37 @@ void Chunk::gen_vertex_data(
}
m_is_on_gen_vertex_data = true;
std::lock_guard lk(m_vertexs_data_mutex);
for (auto& data : m_vertex_data) {
data.m_vertices.clear();
}
gen_normal_vertices(neighbor_block);
gen_cross_plane_vertices();
for (auto& data : m_vertex_data) {
data.update_sum();
}
m_need_upload = true;
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 {
if (m_normal_vertices_sum == 0) {
if (m_vertex_data[0].m_sum == 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 {
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 {
return m_transparent_vertices_sum.load();
return m_vertex_data[2].m_sum.load();
}
void Chunk::gen_phase_one() {
@@ -235,33 +214,12 @@ void Chunk::upload_to_gpu() {
ASSERT(is_need_upload());
if (m_normal_vbo == 0) {
glGenBuffers(1, &m_normal_vbo);
std::lock_guard lk(m_vertexs_data_mutex);
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
clear_dirty();
m_need_upload = false;
@@ -302,8 +260,6 @@ BiomeConditions& Chunk::conditions() { return m_conditions; }
void Chunk::gen_normal_vertices(
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},
{-1, 0, 0}, {0, 1, 0}, {0, -1, 0}};
@@ -410,22 +366,18 @@ void Chunk::gen_normal_vertices(
};
if (BlockManager::is_transparent(cur_id)) {
m_transparent_normal_vertices.emplace_back(vex);
m_vertex_data[2].m_vertices.emplace_back(vex);
} 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() {
m_cross_plane_vertices.clear();
for (int x = 0; x < SIZE_X; x++) {
for (int y = 0; y < SIZE_Y; y++) {
for (int z = 0; z < SIZE_Z; z++) {
@@ -451,13 +403,12 @@ void Chunk::gen_cross_plane_vertices() {
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());
}

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