From 9e56348975dbdaf1cce9dd688129208a61fd4eb5 Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Fri, 21 Jul 2017 19:49:56 +0500 Subject: 2017-07-21 --- CMakeLists.txt | 2 +- cwd/shaders/face.fs | 52 +++++ cwd/shaders/face.vs | 26 +++ include/AssetManager.hpp | 3 + include/Core.hpp | 25 ++- include/Utility.hpp | 4 + include/graphics/RenderSection.hpp | 25 ++- include/world/Section.hpp | 3 + include/world/World.hpp | 21 +- src/core/AssetManager.cpp | 30 +++ src/core/Core.cpp | 267 ++++++++++++++++--------- src/graphics/RenderSection.cpp | 387 ++++++++++++++++++++++--------------- src/network/Stream.cpp | 9 +- src/world/GameState.cpp | 20 +- src/world/Section.cpp | 80 ++++---- src/world/World.cpp | 47 ++++- 16 files changed, 667 insertions(+), 334 deletions(-) create mode 100644 cwd/shaders/face.fs create mode 100644 cwd/shaders/face.vs diff --git a/CMakeLists.txt b/CMakeLists.txt index af0c9cb..33affa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ target_include_directories(AltCraft PUBLIC include/) ################ #Configure easlylogging++ -set(LOGGER_DEFINITIONS "-DELPP_THREAD_SAFE") +set(LOGGER_DEFINITIONS "-DELPP_THREAD_SAFE -DELPP_FEATURE_PERFORMANCE_TRACKING") if (LINUX) set(LOGGER_DENITIONS "${LOGGER_DEFINITIPNS} -DELPP_FEATURE_CRASH_LOG -DELPP_STL_LOGGING") endif () diff --git a/cwd/shaders/face.fs b/cwd/shaders/face.fs new file mode 100644 index 0000000..d132d7e --- /dev/null +++ b/cwd/shaders/face.fs @@ -0,0 +1,52 @@ +#version 330 core + +in VS_OUT { + vec2 UvPosition; + vec4 Texture; + vec3 Color; +} fs_in; + +uniform sampler2D textureAtlas; +uniform float time; +uniform vec2 windowSize; + +vec2 TransformTextureCoord(vec4 TextureAtlasCoords, vec2 UvCoords) { + float x = TextureAtlasCoords.x; + float y = TextureAtlasCoords.y; + float w = TextureAtlasCoords.z; + float h = TextureAtlasCoords.w; + vec2 A = vec2(x, 1 - y - h); + vec2 B = vec2(x + w, 1 - y); + return A + UvCoords * (B - A); +} + +vec3 rgb2hsv(vec3 c) +{ + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + +vec3 hsv2rgb(vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +void main() { + gl_FragColor = texture(textureAtlas,TransformTextureCoord(fs_in.Texture,fs_in.UvPosition)); + if (gl_FragColor.a < 0.3) + discard; + vec3 hsvColor = rgb2hsv(gl_FragColor.xyz); + /*hsvColor[0]+=fs_in.Color; + hsvColor[1]=0.63; + hsvColor[2]+=0.1;*/ + hsvColor+=fs_in.Color; + gl_FragColor = vec4(hsv2rgb(hsvColor),1); + //gl_FragColor = vec4(fs_in.Color,1); +} \ No newline at end of file diff --git a/cwd/shaders/face.vs b/cwd/shaders/face.vs new file mode 100644 index 0000000..c2f75ba --- /dev/null +++ b/cwd/shaders/face.vs @@ -0,0 +1,26 @@ +#version 330 core +layout (location = 0) in vec3 position; +layout (location = 2) in vec2 UvCoordinates; +layout (location = 7) in vec4 Texture; +layout (location = 8) in mat4 model; +layout (location = 12) in vec3 color; + +out VS_OUT { + vec2 UvPosition; + vec4 Texture; + vec3 Color; +} vs_out; + +uniform mat4 view; +uniform mat4 projection; +uniform float time; + +void main() +{ + vec4 sourcePosition = vec4(position,1.0f); + gl_Position = projection * view * model * sourcePosition; + + vs_out.UvPosition = vec2(UvCoordinates.x,UvCoordinates.y); + vs_out.Texture = Texture; + vs_out.Color = color; +} diff --git a/include/AssetManager.hpp b/include/AssetManager.hpp index f91c722..26c7eca 100644 --- a/include/AssetManager.hpp +++ b/include/AssetManager.hpp @@ -53,6 +53,7 @@ class AssetManager { Texture *textureAtlas; std::map assetIds; std::map assetTextures; + std::map textureAtlasIndexes; public: AssetManager(); @@ -66,6 +67,8 @@ public: GLuint GetTextureAtlas(); + const std::map &GetTextureAtlasIndexes(); + void LoadIds(); TextureCoordinates GetTextureByBlock(BlockTextureId block); diff --git a/include/Core.hpp b/include/Core.hpp index 64fab4e..8d60ff6 100644 --- a/include/Core.hpp +++ b/include/Core.hpp @@ -15,6 +15,14 @@ #include #include +struct MyMutex { + std::mutex mtx; + std::string str; + MyMutex(std::string name); + void lock(); + void unlock(); +}; + class Core { GameState *gameState; NetworkClient *client; @@ -56,24 +64,27 @@ class Core { void UpdateGameState(); + void UpdateSections(); + std::thread gameStateLoopThread; + std::thread sectionUpdateLoopThread; Shader *shader; //Cube verticies, Cube VAO, Cube UVs, TextureIndexes UboTextureIndexes, TextureData UboTextureIndexes, TextureData2 UboTextureIndexes, Blocks VBO, Models VBO, Line VAO, Lines VBO - //GLuint VBO, VAO, VBO2, UboTextureIndexes, UboTextureData, VBO3, VBO4, VAO2, VBO5; - GLuint UboTextureIndexes, UboTextureData; - //std::vector toRender; + bool isRendersShouldBeCreated=false; + std::condition_variable waitRendersCreated; + std::vector renders; + std::mutex toRenderMutex; std::vector toRender; std::map availableChunks; + std::mutex availableChunksMutex; - int ChunkDistance = 2; + int ChunkDistance = 1; RenderState renderState; - /*std::map> toRenderModels; - std::map> toRenderBlocks;*/ - double tickRate = 0; + double sectionRate = 0; public: Core(); diff --git a/include/Utility.hpp b/include/Utility.hpp index 92e924f..11b4ff7 100644 --- a/include/Utility.hpp +++ b/include/Utility.hpp @@ -47,6 +47,10 @@ inline GLenum glCheckError_(const char *file, int line) { error = "INVALID_FRAMEBUFFER_OPERATION"; break; } + static int t = 0; + t++; + if (t>10) + LOG(FATAL); LOG(ERROR) << "OpenGL error: " << error << " at " << file << ":" << line; } return errorCode; diff --git a/include/graphics/RenderSection.hpp b/include/graphics/RenderSection.hpp index 6a2f3ce..58c4acf 100644 --- a/include/graphics/RenderSection.hpp +++ b/include/graphics/RenderSection.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -21,21 +22,31 @@ public: class RenderSection { Vector sectionPosition; World *world; - GLuint Vao,VboBlocks,VboModels; + GLuint Vao, VboTextures, VboModels, VboColors; + std::vector models; + std::vector textures; + std::vector colors; - static GLuint VboVertices,VboUvs; - static std::map refCounterVbo; - static std::map refCounterVao; + static GLuint VboVertices, VboUvs; + static std::map refCounterVbo; + static std::map refCounterVao; - size_t numOfBlocks; + size_t numOfFaces = 0; + bool isEnabled = true; + + size_t hash = 0; public: RenderSection(World *world, Vector position); RenderSection(const RenderSection &other); ~RenderSection(); - void UpdateState(); + void UpdateState(const std::map &textureAtlas); void Render(RenderState &state); - Section* GetSection(); + void SetEnabled(bool isEnabled); + + Section *GetSection(); + + bool IsNeedUpdate(); }; \ No newline at end of file diff --git a/include/world/Section.hpp b/include/world/Section.hpp index 139b5b5..2df0cfe 100644 --- a/include/world/Section.hpp +++ b/include/world/Section.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -45,4 +46,6 @@ public: Section(const Section &other); Vector GetPosition(); + + size_t GetHash(); }; \ No newline at end of file diff --git a/include/world/World.hpp b/include/world/World.hpp index 6e5eedb..6b09f1f 100644 --- a/include/world/World.hpp +++ b/include/world/World.hpp @@ -11,17 +11,14 @@ #include class World { - //utility vars - World(const World &other); - - World &operator=(const World &other); - - //game vars + std::map sections; + std::map sectionMutexes; int dimension = 0; - //game methods Section ParseSection(StreamInput *data, Vector position); + World(const World &other); + World &operator=(const World &other); public: World(); @@ -29,7 +26,13 @@ public: void ParseChunkData(std::shared_ptr packet); - std::map sections; - bool isPlayerCollides(double X, double Y, double Z); + + Block &GetBlock(Vector pos); + + std::vector GetSectionsList(); + + Section &GetSection(Vector sectionPos); + + glm::vec3 Raycast(glm::vec3 position, glm::vec3 direction, float maxLength = 1000.0f, float minPrecision = 0.01f); }; \ No newline at end of file diff --git a/src/core/AssetManager.cpp b/src/core/AssetManager.cpp index f4c0801..d263c4a 100644 --- a/src/core/AssetManager.cpp +++ b/src/core/AssetManager.cpp @@ -149,3 +149,33 @@ TextureCoordinates AssetManager::GetTextureByBlock(BlockTextureId block) { std::string assetName = this->GetTextureAssetNameByBlockId(block); return this->GetTextureByAssetName(assetName); } + +const std::map &AssetManager::GetTextureAtlasIndexes() { + if (!textureAtlasIndexes.empty()) + return textureAtlasIndexes; + + LOG(INFO) << "Initializing texture atlas..."; + for (int id = 1; id < 128; id++) { + for (int state = 0; state < 16; state++) { + BlockTextureId blockTextureId(id, state, 6); + if (!this->GetTextureByBlock(blockTextureId) && + !this->GetTextureByBlock(BlockTextureId(id, state, 0))) { + continue; + } + if (this->GetTextureByBlock(blockTextureId)) { + for (int i = 0; i < 6; i++) { + TextureCoordinates tc = this->GetTextureByBlock(BlockTextureId(id, state, 6)); + textureAtlasIndexes[BlockTextureId(id, state, i)] = glm::vec4(tc.x, tc.y, tc.w, tc.h); + } + } else { + for (int i = 0; i < 6; i++) { + TextureCoordinates tc = this->GetTextureByBlock(BlockTextureId(id, state, i)); + textureAtlasIndexes[BlockTextureId(id, state, i)] = glm::vec4(tc.x, tc.y, tc.w, tc.h); + } + } + } + } + LOG(INFO) << "Created " << textureAtlasIndexes.size() << " texture indexes"; + + return textureAtlasIndexes; +} diff --git a/src/core/Core.cpp b/src/core/Core.cpp index 5538439..44e2648 100644 --- a/src/core/Core.cpp +++ b/src/core/Core.cpp @@ -1,5 +1,6 @@ #include "Core.hpp" +//Core::Core():toRenderMutex("toRender"),availableChunksMutex("availableChunks") { Core::Core() { LOG(INFO) << "Core initializing..."; InitSfml(900, 450, "AltCraft"); @@ -8,8 +9,8 @@ Core::Core() { glCheckError(); client = new NetworkClient("127.0.0.1", 25565, "HelloOne", isRunning); gameState = new GameState(client, isRunning); - std::thread loop = std::thread(&Core::UpdateGameState, this); - std::swap(loop, gameStateLoopThread); + gameStateLoopThread = std::thread(&Core::UpdateGameState, this); + sectionUpdateLoopThread = std::thread(&Core::UpdateSections, this); assetManager = new AssetManager; PrepareToRendering(); LOG(INFO) << "Core is initialized"; @@ -19,6 +20,7 @@ Core::Core() { Core::~Core() { LOG(INFO) << "Core stopping..."; gameStateLoopThread.join(); + sectionUpdateLoopThread.join(); delete shader; delete gameState; delete client; @@ -42,26 +44,37 @@ void Core::Exec() { UpdateChunksToRender(); } - std::ostringstream toWindow; + /*std::ostringstream toWindow; auto camPos = gameState->Position(); auto velPos = glm::vec3(gameState->g_PlayerVelocityX, gameState->g_PlayerVelocityY, gameState->g_PlayerVelocityZ); toWindow << std::setprecision(2) << std::fixed; - toWindow << "Pos: " << camPos.x << ", " << camPos.y - 1.12 << ", " << camPos.z << "; "; + toWindow << "Pos: " << camPos.x << ", " << camPos.y << ", " << camPos.z << "; "; toWindow << "Health: " << gameState->g_PlayerHealth << "; "; //toWindow << "OG: " << gameState->g_OnGround << "; "; toWindow << "Vel: " << velPos.x << ", " << velPos.y << ", " << velPos.z << "; "; toWindow << "FPS: " << (1.0f / deltaTime) << " "; toWindow << " (" << deltaTime * 1000 << "ms); "; toWindow << "Tickrate: " << tickRate << " (" << (1.0 / tickRate * 1000) << "ms); "; - window->setTitle(toWindow.str()); + toWindow << "Sections: " << sectionRate << " (" << (1.0 / sectionRate * 1000) << "ms); "; + window->setTitle(toWindow.str());*/ HandleEvents(); - if (isMouseCaptured) - HandleMouseCapture(); + if (isMouseCaptured) HandleMouseCapture(); glCheckError(); RenderFrame(); + if (isRendersShouldBeCreated) { + availableChunksMutex.lock(); + for (auto &it:renders) { + auto pair = std::make_pair(it, RenderSection(&gameState->world, it)); + availableChunks.insert(pair); + } + renders.clear(); + availableChunksMutex.unlock(); + isRendersShouldBeCreated = false; + waitRendersCreated.notify_all(); + } } } @@ -99,7 +112,7 @@ void Core::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string W contextSetting.depthBits = 24; window = new sf::Window(sf::VideoMode(WinWidth, WinHeight), WinTitle, sf::Style::Default, contextSetting); glCheckError(); - window->setVerticalSyncEnabled(true); + //window->setVerticalSyncEnabled(true); //window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2, sf::VideoMode::getDesktopMode().height / 2)); window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2 - window->getSize().x / 2, sf::VideoMode::getDesktopMode().height / 2 - window->getSize().y / 2)); @@ -117,7 +130,7 @@ void Core::InitGlew() { } glViewport(0, 0, width(), height()); glEnable(GL_DEPTH_TEST); - //glEnable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CCW); //glEnable(GL_BLEND); @@ -145,8 +158,7 @@ void Core::HandleEvents() { glViewport(0, 0, width(), height()); break; case sf::Event::KeyPressed: - if (!window->hasFocus()) - break; + if (!window->hasFocus()) break; switch (event.key.code) { case sf::Keyboard::Escape: LOG(INFO) << "Received close event by esc"; @@ -168,26 +180,16 @@ void Core::HandleEvents() { default: break; } - /*case sf::Event::MouseWheelScrolled: - if (!window->hasFocus()) - break; - camera.ProcessMouseScroll(event.mouseWheelScroll.delta); - break;*/ default: break; } } if (window->hasFocus()) { - if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) - gameState->HandleMovement(GameState::FORWARD, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) - gameState->HandleMovement(GameState::BACKWARD, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) - gameState->HandleMovement(GameState::LEFT, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) - gameState->HandleMovement(GameState::RIGHT, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) - gameState->HandleMovement(GameState::JUMP, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) gameState->HandleMovement(GameState::FORWARD, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) gameState->HandleMovement(GameState::BACKWARD, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) gameState->HandleMovement(GameState::LEFT, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) gameState->HandleMovement(GameState::RIGHT, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) gameState->HandleMovement(GameState::JUMP, deltaTime); UpdateChunksToRender(); } } @@ -218,8 +220,16 @@ void Core::RenderWorld() { glCheckError(); + toRenderMutex.lock(); for (auto &render : toRender) { - Section §ion = *availableChunks.find(render)->second.GetSection(); + availableChunksMutex.lock(); + auto iterator = availableChunks.find(render); + if (iterator == availableChunks.end()) { + availableChunksMutex.unlock(); + continue; + } + /*Section §ion = *iterator->second.GetSection(); + //availableChunksMutex.unlock(); std::vector sectionCorners = { Vector(0, 0, 0), @@ -232,8 +242,8 @@ void Core::RenderWorld() { Vector(16, 16, 16), }; bool isBreak = true; + glm::mat4 vp = projection * view; for (auto &it:sectionCorners) { - glm::mat4 vp = projection * view; glm::vec3 point(section.GetPosition().GetX() * 16 + it.GetX(), section.GetPosition().GetY() * 16 + it.GetY(), section.GetPosition().GetZ() * 16 + it.GetZ()); @@ -248,10 +258,14 @@ void Core::RenderWorld() { glm::vec3(section.GetPosition().GetX() * 16, section.GetPosition().GetY() * 16, section.GetPosition().GetZ() * 16)) > 30.0f) { + availableChunksMutex.unlock(); continue; } - availableChunks.find(render)->second.Render(renderState); + //availableChunksMutex.lock();*/ + iterator->second.Render(renderState); + availableChunksMutex.unlock(); } + toRenderMutex.unlock(); glCheckError(); } @@ -263,71 +277,17 @@ void Core::SetMouseCapture(bool IsCaptured) { } void Core::PrepareToRendering() { - shader = new Shader("./shaders/block.vs", "./shaders/block.fs"); + shader = new Shader("./shaders/face.vs", "./shaders/face.fs"); shader->Use(); - LOG(INFO) << "Initializing texture atlas..."; //TextureAtlas texture glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, assetManager->GetTextureAtlas()); glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0); - - //TextureAtlas coordinates - std::vector textureCoordinates; - std::vector indexes; - GLint totalTextures; - for (int id = 1; id < 128; id++) { - for (int state = 0; state < 16; state++) { - BlockTextureId blockTextureId(id, state, 6); - if (!assetManager->GetTextureByBlock(blockTextureId) && - !assetManager->GetTextureByBlock(BlockTextureId(id, state, 0))) { - continue; - } - int side = assetManager->GetTextureByBlock(blockTextureId) ? 6 : 0; - do { - int index = (side << 16) | (id << 4) | state; - TextureCoordinates tc = assetManager->GetTextureByBlock(BlockTextureId(id, state, side)); - textureCoordinates.push_back(glm::vec4(tc.x, tc.y, tc.w, tc.h)); - indexes.push_back(index); - side++; - } while (side < 6); - } - } - totalTextures = indexes.size(); - LOG(INFO) << "Created " << totalTextures << " texture indexes"; - CHECK_EQ(indexes.size(), textureCoordinates.size()) - << "Arrays of textureCoordinates and of indexes is not equals"; - CHECK_LE(totalTextures, 1023) << "There is more texture indexes, than GLSL buffer allows"; - - GLuint bp1 = 0; - GLuint ubo = glGetUniformBlockIndex(shader->Program, "TextureIndexes"); - glUniformBlockBinding(shader->Program, ubo, bp1); - glGenBuffers(1, &UboTextureIndexes); - glBindBuffer(GL_UNIFORM_BUFFER, UboTextureIndexes); - glBindBufferBase(GL_UNIFORM_BUFFER, bp1, UboTextureIndexes); - glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) + sizeof(glm::vec4) * 1023, nullptr, GL_STATIC_DRAW); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLint), &totalTextures); //copy totalTextures - for (size_t i = 0; i < indexes.size(); i++) { - size_t baseOffset = sizeof(glm::vec4); - size_t itemOffset = sizeof(glm::vec4); - size_t offset = baseOffset + i * itemOffset; - glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(GLint), &indexes[i]); //copy indexes' item - } - glCheckError(); - - GLuint bp2 = 1; - GLuint ubo2_index = glGetUniformBlockIndex(shader->Program, "TextureData"); - glUniformBlockBinding(shader->Program, ubo2_index, bp2); - glGenBuffers(1, &UboTextureData); - glBindBuffer(GL_UNIFORM_BUFFER, UboTextureData); - glBindBufferBase(GL_UNIFORM_BUFFER, bp2, UboTextureData); - glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) * 1024, nullptr, GL_STATIC_DRAW); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::vec4) * textureCoordinates.size(), textureCoordinates.data()); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - glCheckError(); } void Core::UpdateChunksToRender() { + return; Vector playerChunk = Vector(floor(gameState->g_PlayerX / 16.0f), 0, floor(gameState->g_PlayerZ / 16.0f)); static Vector previousPlayerChunk = playerChunk; static bool firstTime = true; @@ -338,24 +298,23 @@ void Core::UpdateChunksToRender() { previousPlayerChunk = playerChunk; previousRenderDistance = ChunkDistance; toRender.clear(); - for (auto &it:gameState->world.sections) { - Vector chunkPosition = it.first; + for (auto &it:gameState->world.GetSectionsList()) { + Vector chunkPosition = it; chunkPosition.SetY(0); Vector delta = chunkPosition - playerChunk; - if (delta.GetMagnitude() > ChunkDistance) - continue; - toRender.push_back(it.first); + if (delta.GetMagnitude() > ChunkDistance) continue; + toRender.push_back(it); } for (auto &it:toRender) { if (availableChunks.find(it) == availableChunks.end()) { auto pair = std::make_pair(it, RenderSection(&gameState->world, it)); + pair.second.UpdateState(assetManager->GetTextureAtlasIndexes()); availableChunks.insert(pair); } else { - availableChunks.find(it)->second.UpdateState(); + //availableChunks.find(it)->second.UpdateState(); } } - if (firstTime) - LOG(INFO) << "Chunks to render: " << toRender.size() << " of " << availableChunks.size(); + if (firstTime) LOG(INFO) << "Chunks to render: " << toRender.size() << " of " << availableChunks.size(); firstTime = false; } @@ -373,4 +332,126 @@ void Core::UpdateGameState() { tickRate = 1 / delta.getElapsedTime().asSeconds(); } LOG(INFO) << "GameState thread is stopped"; +} + +void Core::UpdateSections() { + glm::vec3 playerPosition = gameState->Position(); + float playerPitch = gameState->Pitch(); + float playerYaw = gameState->Yaw(); + sf::Clock delta; + std::vector chunksToRender; + auto currentSectionIterator = chunksToRender.begin(); + while (isRunning) { + delta.restart(); + if (glm::length(glm::distance(gameState->Position(), playerPosition)) > 5.0f) { + chunksToRender.clear(); + playerPosition = gameState->Position(); + Vector playerChunk = Vector(floor(playerPosition.x / 16.0f), 0, floor(playerPosition.z / 16.0f)); + for (auto &it:gameState->world.GetSectionsList()) { + Vector chunkPosition = it; + chunkPosition.SetY(0); + Vector delta = chunkPosition - playerChunk; + if (delta.GetMagnitude() > ChunkDistance) continue; + chunksToRender.push_back(it); + } + std::sort(chunksToRender.begin(), chunksToRender.end(), [playerChunk](auto first, auto second) { + glm::vec3 fDistance = first - playerChunk; + glm::vec3 sDistance = second - playerChunk; + return glm::length(fDistance) < glm::length(sDistance); + }); + for (auto &it:chunksToRender) { + availableChunksMutex.lock(); + if (availableChunks.find(it) == availableChunks.end()) { + availableChunksMutex.unlock(); + renders.push_back(it); + } else + availableChunksMutex.unlock(); + } + if (!renders.empty()) { + std::mutex mutex; + std::unique_lock lock(mutex); + isRendersShouldBeCreated = true; + while (isRendersShouldBeCreated) + waitRendersCreated.wait(lock); + } + currentSectionIterator = chunksToRender.begin(); + toRenderMutex.lock(); + toRender = chunksToRender; + toRenderMutex.unlock(); + } + if (currentSectionIterator != chunksToRender.end()) { + availableChunksMutex.lock(); + auto iterator = availableChunks.find(*currentSectionIterator); + if (iterator != availableChunks.end() && iterator->second.IsNeedUpdate()) { + RenderSection rs = std::move(iterator->second); + availableChunks.erase(iterator); + auto pair = std::make_pair(*currentSectionIterator, rs); + availableChunksMutex.unlock(); + + pair.second.UpdateState(assetManager->GetTextureAtlasIndexes()); + + availableChunksMutex.lock(); + availableChunks.insert(pair); + } + availableChunksMutex.unlock(); + currentSectionIterator = std::next(currentSectionIterator); + } + if (gameState->Pitch() != playerPitch || gameState->Yaw() != playerYaw) { + playerPitch = gameState->Pitch(); + playerYaw = gameState->Yaw(); + const std::vector sectionCorners = { + Vector(0, 0, 0), + Vector(0, 0, 16), + Vector(0, 16, 0), + Vector(0, 16, 16), + Vector(16, 0, 0), + Vector(16, 0, 16), + Vector(16, 16, 0), + Vector(16, 16, 16), + }; + const glm::mat4 projection = glm::perspective(45.0f, (float)width() / (float)height(), 0.1f, 10000000.0f); + const glm::mat4 view = gameState->GetViewMatrix(); + const glm::mat4 vp = projection * view; + for (auto& section: toRender) { + bool isCulled = true; + for (auto &it : sectionCorners) { + glm::vec3 point(section.GetX() * 16 + it.GetX(), + section.GetY() * 16 + it.GetY(), + section.GetZ() * 16 + it.GetZ()); + glm::vec4 p = vp * glm::vec4(point, 1); + glm::vec3 res = glm::vec3(p) / p.w; + if (res.x < 1 && res.x > -1 && res.y < 1 && res.y > -1 && res.z > 0) { + isCulled = false; + break; + } + } + bool isVisible = !isCulled || glm::length(gameState->Position() - + glm::vec3(section.GetX() * 16, section.GetY() * 16, section.GetZ() * 16)) < 30.0f; + availableChunksMutex.lock(); + auto iter = availableChunks.find(section); + if (iter != availableChunks.end()) + iter->second.SetEnabled(isVisible); + availableChunksMutex.unlock(); + + } + } + using namespace std::chrono_literals; + std::this_thread::sleep_for(5ms); + sectionRate = delta.getElapsedTime().asSeconds(); + delta.restart(); + } +} + +MyMutex::MyMutex(std::string name) { + str = name; +} + +void MyMutex::lock() { + LOG(WARNING) << "Thread " << std::this_thread::get_id() << " locked mutex " << str; + mtx.lock(); +} + +void MyMutex::unlock() { + LOG(WARNING) << "Thread " << std::this_thread::get_id() << " unlocked mutex " << str; + mtx.unlock(); } \ No newline at end of file diff --git a/src/graphics/RenderSection.cpp b/src/graphics/RenderSection.cpp index fec67b5..90d4329 100644 --- a/src/graphics/RenderSection.cpp +++ b/src/graphics/RenderSection.cpp @@ -1,103 +1,24 @@ #include +#include const GLfloat vertices[] = { - //Z+ edge - -0.5f, 0.5f, 0.5f, - -0.5f, -0.5f, 0.5f, - 0.5f, -0.5f, 0.5f, - -0.5f, 0.5f, 0.5f, - 0.5f, -0.5f, 0.5f, - 0.5f, 0.5f, 0.5f, - - //Z- edge - -0.5f, -0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, -0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, - 0.5f, 0.5f, -0.5f, - - //X+ edge - -0.5f, -0.5f, -0.5f, - -0.5f, -0.5f, 0.5f, - -0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, - -0.5f, -0.5f, 0.5f, - -0.5f, 0.5f, 0.5f, - - //X- edge - 0.5f, -0.5f, 0.5f, - 0.5f, 0.5f, -0.5f, - 0.5f, 0.5f, 0.5f, - 0.5f, -0.5f, 0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, 0.5f, -0.5f, - - //Y+ edge - 0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, 0.5f, - 0.5f, 0.5f, 0.5f, - 0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, 0.5f, - - //Y- edge - -0.5f, -0.5f, 0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, -0.5f, 0.5f, - -0.5f, -0.5f, -0.5f, - 0.5f, -0.5f, -0.5f, - -0.5f, -0.5f, 0.5f, + 0, 0, 0, + 1, 0, 1, + 1, 0, 0, + + 0, 0, 0, + 0, 0, 1, + 1, 0, 1, }; const GLfloat uv_coords[] = { - //Z+ - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, - - //Z- - 1.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 0.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 1.0f, - - //X+ - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, - - //X- 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, - //Y+ - 0.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - - //Y- - 1.0f, 0.0f, - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, }; void RenderState::SetActiveVao(GLuint Vao) { @@ -122,7 +43,6 @@ std::map RenderSection::refCounterVao; RenderSection::RenderSection(World *world, Vector position) : sectionPosition(position), world(world) { - if (VboVertices == magicUniqueConstant) { glGenBuffers(1, &VboVertices); glGenBuffers(1, &VboUvs); @@ -139,16 +59,21 @@ RenderSection::RenderSection(World *world, Vector position) : sectionPosition(po << ") for ordinary blocks"; } - glGenBuffers(1, &VboBlocks); - if (refCounterVbo.find(VboBlocks) == refCounterVbo.end()) - refCounterVbo[VboBlocks] = 0; - refCounterVbo[VboBlocks]++; + glGenBuffers(1, &VboTextures); + if (refCounterVbo.find(VboTextures) == refCounterVbo.end()) + refCounterVbo[VboTextures] = 0; + refCounterVbo[VboTextures]++; glGenBuffers(1, &VboModels); if (refCounterVbo.find(VboModels) == refCounterVbo.end()) refCounterVbo[VboModels] = 0; refCounterVbo[VboModels]++; + glGenBuffers(1, &VboColors); + if (refCounterVbo.find(VboColors) == refCounterVbo.end()) + refCounterVbo[VboColors] = 0; + refCounterVbo[VboColors]++; + glGenVertexArrays(1, &Vao); if (refCounterVao.find(Vao) == refCounterVao.end()) refCounterVao[Vao] = 0; @@ -157,125 +82,277 @@ RenderSection::RenderSection(World *world, Vector position) : sectionPosition(po glBindVertexArray(Vao); { //Cube vertices + GLuint VertAttribPos = 0; glBindBuffer(GL_ARRAY_BUFFER, VboVertices); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(0); + glVertexAttribPointer(VertAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(VertAttribPos); //Cube UVs + GLuint UvAttribPos = 2; glBindBuffer(GL_ARRAY_BUFFER, VboUvs); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(2); - - //Blocks ids - glBindBuffer(GL_ARRAY_BUFFER, VboBlocks); - glVertexAttribPointer(7, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(7); - glVertexAttribDivisor(7, 1); + glVertexAttribPointer(UvAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(UvAttribPos); + + //Textures + GLuint textureAttribPos = 7; + glBindBuffer(GL_ARRAY_BUFFER, VboTextures); + glVertexAttribPointer(textureAttribPos, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(textureAttribPos); + glVertexAttribDivisor(textureAttribPos, 1); glCheckError(); //Blocks models + GLuint matAttribPos = 8; size_t sizeOfMat4 = 4 * 4 * sizeof(GLfloat); glBindBuffer(GL_ARRAY_BUFFER, VboModels); - glVertexAttribPointer(8 + 0, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, nullptr); - glVertexAttribPointer(8 + 1, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (1 * 4 * sizeof(GLfloat))); - glVertexAttribPointer(8 + 2, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (2 * 4 * sizeof(GLfloat))); - glVertexAttribPointer(8 + 3, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (3 * 4 * sizeof(GLfloat))); - glEnableVertexAttribArray(8 + 0); - glEnableVertexAttribArray(8 + 1); - glEnableVertexAttribArray(8 + 2); - glEnableVertexAttribArray(8 + 3); - glVertexAttribDivisor(8 + 0, 1); - glVertexAttribDivisor(8 + 1, 1); - glVertexAttribDivisor(8 + 2, 1); - glVertexAttribDivisor(8 + 3, 1); + glVertexAttribPointer(matAttribPos + 0, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, nullptr); + glVertexAttribPointer(matAttribPos + 1, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (1 * 4 * sizeof(GLfloat))); + glVertexAttribPointer(matAttribPos + 2, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (2 * 4 * sizeof(GLfloat))); + glVertexAttribPointer(matAttribPos + 3, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (3 * 4 * sizeof(GLfloat))); + glEnableVertexAttribArray(matAttribPos + 0); + glEnableVertexAttribArray(matAttribPos + 1); + glEnableVertexAttribArray(matAttribPos + 2); + glEnableVertexAttribArray(matAttribPos + 3); + glVertexAttribDivisor(matAttribPos + 0, 1); + glVertexAttribDivisor(matAttribPos + 1, 1); + glVertexAttribDivisor(matAttribPos + 2, 1); + glVertexAttribDivisor(matAttribPos + 3, 1); + + //Color + GLuint colorAttribPos = 12; + glBindBuffer(GL_ARRAY_BUFFER, VboColors); + glVertexAttribPointer(colorAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(colorAttribPos); + glVertexAttribDivisor(colorAttribPos, 1); glBindBuffer(GL_ARRAY_BUFFER, 0); } glBindVertexArray(0); - UpdateState(); glCheckError(); } RenderSection::~RenderSection() { - refCounterVbo[VboBlocks]--; + refCounterVbo[VboTextures]--; refCounterVbo[VboModels]--; + refCounterVbo[VboColors]--; refCounterVao[Vao]--; - if (refCounterVbo[VboBlocks] <= 0) - glDeleteBuffers(1, &VboBlocks); + if (refCounterVbo[VboTextures] <= 0) + glDeleteBuffers(1, &VboTextures); + if (refCounterVbo[VboModels] <= 0) - glDeleteBuffers(1, &VboBlocks); + glDeleteBuffers(1, &VboTextures); + if (refCounterVbo[VboColors] <= 0) + glDeleteBuffers(1, &VboColors); + if (refCounterVao[Vao] <= 0) glDeleteVertexArrays(1, &Vao); } -void RenderSection::UpdateState() { - Section *section = &world->sections.find(sectionPosition)->second; - std::vector models; - std::vector blocks; +void RenderSection::UpdateState(const std::map &textureAtlas) { + Section §ion = world->GetSection(sectionPosition); + models.clear(); + textures.clear(); + colors.clear(); for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { - Block block = section->GetBlock(Vector(x, y, z)); + Vector blockPos = Vector(x, y, z) + (sectionPosition * 16); + Block &block = world->GetBlock(blockPos); if (block.id == 0) continue; + auto checkBlockVisibility = [&](Vector block) -> bool { + return section.GetBlock(block).id == 0 || + section.GetBlock(block).id == 31 || + section.GetBlock(block).id == 18; + }; + unsigned char isVisible = 0; if (x == 0 || x == 15 || y == 0 || y == 15 || z == 0 || z == 15) { - isVisible = 0; + isVisible = 0b1111'1111; //All faces is visible } else { - isVisible |= (section->GetBlock(Vector(x + 1, y, z)).id != 0) << 0; - isVisible |= (section->GetBlock(Vector(x - 1, y, z)).id != 0) << 1; - isVisible |= (section->GetBlock(Vector(x, y + 1, z)).id != 0) << 2; - isVisible |= (section->GetBlock(Vector(x, y - 1, z)).id != 0) << 3; - isVisible |= (section->GetBlock(Vector(x, y, z + 1)).id != 0) << 4; - isVisible |= (section->GetBlock(Vector(x, y, z - 1)).id != 0) << 5; + isVisible |= checkBlockVisibility(Vector(x - 1, y, z)) << 0; + isVisible |= checkBlockVisibility(Vector(x + 1, y, z)) << 1; + isVisible |= checkBlockVisibility(Vector(x, y + 1, z)) << 2; + isVisible |= checkBlockVisibility(Vector(x, y - 1, z)) << 3; + isVisible |= checkBlockVisibility(Vector(x, y, z - 1)) << 4; + isVisible |= checkBlockVisibility(Vector(x, y, z + 1)) << 5; } - if (isVisible == 0x3F) + + if (isVisible == 0x00) continue; - glm::vec2 data(block.id, block.state); - blocks.push_back(data); - glm::mat4 model; - model = glm::translate(model, glm::vec3(section->GetPosition().GetX() * 16, - section->GetPosition().GetY() * 16, - section->GetPosition().GetZ() * 16)); - model = glm::translate(model, glm::vec3(x, y, z)); - double size = 0.999; - model = glm::scale(model, glm::vec3(size, size, size)); - models.push_back(model); + glm::mat4 transform; + transform = glm::translate(transform, glm::vec3(sectionPosition.GetX() * 16, + sectionPosition.GetY() * 16, + sectionPosition.GetZ() * 16)); + transform = glm::translate(transform, glm::vec3(x, y, z)); + glm::vec3 biomeColor(0.275, 0.63, 0.1); + glm::vec3 color(0.0f, 0.0f, 0.0f); + if (block.id == 31 || block.id == 18) + color = biomeColor; + + if (block.id == 31) { //X-cross like blocks rendering + auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 2)); + for (int i = 0; i < 4; i++) { + textures.push_back(texture->second); + colors.push_back(color); + } + glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0.15f, 0, 0.15f)); + faceTransform = glm::scale(faceTransform, glm::vec3(1.0f, 0.9f, 1.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0)); + for (int i = 0; i < 4; i++) { + models.push_back(faceTransform); + faceTransform = glm::translate(faceTransform, glm::vec3(0.0f, 0.0f, 0.5f)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + faceTransform = glm::translate(faceTransform, glm::vec3(0.0f, 0.0f, -0.5f)); + } + continue; + } + + if (isVisible >> 0 & 0x1) { //east side of block (X+) + glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f)); + models.push_back(faceTransform); + auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 2)); + if (texture != textureAtlas.end()) + textures.push_back(texture->second); + else + textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, + 0.0078125, 0.00442477876106194690)); //Fallback TNT texture + colors.push_back(color); + } + if (isVisible >> 1 & 0x1) { //west side X- + glm::mat4 faceTransform = glm::translate(transform, glm::vec3(1, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); + models.push_back(faceTransform); + auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 3)); + if (texture != textureAtlas.end()) + textures.push_back(texture->second); + else + textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, + 0.0078125, 0.00442477876106194690)); //Fallback TNT texture + colors.push_back(color); + } + if (isVisible >> 2 & 0x1) { //Top side Y+ + glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 1, 0)); + models.push_back(faceTransform); + auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 1)); + if (texture != textureAtlas.end()) + textures.push_back(texture->second); + else + textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, + 0.0078125, 0.00442477876106194690)); //Fallback TNT texture + if (block.id != 2) + colors.push_back(color); + else + colors.push_back(biomeColor); + } + if (isVisible >> 3 & 0x1) { //Bottom side Y- + glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0, 0)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); + models.push_back(faceTransform); + auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 0)); + if (texture != textureAtlas.end()) + textures.push_back(texture->second); + else + textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, + 0.0078125, 0.00442477876106194690)); //Fallback TNT texture + colors.push_back(color); + } + if (isVisible >> 4 & 0x1) { //south side Z+ + glm::mat4 faceTransform = glm::translate(transform, glm::vec3(1, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); + models.push_back(faceTransform); + auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 3)); + if (texture != textureAtlas.end()) + textures.push_back(texture->second); + else + textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, + 0.0078125, 0.00442477876106194690)); //Fallback TNT texture + colors.push_back(color); + } + if (isVisible >> 5 & 0x1) { //north side Z- + glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 1)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); + faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1, 0, 0.0f)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1.0f)); + models.push_back(faceTransform); + auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 4)); + if (texture != textureAtlas.end()) + textures.push_back(texture->second); + else + textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, + 0.0078125, 0.00442477876106194690)); //Fallback TNT texture + colors.push_back(color); + } } } } - glBindBuffer(GL_ARRAY_BUFFER, VboBlocks); - glBufferData(GL_ARRAY_BUFFER, blocks.size() * sizeof(glm::vec2), blocks.data(), GL_DYNAMIC_DRAW); + numOfFaces = textures.size(); + hash = section.GetHash(); +} - glBindBuffer(GL_ARRAY_BUFFER, VboModels); - glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_DYNAMIC_DRAW); +void RenderSection::Render(RenderState &state) { + if (!isEnabled) { + return; + } + if (!models.empty()) { + glBindBuffer(GL_ARRAY_BUFFER, VboTextures); + glBufferData(GL_ARRAY_BUFFER, textures.size() * sizeof(glm::vec4), textures.data(), GL_DYNAMIC_DRAW); + textures.clear(); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, VboModels); + glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_DYNAMIC_DRAW); + models.clear(); - numOfBlocks = blocks.size(); -} + glBindBuffer(GL_ARRAY_BUFFER, VboColors); + glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_DYNAMIC_DRAW); + colors.clear(); -void RenderSection::Render(RenderState &state) { + glBindBuffer(GL_ARRAY_BUFFER, 0); + } state.SetActiveVao(Vao); - glDrawArraysInstanced(GL_TRIANGLES, 0, 36, numOfBlocks); + glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numOfFaces); glCheckError(); } Section *RenderSection::GetSection() { - return &world->sections.find(sectionPosition)->second; + return &world->GetSection(sectionPosition); } RenderSection::RenderSection(const RenderSection &other) { this->world = other.world; this->VboModels = other.VboModels; - this->VboBlocks = other.VboBlocks; + this->VboTextures = other.VboTextures; + this->VboColors = other.VboColors; this->sectionPosition = other.sectionPosition; this->Vao = other.Vao; - this->numOfBlocks = other.numOfBlocks; + this->numOfFaces = other.numOfFaces; + this->models = other.models; + this->textures = other.textures; + this->colors = other.colors; + this->hash = other.hash; - refCounterVbo[VboBlocks]++; + refCounterVbo[VboTextures]++; refCounterVbo[VboModels]++; + refCounterVbo[VboColors]++; refCounterVao[Vao]++; } + +void RenderSection::SetEnabled(bool isEnabled) { + this->isEnabled = isEnabled; +} + +bool RenderSection::IsNeedUpdate() { + size_t currentHash = world->GetSection(sectionPosition).GetHash(); + bool isNeedUpdate = currentHash != hash; + return isNeedUpdate; +} \ No newline at end of file diff --git a/src/network/Stream.cpp b/src/network/Stream.cpp index 447b13f..2545b48 100644 --- a/src/network/Stream.cpp +++ b/src/network/Stream.cpp @@ -30,11 +30,10 @@ short StreamInput::ReadShort() { } unsigned short StreamInput::ReadUShort() { - unsigned char buff[2]; - ReadData(buff, 2); - unsigned short val = *(reinterpret_cast(buff)); - endswap(val); - return val; + unsigned short value; + ReadData((unsigned char *) &value, 2); + endswap(value); + return value; } int StreamInput::ReadInt() { diff --git a/src/world/GameState.cpp b/src/world/GameState.cpp index b484b06..79e2f1b 100644 --- a/src/world/GameState.cpp +++ b/src/world/GameState.cpp @@ -325,14 +325,6 @@ void GameState::HandleMovement(GameState::Direction direction, float deltaTime) g_PlayerVelocityX = vel.x; g_PlayerVelocityY = vel.y; g_PlayerVelocityZ = vel.z; - - /*bool isCollides = world.isPlayerCollides(g_PlayerX, g_PlayerY, g_PlayerZ); - if (isCollides) { - SetPosition(previousPos); - return; - } - auto updatePacket = std::make_shared(g_PlayerX, g_PlayerY, g_PlayerZ, true); - nc->SendPacket(updatePacket);*/ } void GameState::HandleRotation(double yaw, double pitch) { @@ -349,7 +341,9 @@ void GameState::HandleRotation(double yaw, double pitch) { } glm::mat4 GameState::GetViewMatrix() { - return glm::lookAt(this->Position(), this->Position() + this->Front, this->Up); + auto pos = this->Position(); + pos.y+=1.62; + return glm::lookAt(pos, pos + this->Front, this->Up); } void GameState::updateCameraVectors() { @@ -379,11 +373,11 @@ void GameState::SetPitch(float pitch) { } glm::vec3 GameState::Position() { - return glm::vec3(g_PlayerX - 0.5, g_PlayerY + 1.12, g_PlayerZ - 0.5); + return glm::vec3(g_PlayerX, g_PlayerY, g_PlayerZ); } void GameState::SetPosition(glm::vec3 Position) { - g_PlayerX = Position.x + 0.5; - g_PlayerY = Position.y - 1.12; - g_PlayerZ = Position.z + 0.5; + g_PlayerX = Position.x; + g_PlayerY = Position.y; + g_PlayerZ = Position.z; } diff --git a/src/world/Section.cpp b/src/world/Section.cpp index a338e49..279d2b2 100644 --- a/src/world/Section.cpp +++ b/src/world/Section.cpp @@ -33,20 +33,13 @@ Section::~Section() { } Block &Section::GetBlock(Vector pos) { - if (m_dataBlocks != nullptr) { - std::mutex parseMutex; - std::unique_lock parseLocker(parseMutex); - parseWaiter.wait(parseLocker); - while (m_dataBlocks != nullptr) { - parseWaiter.wait(parseLocker); - } - LOG(WARNING) << "Successfully waited for block render!"; - } return m_blocks[pos.GetY() * 256 + pos.GetZ() * 16 + pos.GetX()]; } +double totalParsingTime = 0; + void Section::Parse() { - if (m_dataBlocks == nullptr) + if (!m_blocks.empty()) return; long long *longArray = reinterpret_cast(m_dataBlocks); @@ -54,23 +47,28 @@ void Section::Parse() { endswap(&longArray[i]); std::vector blocks; blocks.reserve(4096); - int bitPos = 0; - unsigned short t = 0; - for (size_t i = 0; i < m_dataBlocksLen; i++) { - for (int j = 0; j < 8; j++) { - t |= (m_dataBlocks[i] & 0x01) ? 0x80 : 0x00; - t >>= 1; - m_dataBlocks[i] >>= 1; - bitPos++; - if (bitPos >= m_bitsPerBlock) { - bitPos = 0; - t >>= m_bitsPerBlock - 1; - blocks.push_back(t); - t = 0; - } - } - } - + { + auto begin = std::chrono::steady_clock::now(); + int bitPos = 0; + unsigned short t = 0; + for (size_t i = 0; i < m_dataBlocksLen; i++) { + for (int j = 0; j < 8; j++) { + t |= (m_dataBlocks[i] & 0x01) ? 0x80 : 0x00; + t >>= 1; + m_dataBlocks[i] >>= 1; + bitPos++; + if (bitPos >= m_bitsPerBlock) { + bitPos = 0; + t >>= m_bitsPerBlock - 1; + blocks.push_back(t); + t = 0; + } + } + } + auto end = std::chrono::steady_clock::now(); + std::chrono::duration time = end - begin; + totalParsingTime += time.count(); + } std::vector light; light.reserve(4096); for (int i = 0; i < 2048; i++) { @@ -85,9 +83,6 @@ void Section::Parse() { Block block(blockId >> 4, blockId & 0xF); m_blocks.push_back(block); } - if ((light.size() + blocks.size()) / 2 != 4096) { - throw 118; - } delete[] m_dataBlocks; m_dataBlocksLen = 0; m_dataBlocks = nullptr; @@ -118,15 +113,19 @@ void swap(Section &a, Section &b) { Section::Section(const Section &other) { worldPosition = other.worldPosition; m_dataBlocksLen = other.m_dataBlocksLen; - m_dataBlocks = new byte[m_dataBlocksLen]; - std::copy(other.m_dataBlocks, other.m_dataBlocks + m_dataBlocksLen, m_dataBlocks); + if (other.m_blocks.empty()) { + m_dataBlocks = new byte[m_dataBlocksLen]; + std::copy(other.m_dataBlocks, other.m_dataBlocks + m_dataBlocksLen, m_dataBlocks); - m_dataLight = new byte[2048]; - std::copy(other.m_dataLight, other.m_dataLight + 2048, m_dataLight); + m_dataLight = new byte[2048]; + std::copy(other.m_dataLight, other.m_dataLight + 2048, m_dataLight); - if (other.m_dataSkyLight) { - m_dataSkyLight = new byte[2048]; - std::copy(other.m_dataSkyLight, other.m_dataSkyLight + 2048, m_dataSkyLight); + if (other.m_dataSkyLight) { + m_dataSkyLight = new byte[2048]; + std::copy(other.m_dataSkyLight, other.m_dataSkyLight + 2048, m_dataSkyLight); + } + } else { + std::copy(other.m_blocks.begin(), other.m_blocks.end(), std::back_inserter(m_blocks)); } m_palette = other.m_palette; @@ -136,3 +135,10 @@ Section::Section(const Section &other) { Vector Section::GetPosition() { return worldPosition; } + +size_t Section::GetHash() { + if (m_blocks.empty()) + return 0; + std::string str((unsigned char*)m_blocks.data(), (unsigned char*)m_blocks.data() + m_blocks.size() * sizeof(Block)); + return std::hash{}(str); +} \ No newline at end of file diff --git a/src/world/World.cpp b/src/world/World.cpp index abcfebf..c83bdce 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -7,6 +7,8 @@ void World::ParseChunkData(std::shared_ptr packet) { if (bitmask[i]) { Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ); Section section = ParseSection(&chunkData, chunkPosition); + section.Parse(); + sectionMutexes[chunkPosition].lock(); auto it = sections.find(chunkPosition); if (it == sections.end()) { sections.insert(std::make_pair(chunkPosition, section)); @@ -14,7 +16,7 @@ void World::ParseChunkData(std::shared_ptr packet) { using std::swap; swap(it->second, section); } - sections.find(chunkPosition)->second.Parse(); + sectionMutexes[chunkPosition].unlock(); } } } @@ -70,11 +72,11 @@ bool World::isPlayerCollides(double X, double Y, double Z) { const double PlayerLength = 0.6; AABB playerColl; - playerColl.x = X - PlayerWidth / 2 - 0.5; + playerColl.x = X - PlayerWidth / 2.0; playerColl.w = PlayerWidth; - playerColl.y = Y - 0.5f; + playerColl.y = Y; playerColl.h = PlayerHeight; - playerColl.z = Z - PlayerLength / 2 - 0.5; + playerColl.z = Z - PlayerLength / 2.0; playerColl.l = PlayerLength; for (int x = 0; x < 16; x++) { @@ -83,9 +85,9 @@ bool World::isPlayerCollides(double X, double Y, double Z) { Block block = it->second.GetBlock(Vector(x, y, z)); if (block.id == 0 || block.id == 31) continue; - AABB blockColl{(x + it->first.GetX() * 16) - 0.5, - (y + it->first.GetY() * 16) - 0.5, - (z + it->first.GetZ() * 16) - 0.5, 1, 1, 1}; + AABB blockColl{(x + it->first.GetX() * 16.0), + (y + it->first.GetY() * 16.0), + (z + it->first.GetZ() * 16.0), 1, 1, 1}; if (TestCollision(playerColl, blockColl)) return true; } @@ -94,3 +96,34 @@ bool World::isPlayerCollides(double X, double Y, double Z) { } return false; } + +Block &World::GetBlock(Vector pos) { + Vector sectionPos (floor(pos.GetX() / 16.0f),floor(pos.GetY() / 16.0f),floor(pos.GetZ()/16.0f)); + Vector inSectionPos = pos - (sectionPos * 16); + if (sections.find(sectionPos)==sections.end()){ + static Block block(0,0); + return block; + } + sectionMutexes[sectionPos].lock(); + Block& block = sections.find(sectionPos)->second.GetBlock(inSectionPos); + sectionMutexes[sectionPos].unlock(); + return block; +} + +std::vector World::GetSectionsList() { + std::vector sectionsList; + for (auto& it:sections) { + sectionsList.push_back(it.first); + } + return sectionsList; +} + +Section &World::GetSection(Vector sectionPos) { + sectionMutexes[sectionPos].lock(); + sectionMutexes[sectionPos].unlock(); + return sections.find(sectionPos)->second; +} + +glm::vec3 World::Raycast(glm::vec3 position, glm::vec3 direction, float maxLength, float minPrecision) { + return glm::vec3(position * direction / maxLength * minPrecision); +} -- cgit v1.2.3