summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTyler Murphy <tylermurphy534@gmail.com>2022-09-27 17:03:43 -0400
committerTyler Murphy <tylermurphy534@gmail.com>2022-09-27 17:03:43 -0400
commit9b60b862e58905780bf47f69a34522fde046ebea (patch)
treebda8f9c998cdeec6ad1a5b4fb6e60800dbaca8ad /src
parentasync chunk meshing (diff)
downloadminecraftvulkan-9b60b862e58905780bf47f69a34522fde046ebea.tar.gz
minecraftvulkan-9b60b862e58905780bf47f69a34522fde046ebea.tar.bz2
minecraftvulkan-9b60b862e58905780bf47f69a34522fde046ebea.zip
procedural chunk loading
Diffstat (limited to '')
-rw-r--r--src/chunk.cpp24
-rw-r--r--src/chunk.hpp1
-rwxr-xr-xsrc/first_app.cpp64
-rwxr-xr-xsrc/first_app.hpp11
-rw-r--r--src/simple_renderer.cpp4
5 files changed, 77 insertions, 27 deletions
diff --git a/src/chunk.cpp b/src/chunk.cpp
index f9ddb54..e830c57 100644
--- a/src/chunk.cpp
+++ b/src/chunk.cpp
@@ -16,14 +16,14 @@ Chunk::Chunk(int32_t gridX, int32_t gridZ, uint32_t world_seed)
}
Chunk::~Chunk() {
- if(chunkMesh != nullptr)
- delete chunkMesh;
if(worker.joinable())
worker.join();
+ if(chunkMesh != nullptr)
+ delete chunkMesh;
}
//
-// CHUNK CREATION AND DELETION
+// CHUNK CREATION, DELETION, AND RETREVAL
//
static std::map<std::pair<int32_t, int32_t>, Chunk*> chunks{};
@@ -38,10 +38,17 @@ Chunk* Chunk::getChunk(int32_t gridX, int32_t gridZ) {
if(chunks.count({gridX, gridZ})) {
return chunks[{gridX, gridZ}];
} else {
- return NULL;
+ return nullptr;
}
}
+void Chunk::deleteChunk(int32_t gridX, int32_t gridZ) {
+ Chunk* chunk = getChunk(gridX, gridZ);
+ if(chunk == nullptr) return; // Chunk does not exist or is already deleted
+ delete chunk;
+ chunks.erase({gridX, gridZ});
+}
+
//
// CHUNK TEXTURE AND BLOCK LOADING
//
@@ -51,7 +58,7 @@ static std::map<std::string, uint32_t> texturesIds{};
static std::vector<xe::Image*> textures{};
void loadTexture(const std::string& filePath) {
- xe::Image* image = xe::Engine::getInstance()->loadImageFromFile(filePath, false);
+ xe::Image* image = new xe::Image(filePath, false);
texturesIds[filePath] = static_cast<uint32_t>(textures.size());
textures.push_back(image);
}
@@ -88,12 +95,15 @@ void Chunk::unload() {
//
void Chunk::createMeshAsync(Chunk* c) {
+ if(c == nullptr) return;
if(c->working) return;
+ if(c->worker.joinable())
+ c->worker.join();
c->worker = std::thread(createMesh, c);
}
void Chunk::createMesh(Chunk* c) {
- c->working = true;
+ if(c == nullptr) return;
c->vertexData.data.clear();
for(int32_t x=0;x<16;x++) {
for(int32_t y=0; y<256; y++) {
@@ -152,7 +162,7 @@ xe::Model* Chunk::getMesh() {
xe::Model::Builder builder{};
builder.vertexData = vertexData;
builder.vertexSize = 36;
- chunkMesh = new xe::Model(xe::Engine::getInstance()->getDevice(), builder);
+ chunkMesh = new xe::Model(builder);
reloadRequired = false;
}
return chunkMesh;
diff --git a/src/chunk.hpp b/src/chunk.hpp
index c506ca0..c53a0d3 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -39,6 +39,7 @@ class Chunk {
static Chunk* newChunk(int32_t gridX, int32_t gridZ, uint32_t world_seed);
static Chunk* getChunk(int32_t gridX, int32_t gridZ);
+ static void deleteChunk(int32_t gridX, int32_t gridZ);
static void createMesh(Chunk* c);
static void createMeshAsync(Chunk* c);
diff --git a/src/first_app.cpp b/src/first_app.cpp
index 08f6f0c..43047f7 100755
--- a/src/first_app.cpp
+++ b/src/first_app.cpp
@@ -1,5 +1,4 @@
#include "first_app.hpp"
-#include "chunk.hpp"
namespace app {
@@ -11,15 +10,11 @@ void FirstApp::run() {
Chunk::load();
- for(int32_t x = 0; x < 10; x++) {
- for(int32_t z = 0; z < 10; z++) {
- Chunk* chunk = Chunk::newChunk(x, z, 53463);
- Chunk::createMeshAsync(chunk);
- auto chunkObject = xe::GameObject::createGameObject();
- chunkObject.transform.translation = {16.f*x, 0.f, 16.f*z};
- gameObjects.push_back(std::move(chunkObject));
- }
- }
+ auto viewerObject = xe::GameObject::createGameObject();
+ viewerObject.transform.translation = {0.f, 10.f, 0.f};
+ viewerObject.transform.rotation.y = glm::radians(45.f);
+
+ createGameObjects(viewerObject);
SimpleRenderer renderer{xeEngine, Chunk::getTextures()};
@@ -27,9 +22,6 @@ void FirstApp::run() {
sound.setLooping(true);
sound.play();
- auto viewerObject = xe::GameObject::createGameObject();
- viewerObject.transform.translation = {0.f, 10.f, 0.f};
- viewerObject.transform.rotation.y = glm::radians(45.f);
KeyboardMovementController cameraController{xeEngine.getInput(), viewerObject};
while (xeEngine.poll()) {
@@ -40,10 +32,12 @@ void FirstApp::run() {
xeEngine.getCamera().setViewYXZ(viewerObject.transform.translation, viewerObject.transform.rotation);
if(xeEngine.beginFrame()) {
- renderer.render(gameObjects, xeEngine.getCamera());
+ renderer.render(loadedChunks, xeEngine.getCamera());
xeEngine.endFrame();
}
+ reloadLoadedChunks(viewerObject);
+
}
xeEngine.close();
@@ -52,4 +46,46 @@ void FirstApp::run() {
}
+void FirstApp::createGameObjects(xe::GameObject& viewer) {
+ int width = 2*RENDER_DISTANCE+1;
+ loadedChunks.clear();
+ for(int32_t x = 0; x < width; x++) {
+ for(int32_t z = 0; z < width; z++) {
+ auto gameObject = xe::GameObject::createGameObject();
+ gameObject.transform.translation = glm::vec3(0.f);
+ loadedChunks.push_back(std::move(gameObject));
+ }
+ }
+}
+
+void FirstApp::reloadLoadedChunks(xe::GameObject& viewer) {
+ viewX = static_cast<int>(floor(viewer.transform.translation.x / 16.f));
+ viewZ = static_cast<int>(floor(viewer.transform.translation.z / 16.f));
+ int width = 2*RENDER_DISTANCE+1;
+ int minX = viewX - RENDER_DISTANCE;
+ int minZ = viewZ - RENDER_DISTANCE;
+ int maxX = viewX + RENDER_DISTANCE;
+ int maxZ = viewZ + RENDER_DISTANCE;
+ for(int32_t x = 0; x < width; x++) {
+ for(int32_t z = 0; z < width; z++) {
+ auto& gameObject = loadedChunks[x + z * width];
+ int gridX = static_cast<int>(floor(gameObject.transform.translation.x / 16.f));
+ int gridZ = static_cast<int>(floor(gameObject.transform.translation.z / 16.f));
+ int newGridX = minX + x;
+ int newGridZ = minZ + z;
+ if(gridX < minX || gridZ < minZ || gridX > maxX || gridZ > maxZ)
+ Chunk::deleteChunk(gridX, gridZ);
+ Chunk* chunk = Chunk::getChunk(newGridX, newGridZ);
+ if(chunk == nullptr) {
+ chunk = Chunk::newChunk(newGridX, newGridZ, 12345);
+ Chunk::createMeshAsync(chunk);
+ Chunk::createMeshAsync(Chunk::getChunk(newGridX-1, newGridZ));
+ Chunk::createMeshAsync(Chunk::getChunk(newGridX, newGridZ+1));
+ }
+ gameObject.model = chunk->getMesh();
+ gameObject.transform.translation = glm::vec3(newGridX * 16.f, 0, newGridZ * 16.f);
+ }
+ }
+}
+
} \ No newline at end of file
diff --git a/src/first_app.hpp b/src/first_app.hpp
index 3339b04..d361296 100755
--- a/src/first_app.hpp
+++ b/src/first_app.hpp
@@ -4,6 +4,7 @@
#include "keyboard_movement_controller.hpp"
#include "simple_renderer.hpp"
+#include "chunk.hpp"
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
@@ -31,9 +32,15 @@ class FirstApp {
static constexpr int WIDTH = 800;
static constexpr int HEIGHT = 600;
+ static constexpr int RENDER_DISTANCE = 10;
- xe::Engine xeEngine;
+ void createGameObjects(xe::GameObject& viewer);
+ void reloadLoadedChunks(xe::GameObject& viewer);
+
+
+ int viewX, viewZ;
- std::vector<xe::GameObject> gameObjects;
+ xe::Engine xeEngine;
+ std::vector<xe::GameObject> loadedChunks;
};
} \ No newline at end of file
diff --git a/src/simple_renderer.cpp b/src/simple_renderer.cpp
index 22046be..d13e7ac 100644
--- a/src/simple_renderer.cpp
+++ b/src/simple_renderer.cpp
@@ -29,10 +29,6 @@ void SimpleRenderer::render(std::vector<xe::GameObject> &gameObjects, xe::Camera
PushConstant pc{};
pc.modelMatrix = obj.transform.mat4();
pc.normalMatrix = obj.transform.normalMatrix();
-
- Chunk* chunk = Chunk::getChunk(obj.transform.translation.x/16.f, obj.transform.translation.z/16.f);
- obj.model = chunk->getMesh();
-
xeRenderSystem->loadPushConstant(&pc);
xeRenderSystem->render(obj);
}