summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--cwd/shaders/face.fs52
-rw-r--r--cwd/shaders/face.vs26
-rw-r--r--include/AssetManager.hpp3
-rw-r--r--include/Core.hpp25
-rw-r--r--include/Utility.hpp4
-rw-r--r--include/graphics/RenderSection.hpp25
-rw-r--r--include/world/Section.hpp3
-rw-r--r--include/world/World.hpp21
-rw-r--r--src/core/AssetManager.cpp30
-rw-r--r--src/core/Core.cpp267
-rw-r--r--src/graphics/RenderSection.cpp387
-rw-r--r--src/network/Stream.cpp9
-rw-r--r--src/world/GameState.cpp20
-rw-r--r--src/world/Section.cpp80
-rw-r--r--src/world/World.cpp47
16 files changed, 667 insertions, 334 deletions
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<std::string, Block> assetIds;
std::map<std::string, TextureCoordinates> assetTextures;
+ std::map<BlockTextureId,glm::vec4> textureAtlasIndexes;
public:
AssetManager();
@@ -66,6 +67,8 @@ public:
GLuint GetTextureAtlas();
+ const std::map<BlockTextureId,glm::vec4> &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 <graphics/RenderSection.hpp>
#include <network/NetworkClient.hpp>
+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<Vector> toRender;
+ bool isRendersShouldBeCreated=false;
+ std::condition_variable waitRendersCreated;
+ std::vector<Vector> renders;
+ std::mutex toRenderMutex;
std::vector<Vector> toRender;
std::map<Vector, RenderSection> availableChunks;
+ std::mutex availableChunksMutex;
- int ChunkDistance = 2;
+ int ChunkDistance = 1;
RenderState renderState;
- /*std::map<Vector, std::vector<glm::mat4>> toRenderModels;
- std::map<Vector, std::vector<glm::vec2>> 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 <glm/gtx/transform.hpp>
#include <easylogging++.h>
+#include <AssetManager.hpp>
#include <world/Section.hpp>
#include <world/World.hpp>
@@ -21,21 +22,31 @@ public:
class RenderSection {
Vector sectionPosition;
World *world;
- GLuint Vao,VboBlocks,VboModels;
+ GLuint Vao, VboTextures, VboModels, VboColors;
+ std::vector<glm::mat4> models;
+ std::vector<glm::vec4> textures;
+ std::vector<glm::vec3> colors;
- static GLuint VboVertices,VboUvs;
- static std::map<GLuint,int> refCounterVbo;
- static std::map<GLuint,int> refCounterVao;
+ static GLuint VboVertices, VboUvs;
+ static std::map<GLuint, int> refCounterVbo;
+ static std::map<GLuint, int> 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<BlockTextureId, glm::vec4> &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 <vector>
#include <map>
#include <condition_variable>
+#include <functional>
#include <easylogging++.h>
@@ -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 <world/Collision.hpp>
class World {
- //utility vars
- World(const World &other);
-
- World &operator=(const World &other);
-
- //game vars
+ std::map<Vector, Section> sections;
+ std::map<Vector, std::mutex> 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<PacketChunkData> packet);
- std::map<Vector, Section> sections;
-
bool isPlayerCollides(double X, double Y, double Z);
+
+ Block &GetBlock(Vector pos);
+
+ std::vector<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<BlockTextureId, glm::vec4> &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 &section = *availableChunks.find(render)->second.GetSection();
+ availableChunksMutex.lock();
+ auto iterator = availableChunks.find(render);
+ if (iterator == availableChunks.end()) {
+ availableChunksMutex.unlock();
+ continue;
+ }
+ /*Section &section = *iterator->second.GetSection();
+ //availableChunksMutex.unlock();
std::vector<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<glm::vec4> textureCoordinates;
- std::vector<GLint> 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<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
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 <graphics/RenderSection.hpp>
+#include <thread>
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<GLuint, int> 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<glm::mat4> models;
- std::vector<glm::vec2> blocks;
+void RenderSection::UpdateState(const std::map<BlockTextureId, glm::vec4> &textureAtlas) {
+ Section &section = 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<unsigned short *>(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<PacketPlayerPosition>(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<std::mutex> 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<long long *>(m_dataBlocks);
@@ -54,23 +47,28 @@ void Section::Parse() {
endswap(&longArray[i]);
std::vector<unsigned short> 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<double, std::milli> time = end - begin;
+ totalParsingTime += time.count();
+ }
std::vector<byte> 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<std::string>{}(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<PacketChunkData> 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<PacketChunkData> 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<Vector> World::GetSectionsList() {
+ std::vector<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);
+}