diff --git a/ScuffedMinecraft/ScuffedMinecraft.vcxproj b/ScuffedMinecraft/ScuffedMinecraft.vcxproj
index 0a87fb3..0d702c2 100644
--- a/ScuffedMinecraft/ScuffedMinecraft.vcxproj
+++ b/ScuffedMinecraft/ScuffedMinecraft.vcxproj
@@ -157,11 +157,14 @@
+
+
+
-
+
@@ -178,7 +181,10 @@
+
+
+
@@ -198,6 +204,10 @@
+
+
+
+
@@ -207,6 +217,7 @@
+
diff --git a/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters b/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters
index 44ed770..45330a1 100644
--- a/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters
+++ b/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters
@@ -33,7 +33,7 @@
Source Files
-
+
Source Files
@@ -72,6 +72,15 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -134,6 +143,15 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
@@ -144,11 +162,18 @@
+
+
+
+
Resource Files
+
+ Resource Files
+
diff --git a/ScuffedMinecraft/assets/shaders/block_outline_frag.glsl b/ScuffedMinecraft/assets/shaders/block_outline_frag.glsl
new file mode 100644
index 0000000..98fc3a8
--- /dev/null
+++ b/ScuffedMinecraft/assets/shaders/block_outline_frag.glsl
@@ -0,0 +1,10 @@
+#version 330 core
+
+out vec4 FragColor;
+
+uniform float time;
+
+void main()
+{
+ FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/assets/shaders/block_outline_vert.glsl b/ScuffedMinecraft/assets/shaders/block_outline_vert.glsl
new file mode 100644
index 0000000..bdc6af2
--- /dev/null
+++ b/ScuffedMinecraft/assets/shaders/block_outline_vert.glsl
@@ -0,0 +1,12 @@
+#version 330 core
+
+layout (location = 0) in vec3 aPos;
+
+uniform vec3 model;
+uniform mat4 view;
+uniform mat4 projection;
+
+void main()
+{
+ gl_Position = projection * view * vec4(aPos + model, 1.0);
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/assets/shaders/crosshair_frag.glsl b/ScuffedMinecraft/assets/shaders/crosshair_frag.glsl
new file mode 100644
index 0000000..1e0de06
--- /dev/null
+++ b/ScuffedMinecraft/assets/shaders/crosshair_frag.glsl
@@ -0,0 +1,18 @@
+#version 330 core
+
+in vec2 TexCoord;
+
+out vec4 FragColor;
+
+uniform sampler2D tex;
+
+void main()
+{
+ vec4 texResult = texture(tex, TexCoord);
+
+ if (texResult.a == 0)
+ discard;
+
+ texResult.a = 0.8;
+ FragColor = texResult;
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/assets/shaders/crosshair_vert.glsl b/ScuffedMinecraft/assets/shaders/crosshair_vert.glsl
new file mode 100644
index 0000000..0f479d5
--- /dev/null
+++ b/ScuffedMinecraft/assets/shaders/crosshair_vert.glsl
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout (location = 0) in vec2 inPos;
+layout (location = 1) in vec2 inTexCoords;
+
+uniform mat4 projection;
+
+out vec2 TexCoord;
+
+void main()
+{
+ gl_Position = projection * vec4(inPos, 0.0, 1.0);
+ TexCoord = inTexCoords;
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/assets/sprites/block_map.png b/ScuffedMinecraft/assets/sprites/block_map.png
index 79efa49..38e8f0d 100644
Binary files a/ScuffedMinecraft/assets/sprites/block_map.png and b/ScuffedMinecraft/assets/sprites/block_map.png differ
diff --git a/ScuffedMinecraft/assets/sprites/block_map.psd b/ScuffedMinecraft/assets/sprites/block_map.psd
index 378f4e4..da11a0e 100644
Binary files a/ScuffedMinecraft/assets/sprites/block_map.psd and b/ScuffedMinecraft/assets/sprites/block_map.psd differ
diff --git a/ScuffedMinecraft/assets/sprites/crosshair.png b/ScuffedMinecraft/assets/sprites/crosshair.png
new file mode 100644
index 0000000..41f5523
Binary files /dev/null and b/ScuffedMinecraft/assets/sprites/crosshair.png differ
diff --git a/ScuffedMinecraft/src/Application.cpp b/ScuffedMinecraft/src/Application.cpp
index 18f01d1..811ec4b 100644
--- a/ScuffedMinecraft/src/Application.cpp
+++ b/ScuffedMinecraft/src/Application.cpp
@@ -24,11 +24,13 @@
#include "Camera.h"
#include "Planet.h"
#include "Blocks.h"
+#include "Physics.h"
void framebufferSizeCallback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
+void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
float deltaTime = 0.0f;
float lastFrame = 0.0f;
@@ -42,18 +44,22 @@ bool firstMouse = true;
bool menuMode = false;
bool escapeDown = false;
+bool f1Down = false;
+// Window settings
float windowX = 1920;
float windowY = 1080;
+bool vsync = true;
+
+uint16_t selectedBlock = 1;
+
+bool uiEnabled = true;
Camera camera;
GLuint framebufferTexture;
GLuint depthTexture;
-// Window options
-#define VSYNC 1 // 0 for off, 1 for on
-
float rectangleVertices[] =
{
// Coords // TexCoords
@@ -66,39 +72,66 @@ float rectangleVertices[] =
-1.0f, 1.0f, 0.0f, 1.0f
};
-int main (int argc, char *argv[]) {
+float outlineVertices[] =
+{
+ -.001f, -.001f, -.001f, 1.001f, -.001f, -.001f,
+ 1.001f, -.001f, -.001f, 1.001f, 1.001f, -.001f,
+ 1.001f, 1.001f, -.001f, -.001f, 1.001f, -.001f,
+ -.001f, 1.001f, -.001f, -.001f, -.001f, -.001f,
+
+ -.001f, -.001f, -.001f, -.001f, -.001f, 1.001f,
+ -.001f, -.001f, 1.001f, -.001f, 1.001f, 1.001f,
+ -.001f, 1.001f, 1.001f, -.001f, 1.001f, -.001f,
+
+ 1.001f, -.001f, -.001f, 1.001f, -.001f, 1.001f,
+ 1.001f, -.001f, 1.001f, 1.001f, 1.001f, 1.001f,
+ 1.001f, 1.001f, 1.001f, 1.001f, 1.001f, -.001f,
+
+ -.001f, -.001f, 1.001f, 1.001f, -.001f, 1.001f,
+ -.001f, 1.001f, 1.001f, 1.001f, 1.001f, 1.001f,
+};
+
+float crosshairVertices[] =
+{
+ windowX / 2 - 13.5, windowY / 2 - 13.5, 0.0f, 0.0f,
+ windowX / 2 + 13.5, windowY / 2 - 13.5, 1.0f, 0.0f,
+ windowX / 2 + 13.5, windowY / 2 + 13.5, 1.0f, 1.0f,
+
+ windowX / 2 - 13.5, windowY / 2 - 13.5, 0.0f, 0.0f,
+ windowX / 2 - 13.5, windowY / 2 + 13.5, 0.0f, 1.0f,
+ windowX / 2 + 13.5, windowY / 2 + 13.5, 1.0f, 1.0f,
+};
+
+int main(int argc, char *argv[])
+{
#ifdef LINUX
- char* resolved_path = realpath(argv[0],NULL);
- if (resolved_path == NULL) {
- printf("%s: Please do not place binary in PATH\n", argv[0]);
- exit(1);
- }
- size_t resolved_length = strlen(resolved_path);
+ char* resolved_path = realpath(argv[0], NULL);
+ if (resolved_path == NULL) {
+ printf("%s: Please do not place binary in PATH\n", argv[0]);
+ exit(1);
+ }
+ size_t resolved_length = strlen(resolved_path);
+ // remove executable from path
+ for (size_t i = resolved_length; i > 0; i--) {
+ if (resolved_path[i] == '/' && resolved_path[i + 1] != 0) {
+ resolved_path[i + 1] = 0;
+ resolved_length = i;
+ break;
+ }
+ }
+ char* assets_path = (char*)malloc(resolved_length + strlen("assets") + 2);
+ strcpy(assets_path, resolved_path);
+ strcpy(assets_path + resolved_length + 1, "assets");
+ struct stat path_stat;
+ if (stat(assets_path, &path_stat) == -1 || !S_ISDIR(path_stat.st_mode)) {
+ printf("%s: Asset directory not found\n", argv[0]);
+ exit(1);
+ }
+ free(assets_path);
- // remove executable from path
- for (size_t i = resolved_length; i > 0; i--) {
- if (resolved_path[i] == '/' && resolved_path[i+1] != 0) {
- resolved_path[i+1] = 0;
- resolved_length = i;
- break;
- }
- }
-
- char* assets_path = (char *)malloc(resolved_length + strlen("assets") + 2);
- strcpy(assets_path, resolved_path);
- strcpy(assets_path + resolved_length + 1, "assets");
- struct stat path_stat;
- if(stat(assets_path, &path_stat) == -1 || !S_ISDIR(path_stat.st_mode)) {
- printf("%s: Asset directory not found\n", argv[0]);
- exit(1);
- }
-
- free(assets_path);
-
- chdir(resolved_path);
- free(resolved_path);
+ chdir(resolved_path);
+ free(resolved_path);
#endif
-
// Initialize GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
@@ -114,7 +147,7 @@ int main (int argc, char *argv[]) {
return -1;
}
glfwMakeContextCurrent(window);
- glfwSwapInterval(VSYNC);
+ glfwSwapInterval(vsync ? 1 : 0);
// Initialize GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
@@ -128,6 +161,7 @@ int main (int argc, char *argv[]) {
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
+ glfwSetMouseButtonCallback(window, mouse_button_callback);
glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
@@ -156,6 +190,10 @@ int main (int argc, char *argv[]) {
Shader framebufferShader("assets/shaders/framebuffer_vert.glsl", "assets/shaders/framebuffer_frag.glsl");
+ Shader outlineShader("assets/shaders/block_outline_vert.glsl", "assets/shaders/block_outline_frag.glsl");
+
+ Shader crosshairShader("assets/shaders/crosshair_vert.glsl", "assets/shaders/crosshair_frag.glsl");
+
// Create post-processing framebuffer
unsigned int FBO;
glGenFramebuffers(1, &FBO);
@@ -198,6 +236,26 @@ int main (int argc, char *argv[]) {
glUniform1i(glGetUniformLocation(framebufferShader.ID, "screenTexture"), 0);
glUniform1i(glGetUniformLocation(framebufferShader.ID, "depthTexture"), 1);
+ unsigned int outlineVAO, outlineVBO;
+ glGenVertexArrays(1, &outlineVAO);
+ glGenBuffers(1, &outlineVBO);
+ glBindVertexArray(outlineVAO);
+ glBindBuffer(GL_ARRAY_BUFFER, outlineVBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(outlineVertices), &outlineVertices, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
+
+ unsigned int crosshairVAO, crosshairVBO;
+ glGenVertexArrays(1, &crosshairVAO);
+ glGenBuffers(1, &crosshairVBO);
+ glBindVertexArray(crosshairVAO);
+ glBindBuffer(GL_ARRAY_BUFFER, crosshairVBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(crosshairVertices), &crosshairVertices, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Create terrain texture
@@ -227,6 +285,30 @@ int main (int argc, char *argv[]) {
stbi_image_free(data);
+ // Create crosshair texture
+ unsigned int crosshairTexture;
+ glGenTextures(1, &crosshairTexture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, crosshairTexture);
+
+ // Set texture parameters
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ // Load Crosshair Texture
+ unsigned char* data2 = stbi_load("assets/sprites/crosshair.png", &width, &height, &nrChannels, 0);
+ if (data2)
+ {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ }
+ else
+ {
+ std::cout << "Failed to load texture\n";
+ }
+
+ stbi_image_free(data2);
+
// Create camera
camera = Camera(glm::vec3(0.0f, 25.0f, 0.0f));
@@ -234,6 +316,8 @@ int main (int argc, char *argv[]) {
Planet::planet = new Planet(&shader, &waterShader, &billboardShader);
+ glm::mat4 ortho = glm::ortho(0.0f, (float)windowX, (float)windowY, 0.0f, 0.0f, 10.0f);
+
// Initialize ImGui
IMGUI_CHECKVERSION();
ImGui::CreateContext();
@@ -270,6 +354,8 @@ int main (int argc, char *argv[]) {
waterShader.use();
waterShader.setFloat("time", currentFrame);
+ outlineShader.use();
+ outlineShader.setFloat("time", currentFrame);
// Input
processInput(window);
@@ -311,24 +397,60 @@ int main (int argc, char *argv[]) {
projectionLoc = glGetUniformLocation(billboardShader.ID, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
- Planet::planet->Update(camera.Position.x, camera.Position.y, camera.Position.z);
+ outlineShader.use();
+ viewLoc = glGetUniformLocation(outlineShader.ID, "view");
+ glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
+ projectionLoc = glGetUniformLocation(outlineShader.ID, "projection");
+ glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
+
+ Planet::planet->Update(camera.Position);
+
+ // -- Render block outline -- //
+ if (uiEnabled)
+ {
+ // Get block position
+ auto result = Physics::Raycast(camera.Position, camera.Front, 5);
+ if (result.hit)
+ {
+ outlineShader.use();
+
+ // Set outline view to position
+ unsigned int modelLoc = glGetUniformLocation(outlineShader.ID, "model");
+ glUniform3f(modelLoc, result.blockX, result.blockY, result.blockZ);
+
+ // Render
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ //glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_INVERT);
+ glDisable(GL_CULL_FACE);
+ glBindVertexArray(outlineVAO);
+ glLineWidth(2.0);
+ glDrawArrays(GL_LINES, 0, 24);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_CULL_FACE);
+ //glDisable(GL_COLOR_LOGIC_OP);
+ }
+ }
framebufferShader.use();
+ // -- Post Processing Stuff -- //
+
// Check if player is underwater
int blockX = camera.Position.x < 0 ? camera.Position.x - 1 : camera.Position.x;
int blockY = camera.Position.y < 0 ? camera.Position.y - 1 : camera.Position.y;
int blockZ = camera.Position.z < 0 ? camera.Position.z - 1 : camera.Position.z;
- int chunkX = blockX < 0 ? floorf(blockX / (float)Planet::chunkSize) : blockX / (int)Planet::chunkSize;
- int chunkY = blockY < 0 ? floorf(blockY / (float)Planet::chunkSize) : blockY / (int)Planet::chunkSize;
- int chunkZ = blockZ < 0 ? floorf(blockZ / (float)Planet::chunkSize) : blockZ / (int)Planet::chunkSize;
+ int chunkX = blockX < 0 ? floorf(blockX / (float)CHUNK_SIZE) : blockX / (int)CHUNK_SIZE;
+ int chunkY = blockY < 0 ? floorf(blockY / (float)CHUNK_SIZE) : blockY / (int)CHUNK_SIZE;
+ int chunkZ = blockZ < 0 ? floorf(blockZ / (float)CHUNK_SIZE) : blockZ / (int)CHUNK_SIZE;
- int localBlockX = blockX - (chunkX * Planet::chunkSize);
- int localBlockY = blockY - (chunkY * Planet::chunkSize);
- int localBlockZ = blockZ - (chunkZ * Planet::chunkSize);
+ int localBlockX = blockX - (chunkX * CHUNK_SIZE);
+ int localBlockY = blockY - (chunkY * CHUNK_SIZE);
+ int localBlockZ = blockZ - (chunkZ * CHUNK_SIZE);
- Chunk* chunk = Planet::planet->GetChunk(chunkX, chunkY, chunkZ);
+ Chunk* chunk = Planet::planet->GetChunk(ChunkPos(chunkX, chunkY, chunkZ));
if (chunk != nullptr)
{
unsigned int blockType = chunk->GetBlockAtPos(
@@ -346,6 +468,7 @@ int main (int argc, char *argv[]) {
}
}
+ // Post Processing
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindVertexArray(rectVAO);
glDisable(GL_DEPTH_TEST);
@@ -355,15 +478,50 @@ int main (int argc, char *argv[]) {
glBindTexture(GL_TEXTURE_2D, depthTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);
- // Draw ImGui UI
- ImGui::Begin("Test");
- ImGui::Text("FPS: %f (Avg: %f, Min: %f, Max: %f)", fps, avgFps, lowestFps, highestFps);
- ImGui::Text("MS: %f", deltaTime * 100.0f);
- ImGui::Text("Chunks: %d (%d rendered)", Planet::planet->numChunks, Planet::planet->numChunksRendered);
- ImGui::End();
+ if (uiEnabled)
+ {
+ // -- Render Crosshair -- //
- ImGui::Render();
- ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+ // Render
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, crosshairTexture);
+
+ crosshairShader.use();
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glEnable(GL_COLOR_LOGIC_OP);
+
+ unsigned int crosshairProjLoc = glGetUniformLocation(crosshairShader.ID, "projection");
+ glUniformMatrix4fv(crosshairProjLoc, 1, GL_FALSE, glm::value_ptr(ortho));
+ glBindVertexArray(crosshairVAO);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_COLOR_LOGIC_OP);
+
+ // Draw ImGui UI
+ ImGui::Begin("Test");
+ ImGui::Text("FPS: %d (Avg: %d, Min: %d, Max: %d)", (int)fps, (int)avgFps, (int)lowestFps, (int)highestFps);
+ ImGui::Text("MS: %f", deltaTime * 100.0f);
+ if (ImGui::Checkbox("VSYNC", &vsync))
+ glfwSwapInterval(vsync ? 1 : 0);
+ ImGui::Text("Chunks: %d (%d rendered)", Planet::planet->numChunks, Planet::planet->numChunksRendered);
+ ImGui::Text("Position: x: %f, y: %f, z: %f", camera.Position.x, camera.Position.y, camera.Position.z);
+ ImGui::Text("Direction: x: %f, y: %f, z: %f", camera.Front.x, camera.Front.y, camera.Front.z);
+ ImGui::Text("Selected Block: %s", Blocks::blocks[selectedBlock].blockName);
+ if (ImGui::SliderInt("Render Distance", &Planet::planet->renderDistance, 0, 30))
+ Planet::planet->ClearChunkQueue();
+ if (ImGui::SliderInt("Render Height", &Planet::planet->renderHeight, 0, 10))
+ Planet::planet->ClearChunkQueue();
+ ImGui::Checkbox("Use absolute Y axis for camera vertical movement", &camera.absoluteVerticalMovement);
+ ImGui::End();
+
+ ImGui::Render();
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+ }
// Check and call events and swap buffers
glfwSwapBuffers(window);
@@ -372,6 +530,8 @@ int main (int argc, char *argv[]) {
//std::cout << camera.Position.x << ", " << camera.Position.y << ", " << camera.Position.z << '\n';
}
+ delete Planet::planet;
+
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
@@ -388,7 +548,6 @@ void framebufferSizeCallback(GLFWwindow* window, int width, int height)
// resize framebuffer texture
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, windowX, windowY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-
// resize framebuffer depth texture
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, windowX, windowY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
@@ -396,6 +555,7 @@ void framebufferSizeCallback(GLFWwindow* window, int width, int height)
void processInput(GLFWwindow* window)
{
+ // Pause
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
if (escapeDown)
@@ -410,6 +570,18 @@ void processInput(GLFWwindow* window)
else
escapeDown = false;
+ // UI Toggle
+ if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_PRESS)
+ {
+ if (f1Down)
+ return;
+
+ f1Down = true;
+ uiEnabled = !uiEnabled;
+ }
+ else
+ f1Down = false;
+
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
@@ -429,6 +601,61 @@ void processInput(GLFWwindow* window)
camera.ProcessKeyboard(DOWN, deltaTime);
}
+void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
+{
+ if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
+ {
+ auto result = Physics::Raycast(camera.Position, camera.Front, 5);
+ if (!result.hit)
+ return;
+
+ result.chunk->UpdateBlock(result.localBlockX, result.localBlockY, result.localBlockZ, 0);
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
+ {
+ auto result = Physics::Raycast(camera.Position, camera.Front, 5);
+ if (!result.hit)
+ return;
+
+ selectedBlock = result.chunk->GetBlockAtPos(result.localBlockX, result.localBlockY, result.localBlockZ);
+ }
+ else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
+ {
+ auto result = Physics::Raycast(camera.Position, camera.Front, 5);
+ if (!result.hit)
+ return;
+
+ float distX = result.hitPos.x - (result.blockX + .5f);
+ float distY = result.hitPos.y - (result.blockY + .5f);
+ float distZ = result.hitPos.z - (result.blockZ + .5f);
+
+ int blockX = result.blockX;
+ int blockY = result.blockY;
+ int blockZ = result.blockZ;
+
+ // Choose face to place on
+ if (abs(distX) > abs(distY) && abs(distX) > abs(distZ))
+ blockX += (distX > 0 ? 1 : -1);
+ else if (abs(distY) > abs(distX) && abs(distY) > abs(distZ))
+ blockY += (distY > 0 ? 1 : -1);
+ else
+ blockZ += (distZ > 0 ? 1 : -1);
+
+ int chunkX = blockX < 0 ? floorf(blockX / (float)CHUNK_SIZE) : blockX / (int)CHUNK_SIZE;
+ int chunkY = blockY < 0 ? floorf(blockY / (float)CHUNK_SIZE) : blockY / (int)CHUNK_SIZE;
+ int chunkZ = blockZ < 0 ? floorf(blockZ / (float)CHUNK_SIZE) : blockZ / (int)CHUNK_SIZE;
+
+ int localBlockX = blockX - (chunkX * CHUNK_SIZE);
+ int localBlockY = blockY - (chunkY * CHUNK_SIZE);
+ int localBlockZ = blockZ - (chunkZ * CHUNK_SIZE);
+
+ Chunk* chunk = Planet::planet->GetChunk(ChunkPos(chunkX, chunkY, chunkZ));
+ uint16_t blockToReplace = chunk->GetBlockAtPos(localBlockX, localBlockY, localBlockZ);
+ if (chunk != nullptr && (blockToReplace == 0 || Blocks::blocks[blockToReplace].blockType == Block::LIQUID))
+ chunk->UpdateBlock(localBlockX, localBlockY, localBlockZ, selectedBlock);
+ }
+}
+
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (menuMode)
@@ -452,4 +679,4 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(yoffset);
-}
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Block.cpp b/ScuffedMinecraft/src/Block.cpp
index 7ab0153..c127080 100644
--- a/ScuffedMinecraft/src/Block.cpp
+++ b/ScuffedMinecraft/src/Block.cpp
@@ -1,7 +1,7 @@
#include "Block.h"
-Block::Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType)
- : blockType(blockType)
+Block::Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType, std::string blockName)
+ : blockType(blockType), blockName(blockName)
{
topMinX = minX;
topMinY = minY;
@@ -21,8 +21,8 @@ Block::Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType)
Block::Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
- char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType)
- : blockType(blockType)
+ char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType, std::string blockName)
+ : blockType(blockType), blockName(blockName)
{
this->topMinX = topMinX;
this->topMinY = topMinY;
diff --git a/ScuffedMinecraft/src/Block.h b/ScuffedMinecraft/src/Block.h
index e828c4a..8df22f8 100644
--- a/ScuffedMinecraft/src/Block.h
+++ b/ScuffedMinecraft/src/Block.h
@@ -1,5 +1,7 @@
#pragma once
+#include
+
struct Block
{
public:
@@ -16,10 +18,11 @@ public:
char bottomMinX, bottomMinY, bottomMaxX, bottomMaxY;
char sideMinX, sideMinY, sideMaxX, sideMaxY;
BLOCK_TYPE blockType;
+ std::string blockName;
- Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType);
+ Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType, std::string blockName);
Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
- char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType);
+ char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType, std::string blockName);
};
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Blocks.h b/ScuffedMinecraft/src/Blocks.h
index ae0a4eb..e3a71c3 100644
--- a/ScuffedMinecraft/src/Blocks.h
+++ b/ScuffedMinecraft/src/Blocks.h
@@ -1,34 +1,36 @@
#pragma once
#include
+#include
#include "Block.h"
namespace Blocks
{
const std::vector blocks{
- Block(0, 0, 0, 0, Block::TRANSPARENT), // Air block
- Block(0, 0, 1, 1, Block::SOLID), // Dirt block
+ Block(0, 0, 0, 0, Block::TRANSPARENT, "Air"), // Air block
+ Block(0, 0, 1, 1, Block::SOLID, "Dirt"), // Dirt block
- Block(1, 1, 2, 2, // Grass block
+ Block(1, 1, 2, 2, // Grass block
0, 0, 1, 1,
- 1, 0, 2, 1, Block::SOLID),
+ 1, 0, 2, 1, Block::SOLID, "Grass Block"),
- Block(0, 1, 1, 2, Block::SOLID), // Stone block
+ Block(0, 1, 1, 2, Block::SOLID, "Stone"), // Stone block
- Block(2, 1, 3, 2, // Log
+ Block(2, 1, 3, 2, // Log
2, 1, 3, 2,
- 2, 0, 3, 1, Block::SOLID),
+ 2, 0, 3, 1, Block::SOLID, "Log"),
- Block(0, 2, 1, 3, Block::LEAVES), // Leaves
- Block(1, 2, 2, 3, Block::BILLBOARD), // Grass
- Block(3, 0, 4, 1, Block::BILLBOARD), // Tall Grass Bottom
- Block(3, 1, 4, 2, Block::BILLBOARD), // Tall Grass Top
- Block(0, 3, 1, 4, Block::BILLBOARD), // Poppy
- Block(2, 2, 3, 3, Block::BILLBOARD), // White Tulip
- Block(3, 2, 4, 3, Block::BILLBOARD), // Pink Tulip
- Block(1, 3, 2, 4, Block::BILLBOARD), // Orange Tulip
- Block(0, 4, 1, 5, Block::LIQUID) // Water
+ Block(0, 2, 1, 3, Block::LEAVES, "Leaves"), // Leaves
+ Block(1, 2, 2, 3, Block::BILLBOARD, "Grass"), // Grass
+ Block(3, 0, 4, 1, Block::BILLBOARD, "Tall Grass Bot"), // Tall Grass Bottom
+ Block(3, 1, 4, 2, Block::BILLBOARD, "Tall Grass Top"), // Tall Grass Top
+ Block(0, 3, 1, 4, Block::BILLBOARD, "Poppy"), // Poppy
+ Block(2, 2, 3, 3, Block::BILLBOARD, "White Tulip"), // White Tulip
+ Block(3, 2, 4, 3, Block::BILLBOARD, "Pink Tulip"), // Pink Tulip
+ Block(1, 3, 2, 4, Block::BILLBOARD, "Orange Tulip"), // Orange Tulip
+ Block(0, 4, 1, 5, Block::LIQUID, "Water"), // Water
+ Block(4, 0, 5, 1, Block::SOLID, "Sand"), // Sand
};
enum BLOCKS
@@ -46,6 +48,7 @@ namespace Blocks
WHITE_TULIP = 10,
PINK_TULIP = 11,
ORANGE_TULIP = 12,
- WATER = 13
+ WATER = 13,
+ SAND = 14,
};
}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Camera.cpp b/ScuffedMinecraft/src/Camera.cpp
index 621906a..fd9e3b5 100644
--- a/ScuffedMinecraft/src/Camera.cpp
+++ b/ScuffedMinecraft/src/Camera.cpp
@@ -38,9 +38,9 @@ void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime)
if (direction == RIGHT)
Position += Right * velocity;
if (direction == UP)
- Position.y += 1 * velocity;
+ Position += (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
if (direction == DOWN)
- Position.y -= 1 * velocity;
+ Position -= (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
if (direction == FORWARD_NO_Y)
{
glm::vec3 moveDir = Front;
diff --git a/ScuffedMinecraft/src/Camera.h b/ScuffedMinecraft/src/Camera.h
index 2fa7448..d07e5f3 100644
--- a/ScuffedMinecraft/src/Camera.h
+++ b/ScuffedMinecraft/src/Camera.h
@@ -36,6 +36,7 @@ public:
float MovementSpeed;
float MouseSensitivity;
float Zoom;
+ bool absoluteVerticalMovement = true;
Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH);
diff --git a/ScuffedMinecraft/src/Chunk.cpp b/ScuffedMinecraft/src/Chunk.cpp
index 4b7e95a..f40bfe5 100644
--- a/ScuffedMinecraft/src/Chunk.cpp
+++ b/ScuffedMinecraft/src/Chunk.cpp
@@ -10,14 +10,13 @@
#include "Blocks.h"
#include "WorldGen.h"
-Chunk::Chunk(unsigned int chunkSize, glm::vec3 chunkPos, Shader* shader, Shader* waterShader)
- : chunkSize(chunkSize), chunkPos(chunkPos)
+Chunk::Chunk(ChunkPos chunkPos, Shader* shader, Shader* waterShader)
+ : chunkPos(chunkPos)
{
- worldPos = glm::vec3(chunkPos.x * chunkSize, chunkPos.y * chunkSize, chunkPos.z * chunkSize);
+ worldPos = glm::vec3(chunkPos.x * (float)CHUNK_SIZE, chunkPos.y * (float)CHUNK_SIZE, chunkPos.z * (float)CHUNK_SIZE);
ready = false;
generated = false;
- chunkThread = std::thread(&Chunk::GenerateChunk, this);
}
Chunk::~Chunk()
@@ -38,47 +37,41 @@ Chunk::~Chunk()
glDeleteVertexArrays(1, &billboardVAO);
}
-void Chunk::GenerateChunk()
+void Chunk::GenerateChunkMesh()
{
- //std::cout << "Started thread: " << std::this_thread::get_id() << '\n';
-
- WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z, chunkSize, &chunkData);
- std::vector northData, southData, eastData, westData, upData, downData;
-
- WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z - 1, chunkSize, &northData);
- WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z + 1, chunkSize, &southData);
- WorldGen::GenerateChunkData(chunkPos.x + 1, chunkPos.y, chunkPos.z, chunkSize, &eastData);
- WorldGen::GenerateChunkData(chunkPos.x - 1, chunkPos.y, chunkPos.z, chunkSize, &westData);
- WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y + 1, chunkPos.z, chunkSize, &upData);
- WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y - 1, chunkPos.z, chunkSize, &downData);
-
- //std::cout << "Got chunk data in thread: " << std::this_thread::get_id() << '\n';
+ mainVertices.clear();
+ mainIndices.clear();
+ waterVertices.clear();
+ waterIndices.clear();
+ billboardVertices.clear();
+ billboardIndices.clear();
+ numTrianglesMain = 0;
+ numTrianglesWater = 0;
+ numTrianglesBillboard = 0;
unsigned int currentVertex = 0;
unsigned int currentLiquidVertex = 0;
unsigned int currentBillboardVertex = 0;
- for (char x = 0; x < chunkSize; x++)
+ for (char x = 0; x < CHUNK_SIZE; x++)
{
- for (char z = 0; z < chunkSize; z++)
+ for (char z = 0; z < CHUNK_SIZE; z++)
{
- for (char y = 0; y < chunkSize; y++)
+ for (char y = 0; y < CHUNK_SIZE; y++)
{
- int index = x * chunkSize * chunkSize + z * chunkSize + y;
- if (chunkData[index] == 0)
+ if (chunkData->GetBlock(x, y, z) == 0)
continue;
- const Block* block = &Blocks::blocks[chunkData[index]];
+ const Block* block = &Blocks::blocks[chunkData->GetBlock(x, y, z)];
int topBlock;
- if (y < chunkSize - 1)
+ if (y < CHUNK_SIZE - 1)
{
- int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y + 1);
- topBlock = chunkData[blockIndex];
+ topBlock = chunkData->GetBlock(x, y + 1, z);
}
else
{
- int blockIndex = x * chunkSize * chunkSize + z * chunkSize + 0;
- topBlock = upData[blockIndex];
+ int blockIndex = x * CHUNK_SIZE * CHUNK_SIZE + z * CHUNK_SIZE + 0;
+ topBlock = upData->GetBlock(x, 0, z);
}
const Block* topBlockType = &Blocks::blocks[topBlock];
@@ -119,13 +112,11 @@ void Chunk::GenerateChunk()
int northBlock;
if (z > 0)
{
- int northIndex = x * chunkSize * chunkSize + (z - 1) * chunkSize + y;
- northBlock = chunkData[northIndex];
+ northBlock = chunkData->GetBlock(x, y, z - 1);
}
else
{
- int northIndex = x * chunkSize * chunkSize + (chunkSize - 1) * chunkSize + y;
- northBlock = northData[northIndex];
+ northBlock = northData->GetBlock(x, y, CHUNK_SIZE - 1);
}
const Block* northBlockType = &Blocks::blocks[northBlock];
@@ -157,12 +148,12 @@ void Chunk::GenerateChunk()
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0));
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 3);
- mianIndices.push_back(currentVertex + 1);
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 2);
- mianIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 1);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 2);
+ mainIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
@@ -171,15 +162,13 @@ void Chunk::GenerateChunk()
// South
{
int southBlock;
- if (z < chunkSize - 1)
+ if (z < CHUNK_SIZE - 1)
{
- int southIndex = x * chunkSize * chunkSize + (z + 1) * chunkSize + y;
- southBlock = chunkData[southIndex];
+ southBlock = chunkData->GetBlock(x, y, z + 1);
}
else
{
- int southIndex = x * chunkSize * chunkSize + 0 * chunkSize + y;
- southBlock = southData[southIndex];
+ southBlock = southData->GetBlock(x, y, 0);
}
const Block* southBlockType = &Blocks::blocks[southBlock];
@@ -211,12 +200,12 @@ void Chunk::GenerateChunk()
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1));
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 3);
- mianIndices.push_back(currentVertex + 1);
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 2);
- mianIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 1);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 2);
+ mainIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
@@ -227,13 +216,11 @@ void Chunk::GenerateChunk()
int westBlock;
if (x > 0)
{
- int blockIndex = (x - 1) * chunkSize * chunkSize + z * chunkSize + y;
- westBlock = chunkData[blockIndex];
+ westBlock = chunkData->GetBlock(x - 1, y, z);
}
else
{
- int blockIndex = (chunkSize - 1) * chunkSize * chunkSize + z * chunkSize + y;
- westBlock = westData[blockIndex];
+ westBlock = westData->GetBlock(CHUNK_SIZE - 1, y, z);
}
const Block* westBlockType = &Blocks::blocks[westBlock];
@@ -265,12 +252,12 @@ void Chunk::GenerateChunk()
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2));
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 3);
- mianIndices.push_back(currentVertex + 1);
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 2);
- mianIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 1);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 2);
+ mainIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
@@ -279,15 +266,13 @@ void Chunk::GenerateChunk()
// East
{
int eastBlock;
- if (x < chunkSize - 1)
+ if (x < CHUNK_SIZE - 1)
{
- int blockIndex = (x + 1) * chunkSize * chunkSize + z * chunkSize + y;
- eastBlock = chunkData[blockIndex];
+ eastBlock = chunkData->GetBlock(x + 1, y, z);
}
else
{
- int blockIndex = 0 * chunkSize * chunkSize + z * chunkSize + y;
- eastBlock = eastData[blockIndex];
+ eastBlock = eastData->GetBlock(0, y, z);
}
const Block* eastBlockType = &Blocks::blocks[eastBlock];
@@ -319,12 +304,12 @@ void Chunk::GenerateChunk()
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3));
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 3);
- mianIndices.push_back(currentVertex + 1);
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 2);
- mianIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 1);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 2);
+ mainIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
@@ -335,13 +320,12 @@ void Chunk::GenerateChunk()
int bottomBlock;
if (y > 0)
{
- int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y - 1);
- bottomBlock = chunkData[blockIndex];
+ bottomBlock = chunkData->GetBlock(x, y - 1, z);
}
else
{
- int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1);
- bottomBlock = downData[blockIndex];
+ //int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1);
+ bottomBlock = downData->GetBlock(x, CHUNK_SIZE - 1, z);
}
const Block* bottomBlockType = &Blocks::blocks[bottomBlock];
@@ -373,12 +357,12 @@ void Chunk::GenerateChunk()
mainVertices.push_back(Vertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4));
mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4));
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 3);
- mianIndices.push_back(currentVertex + 1);
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 2);
- mianIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 1);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 2);
+ mainIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
@@ -427,12 +411,12 @@ void Chunk::GenerateChunk()
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5));
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 3);
- mianIndices.push_back(currentVertex + 1);
- mianIndices.push_back(currentVertex + 0);
- mianIndices.push_back(currentVertex + 2);
- mianIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 3);
+ mainIndices.push_back(currentVertex + 1);
+ mainIndices.push_back(currentVertex + 0);
+ mainIndices.push_back(currentVertex + 2);
+ mainIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
@@ -455,7 +439,7 @@ void Chunk::Render(Shader* mainShader, Shader* billboardShader)
if (generated)
{
// Solid
- numTrianglesMain = mianIndices.size();
+ numTrianglesMain = mainIndices.size();
glGenVertexArrays(1, &mainVAO);
glGenBuffers(1, &mainVBO);
@@ -467,7 +451,7 @@ void Chunk::Render(Shader* mainShader, Shader* billboardShader)
glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, mianIndices.size() * sizeof(unsigned int), mianIndices.data(), GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, mainIndices.size() * sizeof(unsigned int), mainIndices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX));
glEnableVertexAttribArray(0);
@@ -543,7 +527,7 @@ void Chunk::Render(Shader* mainShader, Shader* billboardShader)
glDrawElements(GL_TRIANGLES, numTrianglesMain, GL_UNSIGNED_INT, 0);
// Render billboard mesh
- billboardShader->use();
+ billboardShader->use();
modelLoc = glGetUniformLocation(billboardShader->ID, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
@@ -572,11 +556,128 @@ void Chunk::RenderWater(Shader* shader)
glDrawElements(GL_TRIANGLES, numTrianglesWater, GL_UNSIGNED_INT, 0);
}
-unsigned int Chunk::GetBlockAtPos(int x, int y, int z)
+uint16_t Chunk::GetBlockAtPos(int x, int y, int z)
{
if (!ready)
return 0;
- int index = x * chunkSize * chunkSize + z * chunkSize + y;
- return chunkData[index];
+ return chunkData->GetBlock(x, y, z);
+}
+
+void Chunk::UpdateBlock(int x, int y, int z, uint16_t newBlock)
+{
+ chunkData->SetBlock(x, y, z, newBlock);
+
+ GenerateChunkMesh();
+
+ // Main
+ numTrianglesMain = mainIndices.size();
+
+ glBindVertexArray(mainVAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, mainVBO);
+ glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, mainIndices.size() * sizeof(unsigned int), mainIndices.data(), GL_STATIC_DRAW);
+
+ // Water
+ numTrianglesWater = waterIndices.size();
+
+ glBindVertexArray(waterVAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, waterVBO);
+ glBufferData(GL_ARRAY_BUFFER, waterVertices.size() * sizeof(WaterVertex), waterVertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, waterIndices.size() * sizeof(unsigned int), waterIndices.data(), GL_STATIC_DRAW);
+
+ // Billboard
+ numTrianglesBillboard = billboardIndices.size();;
+
+ glBindVertexArray(billboardVAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, billboardVBO);
+ glBufferData(GL_ARRAY_BUFFER, billboardVertices.size() * sizeof(BillboardVertex), billboardVertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, billboardEBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, billboardIndices.size() * sizeof(unsigned int), billboardIndices.data(), GL_STATIC_DRAW);
+
+
+ if (x == 0)
+ {
+ Chunk* westChunk = Planet::planet->GetChunk({ chunkPos.x - 1, chunkPos.y, chunkPos.z });
+ if (westChunk != nullptr)
+ westChunk->UpdateChunk();
+ }
+ else if (x == CHUNK_SIZE - 1)
+ {
+ Chunk* eastChunk = Planet::planet->GetChunk({ chunkPos.x + 1, chunkPos.y, chunkPos.z });
+ if (eastChunk != nullptr)
+ eastChunk->UpdateChunk();
+ }
+
+ if (y == 0)
+ {
+ Chunk* downChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y - 1, chunkPos.z });
+ if (downChunk != nullptr)
+ downChunk->UpdateChunk();
+ }
+ else if (y == CHUNK_SIZE - 1)
+ {
+ Chunk* upChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y + 1, chunkPos.z });
+ if (upChunk != nullptr)
+ upChunk->UpdateChunk();
+ }
+
+ if (z == 0)
+ {
+ Chunk* northChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y, chunkPos.z - 1 });
+ if (northChunk != nullptr)
+ northChunk->UpdateChunk();
+ }
+ else if (z == CHUNK_SIZE - 1)
+ {
+ Chunk* southChunk = Planet::planet->GetChunk({ chunkPos.x, chunkPos.y, chunkPos.z + 1 });
+ if (southChunk != nullptr)
+ southChunk->UpdateChunk();
+ }
+}
+
+void Chunk::UpdateChunk()
+{
+ GenerateChunkMesh();
+
+ // Main
+ numTrianglesMain = mainIndices.size();
+
+ glBindVertexArray(mainVAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, mainVBO);
+ glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, mainIndices.size() * sizeof(unsigned int), mainIndices.data(), GL_STATIC_DRAW);
+
+ // Water
+ numTrianglesWater = waterIndices.size();
+
+ glBindVertexArray(waterVAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, waterVBO);
+ glBufferData(GL_ARRAY_BUFFER, waterVertices.size() * sizeof(WaterVertex), waterVertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, waterIndices.size() * sizeof(unsigned int), waterIndices.data(), GL_STATIC_DRAW);
+
+ // Billboard
+ numTrianglesBillboard = billboardIndices.size();
+
+ glBindVertexArray(billboardVAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, billboardVBO);
+ glBufferData(GL_ARRAY_BUFFER, billboardVertices.size() * sizeof(BillboardVertex), billboardVertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, billboardEBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, billboardIndices.size() * sizeof(unsigned int), billboardIndices.data(), GL_STATIC_DRAW);
}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Chunk.h b/ScuffedMinecraft/src/Chunk.h
index 1c380f2..08a4314 100644
--- a/ScuffedMinecraft/src/Chunk.h
+++ b/ScuffedMinecraft/src/Chunk.h
@@ -6,31 +6,40 @@
#include "Shader.h"
#include "Vertex.h"
+#include "ChunkPos.h"
+#include "ChunkData.h"
class Chunk
{
public:
- Chunk(unsigned int chunkSize, glm::vec3 chunkPos, Shader* shader, Shader* waterShader);
+ Chunk(ChunkPos chunkPos, Shader* shader, Shader* waterShader);
~Chunk();
- void GenerateChunk();
+ void GenerateChunkMesh();
void Render(Shader* mainShader, Shader* billboardShader);
void RenderWater(Shader* shader);
- unsigned int GetBlockAtPos(int x, int y, int z);
+ uint16_t GetBlockAtPos(int x, int y, int z);
+ void UpdateBlock(int x, int y, int z, uint16_t newBlock);
+ void UpdateChunk();
public:
- std::vector chunkData;
- glm::vec3 chunkPos;
+ ChunkData* chunkData;
+ ChunkData* northData;
+ ChunkData* southData;
+ ChunkData* upData;
+ ChunkData* downData;
+ ChunkData* eastData;
+ ChunkData* westData;
+ ChunkPos chunkPos;
bool ready;
bool generated;
private:
- unsigned int chunkSize;
glm::vec3 worldPos;
std::thread chunkThread;
std::vector mainVertices;
- std::vector mianIndices;
+ std::vector mainIndices;
std::vector waterVertices;
std::vector waterIndices;
std::vector billboardVertices;
diff --git a/ScuffedMinecraft/src/ChunkData.cpp b/ScuffedMinecraft/src/ChunkData.cpp
new file mode 100644
index 0000000..30895e0
--- /dev/null
+++ b/ScuffedMinecraft/src/ChunkData.cpp
@@ -0,0 +1,39 @@
+#include "ChunkData.h"
+
+#include "Planet.h"
+
+ChunkData::ChunkData(uint16_t* data)
+ : data(data)
+{
+
+}
+
+ChunkData::~ChunkData()
+{
+ delete[] data;
+}
+
+inline int ChunkData::GetIndex(int x, int y, int z) const
+{
+ return x * CHUNK_SIZE * CHUNK_SIZE + z * CHUNK_SIZE + y;
+}
+
+inline int ChunkData::GetIndex(ChunkPos localBlockPos) const
+{
+ return localBlockPos.x * CHUNK_SIZE * CHUNK_SIZE + localBlockPos.z * CHUNK_SIZE + localBlockPos.y;
+}
+
+uint16_t ChunkData::GetBlock(ChunkPos blockPos)
+{
+ return data[GetIndex(blockPos)];
+}
+
+uint16_t ChunkData::GetBlock(int x, int y, int z)
+{
+ return data[GetIndex(x, y, z)];
+}
+
+void ChunkData::SetBlock(int x, int y, int z, uint16_t block)
+{
+ data[GetIndex(x, y, z)] = block;
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/ChunkData.h b/ScuffedMinecraft/src/ChunkData.h
new file mode 100644
index 0000000..1dce469
--- /dev/null
+++ b/ScuffedMinecraft/src/ChunkData.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include
+
+#include "ChunkPos.h"
+
+struct ChunkData
+{
+ uint16_t* data;
+
+ ChunkData(uint16_t* data);
+ ~ChunkData();
+
+ inline int GetIndex(int x, int y, int z) const;
+ inline int GetIndex(ChunkPos localBlockPos) const;
+
+ uint16_t GetBlock(ChunkPos blockPos);
+ uint16_t GetBlock(int x, int y, int z);
+ void SetBlock(int x, int y, int z, uint16_t block);
+};
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/ChunkPos.cpp b/ScuffedMinecraft/src/ChunkPos.cpp
new file mode 100644
index 0000000..f2930e2
--- /dev/null
+++ b/ScuffedMinecraft/src/ChunkPos.cpp
@@ -0,0 +1,18 @@
+#include "ChunkPos.h"
+
+ChunkPos::ChunkPos()
+ : x(0), y(0), z(0)
+{
+
+}
+
+ChunkPos::ChunkPos(int x, int y, int z)
+ : x(x), y(y), z(z)
+{
+
+}
+
+bool ChunkPos::operator==(const ChunkPos& other) const
+{
+ return other.x == x && other.y == y && other.z == z;
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/ChunkPos.h b/ScuffedMinecraft/src/ChunkPos.h
new file mode 100644
index 0000000..3358463
--- /dev/null
+++ b/ScuffedMinecraft/src/ChunkPos.h
@@ -0,0 +1,13 @@
+#pragma once
+
+struct ChunkPos
+{
+ int x;
+ int y;
+ int z;
+
+ ChunkPos();
+ ChunkPos(int x, int y, int z);
+
+ bool operator==(const ChunkPos& other) const;
+};
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/ChunkPosHash.h b/ScuffedMinecraft/src/ChunkPosHash.h
new file mode 100644
index 0000000..98a5852
--- /dev/null
+++ b/ScuffedMinecraft/src/ChunkPosHash.h
@@ -0,0 +1,15 @@
+#include "ChunkPos.h"
+#include
+
+struct ChunkPosHash
+{
+ std::size_t operator()(const ChunkPos& key) const
+ {
+ std::size_t hx = std::hash()(key.x);
+ std::size_t hy = std::hash()(key.y);
+ std::size_t hz = std::hash()(key.z);
+
+ // Combine the hashes using bitwise XOR and shifting
+ return hx ^ (hy << 1) ^ (hz << 2);
+ }
+};
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Physics.cpp b/ScuffedMinecraft/src/Physics.cpp
new file mode 100644
index 0000000..6c020cd
--- /dev/null
+++ b/ScuffedMinecraft/src/Physics.cpp
@@ -0,0 +1,47 @@
+#include "Physics.h"
+#include
+#include "Blocks.h"
+
+Physics::RaycastResult Physics::Raycast(const glm::vec3 startPos, const glm::vec3 direction, const float maxDistance)
+{
+ float currentDistance = 0;
+
+ while (currentDistance < maxDistance)
+ {
+ currentDistance += Physics::RAY_STEP;
+ if (currentDistance > maxDistance)
+ currentDistance = maxDistance;
+
+ // Get chunk
+ glm::vec3 resultPos = startPos + direction * currentDistance;
+ int chunkX = resultPos.x >= 0 ? resultPos.x / CHUNK_SIZE : resultPos.x / CHUNK_SIZE - 1;
+ int chunkY = resultPos.y >= 0 ? resultPos.y / CHUNK_SIZE : resultPos.y / CHUNK_SIZE - 1;
+ int chunkZ = resultPos.z >= 0 ? resultPos.z / CHUNK_SIZE : resultPos.z / CHUNK_SIZE - 1;
+ Chunk* chunk = Planet::planet->GetChunk(ChunkPos(chunkX, chunkY, chunkZ));
+ if (chunk == nullptr)
+ continue;
+
+ // Get block pos
+ int localBlockX = (int)floor(resultPos.x) % CHUNK_SIZE;
+ int localBlockZ = (int)floor(resultPos.z) % CHUNK_SIZE;
+ int localBlockY = (int)floor(resultPos.y) % CHUNK_SIZE;
+
+ // Get block from chunk
+ unsigned int block = chunk->GetBlockAtPos(localBlockX, localBlockY, localBlockZ);
+
+ // Get result pos
+ int blockX = resultPos.x >= 0 ? (int)resultPos.x : (int)resultPos.x - 1;
+ int blockY = resultPos.y >= 0 ? (int)resultPos.y : (int)resultPos.y - 1;
+ int blockZ = resultPos.z >= 0 ? (int)resultPos.z : (int)resultPos.z - 1;
+
+ // Return true if it hit a block
+ if (block != 0 && Blocks::blocks[block].blockType != Block::LIQUID)
+ return { true, resultPos, chunk,
+ blockX, blockY, blockZ,
+ localBlockX, localBlockY, localBlockZ};
+ }
+
+ return { false, glm::vec3(0), nullptr,
+ 0, 0, 0,
+ 0, 0, 0};
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Physics.h b/ScuffedMinecraft/src/Physics.h
new file mode 100644
index 0000000..9c5e80c
--- /dev/null
+++ b/ScuffedMinecraft/src/Physics.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "glm/glm.hpp"
+#include "Planet.h"
+
+namespace Physics
+{
+ struct RaycastResult
+ {
+ bool hit;
+ glm::vec3 hitPos;
+ Chunk* chunk;
+ int blockX;
+ int blockY;
+ int blockZ;
+ int localBlockX;
+ int localBlockY;
+ int localBlockZ;
+
+ RaycastResult(bool hit, glm::vec3 hitPos, Chunk* chunk, int blockX, int blockY, int blockZ, int localBlockX, int localBlockY, int localBlockZ)
+ : hit(hit), hitPos(hitPos), chunk(chunk), blockX(blockX), blockY(blockY), blockZ(blockZ), localBlockX(localBlockX), localBlockY(localBlockY), localBlockZ(localBlockZ)
+ {
+
+ }
+ };
+
+ RaycastResult Raycast(glm::vec3 startPos, glm::vec3 direction, float maxDistance);
+
+ static constexpr float RAY_STEP = 0.01f;
+}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Planet.cpp b/ScuffedMinecraft/src/Planet.cpp
index d251d90..1e40bd4 100644
--- a/ScuffedMinecraft/src/Planet.cpp
+++ b/ScuffedMinecraft/src/Planet.cpp
@@ -4,169 +4,69 @@
#include
#include
+#include "WorldGen.h"
+
Planet* Planet::planet = nullptr;
-const unsigned int Planet::chunkSize = 32;
+//static const unsigned int CHUNK_SIZE = 32;
// Public
Planet::Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader)
: solidShader(solidShader), waterShader(waterShader), billboardShader(billboardShader)
{
-
+ chunkThread = std::thread(&Planet::ChunkThreadUpdate, this);
}
Planet::~Planet()
{
-
+ shouldEnd = true;
+ chunkThread.join();
}
-std::vector Planet::GetChunkData(int chunkX, int chunkY, int chunkZ)
+void Planet::Update(glm::vec3 cameraPos)
{
- std::tuple chunkTuple{ chunkX, chunkY, chunkZ };
-
- if (chunks.find(chunkTuple) == chunks.end())
- {
- return std::vector{};
- //return GenerateChunkData(chunkX, chunkY, chunkZ);
- }
- else
- {
- return std::vector{};
- //return chunks.at(chunkTuple).chunkData;
- }
-}
-
-void Planet::Update(float camX, float camY, float camZ)
-{
- int camChunkX = camX < 0 ? floor(camX / chunkSize) : camX / chunkSize;
- int camChunkY = camY < 0 ? floor(camY / chunkSize) : camY / chunkSize;
- int camChunkZ = camZ < 0 ? floor(camZ / chunkSize) : camZ / chunkSize;
-
- // Check if camera moved to new chunk
- if (camChunkX != lastCamX || camChunkY != lastCamY || camChunkZ != lastCamZ)
- {
- // Player moved chunks, start new chunk queue
- lastCamX = camChunkX;
- lastCamY = camChunkY;
- lastCamZ = camChunkZ;
-
- // Current chunk
- chunkQueue = {};
- if (chunks.find({ camChunkX, camChunkY, camChunkZ }) == chunks.end())
- chunkQueue.push({ camChunkX, camChunkY, camChunkZ });
-
- for (int r = 0; r < renderDistance; r++)
- {
- // Add middle chunks
- for (int y = 0; y <= renderHeight; y++)
- {
- chunkQueue.push({ camChunkX, camChunkY + y, camChunkZ + r });
- chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ });
- chunkQueue.push({ camChunkX, camChunkY + y, camChunkZ - r });
- chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ });
-
- if (y > 0)
- {
- chunkQueue.push({ camChunkX, camChunkY - y, camChunkZ + r });
- chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ });
- chunkQueue.push({ camChunkX, camChunkY - y, camChunkZ - r });
- chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ });
- }
- }
-
- // Add edges
- for (int e = 1; e < r; e++)
- {
- for (int y = 0; y <= renderHeight; y++)
- {
- chunkQueue.push({ camChunkX + e, camChunkY + y, camChunkZ + r });
- chunkQueue.push({ camChunkX - e, camChunkY + y, camChunkZ + r });
-
- chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ + e });
- chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ - e });
-
- chunkQueue.push({ camChunkX + e, camChunkY + y, camChunkZ - r });
- chunkQueue.push({ camChunkX - e, camChunkY + y, camChunkZ - r });
-
- chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ + e });
- chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ - e });
-
- if (y > 0)
- {
- chunkQueue.push({ camChunkX + e, camChunkY - y, camChunkZ + r });
- chunkQueue.push({ camChunkX - e, camChunkY - y, camChunkZ + r });
-
- chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ + e });
- chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ - e });
-
- chunkQueue.push({ camChunkX + e, camChunkY - y, camChunkZ - r });
- chunkQueue.push({ camChunkX - e, camChunkY - y, camChunkZ - r });
-
- chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ + e });
- chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ - e });
- }
- }
- }
-
- // Add corners
- for (int y = 0; y <= renderHeight; y++)
- {
- chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ + r });
- chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ - r });
- chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ + r });
- chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ - r });
-
- if (y > 0)
- {
- chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ + r });
- chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ - r });
- chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ + r });
- chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ - r });
- }
- }
- }
- }
- else if (chunksLoading == 0 && !chunkQueue.empty())
- {
- // Queue is not empty. Process front item in queue
- glm::vec3 next = chunkQueue.front();
- chunkQueue.pop();
-
- std::tuple chunkTuple{ next.x, next.y, next.z };
-
- if (chunks.find(chunkTuple) == chunks.end())
- {
- chunks.try_emplace(chunkTuple,
- chunkSize, next, solidShader, waterShader
- );
- }
- }
+ camChunkX = cameraPos.x < 0 ? floor(cameraPos.x / CHUNK_SIZE) : cameraPos.x / CHUNK_SIZE;
+ camChunkY = cameraPos.y < 0 ? floor(cameraPos.y / CHUNK_SIZE) : cameraPos.y / CHUNK_SIZE;
+ camChunkZ = cameraPos.z < 0 ? floor(cameraPos.z / CHUNK_SIZE) : cameraPos.z / CHUNK_SIZE;
glDisable(GL_BLEND);
chunksLoading = 0;
numChunks = 0;
numChunksRendered = 0;
+ chunkMutex.lock();
for (auto it = chunks.begin(); it != chunks.end(); )
{
numChunks++;
- if (!it->second.ready)
+ if (!(*it->second).ready)
chunksLoading++;
- int chunkX = it->second.chunkPos.x;
- int chunkY = it->second.chunkPos.y;
- int chunkZ = it->second.chunkPos.z;
- if (it->second.ready && (abs(chunkX - camChunkX) > renderDistance ||
+ int chunkX = (*it->second).chunkPos.x;
+ int chunkY = (*it->second).chunkPos.y;
+ int chunkZ = (*it->second).chunkPos.z;
+ if ((*it->second).ready && (abs(chunkX - camChunkX) > renderDistance ||
abs(chunkY - camChunkY) > renderDistance ||
abs(chunkZ - camChunkZ) > renderDistance))
{
+ // Out of range
+ // Add chunk data to delete queue
+ chunkDataDeleteQueue.push({ chunkX, chunkY, chunkZ });
+ chunkDataDeleteQueue.push({ chunkX + 1, chunkY, chunkZ });
+ chunkDataDeleteQueue.push({ chunkX - 1, chunkY, chunkZ });
+ chunkDataDeleteQueue.push({ chunkX, chunkY + 1, chunkZ });
+ chunkDataDeleteQueue.push({ chunkX, chunkY - 1, chunkZ });
+ chunkDataDeleteQueue.push({ chunkX, chunkY, chunkZ + 1 });
+ chunkDataDeleteQueue.push({ chunkX, chunkY, chunkZ - 1 });
+
+ // Delete chunk
+ delete it->second;
it = chunks.erase(it);
}
else
{
numChunksRendered++;
- it->second.Render(solidShader, billboardShader);
+ (*it->second).Render(solidShader, billboardShader);
++it;
}
}
@@ -175,25 +75,387 @@ void Planet::Update(float camX, float camY, float camZ)
waterShader->use();
for (auto it = chunks.begin(); it != chunks.end(); )
{
- int chunkX = it->second.chunkPos.x;
- int chunkY = it->second.chunkPos.y;
- int chunkZ = it->second.chunkPos.z;
+ int chunkX = (*it->second).chunkPos.x;
+ int chunkY = (*it->second).chunkPos.y;
+ int chunkZ = (*it->second).chunkPos.z;
- it->second.RenderWater(waterShader);
+ (*it->second).RenderWater(waterShader);
++it;
}
+
+ chunkMutex.unlock();
+}
+
+void Planet::ChunkThreadUpdate()
+{
+ while (!shouldEnd)
+ {
+ for (auto it = chunkData.begin(); it != chunkData.end(); )
+ {
+ ChunkPos pos = it->first;
+
+ if (chunks.find(pos) == chunks.end() &&
+ chunks.find({ pos.x + 1, pos.y, pos.z }) == chunks.end() &&
+ chunks.find({ pos.x - 1, pos.y, pos.z }) == chunks.end() &&
+ chunks.find({ pos.x, pos.y + 1, pos.z }) == chunks.end() &&
+ chunks.find({ pos.x, pos.y - 1, pos.z }) == chunks.end() &&
+ chunks.find({ pos.x, pos.y, pos.z + 1 }) == chunks.end() &&
+ chunks.find({ pos.x, pos.y, pos.z - 1 }) == chunks.end())
+ {
+ delete chunkData.at(pos);
+ chunkData.erase(pos);
+ }
+ ++it;
+ }
+
+ // Check if camera moved to new chunk
+ if (camChunkX != lastCamX || camChunkY != lastCamY || camChunkZ != lastCamZ)
+ {
+ // Player moved chunks, start new chunk queue
+ lastCamX = camChunkX;
+ lastCamY = camChunkY;
+ lastCamZ = camChunkZ;
+
+ // Current chunk
+ chunkMutex.lock();
+ chunkQueue = {};
+ if (chunks.find({ camChunkX, camChunkY, camChunkZ }) == chunks.end())
+ chunkQueue.push({ camChunkX, camChunkY, camChunkZ });
+
+ for (int r = 0; r < renderDistance; r++)
+ {
+ // Add middle chunks
+ for (int y = 0; y <= renderHeight; y++)
+ {
+ chunkQueue.push({ camChunkX, camChunkY + y, camChunkZ + r });
+ chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ });
+ chunkQueue.push({ camChunkX, camChunkY + y, camChunkZ - r });
+ chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ });
+
+ if (y > 0)
+ {
+ chunkQueue.push({ camChunkX, camChunkY - y, camChunkZ + r });
+ chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ });
+ chunkQueue.push({ camChunkX, camChunkY - y, camChunkZ - r });
+ chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ });
+ }
+ }
+
+ // Add edges
+ for (int e = 1; e < r; e++)
+ {
+ for (int y = 0; y <= renderHeight; y++)
+ {
+ chunkQueue.push({ camChunkX + e, camChunkY + y, camChunkZ + r });
+ chunkQueue.push({ camChunkX - e, camChunkY + y, camChunkZ + r });
+
+ chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ + e });
+ chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ - e });
+
+ chunkQueue.push({ camChunkX + e, camChunkY + y, camChunkZ - r });
+ chunkQueue.push({ camChunkX - e, camChunkY + y, camChunkZ - r });
+
+ chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ + e });
+ chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ - e });
+
+ if (y > 0)
+ {
+ chunkQueue.push({ camChunkX + e, camChunkY - y, camChunkZ + r });
+ chunkQueue.push({ camChunkX - e, camChunkY - y, camChunkZ + r });
+
+ chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ + e });
+ chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ - e });
+
+ chunkQueue.push({ camChunkX + e, camChunkY - y, camChunkZ - r });
+ chunkQueue.push({ camChunkX - e, camChunkY - y, camChunkZ - r });
+
+ chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ + e });
+ chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ - e });
+ }
+ }
+ }
+
+ // Add corners
+ for (int y = 0; y <= renderHeight; y++)
+ {
+ chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ + r });
+ chunkQueue.push({ camChunkX + r, camChunkY + y, camChunkZ - r });
+ chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ + r });
+ chunkQueue.push({ camChunkX - r, camChunkY + y, camChunkZ - r });
+
+ if (y > 0)
+ {
+ chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ + r });
+ chunkQueue.push({ camChunkX + r, camChunkY - y, camChunkZ - r });
+ chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ + r });
+ chunkQueue.push({ camChunkX - r, camChunkY - y, camChunkZ - r });
+ }
+ }
+ }
+
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunkMutex.lock();
+ if (!chunkDataQueue.empty())
+ {
+ ChunkPos chunkPos = chunkDataQueue.front();
+
+ if (chunkData.find(chunkPos) != chunkData.end())
+ {
+ chunkDataQueue.pop();
+ chunkMutex.unlock();
+ continue;
+ }
+
+ chunkMutex.unlock();
+
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+ ChunkData* data = new ChunkData(d);
+
+ WorldGen::GenerateChunkData(chunkPos, d);
+
+ chunkMutex.lock();
+ chunkData[chunkPos] = data;
+ chunkDataQueue.pop();
+ chunkMutex.unlock();
+ }
+ else
+ {
+ if (!chunkQueue.empty())
+ {
+ // Check if chunk exists
+ ChunkPos chunkPos = chunkQueue.front();
+ if (chunks.find(chunkPos) != chunks.end())
+ {
+ chunkQueue.pop();
+ chunkMutex.unlock();
+ continue;
+ }
+
+ chunkMutex.unlock();
+
+ // Create chunk object
+ Chunk* chunk = new Chunk(chunkPos, solidShader, waterShader);
+
+ // Set chunk data
+ {
+ chunkMutex.lock();
+ if (chunkData.find(chunkPos) == chunkData.end())
+ {
+ chunkMutex.unlock();
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+
+ WorldGen::GenerateChunkData(chunkPos, d);
+
+ ChunkData* data = new ChunkData(d);
+
+ chunk->chunkData = data;
+
+ chunkMutex.lock();
+ chunkData[chunkPos] = data;
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunk->chunkData = chunkData.at(chunkPos);
+ chunkMutex.unlock();
+ }
+ }
+
+ // Set top data
+ {
+ ChunkPos topPos(chunkPos.x, chunkPos.y + 1, chunkPos.z);
+ chunkMutex.lock();
+ if (chunkData.find(topPos) == chunkData.end())
+ {
+ chunkMutex.unlock();
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+
+ WorldGen::GenerateChunkData(topPos, d);
+
+ ChunkData* data = new ChunkData(d);
+
+ chunk->upData = data;
+
+ chunkMutex.lock();
+ chunkData[topPos] = data;
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunk->upData = chunkData.at(topPos);
+ chunkMutex.unlock();
+ }
+ }
+
+ // Set bottom data
+ {
+ ChunkPos bottomPos(chunkPos.x, chunkPos.y - 1, chunkPos.z);
+ chunkMutex.lock();
+ if (chunkData.find(bottomPos) == chunkData.end())
+ {
+ chunkMutex.unlock();
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+
+ WorldGen::GenerateChunkData(bottomPos, d);
+
+ ChunkData* data = new ChunkData(d);
+
+ chunk->downData = data;
+
+ chunkMutex.lock();
+ chunkData[bottomPos] = data;
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunk->downData = chunkData.at(bottomPos);
+ chunkMutex.unlock();
+ }
+ }
+
+ // Set north data
+ {
+ ChunkPos northPos(chunkPos.x, chunkPos.y, chunkPos.z - 1);
+ chunkMutex.lock();
+ if (chunkData.find(northPos) == chunkData.end())
+ {
+ chunkMutex.unlock();
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+
+ WorldGen::GenerateChunkData(northPos, d);
+
+ ChunkData* data = new ChunkData(d);
+
+ chunk->northData = data;
+
+ chunkMutex.lock();
+ chunkData[northPos] = data;
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunk->northData = chunkData.at(northPos);
+ chunkMutex.unlock();
+ }
+ }
+
+ // Set south data
+ {
+ ChunkPos southPos(chunkPos.x, chunkPos.y, chunkPos.z + 1);
+ chunkMutex.lock();
+ if (chunkData.find(southPos) == chunkData.end())
+ {
+ chunkMutex.unlock();
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+
+ WorldGen::GenerateChunkData(southPos, d);
+
+ ChunkData* data = new ChunkData(d);
+
+ chunk->southData = data;
+
+ chunkMutex.lock();
+ chunkData[southPos] = data;
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunk->southData = chunkData.at(southPos);
+ chunkMutex.unlock();
+ }
+ }
+
+ // Set east data
+ {
+ ChunkPos eastPos(chunkPos.x + 1, chunkPos.y, chunkPos.z);
+ chunkMutex.lock();
+ if (chunkData.find(eastPos) == chunkData.end())
+ {
+ chunkMutex.unlock();
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+
+ WorldGen::GenerateChunkData(eastPos, d);
+
+ ChunkData* data = new ChunkData(d);
+
+ chunk->eastData = data;
+
+ chunkMutex.lock();
+ chunkData[eastPos] = data;
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunk->eastData = chunkData.at(eastPos);
+ chunkMutex.unlock();
+ }
+ }
+
+ // Set west data
+ {
+ ChunkPos westPos(chunkPos.x - 1, chunkPos.y, chunkPos.z);
+ chunkMutex.lock();
+ if (chunkData.find(westPos) == chunkData.end())
+ {
+ chunkMutex.unlock();
+ uint16_t* d = new uint16_t[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+
+ WorldGen::GenerateChunkData(westPos, d);
+
+ ChunkData* data = new ChunkData(d);
+
+ chunk->westData = data;
+
+ chunkMutex.lock();
+ chunkData[westPos] = data;
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunk->westData = chunkData.at(westPos);
+ chunkMutex.unlock();
+ }
+ }
+
+ // Generate chunk mesh
+ chunk->GenerateChunkMesh();
+
+ // Finish
+ chunkMutex.lock();
+ chunks[chunkPos] = chunk;
+ chunkQueue.pop();
+ chunkMutex.unlock();
+ }
+ else
+ {
+ chunkMutex.unlock();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ }
+ }
+ }
+ }
}
-Chunk* Planet::GetChunk(int chunkX, int chunkY, int chunkZ)
+Chunk* Planet::GetChunk(ChunkPos chunkPos)
{
- std::tuple chunkTuple{ chunkX, chunkY, chunkZ };
-
- if (chunks.find(chunkTuple) == chunks.end())
+ chunkMutex.lock();
+ if (chunks.find(chunkPos) == chunks.end())
{
+ chunkMutex.unlock();
return nullptr;
}
else
{
- return &chunks.at(chunkTuple);
+ chunkMutex.unlock();
+ return chunks.at(chunkPos);
}
+}
+
+void Planet::ClearChunkQueue()
+{
+ lastCamX++;
}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/Planet.h b/ScuffedMinecraft/src/Planet.h
index 93daad5..7394e1b 100644
--- a/ScuffedMinecraft/src/Planet.h
+++ b/ScuffedMinecraft/src/Planet.h
@@ -5,9 +5,15 @@
#include
#include
#include
+#include
+#include
+#include "ChunkPos.h"
+#include "ChunkData.h"
#include "Chunk.h"
-#include "TupleHash.h"
+#include "ChunkPosHash.h"
+
+constexpr unsigned int CHUNK_SIZE = 32;
class Planet
{
@@ -16,26 +22,38 @@ public:
Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader);
~Planet();
- std::vector GetChunkData(int chunkX, int chunkY, int chunkZ);
- void Update(float camX, float camY, float camZ);
+ ChunkData* GetChunkData(ChunkPos chunkPos);
+ void Update(glm::vec3 cameraPos);
- Chunk* GetChunk(int chunkX, int chunkY, int chunkZ);
+ Chunk* GetChunk(ChunkPos chunkPos);
+ void ClearChunkQueue();
+
+private:
+ void ChunkThreadUpdate();
// Variables
public:
static Planet* planet;
unsigned int numChunks = 0, numChunksRendered = 0;
- static const unsigned int chunkSize;
+ int renderDistance = 10;
+ int renderHeight = 3;
private:
- std::unordered_map, Chunk> chunks;
- std::queue chunkQueue;
- int renderDistance = 3;
- int renderHeight = 1;
+ std::unordered_map chunks;
+ std::unordered_map chunkData;
+ std::queue chunkQueue;
+ std::queue chunkDataQueue;
+ std::queue chunkDataDeleteQueue;
unsigned int chunksLoading = 0;
int lastCamX = -100, lastCamY = -100, lastCamZ = -100;
+ int camChunkX = -100, camChunkY = -100, camChunkZ = -100;
Shader* solidShader;
Shader* waterShader;
Shader* billboardShader;
+
+ std::thread chunkThread;
+ std::mutex chunkMutex;
+
+ bool shouldEnd = false;
};
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/TupleHash.h b/ScuffedMinecraft/src/TupleHash.h
deleted file mode 100644
index 72fdc16..0000000
--- a/ScuffedMinecraft/src/TupleHash.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#include
-// function has to live in the std namespace
-// so that it is picked up by argument-dependent name lookup (ADL).
-namespace std {
- namespace
- {
-
- // Code from boost
- // Reciprocal of the golden ratio helps spread entropy
- // and handles duplicates.
- // See Mike Seymour in magic-numbers-in-boosthash-combine:
- // https://stackoverflow.com/questions/4948780
-
- template
- inline void hash_combine(std::size_t& seed, T const& v)
- {
- seed ^= hash()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- }
-
- // Recursive template code derived from Matthieu M.
- template ::value - 1>
- struct HashValueImpl
- {
- static void apply(size_t& seed, Tuple const& tuple)
- {
- HashValueImpl::apply(seed, tuple);
- hash_combine(seed, get(tuple));
- }
- };
-
- template
- struct HashValueImpl
- {
- static void apply(size_t& seed, Tuple const& tuple)
- {
- hash_combine(seed, get<0>(tuple));
- }
- };
- }
-
- template
- struct hash>
- {
- size_t
- operator()(std::tuple const& tt) const
- {
- size_t seed = 0;
- HashValueImpl >::apply(seed, tt);
- return seed;
- }
-
- };
-}
\ No newline at end of file
diff --git a/ScuffedMinecraft/src/WorldGen.cpp b/ScuffedMinecraft/src/WorldGen.cpp
index 6d434a4..0702c55 100644
--- a/ScuffedMinecraft/src/WorldGen.cpp
+++ b/ScuffedMinecraft/src/WorldGen.cpp
@@ -5,9 +5,12 @@
#include
#include "Blocks.h"
+#include "Planet.h"
-void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector* chunkData)
+void WorldGen::GenerateChunkData(ChunkPos chunkPos, uint16_t* chunkData)
{
+ static int chunkSize = CHUNK_SIZE;
+
// Init noise
static OSN::Noise<2> noise2D;
static OSN::Noise<3> noise3D;
@@ -15,7 +18,7 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
// Init noise settings
static NoiseSettings surfaceSettings[]{
{ 0.01f, 20.0f, 0 },
- { 0.05f, 3.0f, 0 }
+ { 0.05f, 3.0f, 0 }
};
static int surfaceSettingsLength = sizeof(surfaceSettings) / sizeof(*surfaceSettings);
@@ -284,14 +287,12 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
static int waterLevel = 20;
- // Set vector size
- chunkData->reserve(chunkSize * chunkSize * chunkSize);
-
// Account for chunk position
- int startX = chunkX * chunkSize;
- int startY = chunkY * chunkSize;
- int startZ = chunkZ * chunkSize;
+ int startX = chunkPos.x * chunkSize;
+ int startY = chunkPos.y * chunkSize;
+ int startZ = chunkPos.z * chunkSize;
+ int currentIndex = 0;
for (int x = 0; x < chunkSize; x++)
{
for (int z = 0; z < chunkSize; z++)
@@ -334,12 +335,12 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
if (y + startY > noiseY)
{
if (y + startY <= waterLevel)
- chunkData->push_back(Blocks::WATER);
+ chunkData[currentIndex] = Blocks::WATER;
else
- chunkData->push_back(Blocks::AIR);
+ chunkData[currentIndex] = Blocks::AIR;
}
else if (cave)
- chunkData->push_back(Blocks::AIR);
+ chunkData[currentIndex] = Blocks::AIR;
// Ground
else
{
@@ -357,7 +358,7 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
if (noiseOre > oreSettings[i].chance)
{
- chunkData->push_back(oreSettings[i].block);
+ chunkData[currentIndex] = oreSettings[i].block;
blockSet = true;
break;
}
@@ -366,13 +367,21 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
if (!blockSet)
{
if (y + startY == noiseY)
- chunkData->push_back(Blocks::GRASS_BLOCK);
+ if (noiseY > waterLevel + 1)
+ chunkData[currentIndex] = Blocks::GRASS_BLOCK;
+ else
+ chunkData[currentIndex] = Blocks::SAND;
else if (y + startY > 10)
- chunkData->push_back(Blocks::DIRT_BLOCK);
+ if (noiseY > waterLevel + 1)
+ chunkData[currentIndex] = Blocks::DIRT_BLOCK;
+ else
+ chunkData[currentIndex] = Blocks::SAND;
else
- chunkData->push_back(Blocks::STONE_BLOCK);
+ chunkData[currentIndex] = Blocks::STONE_BLOCK;
}
}
+
+ currentIndex++;
}
}
}
@@ -393,11 +402,11 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
* surfaceSettings[s].amplitude;
}
- if (noiseY + surfaceFeatures[i].offsetY > startY + 32 || noiseY + surfaceFeatures[i].sizeY + surfaceFeatures[i].offsetY < startY)
+ if (noiseY + surfaceFeatures[i].offsetY > startY + chunkSize || noiseY + surfaceFeatures[i].sizeY + surfaceFeatures[i].offsetY < startY)
continue;
- // Check if it's in water
- if (noiseY < waterLevel)
+ // Check if it's in water or on sand
+ if (noiseY < waterLevel + 2)
continue;
// Check if it's in a cave
@@ -446,11 +455,11 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
int localZ = featureZ + fZ + surfaceFeatures[i].offsetZ - startZ;
//std::cout << "FeatureZ: " << featureZ << ", fZ: " << fZ << ", startZ: " << startZ << ", localZ: " << localZ << '\n';
- if (localX >= 32 || localX < 0)
+ if (localX >= chunkSize || localX < 0)
continue;
- if (localY >= 32 || localY < 0)
+ if (localY >= chunkSize || localY < 0)
continue;
- if (localZ >= 32 || localZ < 0)
+ if (localZ >= chunkSize || localZ < 0)
continue;
int featureIndex = fY * surfaceFeatures[i].sizeX * surfaceFeatures[i].sizeZ +
@@ -460,8 +469,8 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
int localIndex = localX * chunkSize * chunkSize + localZ * chunkSize + localY;
//std::cout << "Local Index: " << localIndex << ", Max Index: " << chunkData->size() << '\n';
- if (surfaceFeatures[i].replaceBlock[featureIndex] || chunkData->at(localIndex) == 0)
- chunkData->at(localIndex) = surfaceFeatures[i].blocks[featureIndex];
+ if (surfaceFeatures[i].replaceBlock[featureIndex] || chunkData[localIndex] == 0)
+ chunkData[localIndex] = surfaceFeatures[i].blocks[featureIndex];
}
}
}
diff --git a/ScuffedMinecraft/src/WorldGen.h b/ScuffedMinecraft/src/WorldGen.h
index 5b09d1b..101ea91 100644
--- a/ScuffedMinecraft/src/WorldGen.h
+++ b/ScuffedMinecraft/src/WorldGen.h
@@ -3,9 +3,10 @@
#include
#include "NoiseSettings.h"
#include "SurfaceFeature.h"
+#include "ChunkData.h"
+#include "glm/glm.hpp"
namespace WorldGen
{
- void GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector* chunkData);
-
+ void GenerateChunkData(ChunkPos chunkPos, uint16_t* chunkData);
}
\ No newline at end of file