Compare commits
17 Commits
pre-alpha-
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
ccacb3088f | ||
|
93897037b8 | ||
|
90f1cc59d5 | ||
|
b4e22d076b | ||
|
41e3abe45e | ||
|
70157a4f7f | ||
|
a34f2fd9a3 | ||
|
28cc58d2c6 | ||
|
7d074585c1 | ||
|
bffb488446 | ||
|
cced9a2b95 | ||
|
ec70bb48ac | ||
|
7788b5f6be | ||
|
734030edcb | ||
|
6c3f2ddd84 | ||
|
34ba20188f | ||
|
f58173649b |
@ -18,5 +18,9 @@ add_custom_target(copy_assets ALL
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# global dependency directories
|
||||
include_directories(../Dependencies/include/)
|
||||
link_directories(../Dependencies/lib/)
|
||||
|
||||
add_subdirectory(vendor/imgui)
|
||||
add_subdirectory(src)
|
||||
|
@ -130,6 +130,7 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>glfw3.lib;opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@ -148,6 +149,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>glfw3.lib;opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
@ -155,11 +157,14 @@
|
||||
<ClCompile Include="src\Block.cpp" />
|
||||
<ClCompile Include="src\Camera.cpp" />
|
||||
<ClCompile Include="src\Chunk.cpp" />
|
||||
<ClCompile Include="src\ChunkData.cpp" />
|
||||
<ClCompile Include="src\ChunkPos.cpp" />
|
||||
<ClCompile Include="src\NoiseSettings.cpp" />
|
||||
<ClCompile Include="src\Physics.cpp" />
|
||||
<ClCompile Include="src\Planet.cpp" />
|
||||
<ClCompile Include="src\Shader.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.h" />
|
||||
<ClCompile Include="vendor\glad.c" />
|
||||
@ -176,7 +181,10 @@
|
||||
<ClInclude Include="src\Blocks.h" />
|
||||
<ClInclude Include="src\Camera.h" />
|
||||
<ClInclude Include="src\Chunk.h" />
|
||||
<ClInclude Include="src\ChunkData.h" />
|
||||
<ClInclude Include="src\ChunkPos.h" />
|
||||
<ClInclude Include="src\NoiseSettings.h" />
|
||||
<ClInclude Include="src\Physics.h" />
|
||||
<ClInclude Include="src\Planet.h" />
|
||||
<ClInclude Include="src\Shader.h" />
|
||||
<ClInclude Include="src\SurfaceFeature.h" />
|
||||
@ -196,6 +204,10 @@
|
||||
<ItemGroup>
|
||||
<None Include="assets\shaders\billboard_frag.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_vert.glsl" />
|
||||
<None Include="assets\shaders\main_frag.glsl" />
|
||||
@ -205,6 +217,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="assets\sprites\block_map.png" />
|
||||
<Image Include="assets\sprites\crosshair.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="vendor\imgui\LICENSE.txt" />
|
||||
|
@ -33,7 +33,7 @@
|
||||
<ClCompile Include="src\Block.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\TupleHash.h">
|
||||
<ClCompile Include="src\ChunkPosHash.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\WorldGen.h">
|
||||
@ -72,6 +72,15 @@
|
||||
<ClCompile Include="src\SurfaceFeature.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</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>
|
||||
<ClInclude Include="src\Shader.h">
|
||||
@ -134,6 +143,15 @@
|
||||
<ClInclude Include="src\Vertex.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</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>
|
||||
<None Include="assets\shaders\main_vert.glsl" />
|
||||
@ -144,11 +162,18 @@
|
||||
<None Include="assets\shaders\billboard_frag.glsl" />
|
||||
<None Include="assets\shaders\framebuffer_vert.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>
|
||||
<Image Include="assets\sprites\block_map.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="assets\sprites\crosshair.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="vendor\imgui\LICENSE.txt" />
|
||||
|
10
ScuffedMinecraft/assets/shaders/block_outline_frag.glsl
Normal file
10
ScuffedMinecraft/assets/shaders/block_outline_frag.glsl
Normal 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);
|
||||
}
|
12
ScuffedMinecraft/assets/shaders/block_outline_vert.glsl
Normal file
12
ScuffedMinecraft/assets/shaders/block_outline_vert.glsl
Normal 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);
|
||||
}
|
18
ScuffedMinecraft/assets/shaders/crosshair_frag.glsl
Normal file
18
ScuffedMinecraft/assets/shaders/crosshair_frag.glsl
Normal 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;
|
||||
}
|
14
ScuffedMinecraft/assets/shaders/crosshair_vert.glsl
Normal file
14
ScuffedMinecraft/assets/shaders/crosshair_vert.glsl
Normal 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.
BIN
ScuffedMinecraft/assets/sprites/crosshair.png
Normal file
BIN
ScuffedMinecraft/assets/sprites/crosshair.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
@ -2,6 +2,13 @@
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
|
||||
#ifdef LINUX
|
||||
#include <cstdlib>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
@ -17,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;
|
||||
@ -35,14 +44,21 @@ 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;
|
||||
|
||||
// Window options
|
||||
#define VSYNC 1 // 0 for off, 1 for on
|
||||
GLuint framebufferTexture;
|
||||
GLuint depthTexture;
|
||||
|
||||
float rectangleVertices[] =
|
||||
{
|
||||
@ -56,8 +72,66 @@ float rectangleVertices[] =
|
||||
-1.0f, 1.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
int main()
|
||||
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);
|
||||
// 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);
|
||||
#endif
|
||||
// Initialize GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
@ -73,7 +147,7 @@ int main()
|
||||
return -1;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(VSYNC);
|
||||
glfwSwapInterval(vsync ? 1 : 0);
|
||||
|
||||
// Initialize GLAD
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
@ -87,6 +161,7 @@ int main()
|
||||
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);
|
||||
|
||||
@ -115,12 +190,15 @@ int main()
|
||||
|
||||
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);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
|
||||
|
||||
unsigned int framebufferTexture;
|
||||
glGenTextures(1, &framebufferTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, windowX, windowY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
@ -130,7 +208,6 @@ int main()
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture, 0);
|
||||
|
||||
unsigned int depthTexture;
|
||||
glGenTextures(1, &depthTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, windowX, windowY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
@ -159,6 +236,26 @@ int main()
|
||||
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
|
||||
@ -188,6 +285,30 @@ int main()
|
||||
|
||||
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));
|
||||
|
||||
@ -195,6 +316,8 @@ int main()
|
||||
|
||||
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();
|
||||
@ -220,7 +343,7 @@ int main()
|
||||
highestFps = fps;
|
||||
fpsCount++;
|
||||
std::chrono::steady_clock::time_point currentTimePoint = std::chrono::steady_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(currentTimePoint - fpsStartTime).count() > 1000)
|
||||
if (std::chrono::duration_cast<std::chrono::seconds>(currentTimePoint - fpsStartTime).count() >= 1)
|
||||
{
|
||||
avgFps = fpsCount;
|
||||
lowestFps = -1;
|
||||
@ -231,6 +354,8 @@ int main()
|
||||
|
||||
waterShader.use();
|
||||
waterShader.setFloat("time", currentFrame);
|
||||
outlineShader.use();
|
||||
outlineShader.setFloat("time", currentFrame);
|
||||
|
||||
// Input
|
||||
processInput(window);
|
||||
@ -272,24 +397,60 @@ int main()
|
||||
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(
|
||||
@ -307,6 +468,7 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
// Post Processing
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindVertexArray(rectVAO);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
@ -316,15 +478,50 @@ int main()
|
||||
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
if (uiEnabled)
|
||||
{
|
||||
// -- Render Crosshair -- //
|
||||
|
||||
// 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: %f (Avg: %f, Min: %f, Max: %f)", fps, avgFps, lowestFps, highestFps);
|
||||
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.c_str());
|
||||
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);
|
||||
@ -333,6 +530,8 @@ int main()
|
||||
//std::cout << camera.Position.x << ", " << camera.Position.y << ", " << camera.Position.z << '\n';
|
||||
}
|
||||
|
||||
delete Planet::planet;
|
||||
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
@ -345,10 +544,18 @@ void framebufferSizeCallback(GLFWwindow* window, int width, int height)
|
||||
windowX = width;
|
||||
windowY = height;
|
||||
glViewport(0, 0, width, 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);
|
||||
}
|
||||
|
||||
void processInput(GLFWwindow* window)
|
||||
{
|
||||
// Pause
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
{
|
||||
if (escapeDown)
|
||||
@ -363,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)
|
||||
@ -382,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)
|
||||
|
@ -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;
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
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);
|
||||
|
||||
};
|
@ -1,34 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "Block.h"
|
||||
|
||||
namespace Blocks
|
||||
{
|
||||
const std::vector<Block> 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
|
||||
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
|
||||
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 Bottom"), // 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,
|
||||
};
|
||||
}
|
@ -1,9 +1,15 @@
|
||||
add_executable(scuffed_mc
|
||||
Application.cpp Chunk.cpp Shader.cpp
|
||||
Block.cpp NoiseSettings.cpp SurfaceFeature.cpp
|
||||
ChunkData.cpp ChunkPos.cpp Physics.cpp
|
||||
Camera.cpp Planet.cpp WorldGen.cpp ../vendor/glad.c
|
||||
)
|
||||
|
||||
include_directories(../../Dependencies/include/)
|
||||
if(LINUX)
|
||||
add_compile_definitions(LINUX)
|
||||
endif()
|
||||
|
||||
target_link_libraries(scuffed_mc imgui glfw)
|
||||
# make sure the program runs in the right place from visual studio
|
||||
set_target_properties(scuffed_mc PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||
|
||||
target_link_libraries(scuffed_mc imgui $<IF:$<PLATFORM_ID:Windows>,glfw3,glfw>)
|
||||
|
@ -38,9 +38,9 @@ void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime)
|
||||
if (direction == RIGHT)
|
||||
Position += Right * velocity;
|
||||
if (direction == UP)
|
||||
Position += Up * velocity;
|
||||
Position += (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
|
||||
if (direction == DOWN)
|
||||
Position -= Up * velocity;
|
||||
Position -= (absoluteVerticalMovement ? glm::vec3(0, 1, 0) : Up) * velocity;
|
||||
if (direction == FORWARD_NO_Y)
|
||||
{
|
||||
glm::vec3 moveDir = Front;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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<unsigned int> 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);
|
||||
@ -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);
|
||||
}
|
@ -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<unsigned int> 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<Vertex> mainVertices;
|
||||
std::vector<unsigned int> mianIndices;
|
||||
std::vector<unsigned int> mainIndices;
|
||||
std::vector<WaterVertex> waterVertices;
|
||||
std::vector<unsigned int> waterIndices;
|
||||
std::vector<BillboardVertex> billboardVertices;
|
||||
|
39
ScuffedMinecraft/src/ChunkData.cpp
Normal file
39
ScuffedMinecraft/src/ChunkData.cpp
Normal 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;
|
||||
}
|
20
ScuffedMinecraft/src/ChunkData.h
Normal file
20
ScuffedMinecraft/src/ChunkData.h
Normal 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);
|
||||
};
|
18
ScuffedMinecraft/src/ChunkPos.cpp
Normal file
18
ScuffedMinecraft/src/ChunkPos.cpp
Normal 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;
|
||||
}
|
13
ScuffedMinecraft/src/ChunkPos.h
Normal file
13
ScuffedMinecraft/src/ChunkPos.h
Normal 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;
|
||||
};
|
15
ScuffedMinecraft/src/ChunkPosHash.h
Normal file
15
ScuffedMinecraft/src/ChunkPosHash.h
Normal 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);
|
||||
}
|
||||
};
|
47
ScuffedMinecraft/src/Physics.cpp
Normal file
47
ScuffedMinecraft/src/Physics.cpp
Normal 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};
|
||||
}
|
30
ScuffedMinecraft/src/Physics.h
Normal file
30
ScuffedMinecraft/src/Physics.h
Normal 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;
|
||||
}
|
@ -4,41 +4,109 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "WorldGen.h"
|
||||
|
||||
Planet* Planet::planet = nullptr;
|
||||
|
||||
//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<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;
|
||||
camChunkZ = cameraPos.z < 0 ? floor(cameraPos.z / CHUNK_SIZE) : cameraPos.z / CHUNK_SIZE;
|
||||
|
||||
if (chunks.find(chunkTuple) == chunks.end())
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
chunksLoading = 0;
|
||||
numChunks = 0;
|
||||
numChunksRendered = 0;
|
||||
chunkMutex.lock();
|
||||
for (auto it = chunks.begin(); it != chunks.end(); )
|
||||
{
|
||||
return std::vector<unsigned int>{};
|
||||
//return GenerateChunkData(chunkX, chunkY, chunkZ);
|
||||
numChunks++;
|
||||
|
||||
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 ||
|
||||
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
|
||||
{
|
||||
return std::vector<unsigned int>{};
|
||||
//return chunks.at(chunkTuple).chunkData;
|
||||
numChunksRendered++;
|
||||
(*it->second).Render(solidShader, billboardShader);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void Planet::Update(float camX, float camY, float camZ)
|
||||
glEnable(GL_BLEND);
|
||||
waterShader->use();
|
||||
for (auto it = chunks.begin(); it != chunks.end(); )
|
||||
{
|
||||
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;
|
||||
int chunkX = (*it->second).chunkPos.x;
|
||||
int chunkY = (*it->second).chunkPos.y;
|
||||
int chunkZ = (*it->second).chunkPos.z;
|
||||
|
||||
(*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)
|
||||
@ -49,6 +117,7 @@ void Planet::Update(float camX, float camY, float camZ)
|
||||
lastCamZ = camChunkZ;
|
||||
|
||||
// Current chunk
|
||||
chunkMutex.lock();
|
||||
chunkQueue = {};
|
||||
if (chunks.find({ camChunkX, camChunkY, camChunkZ }) == chunks.end())
|
||||
chunkQueue.push({ camChunkX, camChunkY, camChunkZ });
|
||||
@ -123,75 +192,270 @@ void Planet::Update(float camX, float camY, float camZ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
chunksLoading = 0;
|
||||
numChunks = 0;
|
||||
numChunksRendered = 0;
|
||||
for (auto it = chunks.begin(); it != chunks.end(); )
|
||||
{
|
||||
numChunks++;
|
||||
|
||||
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 ||
|
||||
abs(chunkY - camChunkY) > renderDistance ||
|
||||
abs(chunkZ - camChunkZ) > renderDistance))
|
||||
{
|
||||
it = chunks.erase(it);
|
||||
chunkMutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
numChunksRendered++;
|
||||
it->second.Render(solidShader, billboardShader);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
waterShader->use();
|
||||
for (auto it = chunks.begin(); it != chunks.end(); )
|
||||
chunkMutex.lock();
|
||||
if (!chunkDataQueue.empty())
|
||||
{
|
||||
int chunkX = it->second.chunkPos.x;
|
||||
int chunkY = it->second.chunkPos.y;
|
||||
int chunkZ = it->second.chunkPos.z;
|
||||
ChunkPos chunkPos = chunkDataQueue.front();
|
||||
|
||||
it->second.RenderWater(waterShader);
|
||||
++it;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Chunk* Planet::GetChunk(int chunkX, int chunkY, int chunkZ)
|
||||
// Set top data
|
||||
{
|
||||
std::tuple<int, int, int> chunkTuple{ chunkX, chunkY, chunkZ };
|
||||
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];
|
||||
|
||||
if (chunks.find(chunkTuple) == chunks.end())
|
||||
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(ChunkPos chunkPos)
|
||||
{
|
||||
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++;
|
||||
}
|
@ -5,9 +5,15 @@
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <glm/glm.hpp>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#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<unsigned int> 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 = 32;
|
||||
int renderDistance = 10;
|
||||
int renderHeight = 3;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::tuple<int, int, int>, Chunk> chunks;
|
||||
std::queue<glm::vec3> chunkQueue;
|
||||
int renderDistance = 3;
|
||||
int renderHeight = 1;
|
||||
std::unordered_map<ChunkPos, Chunk*, ChunkPosHash> chunks;
|
||||
std::unordered_map<ChunkPos, ChunkData*, ChunkPosHash> chunkData;
|
||||
std::queue<ChunkPos> chunkQueue;
|
||||
std::queue<ChunkPos> chunkDataQueue;
|
||||
std::queue<ChunkPos> 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;
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
@ -5,9 +5,12 @@
|
||||
#include <OpenSimplexNoise.hh>
|
||||
|
||||
#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
|
||||
static OSN::Noise<2> noise2D;
|
||||
static OSN::Noise<3> noise3D;
|
||||
@ -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);
|
||||
else if (y + startY > 10)
|
||||
chunkData->push_back(Blocks::DIRT_BLOCK);
|
||||
if (noiseY > waterLevel + 1)
|
||||
chunkData[currentIndex] = Blocks::GRASS_BLOCK;
|
||||
else
|
||||
chunkData->push_back(Blocks::STONE_BLOCK);
|
||||
chunkData[currentIndex] = Blocks::SAND;
|
||||
else if (y + startY > 10)
|
||||
if (noiseY > waterLevel + 1)
|
||||
chunkData[currentIndex] = Blocks::DIRT_BLOCK;
|
||||
else
|
||||
chunkData[currentIndex] = Blocks::SAND;
|
||||
else
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,10 @@
|
||||
#include <vector>
|
||||
#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<unsigned int>* chunkData);
|
||||
|
||||
void GenerateChunkData(ChunkPos chunkPos, uint16_t* chunkData);
|
||||
}
|
Loading…
Reference in New Issue
Block a user