diff --git a/inc/ui.h b/inc/ui.h index e6817e0..6110d86 100644 --- a/inc/ui.h +++ b/inc/ui.h @@ -2,9 +2,10 @@ #define UI_H #include "world.h" +#include "ui/camera.h" int player_ui( std::vector &require_pipe, std::mutex &require_pipe_lock, - std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock); + std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock, Camera &camera); #endif diff --git a/inc/ui/cube_model.h b/inc/ui/cube_model.h index db2a2c8..56f801e 100644 --- a/inc/ui/cube_model.h +++ b/inc/ui/cube_model.h @@ -52,30 +52,5 @@ float vertices[] = { 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f}; -// world space positions of our cubes -glm::ivec3 cubePositions[] = { - glm::ivec3(0, 0, 0), - glm::ivec3(0, 0, 1), - glm::ivec3(0, 0, 2), - glm::ivec3(0, 0, 3), - glm::ivec3(0, 0, 4), - - glm::ivec3(0, 0, 5), - glm::ivec3(0, 0, 6), - glm::ivec3(0, 0, 7), - glm::ivec3(0, 0, 8), - glm::ivec3(0, 0, 9)}; - -glm::ivec2 cubeTextures[] = { - glm::ivec2(1, 12), - glm::ivec2(1, 11), - glm::ivec2(1, 10), - glm::ivec2(1, 9), - glm::ivec2(1, 8), - - glm::ivec2(1, 7), - glm::ivec2(1, 6), - glm::ivec2(1, 5), - glm::ivec2(1, 4), - glm::ivec2(1, 0)}; \ No newline at end of file + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f +}; diff --git a/inc/world.h b/inc/world.h index 9678204..35ae296 100644 --- a/inc/world.h +++ b/inc/world.h @@ -1,6 +1,7 @@ #ifndef WORLD_H #define WORLD_H +#include "ui/camera.h" #include "world/trunk.h" #include "world/block.h" #include @@ -15,6 +16,6 @@ enum WorldRequire void world_simulator(std::vector &require_pipe, std::mutex &require_pipe_lock, - std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock); + std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock, Camera &camera); #endif diff --git a/inc/world/block.h b/inc/world/block.h index 2c20e41..48e7e88 100644 --- a/inc/world/block.h +++ b/inc/world/block.h @@ -6,9 +6,9 @@ enum BlockType { - Air, - Soil, - Grass, + AirBlock, + SoilBlock, + GrassBlock, }; enum BlockFacing @@ -25,7 +25,7 @@ enum BlockFacing class Block { public: - Block(BlockType type = BlockType::Air, BlockFacing facing = BlockFacing::FacingNone) : type(type), facing(facing) {} + Block(BlockType type = BlockType::AirBlock, BlockFacing facing = BlockFacing::FacingNone) : type(type), facing(facing) {} void set_type(BlockType type) { @@ -43,7 +43,7 @@ private: }; #ifndef WORLD -extern std::map block_type_texture_table; +extern std::map> block_type_texture_table; #endif #endif diff --git a/inc/world/trunk.h b/inc/world/trunk.h index 9351cd9..a76a660 100644 --- a/inc/world/trunk.h +++ b/inc/world/trunk.h @@ -2,6 +2,8 @@ #define TRUNK_H #include +#define GLM_ENABLE_EXPERIMENTAL +#include #include #include @@ -14,31 +16,106 @@ const int TrunkSizeZ = 32; class Trunk { public: - Trunk() + Trunk(long long x, long long z) : trunk_locx(x), trunk_locz(z) { for (int i = 0; i < TrunkSizeX; i++) for (int j = 0; j < 61; j++) for (int k = 0; k < TrunkSizeZ; k++) if (j < 60) - blocks[i][j][k].set_type(BlockType::Soil); + blocks[i][j][k].set_type(BlockType::SoilBlock); else - blocks[i][j][k].set_type(BlockType::Grass); + blocks[i][j][k].set_type(BlockType::GrassBlock); } - std::vector> &getBlockList() + std::vector> &getBlockList(glm::vec3 &camera_pos, glm::vec3 &camera_facing) { static std::vector> res; res.clear(); for (int i = 0; i < TrunkSizeX; i++) for (int j = 0; j < TrunkSizeY; j++) for (int k = 0; k < TrunkSizeZ; k++) - if (blocks[i][j][k].get_type() != BlockType::Air) + if (blocks[i][j][k].get_type() != BlockType::AirBlock) + { + glm::ivec3 worldp(i + trunk_locx, j, k + trunk_locz); + if (!blockInFront(worldp, camera_pos, camera_facing)) + continue; + std::vector surrs{ + glm::ivec3(worldp.x + 1, worldp.y, worldp.z), + glm::ivec3(worldp.x - 1, worldp.y, worldp.z), + glm::ivec3(worldp.x, worldp.y + 1, worldp.z), + glm::ivec3(worldp.x, worldp.y - 1, worldp.z), + glm::ivec3(worldp.x, worldp.y, worldp.z + 1), + glm::ivec3(worldp.x, worldp.y, worldp.z - 1)}; + if (!blockOnTheSurface(worldp, surrs)) + continue; res.push_back(std::tuple({i, j, k}, blocks[i][j][k])); + } return res; } private: Block blocks[TrunkSizeX][TrunkSizeY][TrunkSizeZ]; + const int trunk_locx; + const int trunk_locz; + + bool in_trunk(glm::ivec3 block) + { + return block.x >= 0 && block.x < TrunkSizeX && block.y >= 0 && block.y < TrunkSizeY && block.z >= 0 && block.z < TrunkSizeZ; + } + + bool blockOnTheSurface(glm::ivec3 tblock, std::vector surr_blocks) + { + bool res = false; + for (auto block : surr_blocks) + { + if (!in_trunk(block)) + { + if (block.y >= 0) + { + res = true; + break; + } + else + { + continue; + } + } + if (blocks[block.x][block.y][block.z].get_type() == BlockType::AirBlock) + { + res = true; + break; + } + } + return res; + } + + bool blockInFront(glm::ivec3 block, glm::vec3 &camera_pos, glm::vec3 &camera_facing) + { + glm::vec3 p1(block.x, block.y, block.z); + glm::vec3 p2(block.x + 1, block.y, block.z); + glm::vec3 p3(block.x, block.y, block.z + 1); + glm::vec3 p4(block.x + 1, block.y, block.z + 1); + glm::vec3 p5(block.x, block.y + 1, block.z); + glm::vec3 p6(block.x + 1, block.y + 1, block.z); + glm::vec3 p7(block.x, block.y + 1, block.z + 1); + glm::vec3 p8(block.x + 1, block.y + 1, block.z + 1); + return (isVisible(p1, camera_pos, camera_facing) || + isVisible(p2, camera_pos, camera_facing) || + isVisible(p3, camera_pos, camera_facing) || + isVisible(p4, camera_pos, camera_facing) || + isVisible(p5, camera_pos, camera_facing) || + isVisible(p6, camera_pos, camera_facing) || + isVisible(p7, camera_pos, camera_facing) || + isVisible(p8, camera_pos, camera_facing)); + } + + bool isVisible(glm::vec3 &point, glm::vec3 &camera_pos, glm::vec3 &camera_facing) + { + glm::vec3 cam2p = point - camera_pos; + float prod = glm::dot(camera_facing, cam2p); + // If the vertex out of camera + return prod > 0; + } }; #endif diff --git a/res/demo.fs b/res/demo.fs index 0dd19e0..ef126ff 100644 --- a/res/demo.fs +++ b/res/demo.fs @@ -13,4 +13,4 @@ void main() discard; } FragColor = pixel; -} \ No newline at end of file +} diff --git a/res/demo.vs b/res/demo.vs index a11c2bf..4dee23a 100644 --- a/res/demo.vs +++ b/res/demo.vs @@ -13,4 +13,4 @@ void main() { gl_Position = projection * view * model * vec4(aPos, 1.0f); TexCoord = vec2((aTexCoord.x + index.x)/16, (aTexCoord.y + index.y)/16); -} \ No newline at end of file +} diff --git a/res/terrain.png b/res/terrain.png index ea86cf3..b4ebd80 100644 Binary files a/res/terrain.png and b/res/terrain.png differ diff --git a/src/main.cpp b/src/main.cpp index e8777c5..873137a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include "ui.h" +#include "ui/camera.h" #include "world.h" int main() @@ -12,20 +13,22 @@ int main() std::vector>> blocks_pipe; std::mutex blocks_pipe_lock; + Camera camera(glm::vec3(0.0f, 63.0f, 0.0f)); + // 启动ui渲染线程 std::promise ui_prom; std::future ui_future = ui_prom.get_future(); std::thread ui( - [&ui_prom, &require_pipe, &require_pipe_lock, &blocks_pipe, &blocks_pipe_lock]() + [&ui_prom, &require_pipe, &require_pipe_lock, &blocks_pipe, &blocks_pipe_lock, &camera]() { - int res = player_ui(require_pipe, require_pipe_lock, blocks_pipe, blocks_pipe_lock); + int res = player_ui(require_pipe, require_pipe_lock, blocks_pipe, blocks_pipe_lock, camera); ui_prom.set_value(res); }); // 启动世界模拟器线程 std::thread world_sim( - [&require_pipe, &require_pipe_lock, &blocks_pipe, &blocks_pipe_lock]() + [&require_pipe, &require_pipe_lock, &blocks_pipe, &blocks_pipe_lock, &camera]() { - world_simulator(require_pipe, require_pipe_lock, blocks_pipe, blocks_pipe_lock); + world_simulator(require_pipe, require_pipe_lock, blocks_pipe, blocks_pipe_lock, camera); }); ui.join(); diff --git a/src/ui.cpp b/src/ui.cpp index a1d5f78..bbd8862 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -22,7 +22,7 @@ void framebuffer_size_callback(GLFWwindow *window, int width, int height); void mouse_callback(GLFWwindow *window, double xpos, double ypos); void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); void focus_callback(GLFWwindow *window, int focused); -void processInput(GLFWwindow *window); +void processInput(GLFWwindow *window, Camera &camera); void glfwDump(GLFWwindow *window); @@ -35,7 +35,7 @@ const unsigned int SCR_WIDTH = 1920; const unsigned int SCR_HEIGHT = 1080; // camera -Camera camera(glm::vec3(0.0f, 63.0f, 0.0f)); +Camera *camera_glb; float lastX = SCR_WIDTH / 2.0f; float lastY = SCR_HEIGHT / 2.0f; bool firstMouse = true; @@ -59,8 +59,9 @@ GLFWimage icon; int player_ui( std::vector &require_pipe, std::mutex &require_pipe_lock, - std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock) + std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock, Camera &camera) { + camera_glb = &camera; #ifdef __linux__ nativeSetIcon(); #endif @@ -190,7 +191,7 @@ int player_ui( // input // ----- - processInput(window); + processInput(window, camera); // render // ------ @@ -211,24 +212,14 @@ int player_ui( // render opaque objects first glBindVertexArray(VAO); - /*for (unsigned int i = 0; i < 10; i++) - { - ourShader.setIVec2("index", cubeTextures[i]); - - // calculate the model matrix for each object and pass it to shader before drawing - glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first - model = glm::translate(model, glm::vec3(cubePositions[i])); - ourShader.setMat4("model", model); - glDrawArrays(GL_TRIANGLES, 0, 36); - }*/ - require_pipe_lock.lock(); require_pipe.push_back(WorldRequire::BlockReq); require_pipe_lock.unlock(); - std::vector> blks; + static std::vector> blks; blocks_pipe_lock.lock(); if (!blocks_pipe.empty()) { + blks.clear(); blks = blocks_pipe.back(); blocks_pipe.pop_back(); } @@ -236,11 +227,16 @@ int player_ui( for (auto block : blks) { auto loc = std::get<0>(block); - ourShader.setIVec2("index", block_type_texture_table[std::get<1>(block).get_type()]); glm::mat4 model(1.0f); model = glm::translate(model, glm::vec3(loc)); ourShader.setMat4("model", model); - glDrawArrays(GL_TRIANGLES, 0, 36); + int ind = 0; + for (auto pic : block_type_texture_table[std::get<1>(block).get_type()]) + { + ourShader.setIVec2("index", pic); + glDrawArrays(GL_TRIANGLES, ind * 6, 6); + ind++; + } } // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) @@ -272,7 +268,7 @@ int player_ui( // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly // --------------------------------------------------------------------------------------------------------- bool ESC_KEY_PRESSED = false; -void processInput(GLFWwindow *window) +void processInput(GLFWwindow *window, Camera &camera) { int esc_key_evetype = glfwGetKey(window, GLFW_KEY_ESCAPE); if (!ESC_KEY_PRESSED && esc_key_evetype == GLFW_PRESS) @@ -361,14 +357,14 @@ void mouse_callback(GLFWwindow *window, double xposIn, double yposIn) lastX = xpos; lastY = ypos; - camera.ProcessMouseMovement(xoffset, yoffset); + camera_glb->ProcessMouseMovement(xoffset, yoffset); } // glfw: whenever the mouse scroll wheel scrolls, this callback is called // ---------------------------------------------------------------------- void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { - camera.ProcessMouseScroll(static_cast(yoffset)); + camera_glb->ProcessMouseScroll(static_cast(yoffset)); } void focus_callback(GLFWwindow *window, int focused) diff --git a/src/world.cpp b/src/world.cpp index de5a505..6420601 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,17 +1,15 @@ #define WORLD #include "world.h" #include - -std::map block_type_texture_table{ - std::make_pair(BlockType::Soil, glm::ivec2(2, 15)), - std::make_pair(BlockType::Grass, glm::ivec2(3, 15)), -}; +#include +#include +#include void world_simulator( std::vector &require_pipe, std::mutex &require_pipe_lock, - std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock) + std::vector>> &blocks_pipe, std::mutex &blocks_pipe_lock, Camera &camera) { - Trunk trunk000; + Trunk trunk000(0, 0); bool ends = false; while (true) { @@ -29,7 +27,7 @@ void world_simulator( switch (wreq) { case BlockReq: - list = &trunk000.getBlockList(); + list = &trunk000.getBlockList(camera.Position, camera.Front); blocks_pipe_lock.lock(); blocks_pipe.push_back(*list); blocks_pipe_lock.unlock(); @@ -40,5 +38,11 @@ void world_simulator( } if (ends) break; + std::this_thread::sleep_for(std::chrono::milliseconds(4)); } } + +std::map> block_type_texture_table{ + std::make_pair(BlockType::SoilBlock, std::vector{glm::ivec2(2, 15), glm::ivec2(2, 15), glm::ivec2(2, 15), glm::ivec2(2, 15), glm::ivec2(2, 15), glm::ivec2(2, 15)}), + std::make_pair(BlockType::GrassBlock, std::vector{glm::ivec2(3, 15), glm::ivec2(3, 15), glm::ivec2(3, 15), glm::ivec2(3, 15), glm::ivec2(2, 15), glm::ivec2(9, 6)}), +};