summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/AssetManager.cpp30
-rw-r--r--src/core/Core.cpp267
2 files changed, 204 insertions, 93 deletions
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