From 5d993ce1b7dd64f57b124563794d781676d33342 Mon Sep 17 00:00:00 2001 From: WSAL Evan Date: Fri, 4 Oct 2024 13:53:11 -0400 Subject: [PATCH] Episode 3 --- ScuffedMinecraft/ScuffedMinecraft.vcxproj | 4 +- .../ScuffedMinecraft.vcxproj.filters | 12 +- .../assets/shaders/fragment_shader.glsl | 5 +- .../assets/shaders/vertex_shader.glsl | 15 +- ScuffedMinecraft/assets/sprites/block_map.png | Bin 2005 -> 4492 bytes ScuffedMinecraft/assets/sprites/block_map.psd | Bin 0 -> 72717 bytes .../assets/sprites/direction_test.png | Bin 672 -> 0 bytes .../assets/sprites/grass_block_side.png | Bin 672 -> 0 bytes ScuffedMinecraft/imgui.ini | 80 ---- ScuffedMinecraft/src/Application.cpp | 15 +- ScuffedMinecraft/src/Block.cpp | 6 +- ScuffedMinecraft/src/Block.h | 6 +- ScuffedMinecraft/src/Blocks.h | 32 +- ScuffedMinecraft/src/Camera.cpp | 7 + ScuffedMinecraft/src/Camera.h | 3 +- ScuffedMinecraft/src/Chunk.cpp | 394 +++++++++++------- ScuffedMinecraft/src/Chunk.h | 4 +- ScuffedMinecraft/src/SurfaceFeature.cpp | 11 + ScuffedMinecraft/src/SurfaceFeature.h | 17 + ScuffedMinecraft/src/WorldGen.cpp | 283 ++++++++++++- ScuffedMinecraft/src/WorldGen.h | 2 + 21 files changed, 612 insertions(+), 284 deletions(-) create mode 100644 ScuffedMinecraft/assets/sprites/block_map.psd delete mode 100644 ScuffedMinecraft/assets/sprites/direction_test.png delete mode 100644 ScuffedMinecraft/assets/sprites/grass_block_side.png delete mode 100644 ScuffedMinecraft/imgui.ini create mode 100644 ScuffedMinecraft/src/SurfaceFeature.cpp create mode 100644 ScuffedMinecraft/src/SurfaceFeature.h diff --git a/ScuffedMinecraft/ScuffedMinecraft.vcxproj b/ScuffedMinecraft/ScuffedMinecraft.vcxproj index e179226..da168e1 100644 --- a/ScuffedMinecraft/ScuffedMinecraft.vcxproj +++ b/ScuffedMinecraft/ScuffedMinecraft.vcxproj @@ -158,6 +158,7 @@ + @@ -178,6 +179,7 @@ + @@ -196,8 +198,6 @@ - - diff --git a/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters b/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters index de7702e..92cc2ea 100644 --- a/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters +++ b/ScuffedMinecraft/ScuffedMinecraft.vcxproj.filters @@ -69,6 +69,9 @@ Source Files + + Source Files + @@ -125,18 +128,15 @@ Header Files + + Header Files + - - Resource Files - - - Resource Files - Resource Files diff --git a/ScuffedMinecraft/assets/shaders/fragment_shader.glsl b/ScuffedMinecraft/assets/shaders/fragment_shader.glsl index ed33dfb..890725d 100644 --- a/ScuffedMinecraft/assets/shaders/fragment_shader.glsl +++ b/ScuffedMinecraft/assets/shaders/fragment_shader.glsl @@ -19,5 +19,8 @@ void main() vec4 result = vec4(ambient + diffuse, 1.0); - FragColor = texture(tex, TexCoord) * result; + vec4 texResult = texture(tex, TexCoord); + if (texResult.a == 0) + discard; + FragColor = texResult * result; } \ No newline at end of file diff --git a/ScuffedMinecraft/assets/shaders/vertex_shader.glsl b/ScuffedMinecraft/assets/shaders/vertex_shader.glsl index e15e933..46aea5d 100644 --- a/ScuffedMinecraft/assets/shaders/vertex_shader.glsl +++ b/ScuffedMinecraft/assets/shaders/vertex_shader.glsl @@ -15,13 +15,14 @@ uniform mat4 view; uniform mat4 projection; // Array of possible normals based on direction -const vec3 normals[6] = vec3[6]( - vec3(0, 0, 1), // 0 - vec3(0, 0, -1), // 1 - vec3(1, 0, 0), // 2 - vec3(-1, 0, 0), // 3 - vec3(0, 1, 0), // 4 - vec3(0, -1, 0) // 5 +const vec3 normals[] = vec3[]( + vec3( 0, 0, 1), // 0 + vec3( 0, 0, -1), // 1 + vec3( 1, 0, 0), // 2 + vec3(-1, 0, 0), // 3 + vec3( 0, 1, 0), // 4 + vec3( 0, -1, 0), // 5 + vec3( 0, -1, 0) // 6 ); void main() diff --git a/ScuffedMinecraft/assets/sprites/block_map.png b/ScuffedMinecraft/assets/sprites/block_map.png index b98bf1ec77b2ac680e12018b0ef499354092f29a..401851934d5515caf527068ec80c581c6ebcd56e 100644 GIT binary patch literal 4492 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 diff --git a/ScuffedMinecraft/assets/sprites/block_map.psd b/ScuffedMinecraft/assets/sprites/block_map.psd new file mode 100644 index 0000000000000000000000000000000000000000..95fd05f110d88fbd4d31b112b0d05bda8e7ad810 GIT binary patch literal 72717 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 JC}Gh2{{Wh7*w_F7 literal 0 HcmV?d00001 diff --git a/ScuffedMinecraft/assets/sprites/direction_test.png b/ScuffedMinecraft/assets/sprites/direction_test.png deleted file mode 100644 index 6b4bd72716ad900edb2840f94440a79a3b93d5d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 672 zcmV;R0$=@!P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0r*KoK~y+Tjgm2F zQ&AL#|M!rZm>03Bk5`l@RYY*A=q3~d2c;mmI0z2nC=L!T;@~81q7qybC&9tNK@l7T zq2O5T`#2m*CF9VJuK+P^DS8YTL1@4Jb>S1J|bj>L0{ zqR5&Hg@TeK(O@u8IJ>i?%?Imt((UsvwYFV17r9(c+mC-Lj$_sPO*{GU%mHBkoTmOuFniukTa+{+i}yr?pzmEJqwXy0$p{ zw$V_U?9tWo8*5&eKWOnJ;5n$cv23+VD_>0@q}de#q=P2b%?l^>eCd-mSKb*<4|S)G z9a6{-8%VJG__=X>`RoZ>4v%pFKCf>n7^x50Aav%|GmWlf$$zilyo`Cn7&iCF7{(1unCf|W1@b{p`n{n#brY|&h1TXd^aA9vE=H4uStB|5eYa}UlFgkBS z*xfakUzy-|jDAl*@!LC>OqjXz?}so>Vh&*{HU)Qa_r(V*`XBgI#$O^XP-Gg!*mVxT za}eX@!*a)C0W4u1u;-Durx(J3$^B|I({BY{A8K|_;SvA<002ovPDHLkV1i8__dzx4 zHnPfcH!jYWx#3%v&q_tk%~`pmd~aiKFWLJihYc##2L1t;RaAAj0ve700000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0yRlQK~y+TT~g0$ z)L;;O$!g8IiM3fn)=Jv?qk@Q5TJRtiL@!biym(MNh-VKTdhxcG-bB=c7e)LZ^q>bp z@NBVr6Wr>yvOnBy6L-^Wwvdhc2EGz}5HjD)o0&KBecJN-rBv5-BuRo^uLmNZ&m#x| zSe6Cbwh_lM!Y~vLxjg&656|0rVtG{p@2c4uVolg~~5WnuC-ELzr7-0KF z6WX1{Gih<|8n)IxNn&Yv3e6`QViRKzOzgf1apch?I?w8uDNW#4)0Y@+?d8Lzbh8z} za}VR>Q5$bRe8uA2anMI7GQmbxYgM>k)_zI>okT^dHnzn{(3kDRPpM=M&sQ#-fcA0a zUi$glx&(+r^Ec65eJ3^v1mjto3Y6-cS2W8Ekie=@{X51@1Kpii6eMYiO0@y2V89Ri z;^)U?LRSVWa|AUz!2&#UCqy>J9q^nxKkbxRgk46DLV~n|Fy7mT>Pjf3j5ALc?+9us zig5q>f)J=e`Ds%nKkiBt+`W3PtfX;X&N)9jDI;+gJEaBe3+v*iLaLh{HE92+NI~uK z?Mo>Qb@yr~d=uH*`5#n7$Ozeov)Update(camera.Position.x, camera.Position.y, camera.Position.z, modelLoc); - std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); - - std::cout << "Planet Update: " - << std::chrono::duration_cast(end - begin).count() - << "[ms]\n"; // Draw ImGui UI ImGui::Begin("Test"); @@ -237,7 +231,12 @@ void processInput(GLFWwindow* window) escapeDown = false; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) - camera.ProcessKeyboard(FORWARD, deltaTime); + { + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) + camera.ProcessKeyboard(FORWARD_NO_Y, deltaTime); + else + camera.ProcessKeyboard(FORWARD, deltaTime); + } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard(BACKWARD, deltaTime); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) diff --git a/ScuffedMinecraft/src/Block.cpp b/ScuffedMinecraft/src/Block.cpp index 6e25ced..0552839 100644 --- a/ScuffedMinecraft/src/Block.cpp +++ b/ScuffedMinecraft/src/Block.cpp @@ -1,6 +1,7 @@ #include "Block.h" -Block::Block(char minX, char minY, char maxX, char maxY) +Block::Block(char minX, char minY, char maxX, char maxY, bool transparent, bool billboard) + : transparent(transparent), billboard(billboard) { topMinX = minX; topMinY = minY; @@ -20,7 +21,8 @@ Block::Block(char minX, char minY, char maxX, char maxY) 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) + char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, bool transparent, bool billboard) + : transparent(transparent), billboard(billboard) { this->topMinX = topMinX; this->topMinY = topMinY; diff --git a/ScuffedMinecraft/src/Block.h b/ScuffedMinecraft/src/Block.h index fd62de2..051f22d 100644 --- a/ScuffedMinecraft/src/Block.h +++ b/ScuffedMinecraft/src/Block.h @@ -6,9 +6,11 @@ public: char topMinX, topMinY, topMaxX, topMaxY; char bottomMinX, bottomMinY, bottomMaxX, bottomMaxY; char sideMinX, sideMinY, sideMaxX, sideMaxY; + bool transparent; + bool billboard; - Block(char minX, char minY, char maxX, char maxY); + Block(char minX, char minY, char maxX, char maxY, bool transparent = false, bool billboard = false); 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); + char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, bool transparent = false, bool billboard = false); }; \ No newline at end of file diff --git a/ScuffedMinecraft/src/Blocks.h b/ScuffedMinecraft/src/Blocks.h index 00c1bd9..f2a58bd 100644 --- a/ScuffedMinecraft/src/Blocks.h +++ b/ScuffedMinecraft/src/Blocks.h @@ -7,14 +7,27 @@ namespace Blocks { const std::vector blocks{ - Block(0, 0, 0, 0), // Air block - Block(0, 0, 1, 1), // Dirt block + Block(0, 0, 0, 0, true), // Air block + Block(0, 0, 1, 1), // Dirt block - Block(1, 1, 2, 2, // Grass block + Block(1, 1, 2, 2, // Grass block 0, 0, 1, 1, 1, 0, 2, 1), - Block(0, 1, 1, 2) // Stone block + Block(0, 1, 1, 2), // Stone block + + Block(2, 1, 3, 2, // Log + 2, 1, 3, 2, + 2, 0, 3, 1), + + Block(0, 2, 1, 3, true), // Leaves + Block(1, 2, 2, 3, true, true), // Grass + Block(3, 0, 4, 1, true, true), // Tall Grass Bottom + Block(3, 1, 4, 2, true, true), // Tall Grass Top + Block(0, 3, 1, 4, true, true), // Poppy + Block(2, 2, 3, 3, true, true), // White Tulip + Block(3, 2, 4, 3, true, true), // Pink Tulip + Block(1, 3, 2, 4, true, true), // Orange Tulip }; enum BLOCKS @@ -22,6 +35,15 @@ namespace Blocks AIR = 0, DIRT_BLOCK = 1, GRASS_BLOCK = 2, - STONE_BLOCK = 3 + STONE_BLOCK = 3, + LOG = 4, + LEAVES = 5, + GRASS = 6, + TALL_GRASS_BOTTOM = 7, + TALL_GRASS_TOP = 8, + POPPY = 9, + WHITE_TULIP = 10, + PINK_TULIP = 11, + ORANGE_TULIP = 12, }; } \ No newline at end of file diff --git a/ScuffedMinecraft/src/Camera.cpp b/ScuffedMinecraft/src/Camera.cpp index 00836c1..1b2ddf2 100644 --- a/ScuffedMinecraft/src/Camera.cpp +++ b/ScuffedMinecraft/src/Camera.cpp @@ -41,6 +41,13 @@ void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime) Position += Up * velocity; if (direction == DOWN) Position -= Up * velocity; + if (direction == FORWARD_NO_Y) + { + glm::vec3 moveDir = Front; + moveDir.y = 0; + moveDir = glm::normalize(moveDir); + Position += moveDir * velocity; + } } // processes input received from a mouse input system. Expects the offset value in both the x and y direction. diff --git a/ScuffedMinecraft/src/Camera.h b/ScuffedMinecraft/src/Camera.h index dffdb67..2fa7448 100644 --- a/ScuffedMinecraft/src/Camera.h +++ b/ScuffedMinecraft/src/Camera.h @@ -9,7 +9,8 @@ enum Camera_Movement { LEFT, RIGHT, UP, - DOWN + DOWN, + FORWARD_NO_Y }; // Default camera values diff --git a/ScuffedMinecraft/src/Chunk.cpp b/ScuffedMinecraft/src/Chunk.cpp index 1ca955e..9759b22 100644 --- a/ScuffedMinecraft/src/Chunk.cpp +++ b/ScuffedMinecraft/src/Chunk.cpp @@ -60,184 +60,258 @@ void Chunk::GenerateChunk() const Block* block = &Blocks::blocks[chunkData[index]]; - // North + if (block->billboard) { - int northBlock; - if (z > 0) - { - int northIndex = x * chunkSize * chunkSize + (z - 1) * chunkSize + y; - northBlock = chunkData[northIndex]; - } - else - { - int northIndex = x * chunkSize * chunkSize + (chunkSize - 1) * chunkSize + y; - northBlock = northData[northIndex]; - } + vertices.push_back(Vertex(x + .85355f, y + 0, z + .85355f, block->sideMinX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .14645f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .85355f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY, 6)); + vertices.push_back(Vertex(x + .14645f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY, 6)); - if (northBlock == 0) - { - vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY, 0)); - vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY, 0)); - vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0)); - vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0)); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 3); - indices.push_back(currentVertex + 1); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 2); - indices.push_back(currentVertex + 3); - currentVertex += 4; - } + vertices.push_back(Vertex(x + .14645f, y + 0, z + .14645f, block->sideMinX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .85355f, y + 0, z + .85355f, block->sideMaxX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .14645f, y + 1, z + .14645f, block->sideMinX, block->sideMaxY, 6)); + vertices.push_back(Vertex(x + .85355f, y + 1, z + .85355f, block->sideMaxX, block->sideMaxY, 6)); + + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + + vertices.push_back(Vertex(x + .14645f, y + 0, z + .85355f, block->sideMinX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .85355f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .14645f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY, 6)); + vertices.push_back(Vertex(x + .85355f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY, 6)); + + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + + vertices.push_back(Vertex(x + .85355f, y + 0, z + .14645f, block->sideMinX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .14645f, y + 0, z + .85355f, block->sideMaxX, block->sideMinY, 6)); + vertices.push_back(Vertex(x + .85355f, y + 1, z + .14645f, block->sideMinX, block->sideMaxY, 6)); + vertices.push_back(Vertex(x + .14645f, y + 1, z + .85355f, block->sideMaxX, block->sideMaxY, 6)); + + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; } - - // South + else { - int southBlock; - if (z < chunkSize - 1) + // North { - int southIndex = x * chunkSize * chunkSize + (z + 1) * chunkSize + y; - southBlock = chunkData[southIndex]; - } - else - { - int southIndex = x * chunkSize * chunkSize + 0 * chunkSize + y; - southBlock = southData[southIndex]; - } - if (southBlock == 0) - { - vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY, 1)); - vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY, 1)); - vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1)); - vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1)); + int northBlock; + if (z > 0) + { + int northIndex = x * chunkSize * chunkSize + (z - 1) * chunkSize + y; + northBlock = chunkData[northIndex]; + } + else + { + int northIndex = x * chunkSize * chunkSize + (chunkSize - 1) * chunkSize + y; + northBlock = northData[northIndex]; + } - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 3); - indices.push_back(currentVertex + 1); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 2); - indices.push_back(currentVertex + 3); - currentVertex += 4; - } - } + const Block* northBlockType = &Blocks::blocks[northBlock]; - // West - { - int westBlock; - if (x > 0) - { - int blockIndex = (x - 1) * chunkSize * chunkSize + z * chunkSize + y; - westBlock = chunkData[blockIndex]; - } - else - { - int blockIndex = (chunkSize - 1) *chunkSize * chunkSize + z * chunkSize + y; - westBlock = westData[blockIndex]; - } - if (westBlock == 0) - { - vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY, 2)); - vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY, 2)); - vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2)); - vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2)); + if (northBlockType->transparent) + { + vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY, 0)); + vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY, 0)); + vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0)); + vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0)); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 3); - indices.push_back(currentVertex + 1); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 2); - indices.push_back(currentVertex + 3); - currentVertex += 4; + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + } } - } - // East - { - int eastBlock; - if (x < chunkSize - 1) + // South { - int blockIndex = (x + 1) * chunkSize * chunkSize + z * chunkSize + y; - eastBlock = chunkData[blockIndex]; - } - else - { - int blockIndex = 0 * chunkSize * chunkSize + z * chunkSize + y; - eastBlock = eastData[blockIndex]; - } - if (eastBlock == 0) - { - vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY, 3)); - vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY, 3)); - vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3)); - vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3)); + int southBlock; + if (z < chunkSize - 1) + { + int southIndex = x * chunkSize * chunkSize + (z + 1) * chunkSize + y; + southBlock = chunkData[southIndex]; + } + else + { + int southIndex = x * chunkSize * chunkSize + 0 * chunkSize + y; + southBlock = southData[southIndex]; + } - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 3); - indices.push_back(currentVertex + 1); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 2); - indices.push_back(currentVertex + 3); - currentVertex += 4; - } - } + const Block* southBlockType = &Blocks::blocks[southBlock]; - // Bottom - { - int bottomBlock; - if (y > 0) - { - int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y - 1); - bottomBlock = chunkData[blockIndex]; - } - else - { - int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1); - bottomBlock = downData[blockIndex]; - } - if (bottomBlock == 0) - { - vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY, 4)); - vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY, 4)); - vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4)); - vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4)); + if (southBlockType->transparent) + { + vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY, 1)); + vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY, 1)); + vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1)); + vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1)); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 3); - indices.push_back(currentVertex + 1); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 2); - indices.push_back(currentVertex + 3); - currentVertex += 4; + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + } } - } - // Top - { - int topBlock; - if (y < chunkSize - 1) + // West { - int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y + 1); - topBlock = chunkData[blockIndex]; - } - else - { - int blockIndex = x * chunkSize * chunkSize + z * chunkSize + 0; - topBlock = upData[blockIndex]; - } - if (topBlock == 0) - { - vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY, 5)); - vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY, 5)); - vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5)); - vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5)); + int westBlock; + if (x > 0) + { + int blockIndex = (x - 1) * chunkSize * chunkSize + z * chunkSize + y; + westBlock = chunkData[blockIndex]; + } + else + { + int blockIndex = (chunkSize - 1) * chunkSize * chunkSize + z * chunkSize + y; + westBlock = westData[blockIndex]; + } - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 3); - indices.push_back(currentVertex + 1); - indices.push_back(currentVertex + 0); - indices.push_back(currentVertex + 2); - indices.push_back(currentVertex + 3); - currentVertex += 4; + const Block* westBlockType = &Blocks::blocks[westBlock]; + + if (westBlockType->transparent) + { + vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY, 2)); + vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY, 2)); + vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2)); + vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2)); + + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + } + } + + // East + { + int eastBlock; + if (x < chunkSize - 1) + { + int blockIndex = (x + 1) * chunkSize * chunkSize + z * chunkSize + y; + eastBlock = chunkData[blockIndex]; + } + else + { + int blockIndex = 0 * chunkSize * chunkSize + z * chunkSize + y; + eastBlock = eastData[blockIndex]; + } + + const Block* eastBlockType = &Blocks::blocks[eastBlock]; + + if (eastBlockType->transparent) + { + vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY, 3)); + vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY, 3)); + vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3)); + vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3)); + + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + } + } + + // Bottom + { + int bottomBlock; + if (y > 0) + { + int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y - 1); + bottomBlock = chunkData[blockIndex]; + } + else + { + int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (chunkSize - 1); + bottomBlock = downData[blockIndex]; + } + + const Block* bottomBlockType = &Blocks::blocks[bottomBlock]; + + if (bottomBlockType->transparent) + { + vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY, 4)); + vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY, 4)); + vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4)); + vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4)); + + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + } + } + + // Top + { + int topBlock; + if (y < chunkSize - 1) + { + int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y + 1); + topBlock = chunkData[blockIndex]; + } + else + { + int blockIndex = x * chunkSize * chunkSize + z * chunkSize + 0; + topBlock = upData[blockIndex]; + } + + const Block* topBlockType = &Blocks::blocks[topBlock]; + + if (topBlockType->transparent) + { + vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY, 5)); + vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY, 5)); + vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5)); + vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5)); + + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 3); + indices.push_back(currentVertex + 1); + indices.push_back(currentVertex + 0); + indices.push_back(currentVertex + 2); + indices.push_back(currentVertex + 3); + currentVertex += 4; + } } } } @@ -266,7 +340,7 @@ void Chunk::Render(unsigned int modelLoc) glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW); - glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX)); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX)); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texGridX)); glEnableVertexAttribArray(1); diff --git a/ScuffedMinecraft/src/Chunk.h b/ScuffedMinecraft/src/Chunk.h index 549472c..bbf8152 100644 --- a/ScuffedMinecraft/src/Chunk.h +++ b/ScuffedMinecraft/src/Chunk.h @@ -6,11 +6,11 @@ struct Vertex { - char posX, posY, posZ; + float posX, posY, posZ; char texGridX, texGridY; char direction; - Vertex(char _posX, char _posY, char _posZ, char _texGridX, char _texGridY, char _direction) + Vertex(float _posX, float _posY, float _posZ, char _texGridX, char _texGridY, char _direction) { posX = _posX; posY = _posY; diff --git a/ScuffedMinecraft/src/SurfaceFeature.cpp b/ScuffedMinecraft/src/SurfaceFeature.cpp new file mode 100644 index 0000000..7657851 --- /dev/null +++ b/ScuffedMinecraft/src/SurfaceFeature.cpp @@ -0,0 +1,11 @@ +#include "SurfaceFeature.h" + +SurfaceFeature::SurfaceFeature(NoiseSettings _noiseSettings, std::vector _blocks, std::vector _replaceBlock, + int _sizeX, int _sizeY, int _sizeZ, + int _offsetX, int _offsetY, int _offsetZ) + : noiseSettings(_noiseSettings), blocks(_blocks), replaceBlock(_replaceBlock), + sizeX(_sizeX), sizeY(_sizeY), sizeZ(_sizeZ), + offsetX(_offsetX), offsetY(_offsetY), offsetZ(_offsetZ) +{ + +} \ No newline at end of file diff --git a/ScuffedMinecraft/src/SurfaceFeature.h b/ScuffedMinecraft/src/SurfaceFeature.h new file mode 100644 index 0000000..ec14fd7 --- /dev/null +++ b/ScuffedMinecraft/src/SurfaceFeature.h @@ -0,0 +1,17 @@ +#pragma once + +#include "NoiseSettings.h" +#include + +struct SurfaceFeature +{ + NoiseSettings noiseSettings; + std::vector blocks; + std::vector replaceBlock; + int sizeX, sizeY, sizeZ; + int offsetX, offsetY, offsetZ; + + SurfaceFeature(NoiseSettings _noiseSettings, std::vector _blocks, std::vector _replaceBlock, + int _sizeX, int _sizeY, int _sizeZ, + int _offsetX, int _offsetY, int _offsetZ); +}; \ No newline at end of file diff --git a/ScuffedMinecraft/src/WorldGen.cpp b/ScuffedMinecraft/src/WorldGen.cpp index f72f70a..87d9036 100644 --- a/ScuffedMinecraft/src/WorldGen.cpp +++ b/ScuffedMinecraft/src/WorldGen.cpp @@ -1,6 +1,7 @@ #include "WorldGen.h" #include +#include #include #include "Blocks.h" @@ -8,25 +9,197 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector* chunkData) { // Init noise - OSN::Noise<2> noise2D; - OSN::Noise<3> noise3D; + static OSN::Noise<2> noise2D; + static OSN::Noise<3> noise3D; // Init noise settings - NoiseSettings surfaceSettings[] { + static NoiseSettings surfaceSettings[]{ { 0.01f, 20.0f, 0 }, { 0.1f, 3.0f, 0 } }; - int surfaceSettingsLength = sizeof(surfaceSettings) / sizeof(*surfaceSettings); + static int surfaceSettingsLength = sizeof(surfaceSettings) / sizeof(*surfaceSettings); - NoiseSettings caveSettings[] { + static NoiseSettings caveSettings[]{ { 0.05f, 1.0f, 0, .5f, 0, 100 } }; - int caveSettingsLength = sizeof(caveSettings) / sizeof(*caveSettings); + static int caveSettingsLength = sizeof(caveSettings) / sizeof(*caveSettings); - NoiseSettings oreSettings[] { + static NoiseSettings oreSettings[]{ { 0.075f, 1.0f, 8.54f, .75f, 1, 0 } }; - int oreSettingsLength = sizeof(oreSettings) / sizeof(*oreSettings); + static int oreSettingsLength = sizeof(oreSettings) / sizeof(*oreSettings); + + static SurfaceFeature surfaceFeatures[]{ + // Tree + { + { 4.23f, 1.0f, 8.54f, .8f, 1, 0 }, + { + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 5, 0, + 0, 0, 0, 5, 5, 5, 5, + 0, 0, 0, 5, 5, 5, 0, + 0, 0, 0, 5, 5, 0, 0, + + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 5, 5, + 1, 4, 4, 4, 4, 5, 5, + 0, 0, 0, 5, 5, 5, 5, + 0, 0, 0, 5, 5, 0, 0, + + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 5, 0, + 0, 0, 0, 5, 5, 5, 5, + 0, 0, 0, 5, 5, 5, 0, + 0, 0, 0, 5, 5, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + }, + { + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + true, true, true, true, true, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, false, false, + }, + 5, + 7, + 5, + -2, + 0, + -2 + }, + // Grass + { + { 2.65f, 1.0f, 8.54f, .5f, 1, 0 }, + { + 2, 6 + }, + { + false, false + }, + 1, + 2, + 1, + 0, + 0, + 0 + }, + // Tall Grass + { + { 1.23f, 1.0f, 4.34f, .6f, 1, 0 }, + { + 2, 7, 8 + }, + { + false, false, false + }, + 1, + 3, + 1, + 0, + 0, + 0 + }, + // Poppy + { + { 5.32f, 1.0f, 3.67f, .8f, 1, 0 }, + { + 2, 9 + }, + { + false, false + }, + 1, + 2, + 1, + 0, + 0, + 0 + }, + // White Tulip + { + { 5.57f, 1.0f, 7.654f, .8f, 1, 0 }, + { + 2, 10 + }, + { + false, false + }, + 1, + 2, + 1, + 0, + 0, + 0 + }, + // Pink Tulip + { + { 4.94f, 1.0f, 2.23f, .8f, 1, 0 }, + { + 2, 11 + }, + { + false, false + }, + 1, + 2, + 1, + 0, + 0, + 0 + }, + // Orange Tulip + { + { 6.32f, 1.0f, 8.2f, .85f, 1, 0 }, + { + 2, 12 + }, + { + false, false + }, + 1, + 2, + 1, + 0, + 0, + 0 + }, + }; + static int surfaceFeaturesLength = sizeof(surfaceFeatures) / sizeof(*surfaceFeatures); // Set vector size chunkData->reserve(chunkSize * chunkSize * chunkSize); @@ -115,4 +288,98 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi } } } + + // Step 3: Surface Features + for (int i = 0; i < surfaceFeaturesLength; i++) + { + for (int x = -surfaceFeatures[i].sizeX - surfaceFeatures[i].offsetX; x < chunkSize - surfaceFeatures[i].offsetX; x++) + { + for (int z = -surfaceFeatures[i].sizeZ - surfaceFeatures[i].offsetZ; z < chunkSize - surfaceFeatures[i].offsetZ; z++) + { + int noiseY = 20; + for (int s = 0; s < surfaceSettingsLength; s++) + { + noiseY += noise2D.eval( + (float)((x + startX) * surfaceSettings[s].frequency) + surfaceSettings[s].offset, + (float)((z + startZ) * surfaceSettings[s].frequency) + surfaceSettings[s].offset) + * surfaceSettings[s].amplitude; + } + + if (noiseY + surfaceFeatures[i].offsetY > startY + 32 || noiseY + surfaceFeatures[i].sizeY + surfaceFeatures[i].offsetY < startY) + continue; + + // Check if it's in a cave + bool cave = false; + for (int i = 0; i < caveSettingsLength; i++) + { + if (noiseY + startY > caveSettings[i].maxHeight) + continue; + + float noiseCaves = noise3D.eval( + (float)((x + startX) * caveSettings[i].frequency) + caveSettings[i].offset, + (float)((noiseY) * caveSettings[i].frequency) + caveSettings[i].offset, + (float)((z + startZ) * caveSettings[i].frequency) + caveSettings[i].offset) + * caveSettings[i].amplitude; + + if (noiseCaves > caveSettings[i].chance) + { + cave = true; + break; + } + } + + if (cave) + continue; + + float noise = noise2D.eval( + (float)((x + startX) * surfaceFeatures[i].noiseSettings.frequency) + surfaceFeatures[i].noiseSettings.offset, + (float)((z + startZ) * surfaceFeatures[i].noiseSettings.frequency) + surfaceFeatures[i].noiseSettings.offset); + + if (noise > surfaceFeatures[i].noiseSettings.chance) + { + int featureX = x + startX; + int featureY = noiseY; + int featureZ = z + startZ; + + for (int fX = 0; fX < surfaceFeatures[i].sizeX; fX++) + { + for (int fY = 0; fY < surfaceFeatures[i].sizeY; fY++) + { + for (int fZ = 0; fZ < surfaceFeatures[i].sizeZ; fZ++) + { + int localX = featureX + fX + surfaceFeatures[i].offsetX - startX; + //std::cout << "FeatureX: " << featureX << ", fX: " << fX << ", startX: " << startX << ", localX: " << localX << '\n'; + int localY = featureY + fY + surfaceFeatures[i].offsetY - startY; + //std::cout << "FeatureY: " << featureY << ", fY: " << fY << ", startY: " << startY << ", localY: " << localY << '\n'; + int localZ = featureZ + fZ + surfaceFeatures[i].offsetZ - startZ; + //std::cout << "FeatureZ: " << featureZ << ", fZ: " << fZ << ", startZ: " << startZ << ", localZ: " << localZ << '\n'; + + if (localX >= 32 || localX < 0) + continue; + if (localY >= 32 || localY < 0) + continue; + if (localZ >= 32 || localZ < 0) + continue; + + int featureIndex = fX * surfaceFeatures[i].sizeZ * surfaceFeatures[i].sizeY + + fZ * surfaceFeatures[i].sizeY + + fY; + //std::cout << "Feature Index: " << featureIndex << '\n'; + 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]; + } + } + } + + //int index = x * chunkSize * chunkSize + z * chunkSize + noiseY; + //chunkData->at(index) = surfaceFeatures[i].block; + //index = x * chunkSize * chunkSize + z * chunkSize + noiseY + 1; + //chunkData->at(index) = surfaceFeatures[i].block; + } + } + } + } } \ No newline at end of file diff --git a/ScuffedMinecraft/src/WorldGen.h b/ScuffedMinecraft/src/WorldGen.h index e198a55..5b09d1b 100644 --- a/ScuffedMinecraft/src/WorldGen.h +++ b/ScuffedMinecraft/src/WorldGen.h @@ -2,8 +2,10 @@ #include #include "NoiseSettings.h" +#include "SurfaceFeature.h" namespace WorldGen { void GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSize, std::vector* chunkData); + } \ No newline at end of file