diff options
Diffstat (limited to 'old/core/Core.cpp')
-rw-r--r-- | old/core/Core.cpp | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/old/core/Core.cpp b/old/core/Core.cpp new file mode 100644 index 0000000..e98d204 --- /dev/null +++ b/old/core/Core.cpp @@ -0,0 +1,457 @@ +#include "Core.hpp" + +//Core::Core():toRenderMutex("toRender"),availableChunksMutex("availableChunks") { +Core::Core() { + LOG(INFO) << "Core initializing..."; + InitSfml(900, 450, "AltCraft"); + glCheckError(); + InitGlew(); + glCheckError(); + client = new NetworkClient("127.0.0.1", 25565, "HelloOne", isRunning); + gameState = new GameState(client, isRunning); + gameStateLoopThread = std::thread(&Core::UpdateGameState, this); + sectionUpdateLoopThread = std::thread(&Core::UpdateSections, this); + assetManager = new AssetManager; + PrepareToRendering(); + LOG(INFO) << "Core is initialized"; + glCheckError(); +} + +Core::~Core() { + LOG(INFO) << "Core stopping..."; + gameStateLoopThread.join(); + sectionUpdateLoopThread.join(); + delete shader; + delete gameState; + delete client; + delete assetManager; + delete window; + LOG(INFO) << "Core is stopped"; +} + +void Core::Exec() { + LOG(INFO) << "Main loop is executing!"; + isRunning = true; + while (isRunning) { + static sf::Clock clock, clock1; + deltaTime = clock.getElapsedTime().asSeconds(); + absTime = clock1.getElapsedTime().asSeconds(); + clock.restart(); + + static bool alreadyDone = false; + if (gameState->g_IsGameStarted && !alreadyDone) { + alreadyDone = true; + UpdateChunksToRender(); + } + + 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 << ", " << 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); "; + toWindow << "Sections: " << sectionRate << " (" << (1.0 / sectionRate * 1000) << "ms); "; + window->setTitle(toWindow.str()); + + HandleEvents(); + 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(); + } + + } +} + +void Core::RenderFrame() { + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + switch (currentState) { + case MainMenu: + //RenderGui(MenuScreen); + break; + case Loading: + //RenderGui(LoadingScreen); + break; + case Playing: + RenderWorld(); + //RenderGui(HUD); + break; + case PauseMenu: + RenderWorld(); + //RenderGui(PauseGui); + break; + } + + window->display(); +} + +void Core::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string WinTitle) { + LOG(INFO) << "Creating window: " << WinWidth << "x" << WinHeight << " \"" << WinTitle << "\""; + sf::ContextSettings contextSetting; + contextSetting.majorVersion = 3; + contextSetting.minorVersion = 3; + contextSetting.attributeFlags = contextSetting.Core; + contextSetting.depthBits = 24; + window = new sf::Window(sf::VideoMode(WinWidth, WinHeight), WinTitle, sf::Style::Default, contextSetting); + glCheckError(); + //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)); + + SetMouseCapture(false); +} + +void Core::InitGlew() { + LOG(INFO) << "Initializing GLEW"; + glewExperimental = GL_TRUE; + GLenum glewStatus = glewInit(); + glCheckError(); + if (glewStatus != GLEW_OK) { + LOG(FATAL) << "Failed to initialize GLEW: " << glewGetErrorString(glewStatus); + } + glViewport(0, 0, width(), height()); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glCheckError(); +} + +unsigned int Core::width() { + return window->getSize().x; +} + +unsigned int Core::height() { + return window->getSize().y; +} + +void Core::HandleEvents() { + sf::Event event; + while (window->pollEvent(event)) { + switch (event.type) { + case sf::Event::Closed: + LOG(INFO) << "Received close event by window closing"; + isRunning = false; + break; + case sf::Event::Resized: + glViewport(0, 0, width(), height()); + break; + case sf::Event::KeyPressed: + if (!window->hasFocus()) break; + switch (event.key.code) { + case sf::Keyboard::Escape: + LOG(INFO) << "Received close event by esc"; + isRunning = false; + break; + case sf::Keyboard::T: + SetMouseCapture(!isMouseCaptured); + break; + case sf::Keyboard::L: + ChunkDistance++; + LOG(INFO) << "Increased render distance: " << ChunkDistance; + break; + case sf::Keyboard::K: + if (ChunkDistance > 1) { + ChunkDistance--; + LOG(INFO) << "Decreased render distance: " << ChunkDistance; + } + break; + default: + 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); + UpdateChunksToRender(); + } +} + +void Core::HandleMouseCapture() { + sf::Vector2i mousePos = sf::Mouse::getPosition(*window); + sf::Vector2i center = sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2); + sf::Mouse::setPosition(center, *window); + mouseXDelta = (mousePos - center).x, mouseYDelta = (center - mousePos).y; + const float Sensetivity = 0.7f; + gameState->HandleRotation(mouseXDelta * Sensetivity, mouseYDelta * Sensetivity); + //camera.ProcessMouseMovement(mouseXDelta, mouseYDelta); +} + +void Core::RenderWorld() { + shader->Use(); + glCheckError(); + + GLint projectionLoc = glGetUniformLocation(shader->Program, "projection"); + GLint viewLoc = glGetUniformLocation(shader->Program, "view"); + GLint timeLoc = glGetUniformLocation(shader->Program, "time"); + glm::mat4 projection = glm::perspective(45.0f, (float) width() / (float) height(), 0.1f, 10000000.0f); + glm::mat4 view = gameState->GetViewMatrix(); + glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection)); + glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); + glUniform1f(timeLoc, absTime); + glUniform2f(glGetUniformLocation(shader->Program, "windowSize"), width(), height()); + + glCheckError(); + + toRenderMutex.lock(); + for (auto &render : toRender) { + availableChunksMutex.lock(); + auto iterator = availableChunks.find(render); + if (iterator == availableChunks.end()) { + availableChunksMutex.unlock(); + continue; + } + /*Section §ion = *iterator->second.GetSection(); + //availableChunksMutex.unlock(); + + std::vector<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), + }; + bool isBreak = true; + glm::mat4 vp = projection * view; + for (auto &it:sectionCorners) { + glm::vec3 point(section.GetPosition().GetX() * 16 + it.GetX(), + section.GetPosition().GetY() * 16 + it.GetY(), + section.GetPosition().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) { + isBreak = false; + break; + } + } + if (isBreak && glm::length(gameState->Position() - + glm::vec3(section.GetPosition().GetX() * 16, + section.GetPosition().GetY() * 16, + section.GetPosition().GetZ() * 16)) > 30.0f) { + availableChunksMutex.unlock(); + continue; + } + //availableChunksMutex.lock();*/ + iterator->second.Render(renderState); + availableChunksMutex.unlock(); + } + toRenderMutex.unlock(); + glCheckError(); +} + +void Core::SetMouseCapture(bool IsCaptured) { + window->setMouseCursorVisible(!isMouseCaptured); + sf::Mouse::setPosition(sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2), *window); + isMouseCaptured = IsCaptured; + window->setMouseCursorVisible(!IsCaptured); +} + +void Core::PrepareToRendering() { + shader = new Shader("./shaders/face.vs", "./shaders/face.fs"); + shader->Use(); + + //TextureAtlas texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, assetManager->GetTextureAtlas()); + glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0); +} + +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; + static int previousRenderDistance = ChunkDistance; + if (previousPlayerChunk == playerChunk && !firstTime && ChunkDistance == previousRenderDistance) { + return; + } + previousPlayerChunk = playerChunk; + previousRenderDistance = ChunkDistance; + toRender.clear(); + 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); + } + 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(); + } + } + if (firstTime) LOG(INFO) << "Chunks to render: " << toRender.size() << " of " << availableChunks.size(); + firstTime = false; +} + +void Core::UpdateGameState() { + el::Helpers::setThreadName("Game"); + LOG(INFO) << "GameState thread is started"; + sf::Clock delta; + while (isRunning) { + float deltaTime = delta.getElapsedTime().asSeconds(); + delta.restart(); + gameState->Update(deltaTime); + const double targetDelta = 1 / 60.0; + std::chrono::duration<double, std::ratio<1, 1>> timeToSleep(targetDelta - delta.getElapsedTime().asSeconds()); + std::this_thread::sleep_for(timeToSleep); + 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<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<std::mutex> 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<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 |