From 4a8bf7d05b9543c55809004da394155506705ede Mon Sep 17 00:00:00 2001 From: Xnoe Date: Sun, 7 Aug 2022 15:04:42 +0100 Subject: [PATCH] Make chunks check adjacent chunks when generating mesh --- Makefile | 4 +- src/chunk.cpp | 187 ++++++++++++++++++++++++++++---------------------- src/main.cpp | 2 +- src/world.cpp | 36 +++++++--- src/world.h | 4 +- 5 files changed, 136 insertions(+), 97 deletions(-) diff --git a/Makefile b/Makefile index 9f0aba0..8fcf1af 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ CXX = g++ -CXXFLAGS = -g -Isrc +CXXFLAGS = -O3 -Isrc LD = ld LINKFLAGS = -lGL -lglfw CC = gcc -CCFLAGS = -g -Isrc +CCFLAGS = -O3 -Isrc XNOECRAFT_CPP_SRCS = $(shell find src/ -name '*.cpp') XNOECRAFT_C_SRCS = $(shell find src/ -name '*.c') diff --git a/src/chunk.cpp b/src/chunk.cpp index c572be6..580a119 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -31,12 +31,37 @@ void Chunk::set_block(int x, int y, int z, int block) { } int Chunk::get_block(int x, int y, int z) { - if (x < 0 || x >= Chunk::horiz_size) - return 0; - if (z < 0 || z >= Chunk::horiz_size) - return 0; if (y < 0 || y >= Chunk::vert_size) return 0; + + if (x < 0) { + Chunk* c; + if (c = World::get_chunk(this->x-1, this->z)) + return c->get_block(Chunk::horiz_size-1, y, z); + else + return 0; + } else if (x >= Chunk::horiz_size) { + Chunk* c; + if (c = World::get_chunk(this->x+1, this->z)) + return c->get_block(0, y, z); + else + return 0; + } + + if (z < 0) { + Chunk* c; + if (c = World::get_chunk(this->x, this->z-1)) + return c->get_block(x, y, Chunk::horiz_size-1); + else + return 0; + } else if (z >= Chunk::horiz_size) { + Chunk* c; + if (c = World::get_chunk(this->x, this->z+1)) + return c->get_block(x, y, 0); + else + return 0; + } + return this->blocks[y * Chunk::horiz_size * Chunk::horiz_size + z * Chunk::horiz_size + x]; } @@ -77,100 +102,98 @@ Chunk::~Chunk() { void Chunk::generate() { std::chrono::high_resolution_clock clock; - if (mesh_version < current_version) { - auto t1 = clock.now(); - mesh_version++; + auto t1 = clock.now(); + mesh_version++; - std::vector vertex_positions; - std::vector vertex_normals; - std::vector vertex_tex_coords; - std::vector vertex_indexes; + std::vector vertex_positions; + std::vector vertex_normals; + std::vector vertex_tex_coords; + std::vector vertex_indexes; - int index=0; + int index=0; - for (int x=0; xVAO); - glBindVertexArray(this->VAO); - glGenBuffers(4, this->VBOs); - - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[0]); - glBufferData(GL_ARRAY_BUFFER, vertex_positions.size() * sizeof(glm::vec3), &vertex_positions[0].x, GL_STATIC_DRAW); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); - - glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[1]); - glBufferData(GL_ARRAY_BUFFER, vertex_normals.size() * sizeof(glm::vec3), &vertex_normals[0].x, GL_STATIC_DRAW); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, (void*)0); - - glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[2]); - glBufferData(GL_ARRAY_BUFFER, vertex_tex_coords.size() * sizeof(glm::vec2), &vertex_tex_coords[0].x, GL_STATIC_DRAW); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); - - glEnableVertexAttribArray(3); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->VBOs[3]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertex_indexes.size() * sizeof(int), &vertex_indexes[0], GL_STATIC_DRAW); - glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, 0, (void*)0); - - this->vertex_count = vertex_indexes.size(); - - auto t2 = clock.now(); - - std::chrono::duration d = (t2 - t1); - - std::cerr << "Generated chunk in " << d.count() << " seconds.\n"; } + + glGenVertexArrays(1, &this->VAO); + glBindVertexArray(this->VAO); + glGenBuffers(4, this->VBOs); + + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[0]); + glBufferData(GL_ARRAY_BUFFER, vertex_positions.size() * sizeof(glm::vec3), &vertex_positions[0].x, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[1]); + glBufferData(GL_ARRAY_BUFFER, vertex_normals.size() * sizeof(glm::vec3), &vertex_normals[0].x, GL_STATIC_DRAW); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, (void*)0); + + glEnableVertexAttribArray(2); + glBindBuffer(GL_ARRAY_BUFFER, this->VBOs[2]); + glBufferData(GL_ARRAY_BUFFER, vertex_tex_coords.size() * sizeof(glm::vec2), &vertex_tex_coords[0].x, GL_STATIC_DRAW); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glEnableVertexAttribArray(3); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->VBOs[3]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertex_indexes.size() * sizeof(int), &vertex_indexes[0], GL_STATIC_DRAW); + glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, 0, (void*)0); + + this->vertex_count = vertex_indexes.size(); + + auto t2 = clock.now(); + + std::chrono::duration d = (t2 - t1); + + std::cerr << "Generated chunk in " << d.count() << " seconds.\n"; } bool Chunk::outdated() { diff --git a/src/main.cpp b/src/main.cpp index 49bc0a9..78678f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ extern const char _binary_res_vertex_shader_dat_start[]; extern const char _binary_res_vertex_shader_dat_end[]; extern const char _binary_res_fragment_shader_dat_start[]; -extern const char _binary_res_fragment_shader_dat_end[]; +extern const char _binary_res_fragment_shader_dat_end[]; extern const unsigned char _binary_res_textures_dat_start[]; diff --git a/src/world.cpp b/src/world.cpp index 12574f2..973612b 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -6,10 +6,11 @@ FastNoise World::noise; World::World() { World::noise = FastNoise(); World::noise.SetNoiseType(FastNoise::Perlin); + World::world = this; } void World::generate_around(int x, int z) { - int world_size_half = this->world_size / 2; + int world_size_half = this->world_size; this->world_center = glm::vec2(x, z); @@ -23,8 +24,6 @@ void World::generate_around(int x, int z) { for (Chunk* c : this->chunks) c->generate(); - - World::world = this; } void World::process(int x, int z) { @@ -34,12 +33,13 @@ void World::process(int x, int z) { return; std::vector new_chunks; + std::vector to_generate; // Player has moved from the world center. // Determine world bounds. - int world_size_half = this->world_size / 2; + int world_size_half = this->world_size; int x_low = x - world_size_half; int x_high = x + world_size_half; @@ -68,21 +68,37 @@ void World::process(int x, int z) { Chunk* c = new Chunk(x + rel_x, z + rel_z); new_chunks.push_back(c); + to_generate.push_back(c); this->location_map[std::tuple(x + rel_x, z + rel_z)] = c; // Remove and delete it. this->location_map.erase(std::tuple(chunk->x, chunk->z)); delete chunk; } else { - // If it's in bounds, keep it. + // If it's in bounds, keep it new_chunks.push_back(chunk); + + // Determine if its mesh needs regeneration + if (x < this->world_center[0]) { + if (chunk->x == x_low+2 || chunk->x == x_high) + to_generate.push_back(chunk); + } else if (x > this->world_center[0]) { + if (chunk->x == x_low || chunk->x == x_high-2) + to_generate.push_back(chunk); + } + if (z < this->world_center[1]) { + if (chunk->z == z_low+2 || chunk->z == z_high) + to_generate.push_back(chunk); + } else if (z > this->world_center[1]) { + if (chunk->z == z_low || chunk->z == z_high-2) + to_generate.push_back(chunk); + } } } // Go through all the chunks and regenerate them if they are outdated - for (Chunk* chunk : new_chunks) - if (chunk->outdated()) - chunk->generate(); + for (Chunk* chunk : to_generate) + chunk->generate(); //new_chunks.swap(this->chunks); this->chunks = new_chunks; @@ -95,8 +111,8 @@ float World::get_height_at(int x, int z) { } Chunk* World::get_chunk(int x, int z) { - auto search = this->location_map.find(std::tuple(x, z)); - if (search == this->location_map.end()) + auto search = World::world->location_map.find(std::tuple(x, z)); + if (search == World::world->location_map.end()) return 0; return std::get<1>(*search); } diff --git a/src/world.h b/src/world.h index f10c732..78956d7 100644 --- a/src/world.h +++ b/src/world.h @@ -30,7 +30,7 @@ private: glm::ivec2 world_center; - int world_size = 32; + int world_size = 16; static World* world; @@ -41,7 +41,7 @@ public: void process(int x, int z); static float get_height_at(int x, int z); - Chunk* get_chunk(int x, int z); + static Chunk* get_chunk(int x, int z); void render(Camera* c, Shader* s); };