From ac8905602d1f221a71ddcdc86796344101276321 Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Wed, 14 Jun 2017 19:22:52 +0500 Subject: 2017-06-14 --- src/core/AssetManager.cpp | 169 ++++--- src/core/Core.cpp | 1146 +++++++++++++++++++++++++-------------------- src/core/Core.hpp | 87 ++-- src/graphics/Frustrum.cpp | 111 +++++ src/graphics/Frustrum.hpp | 24 + src/network/Network.cpp | 144 +++--- src/utility/Vector.hpp | 215 ++++----- 7 files changed, 1122 insertions(+), 774 deletions(-) create mode 100644 src/graphics/Frustrum.cpp create mode 100644 src/graphics/Frustrum.hpp (limited to 'src') diff --git a/src/core/AssetManager.cpp b/src/core/AssetManager.cpp index bcf50bc..4fb5388 100644 --- a/src/core/AssetManager.cpp +++ b/src/core/AssetManager.cpp @@ -10,76 +10,131 @@ const std::string pathToAssetsList = "./items.json"; const std::string pathToTextureIndex = "./textures.json"; AssetManager::AssetManager() { - LoadIds(); - LoadTextureResources(); + LoadIds(); + LoadTextureResources(); } void AssetManager::LoadIds() { - std::ifstream in(pathToAssetsList); - nlohmann::json index; - in >> index; - for (auto &it:index) { - int id = it["type"].get(); - int state = it["meta"].get(); - std::string blockName = it["text_type"].get(); - assetIds[blockName] = Block(id, state); - } - LOG(INFO) << "Loaded " << assetIds.size() << " ids"; + std::ifstream in(pathToAssetsList); + nlohmann::json index; + in >> index; + for (auto &it:index) { + int id = it["type"].get(); + int state = it["meta"].get(); + std::string blockName = it["text_type"].get(); + assetIds[blockName] = Block(id, state); + } + LOG(INFO) << "Loaded " << assetIds.size() << " ids"; } AssetManager::~AssetManager() { - delete textureAtlas; + delete textureAtlas; } //TODO: This function must be replaced with runtime texture atlas generating void AssetManager::LoadTextureResources() { - std::ifstream in(pathToTextureIndex); - nlohmann::json index; - in >> index; - std::string filename = index["meta"]["image"].get(); - float textureWidth = index["meta"]["size"]["w"].get(); - float textureHeight = index["meta"]["size"]["h"].get(); - for (auto &it:index["frames"]) { - auto frame = it["frame"]; - TextureCoordinates coord; - coord.x = frame["x"].get() / textureWidth; - coord.y = frame["y"].get() / textureHeight; - coord.w = frame["w"].get() / textureWidth; - coord.h = frame["h"].get() / textureHeight; - std::string assetName = it["filename"].get(); - assetName.insert(0, "minecraft/textures/"); - assetName.erase(assetName.length() - 4); - assetTextures[assetName] = coord; - } - - textureAtlas = new Texture(filename); - LOG(INFO) << "Texture atlas id is " << textureAtlas->texture; + std::ifstream in(pathToTextureIndex); + nlohmann::json index; + in >> index; + std::string filename = index["meta"]["image"].get(); + float textureWidth = index["meta"]["size"]["w"].get(); + float textureHeight = index["meta"]["size"]["h"].get(); + for (auto &it:index["frames"]) { + auto frame = it["frame"]; + TextureCoordinates coord; + coord.x = frame["x"].get() / textureWidth; + coord.y = frame["y"].get() / textureHeight; + coord.w = frame["w"].get() / textureWidth; + coord.h = frame["h"].get() / textureHeight; + std::string assetName = it["filename"].get(); + assetName.insert(0, "minecraft/textures/"); + assetName.erase(assetName.length() - 4); + assetTextures[assetName] = coord; + } + + textureAtlas = new Texture(filename); + LOG(INFO) << "Texture atlas id is " << textureAtlas->texture; } TextureCoordinates AssetManager::GetTextureByAssetName(std::string AssetName) { - if (assetTextures.find(AssetName) != assetTextures.end()) - return assetTextures[AssetName]; - else - return TextureCoordinates{-1, -1, -1, -1}; + if (assetTextures.find(AssetName) != assetTextures.end()) + return assetTextures[AssetName]; + else + return TextureCoordinates{-1, -1, -1, -1}; } std::string AssetManager::GetTextureAssetNameByBlockId(BlockTextureId block) { - //Block sides: 0 - bottom, 1 - top, 2 - north, 3 - south, 4 - west, 5 - east 6 - every side - const std::map lookupTable = { - {BlockTextureId(0, 0), "minecraft/textures/blocks/air"}, - {BlockTextureId(1, 0), "minecraft/textures/blocks/stone"}, - {BlockTextureId(1, 1), "minecraft/textures/blocks/stone_granite"}, - - {BlockTextureId(2, 0, 0), "minecraft/textures/blocks/dirt"}, - {BlockTextureId(2, 0, 1), "minecraft/textures/blocks/grass_top"}, - {BlockTextureId(2, 0, 2), "minecraft/textures/blocks/grass_side"}, - {BlockTextureId(2, 0, 3), "minecraft/textures/blocks/grass_side"}, - {BlockTextureId(2, 0, 4), "minecraft/textures/blocks/grass_side"}, - {BlockTextureId(2, 0, 5), "minecraft/textures/blocks/grass_side"}, - - {BlockTextureId(3, 0), "minecraft/textures/blocks/dirt"}, - {BlockTextureId(4, 0), "minecraft/textures/blocks/cobblestone"}, - }; + //Block sides: 0 - bottom, 1 - top, 2 - north, 3 - south, 4 - west, 5 - east 6 - every side + const std::map lookupTable = { + {BlockTextureId(0, 0), "minecraft/textures/blocks/air"}, + {BlockTextureId(1, 0), "minecraft/textures/blocks/stone"}, + {BlockTextureId(1, 1), "minecraft/textures/blocks/stone_granite"}, + + {BlockTextureId(2, 0, 0), "minecraft/textures/blocks/dirt"}, + {BlockTextureId(2, 0, 1), "minecraft/textures/blocks/grass_top"}, + {BlockTextureId(2, 0, 2), "minecraft/textures/blocks/grass_side"}, + {BlockTextureId(2, 0, 3), "minecraft/textures/blocks/grass_side"}, + {BlockTextureId(2, 0, 4), "minecraft/textures/blocks/grass_side"}, + {BlockTextureId(2, 0, 5), "minecraft/textures/blocks/grass_side"}, + + {BlockTextureId(3, 0), "minecraft/textures/blocks/dirt"}, + {BlockTextureId(4, 0), "minecraft/textures/blocks/cobblestone"}, + {BlockTextureId(5, 0), "minecraft/textures/blocks/planks"}, + + {BlockTextureId(7, 0), "minecraft/textures/blocks/bedrock"}, + + {BlockTextureId(17, 0, 0), "minecraft/textures/blocks/log_oak_top"}, + {BlockTextureId(17, 0, 1), "minecraft/textures/blocks/log_oak_top"}, + {BlockTextureId(17, 0, 2), "minecraft/textures/blocks/log_oak"}, + {BlockTextureId(17, 0, 3), "minecraft/textures/blocks/log_oak"}, + {BlockTextureId(17, 0, 4), "minecraft/textures/blocks/log_oak"}, + {BlockTextureId(17, 0, 5), "minecraft/textures/blocks/log_oak"}, + + {BlockTextureId(17, 1, 0), "minecraft/textures/blocks/log_spruce_top"}, + {BlockTextureId(17, 1, 1), "minecraft/textures/blocks/log_spruce_top"}, + {BlockTextureId(17, 1, 2), "minecraft/textures/blocks/log_spruce"}, + {BlockTextureId(17, 1, 3), "minecraft/textures/blocks/log_spruce"}, + {BlockTextureId(17, 1, 4), "minecraft/textures/blocks/log_spruce"}, + {BlockTextureId(17, 1, 5), "minecraft/textures/blocks/log_spruce"}, + + {BlockTextureId(17, 2, 0), "minecraft/textures/blocks/log_birch_top"}, + {BlockTextureId(17, 2, 1), "minecraft/textures/blocks/log_birch_top"}, + {BlockTextureId(17, 2, 2), "minecraft/textures/blocks/log_birch"}, + {BlockTextureId(17, 2, 3), "minecraft/textures/blocks/log_birch"}, + {BlockTextureId(17, 2, 4), "minecraft/textures/blocks/log_birch"}, + {BlockTextureId(17, 2, 5), "minecraft/textures/blocks/log_birch"}, + + {BlockTextureId(17, 3, 0), "minecraft/textures/blocks/log_jungle_top"}, + {BlockTextureId(17, 3, 1), "minecraft/textures/blocks/log_jungle_top"}, + {BlockTextureId(17, 3, 2), "minecraft/textures/blocks/log_jungle"}, + {BlockTextureId(17, 3, 3), "minecraft/textures/blocks/log_jungle"}, + {BlockTextureId(17, 3, 4), "minecraft/textures/blocks/log_jungle"}, + {BlockTextureId(17, 3, 5), "minecraft/textures/blocks/log_jungle"}, + + {BlockTextureId(18, 0), "minecraft/textures/blocks/leaves_oak"}, + {BlockTextureId(18, 1), "minecraft/textures/blocks/leaves_spruce"}, + {BlockTextureId(18, 2), "minecraft/textures/blocks/leaves_birch"}, + {BlockTextureId(18, 3), "minecraft/textures/blocks/leaves_jungle"}, + + {BlockTextureId(61, 0, 0), "minecraft/textures/blocks/furnace_side"}, + {BlockTextureId(61, 0, 1), "minecraft/textures/blocks/furnace_top"}, + {BlockTextureId(61, 0, 2), "minecraft/textures/blocks/furnace_front_off"}, + {BlockTextureId(61, 0, 3), "minecraft/textures/blocks/furnace_side"}, + {BlockTextureId(61, 0, 4), "minecraft/textures/blocks/furnace_side"}, + {BlockTextureId(61, 0, 5), "minecraft/textures/blocks/furnace_side"}, + + {BlockTextureId(62, 0, 0), "minecraft/textures/blocks/furnace_side"}, + {BlockTextureId(62, 0, 1), "minecraft/textures/blocks/furnace_top"}, + {BlockTextureId(62, 0, 2), "minecraft/textures/blocks/furnace_front_on"}, + {BlockTextureId(62, 0, 3), "minecraft/textures/blocks/furnace_side"}, + {BlockTextureId(62, 0, 4), "minecraft/textures/blocks/furnace_side"}, + {BlockTextureId(62, 0, 5), "minecraft/textures/blocks/furnace_side"}, + + + {BlockTextureId(31, 0), "minecraft/textures/blocks/deadbush"}, + {BlockTextureId(31, 1), "minecraft/textures/blocks/tallgrass"}, + {BlockTextureId(31, 2), "minecraft/textures/blocks/fern"}, + }; auto ret = lookupTable.find(block); if (ret == lookupTable.end()) return ""; @@ -88,10 +143,10 @@ std::string AssetManager::GetTextureAssetNameByBlockId(BlockTextureId block) { } GLuint AssetManager::GetTextureAtlas() { - return textureAtlas->texture; + return textureAtlas->texture; } TextureCoordinates AssetManager::GetTextureByBlock(BlockTextureId block) { - std::string assetName = this->GetTextureAssetNameByBlockId(block); - return this->GetTextureByAssetName(assetName); + std::string assetName = this->GetTextureAssetNameByBlockId(block); + return this->GetTextureByAssetName(assetName); } diff --git a/src/core/Core.cpp b/src/core/Core.cpp index 3257cb6..9ad36ba 100644 --- a/src/core/Core.cpp +++ b/src/core/Core.cpp @@ -1,574 +1,692 @@ #include "Core.hpp" GLenum glCheckError_(const char *file, int line) { - GLenum errorCode; - while ((errorCode = glGetError()) != GL_NO_ERROR) { - std::string error; - switch (errorCode) { - case GL_INVALID_ENUM: - error = "INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - error = "INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - error = "INVALID_OPERATION"; - break; - case GL_STACK_OVERFLOW: - error = "STACK_OVERFLOW"; - break; - case GL_STACK_UNDERFLOW: - error = "STACK_UNDERFLOW"; - break; - case GL_OUT_OF_MEMORY: - error = "OUT_OF_MEMORY"; - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - error = "INVALID_FRAMEBUFFER_OPERATION"; - break; - } - LOG(ERROR) << "OpenGL error: " << error << " at " << file << ":" << line; - } - return errorCode; + GLenum errorCode; + while ((errorCode = glGetError()) != GL_NO_ERROR) { + std::string error; + switch (errorCode) { + case GL_INVALID_ENUM: + error = "INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + error = "INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + error = "INVALID_OPERATION"; + break; + case GL_STACK_OVERFLOW: + error = "STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + error = "STACK_UNDERFLOW"; + break; + case GL_OUT_OF_MEMORY: + error = "OUT_OF_MEMORY"; + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + error = "INVALID_FRAMEBUFFER_OPERATION"; + break; + } + LOG(ERROR) << "OpenGL error: " << error << " at " << file << ":" << line; + } + return errorCode; } #define glCheckError() glCheckError_(__FILE__, __LINE__) 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, + //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, }; -/*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, -};*/ 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, + //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, }; Core::Core() { - LOG(INFO) << "Core initializing..."; - InitSfml(900, 450, "AltCraft"); - glCheckError(); - InitGlew(); - glCheckError(); - client = new NetworkClient("127.0.0.1", 25565, "HelloOne"); - gameState = new GameState(client); - std::thread loop = std::thread(&Core::UpdateGameState, this); - std::swap(loop, gameStateLoopThread); - assetManager = new AssetManager; - PrepareToWorldRendering(); - LOG(INFO) << "Core is initialized"; - glCheckError(); + LOG(INFO) << "Core initializing..."; + InitSfml(900, 450, "AltCraft"); + glCheckError(); + InitGlew(); + glCheckError(); + client = new NetworkClient("127.0.0.1", 25565, "HelloOne"); + gameState = new GameState(client); + std::thread loop = std::thread(&Core::UpdateGameState, this); + std::swap(loop, gameStateLoopThread); + assetManager = new AssetManager; + PrepareToWorldRendering(); + LOG(INFO) << "Core is initialized"; + glCheckError(); } Core::~Core() { - LOG(INFO) << "Core stopping..."; - gameStateLoopThread.join(); - delete shader; - delete gameState; - delete client; - delete assetManager; - delete window; - LOG(INFO) << "Core is stopped"; + LOG(INFO) << "Core stopping..."; + gameStateLoopThread.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; - glm::highp_vec3 camPos(camera.Position); - toWindow << std::setprecision(2) << std::fixed; - toWindow << "Pos: " << camPos.x << ", " << camPos.y << ", " << camPos.z << "; "; - toWindow << "FPS: " << (1.0f / deltaTime) << " "; - window->setTitle(toWindow.str()); - - HandleEvents(); - if (isMouseCaptured) - HandleMouseCapture(); - glCheckError(); - - RenderFrame(); - - } + 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; + glm::highp_vec3 camPos(camera.Position); + toWindow << std::setprecision(2) << std::fixed; + toWindow << "Pos: " << camPos.x << ", " << camPos.y << ", " << camPos.z << "; "; + toWindow << "FPS: " << (1.0f / deltaTime) << " "; + toWindow << " (" << deltaTime * 1000 << "ms) "; + window->setTitle(toWindow.str()); + + HandleEvents(); + if (isMouseCaptured) + HandleMouseCapture(); + glCheckError(); + + RenderFrame(); + + } } 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(); + 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); + 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); - glCheckError(); + 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; + return window->getSize().x; } unsigned int Core::height() { - return window->getSize().y; + 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::Z: - camera.MovementSpeed /= 2; - break; - case sf::Keyboard::X: - camera.MovementSpeed *= 2; - break; - 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)) - camera.ProcessKeyboard(Camera_Movement::FORWARD, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) - camera.ProcessKeyboard(Camera_Movement::BACKWARD, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) - camera.ProcessKeyboard(Camera_Movement::LEFT, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) - camera.ProcessKeyboard(Camera_Movement::RIGHT, deltaTime); - } + 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::Z: + camera.MovementSpeed /= 2; + break; + case sf::Keyboard::X: + camera.MovementSpeed *= 2; + break; + case sf::Keyboard::M: + std::sort(toRender.begin(), toRender.end(), [this](const Vector &lhs, const Vector &rhs) { + return glm::length((glm::vec3) lhs - camera.Position) < + glm::length((glm::vec3) rhs - camera.Position); + }); + LOG(WARNING) << "Render list is optimized"; + break; + case sf::Keyboard::K: + ChunkDistance++; + LOG(INFO)<<"Increased render distance: "<hasFocus()) + break; + camera.ProcessMouseScroll(event.mouseWheelScroll.delta); + break; + default: + break; + } + } + if (window->hasFocus()) { + if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) + camera.ProcessKeyboard(Camera_Movement::FORWARD, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) + camera.ProcessKeyboard(Camera_Movement::BACKWARD, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) + camera.ProcessKeyboard(Camera_Movement::LEFT, deltaTime); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) + camera.ProcessKeyboard(Camera_Movement::RIGHT, deltaTime); + } } 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; - camera.ProcessMouseMovement(mouseXDelta, mouseYDelta); + 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; + camera.ProcessMouseMovement(mouseXDelta, mouseYDelta); } void Core::RenderGui(Gui &Target) { - Target.WHY++; + Target.WHY++; } void Core::RenderWorld() { - shader->Use(); - glCheckError(); - - GLint modelLoc = glGetUniformLocation(shader->Program, "model"); - GLint projectionLoc = glGetUniformLocation(shader->Program, "projection"); - GLint viewLoc = glGetUniformLocation(shader->Program, "view"); - GLint blockLoc = glGetUniformLocation(shader->Program, "Block"); - GLint stateLoc = glGetUniformLocation(shader->Program, "State"); - GLint timeLoc = glGetUniformLocation(shader->Program, "time"); - glm::mat4 projection = glm::perspective(camera.Zoom, (float) width() / (float) height(), 0.1f, 10000000.0f); - glm::mat4 view = camera.GetViewMatrix(); - glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection)); - glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); - glUniform1f(timeLoc, absTime); - - glCheckError(); - - glBindVertexArray(VAO); - - for (auto §ionPos : toRender) { - Section §ion = gameState->world.m_sections.find(sectionPos)->second; - 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)); - if (block.id == 0) - continue; - - glm::mat4 model; - model = glm::translate(model, glm::vec3(sectionPos.GetX() * 16, sectionPos.GetY() * 16, - sectionPos.GetZ() * 16)); - model = glm::translate(model, glm::vec3(x, y, z)); - - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); - glUniform1i(blockLoc, block.id); - glUniform1i(stateLoc, block.state); - - glDrawArrays(GL_TRIANGLES, 0, 36); - } - } - } - } - glBindVertexArray(0); - glCheckError(); + shader->Use(); + glCheckError(); + + GLint modelLoc = glGetUniformLocation(shader->Program, "model"); + GLint projectionLoc = glGetUniformLocation(shader->Program, "projection"); + GLint viewLoc = glGetUniformLocation(shader->Program, "view"); + GLint blockLoc = glGetUniformLocation(shader->Program, "Block"); + GLint stateLoc = glGetUniformLocation(shader->Program, "State"); + GLint timeLoc = glGetUniformLocation(shader->Program, "time"); + glm::mat4 projection = glm::perspective(camera.Zoom, (float) width() / (float) height(), 0.1f, 10000000.0f); + glm::mat4 view = camera.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(); + + glBindVertexArray(VAO); + for (auto §ionPos : toRender) { + Section §ion = gameState->world.m_sections.find(sectionPos)->second; + + 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), + }; + bool isBreak = true; + for (auto &it:sectionCorners) { + glm::mat4 vp = projection * view; + glm::vec3 point(sectionPos.GetX() * 16 + it.GetX(), sectionPos.GetY() * 16 + it.GetY(), + sectionPos.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( + camera.Position - glm::vec3(sectionPos.GetX() * 16, sectionPos.GetY() * 16, sectionPos.GetZ() * 16)) > + 30) { + //zLOG(ERROR)<<"CULL"; + continue; + } + + std::vector &arrOfModels = toRenderModels[sectionPos]; + std::vector &arrOfBlocks = toRenderBlocks[sectionPos]; + + glBindBuffer(GL_ARRAY_BUFFER, VBO3); + glBufferData(GL_ARRAY_BUFFER, arrOfModels.size() * sizeof(glm::mat4), arrOfModels.data(), GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, VBO4); + glBufferData(GL_ARRAY_BUFFER, arrOfBlocks.size() * sizeof(glm::vec2), arrOfBlocks.data(), GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDrawArraysInstanced(GL_TRIANGLES, 0, 36, arrOfModels.size()); + } + glBindVertexArray(0); + 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); + window->setMouseCursorVisible(!isMouseCaptured); + sf::Mouse::setPosition(sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2), *window); + isMouseCaptured = IsCaptured; + window->setMouseCursorVisible(!IsCaptured); } void Core::PrepareToWorldRendering() { - //Cube-rendering data - glGenBuffers(1, &VBO); - glGenBuffers(1, &VBO2); - glGenVertexArrays(1, &VAO); - - glBindVertexArray(VAO); - { - glBindBuffer(GL_ARRAY_BUFFER, VBO2); - glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coords), uv_coords, GL_STATIC_DRAW); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0); - glEnableVertexAttribArray(2); - - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); - glEnableVertexAttribArray(0); - } - glBindVertexArray(0); - - glCheckError(); - - shader = new Shader("./shaders/block.vs", "./shaders/block.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 < 4096; id++) { - bool isReachedEnd = true; - for (int state = 0; state < 16; state++) { - BlockTextureId blockTextureId(id, state, 6); - if (!assetManager->GetTextureByBlock(blockTextureId) && - !assetManager->GetTextureByBlock(BlockTextureId(id, state, 0))) { - continue; - } - isReachedEnd = false; - 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); - /*LOG(ERROR) << "Encoded texture (" << id << " " << state << " " << side << ") as " << index << " (" - << std::bitset<19>(index) << ")" << " = " << tc.x << "," << tc.y << "," << tc.w << "," - << tc.h;*/ - /*LOG(FATAL)<(index); - side = 0x7; - id = 0xFFF; - state = 0xF; - LOG(WARNING) << "side: " << side << " id: " << id << " state: " << state; - int i, si, st, index = 0; - si = side << 15; - i = id<<3; - st = state; - index = i | si | st; - LOG(FATAL) << std::bitset<18>(index) << " (" << index << "): " << std::bitset<18>(si) << " " - << std::bitset<18>(i) << " " << std::bitset<18>(st);*/ - /*if (rand() == 73) //Almost impossible(Almost==1/32768) - { - int index = 393233; - LOG(WARNING) << std::bitset<20>(index) << "(" << index << ")"; - int side = (index & 0xE0000) >> 16; - int id = (index & 0xFF0) >> 4; - int state = index & 0xF; - LOG(WARNING) << std::bitset<20>(side) << " " << std::bitset<20>(id) << " " - << std::bitset<20>(state); - LOG(FATAL) << side << " " << id << " " << state; - }*/ - side++; - } while (side < 6); - } - if (isReachedEnd) - break; - - } - 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, &UBO); - glBindBuffer(GL_UNIFORM_BUFFER, UBO); - glBindBufferBase(GL_UNIFORM_BUFFER, bp1, UBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) + sizeof(glm::vec4) * 1023, NULL, GL_STATIC_DRAW); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLint), &totalTextures); //copy totalTextures - for (int i = 0; i < indexes.size(); i++) { - size_t baseOffset = sizeof(glm::vec4); - size_t itemOffset = sizeof(glm::vec4); - size_t offset = baseOffset + i * itemOffset; - /*int index = indexes[i]; - int side = (index & 0x70000) >> 16; - int id = (index & 0xFF0) >> 4; - int state = index & 0xF; - LOG(WARNING) << "Copying " << indexes[i] << " at " << offset<<" side is "<Program, "TextureData"); - glUniformBlockBinding(shader->Program, ubo2_index, bp2); - glGenBuffers(1, &UBO2); - glBindBuffer(GL_UNIFORM_BUFFER, UBO2); - glBindBufferBase(GL_UNIFORM_BUFFER, bp2, UBO2); - glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) * 1024, NULL, GL_STATIC_DRAW); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::vec4) * textureCoordinates.size(), textureCoordinates.data()); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - glCheckError(); + //Cube-rendering data + glGenBuffers(1, &VBO); + glGenBuffers(1, &VBO2); + glGenBuffers(1, &VBO3); + glGenBuffers(1, &VBO4); + glGenVertexArrays(1, &VAO); + + glBindVertexArray(VAO); + { + //Cube vertices + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); + glEnableVertexAttribArray(0); + + //Cube UVs + glBindBuffer(GL_ARRAY_BUFFER, VBO2); + glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coords), uv_coords, GL_STATIC_DRAW); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0); + glEnableVertexAttribArray(2); + + //Blocks ids + glBindBuffer(GL_ARRAY_BUFFER, VBO4); + glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 16 * 16 * 16, NULL, GL_DYNAMIC_DRAW); + glVertexAttribPointer(7, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0); + glEnableVertexAttribArray(7); + glVertexAttribDivisor(7, 1); + glCheckError(); + + //Blocks models + glBindBuffer(GL_ARRAY_BUFFER, VBO3); + glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * 16 * 16 * 16, NULL, GL_DYNAMIC_DRAW); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), 0); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8 + 1, 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), + (void *) (1 * 4 * sizeof(GLfloat))); + glEnableVertexAttribArray(8 + 1); + glVertexAttribPointer(8 + 2, 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), + (void *) (2 * 4 * sizeof(GLfloat))); + glEnableVertexAttribArray(8 + 2); + glVertexAttribPointer(8 + 3, 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), + (void *) (3 * 4 * sizeof(GLfloat))); + glEnableVertexAttribArray(8 + 3); + glVertexAttribDivisor(8, 1); + glVertexAttribDivisor(8 + 1, 1); + glVertexAttribDivisor(8 + 2, 1); + glVertexAttribDivisor(8 + 3, 1); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + glBindVertexArray(0); + + glCheckError(); + + shader = new Shader("./shaders/block.vs", "./shaders/block.fs"); + shader->Use(); + + shader2 = new Shader("./shaders/simple.vs", "./shaders/simple.fs"); + + 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); + /*LOG(ERROR) << "Encoded texture (" << id << " " << state << " " << side << ") as " << index << " (" + << std::bitset<19>(index) << ")" << " = " << tc.x << "," << tc.y << "," << tc.w << "," + << tc.h;*/ + /*LOG(FATAL)<(index); + side = 0x7; + id = 0xFFF; + state = 0xF; + LOG(WARNING) << "side: " << side << " id: " << id << " state: " << state; + int i, si, st, index = 0; + si = side << 15; + i = id<<3; + st = state; + index = i | si | st; + LOG(FATAL) << std::bitset<18>(index) << " (" << index << "): " << std::bitset<18>(si) << " " + << std::bitset<18>(i) << " " << std::bitset<18>(st);*/ + /*if (rand() == 73) //Almost impossible(Almost==1/32768) + { + int index = 393233; + LOG(WARNING) << std::bitset<20>(index) << "(" << index << ")"; + int side = (index & 0xE0000) >> 16; + int id = (index & 0xFF0) >> 4; + int state = index & 0xF; + LOG(WARNING) << std::bitset<20>(side) << " " << std::bitset<20>(id) << " " + << std::bitset<20>(state); + LOG(FATAL) << side << " " << id << " " << state; + }*/ + 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, &UBO); + glBindBuffer(GL_UNIFORM_BUFFER, UBO); + glBindBufferBase(GL_UNIFORM_BUFFER, bp1, UBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) + sizeof(glm::vec4) * 1023, NULL, GL_STATIC_DRAW); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLint), &totalTextures); //copy totalTextures + for (int i = 0; i < indexes.size(); i++) { + size_t baseOffset = sizeof(glm::vec4); + size_t itemOffset = sizeof(glm::vec4); + size_t offset = baseOffset + i * itemOffset; + /*int index = indexes[i]; + int side = (index & 0x70000) >> 16; + int id = (index & 0xFF0) >> 4; + int state = index & 0xF; + LOG(WARNING) << "Copying " << indexes[i] << " at " << offset<<" side is "<Program, "TextureData"); + glUniformBlockBinding(shader->Program, ubo2_index, bp2); + glGenBuffers(1, &UBO2); + glBindBuffer(GL_UNIFORM_BUFFER, UBO2); + glBindBufferBase(GL_UNIFORM_BUFFER, bp2, UBO2); + glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) * 1024, NULL, GL_STATIC_DRAW); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::vec4) * textureCoordinates.size(), textureCoordinates.data()); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + glCheckError(); + + //Draw Lines preparing + glGenBuffers(1, &VBO5); + glGenVertexArrays(1, &VAO2); + glBindVertexArray(VAO2); + { + glBindBuffer(GL_ARRAY_BUFFER, VBO5); + glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), NULL, GL_DYNAMIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + glBindVertexArray(0); } void Core::UpdateChunksToRender() { - camera.Position = glm::vec3(gameState->g_PlayerX, gameState->g_PlayerY, gameState->g_PlayerZ); - toRender.clear(); - const float ChunkDistance = 2; - Vector playerChunk = Vector(floor(gameState->g_PlayerX / 16.0f), floor(gameState->g_PlayerY / 16.0f), - floor(gameState->g_PlayerZ / 16.0f)); - for (auto &it:gameState->world.m_sections) { - Vector chunkPosition = it.first; - Vector delta = chunkPosition - playerChunk; - if (delta.GetDistance() > ChunkDistance) - continue; - toRender.push_back(chunkPosition); - } - LOG(INFO) << "Chunks to render: " << toRender.size(); + camera.Position = glm::vec3(gameState->g_PlayerX, gameState->g_PlayerY, gameState->g_PlayerZ); + toRender.clear(); + Vector playerChunk = Vector(floor(gameState->g_PlayerX / 16.0f), 0, floor(gameState->g_PlayerZ / 16.0f)); + for (auto &it:gameState->world.m_sections) { + Vector chunkPosition = it.first; + chunkPosition.SetY(0); + Vector delta = chunkPosition - playerChunk; + if (delta.GetMagnitude() > ChunkDistance) + continue; + toRender.push_back(it.first); + } + LOG(INFO) << "Chunks to render: " << toRender.size(); + for (auto &it:toRender) { + Section §ion = gameState->world.m_sections.find(it)->second; + std::vector models; + std::vector blocks; + 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)); + if (block.id == 0) + continue; + unsigned char isVisible = 0; + if (x == 0 || x == 15 || y == 0 || y == 15 || z == 0 || z == 15) { + isVisible = 0; + } 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; + } + if (isVisible == 0x3F) + continue; + glm::vec2 data(block.id, block.state); + blocks.push_back(data); + glm::mat4 model; + model = glm::translate(model, glm::vec3(it.GetX() * 16, it.GetY() * 16, it.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); + } + } + } + toRenderBlocks[it] = blocks; + toRenderModels[it] = models; + } + std::sort(toRender.begin(), toRender.end(), [this](const Vector &lhs, const Vector &rhs) { + return glm::length((glm::vec3) lhs - camera.Position) < glm::length((glm::vec3) rhs - camera.Position); + }); + LOG(INFO) << "Chunks is prepared to rendering..."; } void Core::UpdateGameState() { - el::Helpers::setThreadName("Game"); - LOG(INFO) << "GameState thread is started"; - while (isRunning) { - gameState->Update(); - if (toRender.size() > 0) - break; - } - LOG(INFO) << "GameState thread is stopped"; + el::Helpers::setThreadName("Game"); + LOG(INFO) << "GameState thread is started"; + while (isRunning) { + gameState->Update(); + if (toRender.size() > 0) + break; + } + LOG(INFO) << "GameState thread is stopped"; +} + +void Core::DrawLine(glm::vec3 from, glm::vec3 to, glm::vec3 color) { + shader2->Use(); + glm::mat4 projection = glm::perspective(camera.Zoom, (float) width() / (float) height(), 0.1f, 10000000.0f); + glm::mat4 view = camera.GetViewMatrix(); + glUniformMatrix4fv(glGetUniformLocation(shader2->Program, "projection"), 1, GL_FALSE, + glm::value_ptr(projection)); + glUniformMatrix4fv(glGetUniformLocation(shader2->Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); + + /*GLfloat data[6]; + data[0] = from[0]; + data[1] = from[1]; + data[2] = to[2]; + data[3] = to[0]; + data[4] = to[1]; + data[5] = from[2];*/ + GLfloat data[] = {0.5f, 0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, 0.5f, 0.0f, + + 0.5f, -0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + -0.5f, 0.5f, 0.0f,}; + + glUniform3f(glGetUniformLocation(shader2->Program, "color"), color[0], color[1], color[2]); + + glDisable(GL_DEPTH_TEST); + glBindVertexArray(VAO2); + glBindBuffer(GL_ARRAY_BUFFER, VBO5); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 18, data, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + glEnable(GL_DEPTH_TEST); +} + +void Core::UpdateOptimizedRender() { + + LOG(INFO) << "Render list is optimized"; } diff --git a/src/core/Core.hpp b/src/core/Core.hpp index e5fe315..97a51fd 100644 --- a/src/core/Core.hpp +++ b/src/core/Core.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "../gamestate/GameState.hpp" #include "../network/NetworkClient.hpp" @@ -11,62 +12,74 @@ #include "../graphics/Camera3D.hpp" #include "../graphics/Shader.hpp" #include "AssetManager.hpp" +#include "../graphics/Frustrum.hpp" class Core { - GameState *gameState; - NetworkClient *client; - sf::Window *window; - AssetManager *assetManager; - bool isMouseCaptured = false; - bool isRunning = true; - enum { - MainMenu, - Loading, - Playing, - PauseMenu, - } currentState = Playing; - float mouseXDelta, mouseYDelta; - float deltaTime; - float absTime; + GameState *gameState; + NetworkClient *client; + sf::Window *window; + AssetManager *assetManager; + bool isMouseCaptured = false; + bool isRunning = true; + enum { + MainMenu, + Loading, + Playing, + PauseMenu, + } currentState = Playing; + float mouseXDelta, mouseYDelta; + float deltaTime; + float absTime; - void RenderWorld(); + void RenderWorld(); - void RenderGui(Gui &Target); + void RenderGui(Gui &Target); - void HandleMouseCapture(); + void HandleMouseCapture(); - void HandleEvents(); + void HandleEvents(); - void InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string WinTitle); + void InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string WinTitle); - void InitGlew(); + void InitGlew(); - void SetMouseCapture(bool IsCaptured); + void SetMouseCapture(bool IsCaptured); - void PrepareToWorldRendering(); + void PrepareToWorldRendering(); - void RenderFrame(); + void RenderFrame(); - unsigned int width(); + unsigned int width(); - unsigned int height(); + unsigned int height(); - void UpdateChunksToRender(); + void UpdateChunksToRender(); - void UpdateGameState(); + void UpdateGameState(); - std::thread gameStateLoopThread; + void DrawLine(glm::vec3 from, glm::vec3 to, glm::vec3 color); - Camera3D camera; - Shader *shader; - //Cube verticies, Cube VAO, Cube UVs, TextureIndexes UBO, TextureData UBO, TextureData2 UBO - GLuint VBO, VAO, VBO2, UBO,UBO2,UBO3; - std::vector toRender; + std::thread gameStateLoopThread; + + Camera3D camera; + Shader *shader,*shader2; + //Cube verticies, Cube VAO, Cube UVs, TextureIndexes UBO, TextureData UBO, TextureData2 UBO, Blocks VBO, Models VBO, Line VAO, Lines VBO + GLuint VBO, VAO, VBO2, UBO, UBO2, VBO3, VBO4, VAO2, VBO5; + std::vector toRender; + std::vector optimizedRender; + + void UpdateOptimizedRender(); + + int ChunkDistance = 4; + + std::map> toRenderModels; + std::map> toRenderBlocks; + //std::map, std::vector > > sectionsRenderingData; public: - Core(); + Core(); - ~Core(); + ~Core(); - void Exec(); + void Exec(); }; diff --git a/src/graphics/Frustrum.cpp b/src/graphics/Frustrum.cpp new file mode 100644 index 0000000..75f47c5 --- /dev/null +++ b/src/graphics/Frustrum.cpp @@ -0,0 +1,111 @@ +#include "Frustrum.hpp" + +enum FrustumSide { + RIGHT = 0, // The RIGHT side of the frustum + LEFT = 1, // The LEFT side of the frustum + BOTTOM = 2, // The BOTTOM side of the frustum + TOP = 3, // The TOP side of the frustum + BACK = 4, // The BACK side of the frustum + FRONT = 5 // The FRONT side of the frustum +}; + +enum PlaneData { + A = 0, // The X value of the plane's normal + B = 1, // The Y value of the plane's normal + C = 2, // The Z value of the plane's normal + D = 3 // The distance the plane is from the origin +}; + +void normalizePlane(glm::vec4 &frustum_plane) { + float magnitude = (float) sqrt(frustum_plane[A] * frustum_plane[A] + frustum_plane[B] * frustum_plane[B] + + frustum_plane[C] * frustum_plane[C]); + frustum_plane[A] /= magnitude; + frustum_plane[B] /= magnitude; + frustum_plane[C] /= magnitude; + frustum_plane[D] /= magnitude; +} + +void Frustum::CalculateFrustum(glm::mat4 &view_matrix, glm::mat4 &proj_matrix) { + float proj[16]; + float modl[16]; + const float *projP = glm::value_ptr(proj_matrix); + const float *modlP = glm::value_ptr(view_matrix); + for (int i = 0; i < 16; i++) { + proj[i]=projP[i]; + modl[i]=modlP[i]; + } + + float clip[16]; //clipping planes + + clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12]; + clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13]; + clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14]; + clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15]; + + clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12]; + clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13]; + clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14]; + clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15]; + + clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12]; + clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13]; + clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14]; + clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15]; + + clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12]; + clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13]; + clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14]; + clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15]; + + frustum_planes[RIGHT][A] = clip[3] - clip[0]; + frustum_planes[RIGHT][B] = clip[7] - clip[4]; + frustum_planes[RIGHT][C] = clip[11] - clip[8]; + frustum_planes[RIGHT][D] = clip[15] - clip[12]; + normalizePlane(frustum_planes[RIGHT]); + + frustum_planes[LEFT][A] = clip[3] + clip[0]; + frustum_planes[LEFT][B] = clip[7] + clip[4]; + frustum_planes[LEFT][C] = clip[11] + clip[8]; + frustum_planes[LEFT][D] = clip[15] + clip[12]; + normalizePlane(frustum_planes[LEFT]); + + frustum_planes[BOTTOM][A] = clip[3] + clip[1]; + frustum_planes[BOTTOM][B] = clip[7] + clip[5]; + frustum_planes[BOTTOM][C] = clip[11] + clip[9]; + frustum_planes[BOTTOM][D] = clip[15] + clip[13]; + normalizePlane(frustum_planes[BOTTOM]); + + frustum_planes[TOP][A] = clip[3] - clip[1]; + frustum_planes[TOP][B] = clip[7] - clip[5]; + frustum_planes[TOP][C] = clip[11] - clip[9]; + frustum_planes[TOP][D] = clip[15] - clip[13]; + normalizePlane(frustum_planes[TOP]); + + frustum_planes[BACK][A] = clip[3] - clip[2]; + frustum_planes[BACK][B] = clip[7] - clip[6]; + frustum_planes[BACK][C] = clip[11] - clip[10]; + frustum_planes[BACK][D] = clip[15] - clip[14]; + normalizePlane(frustum_planes[BACK]); + + frustum_planes[FRONT][A] = clip[3] + clip[2]; + frustum_planes[FRONT][B] = clip[7] + clip[6]; + frustum_planes[FRONT][C] = clip[11] + clip[10]; + frustum_planes[FRONT][D] = clip[15] + clip[14]; + normalizePlane(frustum_planes[FRONT]); +} + +bool Frustum::TestInsideFrustrum(glm::vec4 Min, glm::vec4 Max) { + bool inside = true; + //test all 6 frustum planes + for (int i = 0; i < 6; i++) { + //pick closest point to plane and check if it behind the plane + //if yes - object outside frustum + float d = std::max(Min.x * frustum_planes[i].x, Max.x * frustum_planes[i].x) + + std::max(Min.y * frustum_planes[i].y, Max.y * frustum_planes[i].y) + + std::max(Min.z * frustum_planes[i].z, Max.z * frustum_planes[i].z) + + frustum_planes[i].w; + inside &= d > 0; + //return false; //with flag works faster + } + return inside; +} diff --git a/src/graphics/Frustrum.hpp b/src/graphics/Frustrum.hpp new file mode 100644 index 0000000..e8a6fd6 --- /dev/null +++ b/src/graphics/Frustrum.hpp @@ -0,0 +1,24 @@ +#ifndef _FRUSTUM_H +#define _FRUSTUM_H + + +#include +#include +#include +#include +#include + +class Frustum { +public: + Frustum() = default; + + ~Frustum() = default; + + void CalculateFrustum(glm::mat4 &view_matrix, glm::mat4 &proj_matrix); + + glm::vec4 frustum_planes[6]; + + bool TestInsideFrustrum(glm::vec4 Min, glm::vec4 Max); +}; + +#endif \ No newline at end of file diff --git a/src/network/Network.cpp b/src/network/Network.cpp index 399ce20..4ce424c 100644 --- a/src/network/Network.cpp +++ b/src/network/Network.cpp @@ -1,79 +1,101 @@ #include "Network.hpp" Network::Network(std::string address, unsigned short port) : m_address(address), m_port(port) { - LOG(INFO) << "Connecting to server " << m_address << ":" << m_port; - sf::Socket::Status status = m_socket.connect(sf::IpAddress(m_address), m_port); - m_socket.setBlocking(true); - if (status != sf::Socket::Done) { - if (status == sf::Socket::Error) { - LOG(ERROR) << "Can't connect to remote server"; - } else { - LOG(ERROR) << "Connection failed with unknown reason"; + LOG(INFO) << "Connecting to server " << m_address << ":" << m_port; + sf::Socket::Status status = m_socket.connect(sf::IpAddress(m_address), m_port); + m_socket.setBlocking(true); + if (status != sf::Socket::Done) { + if (status == sf::Socket::Error) { + LOG(ERROR) << "Can't connect to remote server"; + } else { + LOG(ERROR) << "Connection failed with unknown reason"; throw std::runtime_error("Connection is failed"); - throw 13; - } - } - LOG(INFO) << "Connected to server"; + throw 13; + } + } + LOG(INFO) << "Connected to server"; } Network::~Network() { - m_socket.disconnect(); - LOG(INFO) << "Disconnected"; + m_socket.disconnect(); + LOG(INFO) << "Disconnected"; } void Network::SendHandshake(std::string username) { - //Handshake packet - Packet handshakePacket = PacketBuilder::CHandshaking0x00(316, m_address, m_port, 2); - SendPacket(handshakePacket); + //Handshake packet + Packet handshakePacket = PacketBuilder::CHandshaking0x00(316, m_address, m_port, 2); + SendPacket(handshakePacket); - //LoginStart packet - Field fName; - fName.SetString(username); - Packet loginPacket(0); - loginPacket.AddField(fName); - SendPacket(loginPacket); + //LoginStart packet + Field fName; + fName.SetString(username); + Packet loginPacket(0); + loginPacket.AddField(fName); + SendPacket(loginPacket); } +void DumpPacket(Packet &packet, std::string DumpName) { + return; + byte *buff = new byte[packet.GetLength()]; + packet.CopyToBuff(buff); + std::ofstream fs(DumpName, std::ios::out | std::ios::binary); + fs.write(reinterpret_cast(buff), packet.GetLength()); + fs.close(); + delete buff; +} + +static int pn = 0; + void Network::SendPacket(Packet &packet) { - m_socket.setBlocking(true); - byte *packetData = new byte[packet.GetLength()]; - packet.CopyToBuff(packetData); - m_socket.send(packetData, packet.GetLength()); - delete[] packetData; + m_socket.setBlocking(true); + byte *packetData = new byte[packet.GetLength()]; + packet.CopyToBuff(packetData); + m_socket.send(packetData, packet.GetLength()); + std::ostringstream out; + out << "s" << pn++ << "-"; + out << "0x" << (packet.GetId() < 15 ? "0" : "") << std::hex << packet.GetId() << std::dec; + DumpPacket(packet, out.str()); + + delete[] packetData; } Packet Network::ReceivePacket() { - byte bufLen[5] = {0}; - size_t rec = 0; - for (int i = 0; i < 5; i++) { - byte buff = 0; - size_t r = 0; - m_socket.receive(&buff, 1, r); - rec += r; - bufLen[i] = buff; - if ((buff & 0b10000000) == 0) { - break; - } - } - Field fLen = FieldParser::Parse(VarIntType, bufLen); - size_t packetLen = fLen.GetVarInt() + fLen.GetLength(); - if (packetLen > 1024 * 1024 * 15) - LOG(WARNING)<<"OMG SIZEOF PACKAGE IS "< 1024 * 1024 * 15) + LOG(WARNING) << "OMG SIZEOF PACKAGE IS " << packetLen; + if (packetLen < rec) { + return Packet(bufLen); + } + byte *bufPack = new byte[packetLen]; + std::copy(bufLen, bufLen + rec, bufPack); + size_t dataLen = rec; + while (m_socket.receive(bufPack + dataLen, packetLen - dataLen, rec) == sf::Socket::Done && dataLen < packetLen) { + dataLen += rec; + } + if (dataLen < packetLen) { + LOG(ERROR) << "Received data is " << dataLen << " but " << packetLen << " is promoted"; + throw std::runtime_error("Data is losted"); + } else { + Packet p(bufPack); + delete[] bufPack; + + std::ostringstream out; + out << "r" << pn++ << "-"; + out << "0x" << (p.GetId() < 15 ? "0" : "") << std::hex << p.GetId() << std::dec; + DumpPacket(p, out.str()); + return p; + } } diff --git a/src/utility/Vector.hpp b/src/utility/Vector.hpp index 7b34ac3..9d6c1be 100644 --- a/src/utility/Vector.hpp +++ b/src/utility/Vector.hpp @@ -1,117 +1,122 @@ #pragma once +#include #include #include #include template class Vector3 { - T x, y, z; + T x, y, z; public: - Vector3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {} - - Vector3(const Vector3 &rhs) : x(rhs.x), y(rhs.y), z(rhs.z) {} - - ~Vector3() = default; - - void SetX(T X) { x = X; } - - void SetY(T Y) { y = Y; } - - void setZ(T Z) { z = Z; } - - T GetX() const { return x; } - - T GetY() const { return y; } - - T GetZ() const { return z; } - - double GetDistance() const { return std::sqrt(std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2)); } - - void swap(Vector3 &rhs){ - std::swap(x,rhs.x); - std::swap(y,rhs.y); - std::swap(z,rhs.z); - } - - Vector3 &operator=(Vector3 rhs) { - rhs.swap(*this); - return *this; - } - - Vector3 operator*(T rhs) const { - return Vector3( - x * rhs, - y * rhs, - z * rhs - ); - } - - Vector3 operator/(T rhs) const { - return Vector3( - x / rhs, - y / rhs, - z / rhs - ); - } - - Vector3 operator+(const Vector3 &rhs) const { - return Vector3( - x + rhs.x, - y + rhs.y, - z + rhs.z - ); - } - - Vector3 operator-(const Vector3 &rhs) const { - return Vector3( - x - rhs.x, - y - rhs.y, - z - rhs.z - ); - } - - Vector3 operator*(const Vector3 &rhs) const { - return Vector3( - x * rhs.x, - y * rhs.y, - z * rhs.z - ); - } - - Vector3 operator/(const Vector3 &rhs) const { - return Vector3( - x / rhs.x, - y / rhs.y, - z / rhs.z - ); - } - - bool operator==(const Vector3 &rhs) const { - return (x == rhs.x && y == rhs.y && z == rhs.z); - } - - bool operator!=(const Vector3 &rhs) const { - return !(*this == rhs); - } - - bool operator<(const Vector3 &rhs) const { - //return (x < rhs.x || y < rhs.y ||z z < rhs.z); - /*if (x < rhs.x) - return true; - else if (z < rhs.z) - return true; - else if (y < rhs.y) - return true; - return false;*/ - return std::tie(x,y,z)( + x * rhs, + y * rhs, + z * rhs + ); + } + + Vector3 operator/(T rhs) const { + return Vector3( + x / rhs, + y / rhs, + z / rhs + ); + } + + Vector3 operator+(const Vector3 &rhs) const { + return Vector3( + x + rhs.x, + y + rhs.y, + z + rhs.z + ); + } + + Vector3 operator-(const Vector3 &rhs) const { + return Vector3( + x - rhs.x, + y - rhs.y, + z - rhs.z + ); + } + + Vector3 operator*(const Vector3 &rhs) const { + return Vector3( + x * rhs.x, + y * rhs.y, + z * rhs.z + ); + } + + Vector3 operator/(const Vector3 &rhs) const { + return Vector3( + x / rhs.x, + y / rhs.y, + z / rhs.z + ); + } + + bool operator==(const Vector3 &rhs) const { + return (x == rhs.x && y == rhs.y && z == rhs.z); + } + + bool operator!=(const Vector3 &rhs) const { + return !(*this == rhs); + } + + bool operator<(const Vector3 &rhs) const { + //return (x < rhs.x || y < rhs.y ||z z < rhs.z); + /*if (x < rhs.x) + return true; + else if (z < rhs.z) + return true; + else if (y < rhs.y) + return true; + return false;*/ + return std::tie(x, y, z) < std::tie(rhs.x, rhs.y, rhs.z); + } + + + friend std::ostream &operator<<(std::ostream &os, const Vector3 &vector3) { + os << vector3.x << ", " << vector3.y << ", " << vector3.z; + return os; + } }; typedef Vector3 VectorF; -- cgit v1.2.3