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 --- src/core/AssetManager.cpp | 30 ++++++ src/core/Core.cpp | 267 ++++++++++++++++++++++++++++++---------------- 2 files changed, 204 insertions(+), 93 deletions(-) (limited to 'src/core') 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 -- cgit v1.2.3