Episode 5

This commit is contained in:
WSAL Evan 2024-11-01 13:41:23 -04:00
parent 70157a4f7f
commit 41e3abe45e
29 changed files with 1257 additions and 404 deletions

View File

@ -157,11 +157,14 @@
<ClCompile Include="src\Block.cpp" /> <ClCompile Include="src\Block.cpp" />
<ClCompile Include="src\Camera.cpp" /> <ClCompile Include="src\Camera.cpp" />
<ClCompile Include="src\Chunk.cpp" /> <ClCompile Include="src\Chunk.cpp" />
<ClCompile Include="src\ChunkData.cpp" />
<ClCompile Include="src\ChunkPos.cpp" />
<ClCompile Include="src\NoiseSettings.cpp" /> <ClCompile Include="src\NoiseSettings.cpp" />
<ClCompile Include="src\Physics.cpp" />
<ClCompile Include="src\Planet.cpp" /> <ClCompile Include="src\Planet.cpp" />
<ClCompile Include="src\Shader.cpp" /> <ClCompile Include="src\Shader.cpp" />
<ClCompile Include="src\SurfaceFeature.cpp" /> <ClCompile Include="src\SurfaceFeature.cpp" />
<ClCompile Include="src\TupleHash.h" /> <ClCompile Include="src\ChunkPosHash.h" />
<ClCompile Include="src\WorldGen.cpp" /> <ClCompile Include="src\WorldGen.cpp" />
<ClCompile Include="src\WorldGen.h" /> <ClCompile Include="src\WorldGen.h" />
<ClCompile Include="vendor\glad.c" /> <ClCompile Include="vendor\glad.c" />
@ -178,7 +181,10 @@
<ClInclude Include="src\Blocks.h" /> <ClInclude Include="src\Blocks.h" />
<ClInclude Include="src\Camera.h" /> <ClInclude Include="src\Camera.h" />
<ClInclude Include="src\Chunk.h" /> <ClInclude Include="src\Chunk.h" />
<ClInclude Include="src\ChunkData.h" />
<ClInclude Include="src\ChunkPos.h" />
<ClInclude Include="src\NoiseSettings.h" /> <ClInclude Include="src\NoiseSettings.h" />
<ClInclude Include="src\Physics.h" />
<ClInclude Include="src\Planet.h" /> <ClInclude Include="src\Planet.h" />
<ClInclude Include="src\Shader.h" /> <ClInclude Include="src\Shader.h" />
<ClInclude Include="src\SurfaceFeature.h" /> <ClInclude Include="src\SurfaceFeature.h" />
@ -198,6 +204,10 @@
<ItemGroup> <ItemGroup>
<None Include="assets\shaders\billboard_frag.glsl" /> <None Include="assets\shaders\billboard_frag.glsl" />
<None Include="assets\shaders\billboard_vert.glsl" /> <None Include="assets\shaders\billboard_vert.glsl" />
<None Include="assets\shaders\block_outline_frag.glsl" />
<None Include="assets\shaders\block_outline_vert.glsl" />
<None Include="assets\shaders\crosshair_frag.glsl" />
<None Include="assets\shaders\crosshair_vert.glsl" />
<None Include="assets\shaders\framebuffer_frag.glsl" /> <None Include="assets\shaders\framebuffer_frag.glsl" />
<None Include="assets\shaders\framebuffer_vert.glsl" /> <None Include="assets\shaders\framebuffer_vert.glsl" />
<None Include="assets\shaders\main_frag.glsl" /> <None Include="assets\shaders\main_frag.glsl" />
@ -207,6 +217,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="assets\sprites\block_map.png" /> <Image Include="assets\sprites\block_map.png" />
<Image Include="assets\sprites\crosshair.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Text Include="vendor\imgui\LICENSE.txt" /> <Text Include="vendor\imgui\LICENSE.txt" />

View File

@ -33,7 +33,7 @@
<ClCompile Include="src\Block.cpp"> <ClCompile Include="src\Block.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\TupleHash.h"> <ClCompile Include="src\ChunkPosHash.h">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\WorldGen.h"> <ClCompile Include="src\WorldGen.h">
@ -72,6 +72,15 @@
<ClCompile Include="src\SurfaceFeature.cpp"> <ClCompile Include="src\SurfaceFeature.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Physics.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ChunkPos.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ChunkData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\Shader.h"> <ClInclude Include="src\Shader.h">
@ -134,6 +143,15 @@
<ClInclude Include="src\Vertex.h"> <ClInclude Include="src\Vertex.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\Physics.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\ChunkPos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\ChunkData.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="assets\shaders\main_vert.glsl" /> <None Include="assets\shaders\main_vert.glsl" />
@ -144,11 +162,18 @@
<None Include="assets\shaders\billboard_frag.glsl" /> <None Include="assets\shaders\billboard_frag.glsl" />
<None Include="assets\shaders\framebuffer_vert.glsl" /> <None Include="assets\shaders\framebuffer_vert.glsl" />
<None Include="assets\shaders\framebuffer_frag.glsl" /> <None Include="assets\shaders\framebuffer_frag.glsl" />
<None Include="assets\shaders\block_outline_vert.glsl" />
<None Include="assets\shaders\block_outline_frag.glsl" />
<None Include="assets\shaders\crosshair_frag.glsl" />
<None Include="assets\shaders\crosshair_vert.glsl" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="assets\sprites\block_map.png"> <Image Include="assets\sprites\block_map.png">
<Filter>Resource Files</Filter> <Filter>Resource Files</Filter>
</Image> </Image>
<Image Include="assets\sprites\crosshair.png">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Text Include="vendor\imgui\LICENSE.txt" /> <Text Include="vendor\imgui\LICENSE.txt" />

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

View File

@ -24,11 +24,13 @@
#include "Camera.h" #include "Camera.h"
#include "Planet.h" #include "Planet.h"
#include "Blocks.h" #include "Blocks.h"
#include "Physics.h"
void framebufferSizeCallback(GLFWwindow* window, int width, int height); void framebufferSizeCallback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window); void processInput(GLFWwindow* window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos); void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); 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 deltaTime = 0.0f;
float lastFrame = 0.0f; float lastFrame = 0.0f;
@ -42,18 +44,22 @@ bool firstMouse = true;
bool menuMode = false; bool menuMode = false;
bool escapeDown = false; bool escapeDown = false;
bool f1Down = false;
// Window settings
float windowX = 1920; float windowX = 1920;
float windowY = 1080; float windowY = 1080;
bool vsync = true;
uint16_t selectedBlock = 1;
bool uiEnabled = true;
Camera camera; Camera camera;
GLuint framebufferTexture; GLuint framebufferTexture;
GLuint depthTexture; GLuint depthTexture;
// Window options
#define VSYNC 1 // 0 for off, 1 for on
float rectangleVertices[] = float rectangleVertices[] =
{ {
// Coords // TexCoords // Coords // TexCoords
@ -66,39 +72,66 @@ float rectangleVertices[] =
-1.0f, 1.0f, 0.0f, 1.0f -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 #ifdef LINUX
char* resolved_path = realpath(argv[0],NULL); char* resolved_path = realpath(argv[0], NULL);
if (resolved_path == NULL) { if (resolved_path == NULL) {
printf("%s: Please do not place binary in PATH\n", argv[0]); printf("%s: Please do not place binary in PATH\n", argv[0]);
exit(1); exit(1);
} }
size_t resolved_length = strlen(resolved_path); 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 chdir(resolved_path);
for (size_t i = resolved_length; i > 0; i--) { free(resolved_path);
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);
#endif #endif
// Initialize GLFW // Initialize GLFW
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
@ -114,7 +147,7 @@ int main (int argc, char *argv[]) {
return -1; return -1;
} }
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glfwSwapInterval(VSYNC); glfwSwapInterval(vsync ? 1 : 0);
// Initialize GLAD // Initialize GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
@ -128,6 +161,7 @@ int main (int argc, char *argv[]) {
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback); glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwSetCursorPosCallback(window, mouse_callback); glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback); glfwSetScrollCallback(window, scroll_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glClearColor(0.6f, 0.8f, 1.0f, 1.0f); 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 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 // Create post-processing framebuffer
unsigned int FBO; unsigned int FBO;
glGenFramebuffers(1, &FBO); glGenFramebuffers(1, &FBO);
@ -198,6 +236,26 @@ int main (int argc, char *argv[]) {
glUniform1i(glGetUniformLocation(framebufferShader.ID, "screenTexture"), 0); glUniform1i(glGetUniformLocation(framebufferShader.ID, "screenTexture"), 0);
glUniform1i(glGetUniformLocation(framebufferShader.ID, "depthTexture"), 1); 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); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Create terrain texture // Create terrain texture
@ -227,6 +285,30 @@ int main (int argc, char *argv[]) {
stbi_image_free(data); 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 // Create camera
camera = Camera(glm::vec3(0.0f, 25.0f, 0.0f)); 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); 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 // Initialize ImGui
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
@ -270,6 +354,8 @@ int main (int argc, char *argv[]) {
waterShader.use(); waterShader.use();
waterShader.setFloat("time", currentFrame); waterShader.setFloat("time", currentFrame);
outlineShader.use();
outlineShader.setFloat("time", currentFrame);
// Input // Input
processInput(window); processInput(window);
@ -311,24 +397,60 @@ int main (int argc, char *argv[]) {
projectionLoc = glGetUniformLocation(billboardShader.ID, "projection"); projectionLoc = glGetUniformLocation(billboardShader.ID, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(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(); framebufferShader.use();
// -- Post Processing Stuff -- //
// Check if player is underwater // Check if player is underwater
int blockX = camera.Position.x < 0 ? camera.Position.x - 1 : camera.Position.x; 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 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 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 chunkX = blockX < 0 ? floorf(blockX / (float)CHUNK_SIZE) : blockX / (int)CHUNK_SIZE;
int chunkY = blockY < 0 ? floorf(blockY / (float)Planet::chunkSize) : blockY / (int)Planet::chunkSize; int chunkY = blockY < 0 ? floorf(blockY / (float)CHUNK_SIZE) : blockY / (int)CHUNK_SIZE;
int chunkZ = blockZ < 0 ? floorf(blockZ / (float)Planet::chunkSize) : blockZ / (int)Planet::chunkSize; int chunkZ = blockZ < 0 ? floorf(blockZ / (float)CHUNK_SIZE) : blockZ / (int)CHUNK_SIZE;
int localBlockX = blockX - (chunkX * Planet::chunkSize); int localBlockX = blockX - (chunkX * CHUNK_SIZE);
int localBlockY = blockY - (chunkY * Planet::chunkSize); int localBlockY = blockY - (chunkY * CHUNK_SIZE);
int localBlockZ = blockZ - (chunkZ * Planet::chunkSize); 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) if (chunk != nullptr)
{ {
unsigned int blockType = chunk->GetBlockAtPos( unsigned int blockType = chunk->GetBlockAtPos(
@ -346,6 +468,7 @@ int main (int argc, char *argv[]) {
} }
} }
// Post Processing
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindVertexArray(rectVAO); glBindVertexArray(rectVAO);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -355,15 +478,50 @@ int main (int argc, char *argv[]) {
glBindTexture(GL_TEXTURE_2D, depthTexture); glBindTexture(GL_TEXTURE_2D, depthTexture);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
// Draw ImGui UI if (uiEnabled)
ImGui::Begin("Test"); {
ImGui::Text("FPS: %f (Avg: %f, Min: %f, Max: %f)", fps, avgFps, lowestFps, highestFps); // -- Render Crosshair -- //
ImGui::Text("MS: %f", deltaTime * 100.0f);
ImGui::Text("Chunks: %d (%d rendered)", Planet::planet->numChunks, Planet::planet->numChunksRendered);
ImGui::End();
ImGui::Render(); // Render
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 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 // Check and call events and swap buffers
glfwSwapBuffers(window); glfwSwapBuffers(window);
@ -372,6 +530,8 @@ int main (int argc, char *argv[]) {
//std::cout << camera.Position.x << ", " << camera.Position.y << ", " << camera.Position.z << '\n'; //std::cout << camera.Position.x << ", " << camera.Position.y << ", " << camera.Position.z << '\n';
} }
delete Planet::planet;
ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown(); ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
@ -388,7 +548,6 @@ void framebufferSizeCallback(GLFWwindow* window, int width, int height)
// resize framebuffer texture // resize framebuffer texture
glBindTexture(GL_TEXTURE_2D, framebufferTexture); glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, windowX, windowY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, windowX, windowY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
// resize framebuffer depth texture // resize framebuffer depth texture
glBindTexture(GL_TEXTURE_2D, depthTexture); glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, windowX, windowY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); 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) void processInput(GLFWwindow* window)
{ {
// Pause
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{ {
if (escapeDown) if (escapeDown)
@ -410,6 +570,18 @@ void processInput(GLFWwindow* window)
else else
escapeDown = false; 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_W) == GLFW_PRESS)
{ {
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
@ -429,6 +601,61 @@ void processInput(GLFWwindow* window)
camera.ProcessKeyboard(DOWN, deltaTime); 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) void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{ {
if (menuMode) if (menuMode)

View File

@ -1,7 +1,7 @@
#include "Block.h" #include "Block.h"
Block::Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType) Block::Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType, std::string blockName)
: blockType(blockType) : blockType(blockType), blockName(blockName)
{ {
topMinX = minX; topMinX = minX;
topMinY = minY; 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, Block::Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY, 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)
: blockType(blockType) : blockType(blockType), blockName(blockName)
{ {
this->topMinX = topMinX; this->topMinX = topMinX;
this->topMinY = topMinY; this->topMinY = topMinY;

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <string>
struct Block struct Block
{ {
public: public:
@ -16,10 +18,11 @@ public:
char bottomMinX, bottomMinY, bottomMaxX, bottomMaxY; char bottomMinX, bottomMinY, bottomMaxX, bottomMaxY;
char sideMinX, sideMinY, sideMaxX, sideMaxY; char sideMinX, sideMinY, sideMaxX, sideMaxY;
BLOCK_TYPE blockType; 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, Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY, 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);
}; };

View File

@ -1,34 +1,36 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <array>
#include "Block.h" #include "Block.h"
namespace Blocks namespace Blocks
{ {
const std::vector<Block> blocks{ const std::vector<Block> blocks{
Block(0, 0, 0, 0, Block::TRANSPARENT), // Air block Block(0, 0, 0, 0, Block::TRANSPARENT, "Air"), // Air block
Block(0, 0, 1, 1, Block::SOLID), // Dirt 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, 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, 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(0, 2, 1, 3, Block::LEAVES, "Leaves"), // Leaves
Block(1, 2, 2, 3, Block::BILLBOARD), // Grass Block(1, 2, 2, 3, Block::BILLBOARD, "Grass"), // Grass
Block(3, 0, 4, 1, Block::BILLBOARD), // Tall Grass Bottom Block(3, 0, 4, 1, Block::BILLBOARD, "Tall Grass Bot"), // Tall Grass Bottom
Block(3, 1, 4, 2, Block::BILLBOARD), // Tall Grass Top Block(3, 1, 4, 2, Block::BILLBOARD, "Tall Grass Top"), // Tall Grass Top
Block(0, 3, 1, 4, Block::BILLBOARD), // Poppy Block(0, 3, 1, 4, Block::BILLBOARD, "Poppy"), // Poppy
Block(2, 2, 3, 3, Block::BILLBOARD), // White Tulip Block(2, 2, 3, 3, Block::BILLBOARD, "White Tulip"), // White Tulip
Block(3, 2, 4, 3, Block::BILLBOARD), // Pink Tulip Block(3, 2, 4, 3, Block::BILLBOARD, "Pink Tulip"), // Pink Tulip
Block(1, 3, 2, 4, Block::BILLBOARD), // Orange Tulip Block(1, 3, 2, 4, Block::BILLBOARD, "Orange Tulip"), // Orange Tulip
Block(0, 4, 1, 5, Block::LIQUID) // Water Block(0, 4, 1, 5, Block::LIQUID, "Water"), // Water
Block(4, 0, 5, 1, Block::SOLID, "Sand"), // Sand
}; };
enum BLOCKS enum BLOCKS
@ -46,6 +48,7 @@ namespace Blocks
WHITE_TULIP = 10, WHITE_TULIP = 10,
PINK_TULIP = 11, PINK_TULIP = 11,
ORANGE_TULIP = 12, ORANGE_TULIP = 12,
WATER = 13 WATER = 13,
SAND = 14,
}; };
} }

View File

@ -38,9 +38,9 @@ void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime)
if (direction == RIGHT) if (direction == RIGHT)
Position += Right * velocity; Position += Right * velocity;
if (direction == UP) if (direction == UP)
Position.y += 1 * velocity; Position += (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
if (direction == DOWN) if (direction == DOWN)
Position.y -= 1 * velocity; Position -= (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
if (direction == FORWARD_NO_Y) if (direction == FORWARD_NO_Y)
{ {
glm::vec3 moveDir = Front; glm::vec3 moveDir = Front;

View File

@ -36,6 +36,7 @@ public:
float MovementSpeed; float MovementSpeed;
float MouseSensitivity; float MouseSensitivity;
float Zoom; 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); 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);

View File

@ -10,14 +10,13 @@
#include "Blocks.h" #include "Blocks.h"
#include "WorldGen.h" #include "WorldGen.h"
Chunk::Chunk(unsigned int chunkSize, glm::vec3 chunkPos, Shader* shader, Shader* waterShader) Chunk::Chunk(ChunkPos chunkPos, Shader* shader, Shader* waterShader)
: chunkSize(chunkSize), chunkPos(chunkPos) : 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; ready = false;
generated = false; generated = false;
chunkThread = std::thread(&Chunk::GenerateChunk, this);
} }
Chunk::~Chunk() Chunk::~Chunk()
@ -38,47 +37,41 @@ Chunk::~Chunk()
glDeleteVertexArrays(1, &billboardVAO); glDeleteVertexArrays(1, &billboardVAO);
} }
void Chunk::GenerateChunk() void Chunk::GenerateChunkMesh()
{ {
//std::cout << "Started thread: " << std::this_thread::get_id() << '\n'; mainVertices.clear();
mainIndices.clear();
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z, chunkSize, &chunkData); waterVertices.clear();
std::vector<unsigned int> northData, southData, eastData, westData, upData, downData; waterIndices.clear();
billboardVertices.clear();
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z - 1, chunkSize, &northData); billboardIndices.clear();
WorldGen::GenerateChunkData(chunkPos.x, chunkPos.y, chunkPos.z + 1, chunkSize, &southData); numTrianglesMain = 0;
WorldGen::GenerateChunkData(chunkPos.x + 1, chunkPos.y, chunkPos.z, chunkSize, &eastData); numTrianglesWater = 0;
WorldGen::GenerateChunkData(chunkPos.x - 1, chunkPos.y, chunkPos.z, chunkSize, &westData); numTrianglesBillboard = 0;
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';
unsigned int currentVertex = 0; unsigned int currentVertex = 0;
unsigned int currentLiquidVertex = 0; unsigned int currentLiquidVertex = 0;
unsigned int currentBillboardVertex = 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->GetBlock(x, y, z) == 0)
if (chunkData[index] == 0)
continue; continue;
const Block* block = &Blocks::blocks[chunkData[index]]; const Block* block = &Blocks::blocks[chunkData->GetBlock(x, y, z)];
int topBlock; int topBlock;
if (y < chunkSize - 1) if (y < CHUNK_SIZE - 1)
{ {
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y + 1); topBlock = chunkData->GetBlock(x, y + 1, z);
topBlock = chunkData[blockIndex];
} }
else else
{ {
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + 0; int blockIndex = x * CHUNK_SIZE * CHUNK_SIZE + z * CHUNK_SIZE + 0;
topBlock = upData[blockIndex]; topBlock = upData->GetBlock(x, 0, z);
} }
const Block* topBlockType = &Blocks::blocks[topBlock]; const Block* topBlockType = &Blocks::blocks[topBlock];
@ -119,13 +112,11 @@ void Chunk::GenerateChunk()
int northBlock; int northBlock;
if (z > 0) if (z > 0)
{ {
int northIndex = x * chunkSize * chunkSize + (z - 1) * chunkSize + y; northBlock = chunkData->GetBlock(x, y, z - 1);
northBlock = chunkData[northIndex];
} }
else else
{ {
int northIndex = x * chunkSize * chunkSize + (chunkSize - 1) * chunkSize + y; northBlock = northData->GetBlock(x, y, CHUNK_SIZE - 1);
northBlock = northData[northIndex];
} }
const Block* northBlockType = &Blocks::blocks[northBlock]; 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 + 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)); mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0));
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1); mainIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2); mainIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
currentVertex += 4; currentVertex += 4;
} }
} }
@ -171,15 +162,13 @@ void Chunk::GenerateChunk()
// South // South
{ {
int southBlock; int southBlock;
if (z < chunkSize - 1) if (z < CHUNK_SIZE - 1)
{ {
int southIndex = x * chunkSize * chunkSize + (z + 1) * chunkSize + y; southBlock = chunkData->GetBlock(x, y, z + 1);
southBlock = chunkData[southIndex];
} }
else else
{ {
int southIndex = x * chunkSize * chunkSize + 0 * chunkSize + y; southBlock = southData->GetBlock(x, y, 0);
southBlock = southData[southIndex];
} }
const Block* southBlockType = &Blocks::blocks[southBlock]; 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 + 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)); mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1));
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1); mainIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2); mainIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
currentVertex += 4; currentVertex += 4;
} }
} }
@ -227,13 +216,11 @@ void Chunk::GenerateChunk()
int westBlock; int westBlock;
if (x > 0) if (x > 0)
{ {
int blockIndex = (x - 1) * chunkSize * chunkSize + z * chunkSize + y; westBlock = chunkData->GetBlock(x - 1, y, z);
westBlock = chunkData[blockIndex];
} }
else else
{ {
int blockIndex = (chunkSize - 1) * chunkSize * chunkSize + z * chunkSize + y; westBlock = westData->GetBlock(CHUNK_SIZE - 1, y, z);
westBlock = westData[blockIndex];
} }
const Block* westBlockType = &Blocks::blocks[westBlock]; 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 + 0, block->sideMinX, block->sideMaxY, 2));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2)); mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2));
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1); mainIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2); mainIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
currentVertex += 4; currentVertex += 4;
} }
} }
@ -279,15 +266,13 @@ void Chunk::GenerateChunk()
// East // East
{ {
int eastBlock; int eastBlock;
if (x < chunkSize - 1) if (x < CHUNK_SIZE - 1)
{ {
int blockIndex = (x + 1) * chunkSize * chunkSize + z * chunkSize + y; eastBlock = chunkData->GetBlock(x + 1, y, z);
eastBlock = chunkData[blockIndex];
} }
else else
{ {
int blockIndex = 0 * chunkSize * chunkSize + z * chunkSize + y; eastBlock = eastData->GetBlock(0, y, z);
eastBlock = eastData[blockIndex];
} }
const Block* eastBlockType = &Blocks::blocks[eastBlock]; 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 + 1, block->sideMinX, block->sideMaxY, 3));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3)); mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3));
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1); mainIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2); mainIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
currentVertex += 4; currentVertex += 4;
} }
} }
@ -335,13 +320,12 @@ void Chunk::GenerateChunk()
int bottomBlock; int bottomBlock;
if (y > 0) if (y > 0)
{ {
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y - 1); bottomBlock = chunkData->GetBlock(x, y - 1, z);
bottomBlock = chunkData[blockIndex];
} }
else else
{ {
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1); //int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1);
bottomBlock = downData[blockIndex]; bottomBlock = downData->GetBlock(x, CHUNK_SIZE - 1, z);
} }
const Block* bottomBlockType = &Blocks::blocks[bottomBlock]; 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 + 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)); mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4));
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1); mainIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2); mainIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
currentVertex += 4; 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 + 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)); mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5));
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1); mainIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0); mainIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2); mainIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3); mainIndices.push_back(currentVertex + 3);
currentVertex += 4; currentVertex += 4;
} }
} }
@ -455,7 +439,7 @@ void Chunk::Render(Shader* mainShader, Shader* billboardShader)
if (generated) if (generated)
{ {
// Solid // Solid
numTrianglesMain = mianIndices.size(); numTrianglesMain = mainIndices.size();
glGenVertexArrays(1, &mainVAO); glGenVertexArrays(1, &mainVAO);
glGenBuffers(1, &mainVBO); 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); glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO); 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)); glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX));
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
@ -572,11 +556,128 @@ void Chunk::RenderWater(Shader* shader)
glDrawElements(GL_TRIANGLES, numTrianglesWater, GL_UNSIGNED_INT, 0); 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) if (!ready)
return 0; return 0;
int index = x * chunkSize * chunkSize + z * chunkSize + y; return chunkData->GetBlock(x, y, z);
return chunkData[index]; }
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);
} }

View File

@ -6,31 +6,40 @@
#include "Shader.h" #include "Shader.h"
#include "Vertex.h" #include "Vertex.h"
#include "ChunkPos.h"
#include "ChunkData.h"
class Chunk class Chunk
{ {
public: public:
Chunk(unsigned int chunkSize, glm::vec3 chunkPos, Shader* shader, Shader* waterShader); Chunk(ChunkPos chunkPos, Shader* shader, Shader* waterShader);
~Chunk(); ~Chunk();
void GenerateChunk(); void GenerateChunkMesh();
void Render(Shader* mainShader, Shader* billboardShader); void Render(Shader* mainShader, Shader* billboardShader);
void RenderWater(Shader* shader); 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: public:
std::vector<unsigned int> chunkData; ChunkData* chunkData;
glm::vec3 chunkPos; ChunkData* northData;
ChunkData* southData;
ChunkData* upData;
ChunkData* downData;
ChunkData* eastData;
ChunkData* westData;
ChunkPos chunkPos;
bool ready; bool ready;
bool generated; bool generated;
private: private:
unsigned int chunkSize;
glm::vec3 worldPos; glm::vec3 worldPos;
std::thread chunkThread; std::thread chunkThread;
std::vector<Vertex> mainVertices; std::vector<Vertex> mainVertices;
std::vector<unsigned int> mianIndices; std::vector<unsigned int> mainIndices;
std::vector<WaterVertex> waterVertices; std::vector<WaterVertex> waterVertices;
std::vector<unsigned int> waterIndices; std::vector<unsigned int> waterIndices;
std::vector<BillboardVertex> billboardVertices; std::vector<BillboardVertex> billboardVertices;

View File

@ -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;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <cstdint>
#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);
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -0,0 +1,15 @@
#include "ChunkPos.h"
#include <unordered_map>
struct ChunkPosHash
{
std::size_t operator()(const ChunkPos& key) const
{
std::size_t hx = std::hash<int>()(key.x);
std::size_t hy = std::hash<int>()(key.y);
std::size_t hz = std::hash<int>()(key.z);
// Combine the hashes using bitwise XOR and shifting
return hx ^ (hy << 1) ^ (hz << 2);
}
};

View File

@ -0,0 +1,47 @@
#include "Physics.h"
#include <iostream>
#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};
}

View File

@ -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;
}

View File

@ -4,169 +4,69 @@
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "WorldGen.h"
Planet* Planet::planet = nullptr; Planet* Planet::planet = nullptr;
const unsigned int Planet::chunkSize = 32; //static const unsigned int CHUNK_SIZE = 32;
// Public // Public
Planet::Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader) Planet::Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader)
: solidShader(solidShader), waterShader(waterShader), billboardShader(billboardShader) : solidShader(solidShader), waterShader(waterShader), billboardShader(billboardShader)
{ {
chunkThread = std::thread(&Planet::ChunkThreadUpdate, this);
} }
Planet::~Planet() Planet::~Planet()
{ {
shouldEnd = true;
chunkThread.join();
} }
std::vector<unsigned int> Planet::GetChunkData(int chunkX, int chunkY, int chunkZ) void Planet::Update(glm::vec3 cameraPos)
{ {
std::tuple<int, int, int> chunkTuple{ chunkX, chunkY, chunkZ }; 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;
if (chunks.find(chunkTuple) == chunks.end()) camChunkZ = cameraPos.z < 0 ? floor(cameraPos.z / CHUNK_SIZE) : cameraPos.z / CHUNK_SIZE;
{
return std::vector<unsigned int>{};
//return GenerateChunkData(chunkX, chunkY, chunkZ);
}
else
{
return std::vector<unsigned int>{};
//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<int, int, int> chunkTuple{ next.x, next.y, next.z };
if (chunks.find(chunkTuple) == chunks.end())
{
chunks.try_emplace(chunkTuple,
chunkSize, next, solidShader, waterShader
);
}
}
glDisable(GL_BLEND); glDisable(GL_BLEND);
chunksLoading = 0; chunksLoading = 0;
numChunks = 0; numChunks = 0;
numChunksRendered = 0; numChunksRendered = 0;
chunkMutex.lock();
for (auto it = chunks.begin(); it != chunks.end(); ) for (auto it = chunks.begin(); it != chunks.end(); )
{ {
numChunks++; numChunks++;
if (!it->second.ready) if (!(*it->second).ready)
chunksLoading++; chunksLoading++;
int chunkX = it->second.chunkPos.x; int chunkX = (*it->second).chunkPos.x;
int chunkY = it->second.chunkPos.y; int chunkY = (*it->second).chunkPos.y;
int chunkZ = it->second.chunkPos.z; int chunkZ = (*it->second).chunkPos.z;
if (it->second.ready && (abs(chunkX - camChunkX) > renderDistance || if ((*it->second).ready && (abs(chunkX - camChunkX) > renderDistance ||
abs(chunkY - camChunkY) > renderDistance || abs(chunkY - camChunkY) > renderDistance ||
abs(chunkZ - camChunkZ) > 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); it = chunks.erase(it);
} }
else else
{ {
numChunksRendered++; numChunksRendered++;
it->second.Render(solidShader, billboardShader); (*it->second).Render(solidShader, billboardShader);
++it; ++it;
} }
} }
@ -175,25 +75,387 @@ void Planet::Update(float camX, float camY, float camZ)
waterShader->use(); waterShader->use();
for (auto it = chunks.begin(); it != chunks.end(); ) for (auto it = chunks.begin(); it != chunks.end(); )
{ {
int chunkX = it->second.chunkPos.x; int chunkX = (*it->second).chunkPos.x;
int chunkY = it->second.chunkPos.y; int chunkY = (*it->second).chunkPos.y;
int chunkZ = it->second.chunkPos.z; int chunkZ = (*it->second).chunkPos.z;
it->second.RenderWater(waterShader); (*it->second).RenderWater(waterShader);
++it; ++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<int, int, int> chunkTuple{ chunkX, chunkY, chunkZ }; chunkMutex.lock();
if (chunks.find(chunkPos) == chunks.end())
if (chunks.find(chunkTuple) == chunks.end())
{ {
chunkMutex.unlock();
return nullptr; return nullptr;
} }
else else
{ {
return &chunks.at(chunkTuple); chunkMutex.unlock();
return chunks.at(chunkPos);
} }
} }
void Planet::ClearChunkQueue()
{
lastCamX++;
}

View File

@ -5,9 +5,15 @@
#include <string> #include <string>
#include <queue> #include <queue>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <thread>
#include <mutex>
#include "ChunkPos.h"
#include "ChunkData.h"
#include "Chunk.h" #include "Chunk.h"
#include "TupleHash.h" #include "ChunkPosHash.h"
constexpr unsigned int CHUNK_SIZE = 32;
class Planet class Planet
{ {
@ -16,26 +22,38 @@ public:
Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader); Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader);
~Planet(); ~Planet();
std::vector<unsigned int> GetChunkData(int chunkX, int chunkY, int chunkZ); ChunkData* GetChunkData(ChunkPos chunkPos);
void Update(float camX, float camY, float camZ); void Update(glm::vec3 cameraPos);
Chunk* GetChunk(int chunkX, int chunkY, int chunkZ); Chunk* GetChunk(ChunkPos chunkPos);
void ClearChunkQueue();
private:
void ChunkThreadUpdate();
// Variables // Variables
public: public:
static Planet* planet; static Planet* planet;
unsigned int numChunks = 0, numChunksRendered = 0; unsigned int numChunks = 0, numChunksRendered = 0;
static const unsigned int chunkSize; int renderDistance = 10;
int renderHeight = 3;
private: private:
std::unordered_map<std::tuple<int, int, int>, Chunk> chunks; std::unordered_map<ChunkPos, Chunk*, ChunkPosHash> chunks;
std::queue<glm::vec3> chunkQueue; std::unordered_map<ChunkPos, ChunkData*, ChunkPosHash> chunkData;
int renderDistance = 3; std::queue<ChunkPos> chunkQueue;
int renderHeight = 1; std::queue<ChunkPos> chunkDataQueue;
std::queue<ChunkPos> chunkDataDeleteQueue;
unsigned int chunksLoading = 0; unsigned int chunksLoading = 0;
int lastCamX = -100, lastCamY = -100, lastCamZ = -100; int lastCamX = -100, lastCamY = -100, lastCamZ = -100;
int camChunkX = -100, camChunkY = -100, camChunkZ = -100;
Shader* solidShader; Shader* solidShader;
Shader* waterShader; Shader* waterShader;
Shader* billboardShader; Shader* billboardShader;
std::thread chunkThread;
std::mutex chunkMutex;
bool shouldEnd = false;
}; };

View File

@ -1,53 +0,0 @@
#include <tuple>
// 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 <class T>
inline void hash_combine(std::size_t& seed, T const& v)
{
seed ^= hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
// Recursive template code derived from Matthieu M.
template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
struct HashValueImpl
{
static void apply(size_t& seed, Tuple const& tuple)
{
HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
hash_combine(seed, get<Index>(tuple));
}
};
template <class Tuple>
struct HashValueImpl<Tuple, 0>
{
static void apply(size_t& seed, Tuple const& tuple)
{
hash_combine(seed, get<0>(tuple));
}
};
}
template <typename ... TT>
struct hash<std::tuple<TT...>>
{
size_t
operator()(std::tuple<TT...> const& tt) const
{
size_t seed = 0;
HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
return seed;
}
};
}

View File

@ -5,9 +5,12 @@
#include <OpenSimplexNoise.hh> #include <OpenSimplexNoise.hh>
#include "Blocks.h" #include "Blocks.h"
#include "Planet.h"
void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector<unsigned int>* chunkData) void WorldGen::GenerateChunkData(ChunkPos chunkPos, uint16_t* chunkData)
{ {
static int chunkSize = CHUNK_SIZE;
// Init noise // Init noise
static OSN::Noise<2> noise2D; static OSN::Noise<2> noise2D;
static OSN::Noise<3> noise3D; static OSN::Noise<3> noise3D;
@ -15,7 +18,7 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
// Init noise settings // Init noise settings
static NoiseSettings surfaceSettings[]{ static NoiseSettings surfaceSettings[]{
{ 0.01f, 20.0f, 0 }, { 0.01f, 20.0f, 0 },
{ 0.05f, 3.0f, 0 } { 0.05f, 3.0f, 0 }
}; };
static int surfaceSettingsLength = sizeof(surfaceSettings) / sizeof(*surfaceSettings); 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; static int waterLevel = 20;
// Set vector size
chunkData->reserve(chunkSize * chunkSize * chunkSize);
// Account for chunk position // Account for chunk position
int startX = chunkX * chunkSize; int startX = chunkPos.x * chunkSize;
int startY = chunkY * chunkSize; int startY = chunkPos.y * chunkSize;
int startZ = chunkZ * chunkSize; int startZ = chunkPos.z * chunkSize;
int currentIndex = 0;
for (int x = 0; x < chunkSize; x++) for (int x = 0; x < chunkSize; x++)
{ {
for (int z = 0; z < chunkSize; z++) 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 > noiseY)
{ {
if (y + startY <= waterLevel) if (y + startY <= waterLevel)
chunkData->push_back(Blocks::WATER); chunkData[currentIndex] = Blocks::WATER;
else else
chunkData->push_back(Blocks::AIR); chunkData[currentIndex] = Blocks::AIR;
} }
else if (cave) else if (cave)
chunkData->push_back(Blocks::AIR); chunkData[currentIndex] = Blocks::AIR;
// Ground // Ground
else else
{ {
@ -357,7 +358,7 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
if (noiseOre > oreSettings[i].chance) if (noiseOre > oreSettings[i].chance)
{ {
chunkData->push_back(oreSettings[i].block); chunkData[currentIndex] = oreSettings[i].block;
blockSet = true; blockSet = true;
break; break;
} }
@ -366,13 +367,21 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
if (!blockSet) if (!blockSet)
{ {
if (y + startY == noiseY) 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) 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 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; * 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; continue;
// Check if it's in water // Check if it's in water or on sand
if (noiseY < waterLevel) if (noiseY < waterLevel + 2)
continue; continue;
// Check if it's in a cave // 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; int localZ = featureZ + fZ + surfaceFeatures[i].offsetZ - startZ;
//std::cout << "FeatureZ: " << featureZ << ", fZ: " << fZ << ", startZ: " << startZ << ", localZ: " << localZ << '\n'; //std::cout << "FeatureZ: " << featureZ << ", fZ: " << fZ << ", startZ: " << startZ << ", localZ: " << localZ << '\n';
if (localX >= 32 || localX < 0) if (localX >= chunkSize || localX < 0)
continue; continue;
if (localY >= 32 || localY < 0) if (localY >= chunkSize || localY < 0)
continue; continue;
if (localZ >= 32 || localZ < 0) if (localZ >= chunkSize || localZ < 0)
continue; continue;
int featureIndex = fY * surfaceFeatures[i].sizeX * surfaceFeatures[i].sizeZ + 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; int localIndex = localX * chunkSize * chunkSize + localZ * chunkSize + localY;
//std::cout << "Local Index: " << localIndex << ", Max Index: " << chunkData->size() << '\n'; //std::cout << "Local Index: " << localIndex << ", Max Index: " << chunkData->size() << '\n';
if (surfaceFeatures[i].replaceBlock[featureIndex] || chunkData->at(localIndex) == 0) if (surfaceFeatures[i].replaceBlock[featureIndex] || chunkData[localIndex] == 0)
chunkData->at(localIndex) = surfaceFeatures[i].blocks[featureIndex]; chunkData[localIndex] = surfaceFeatures[i].blocks[featureIndex];
} }
} }
} }

View File

@ -3,9 +3,10 @@
#include <vector> #include <vector>
#include "NoiseSettings.h" #include "NoiseSettings.h"
#include "SurfaceFeature.h" #include "SurfaceFeature.h"
#include "ChunkData.h"
#include "glm/glm.hpp"
namespace WorldGen namespace WorldGen
{ {
void GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector<unsigned int>* chunkData); void GenerateChunkData(ChunkPos chunkPos, uint16_t* chunkData);
} }