From a493d1521a7f6ba19ce411598d6f8814bd2111f5 Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Fri, 16 Mar 2018 21:19:18 +0500 Subject: Improved RendererSectionData parsing data locality --- src/RendererSectionData.cpp | 140 +++++++++++++++++++++++++++++++------------- src/RendererSectionData.hpp | 17 +++++- src/RendererWorld.cpp | 20 ++++++- 3 files changed, 133 insertions(+), 44 deletions(-) diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp index e3c4870..f7f0baa 100644 --- a/src/RendererSectionData.cpp +++ b/src/RendererSectionData.cpp @@ -6,7 +6,6 @@ #include "World.hpp" #include "AssetManager.hpp" -#include "Section.hpp" inline const BlockId& GetBlockId(const Vector& pos, const std::array &blockIdData) { return blockIdData[pos.y * 256 + pos.z * 16 + pos.x]; @@ -16,7 +15,7 @@ inline const BlockId& GetBlockId(int x, int y, int z, const std::array §ionsList, World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight, const std::array& visibility, std::string &textureName, RendererSectionData &data) { +void AddFacesByBlockModel(Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight, const std::array& visibility, std::string &textureName, RendererSectionData &data) { glm::mat4 elementTransform, faceTransform; for (const auto& element : model.Elements) { Vector t = element.to - element.from; @@ -158,14 +157,7 @@ const BlockModel* GetInternalBlockModel(const BlockId& id, std::vector GetBlockVisibilityData(World *world, const Vector §ionPos, const std::array &blockIdData, std::vector> &idModels) { - const auto& sectionDown = world->GetSection(sectionPos + Vector(0, -1, 0)); - const auto& sectionUp = world->GetSection(sectionPos + Vector(0, +1, 0)); - const auto& sectionNorth = world->GetSection(sectionPos + Vector(0, 0, +1)); - const auto& sectionSouth = world->GetSection(sectionPos + Vector(0, 0, -1)); - const auto& sectionWest = world->GetSection(sectionPos + Vector(+1, 0, 0)); - const auto& sectionEast = world->GetSection(sectionPos + Vector(-1, 0, 0)); - +std::array GetBlockVisibilityData(const SectionsData §ions, const std::array &blockIdData, std::vector> &idModels) { std::array arr; for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { @@ -180,12 +172,12 @@ std::array GetBlockVisibilityData(World *world, const Vecto switch (y) { case 0: - blockIdDown = sectionDown.GetBlockId(Vector(x, 15, z)); + blockIdDown = sections.bottom.GetBlockId(Vector(x, 15, z)); blockIdUp = GetBlockId(x, 1, z, blockIdData); break; case 15: blockIdDown = GetBlockId(x, 14, z, blockIdData); - blockIdUp = sectionUp.GetBlockId(Vector(x, 0, z)); + blockIdUp = sections.top.GetBlockId(Vector(x, 0, z)); break; default: blockIdDown = GetBlockId(x, y - 1, z, blockIdData); @@ -196,10 +188,10 @@ std::array GetBlockVisibilityData(World *world, const Vecto switch (z) { case 0: blockIdNorth = GetBlockId(x, y, 1, blockIdData); - blockIdSouth = sectionSouth.GetBlockId(Vector(x, y, 15)); + blockIdSouth = sections.south.GetBlockId(Vector(x, y, 15)); break; case 15: - blockIdNorth = sectionNorth.GetBlockId(Vector(x, y, 0)); + blockIdNorth = sections.north.GetBlockId(Vector(x, y, 0)); blockIdSouth = GetBlockId(x, y, 14, blockIdData); break; default: @@ -211,10 +203,10 @@ std::array GetBlockVisibilityData(World *world, const Vecto switch (x) { case 0: blockIdWest = GetBlockId(1, y, z, blockIdData); - blockIdEast = sectionEast.GetBlockId(Vector(15, y, z)); + blockIdEast = sections.east.GetBlockId(Vector(15, y, z)); break; case 15: - blockIdWest = sectionWest.GetBlockId(Vector(0, y, z)); + blockIdWest = sections.west.GetBlockId(Vector(0, y, z)); blockIdEast = GetBlockId(14, y, z, blockIdData); break; default: @@ -244,43 +236,32 @@ std::array GetBlockVisibilityData(World *world, const Vecto return arr; } -std::array SetBlockIdData(World* world, const Vector §ionPos) { - const Section& section = world->GetSection(sectionPos); +std::array SetBlockIdData(const SectionsData §ions) { std::array blockIdData; for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { - blockIdData[y * 256 + z * 16 + x] = section.GetBlockId(Vector(x, y, z)); + blockIdData[y * 256 + z * 16 + x] = sections.section.GetBlockId(Vector(x, y, z)); } } } return blockIdData; } -RendererSectionData ParseSection(World * world, Vector sectionPosition) +RendererSectionData ParseSection(const SectionsData §ions) { RendererSectionData data; std::vector> idModels; - std::array blockIdData = SetBlockIdData(world, sectionPosition); - std::array blockVisibility = GetBlockVisibilityData(world, sectionPosition, blockIdData, idModels); + std::array blockIdData = SetBlockIdData(sections); + std::array blockVisibility = GetBlockVisibilityData(sections, blockIdData, idModels); std::string textureName; - - Section* yp = world->GetSectionPtr(sectionPosition + Vector(0, 1, 0)); - Section* yn = world->GetSectionPtr(sectionPosition + Vector(0, -1, 0)); - Section* xp = world->GetSectionPtr(sectionPosition + Vector(1, 0, 0)); - Section* xn = world->GetSectionPtr(sectionPosition + Vector(-1, 0, 0)); - Section* zp = world->GetSectionPtr(sectionPosition + Vector(0, 0, 1)); - Section* zn = world->GetSectionPtr(sectionPosition + Vector(0, 0, -1)); const std::map &textureAtlas = AssetManager::Instance().GetTextureAtlasIndexes(); - const Section §ion = world->GetSection(sectionPosition); - data.hash = section.GetHash(); - data.sectionPos = sectionPosition; + data.hash = sections.section.GetHash(); + data.sectionPos = sections.section.GetPosition(); - glm::mat4 baseOffset = glm::translate(glm::mat4(), (section.GetPosition() * 16).glm()), transform; - - auto sectionsList = world->GetSectionsList(); + glm::mat4 baseOffset = glm::translate(glm::mat4(), (sections.section.GetPosition() * 16).glm()), transform; for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { @@ -289,17 +270,16 @@ RendererSectionData ParseSection(World * world, Vector sectionPosition) if (block.id == 0) continue; - const bool useNewMethod = true; - + Vector vec(x, y, z); - transform = glm::translate(baseOffset, Vector(x, y, z).glm()); + transform = glm::translate(baseOffset, vec.glm()); - unsigned char light = world->GetBlockLight(Vector(x, y, z), §ion, xp, xn, yp, yn, zp, zn); - unsigned char skyLight = world->GetBlockSkyLight(Vector(x, y, z), §ion, xp, xn, yp, yn, zp, zn); + unsigned char light = sections.GetLight(vec); + unsigned char skyLight = sections.GetSkyLight(vec); const BlockModel* model = GetInternalBlockModel(block, idModels); if (model) { - AddFacesByBlockModel(sectionsList, world, Vector(x, y, z), *model, transform, light, skyLight, blockVisibility, textureName, data); + AddFacesByBlockModel(vec, *model, transform, light, skyLight, blockVisibility, textureName, data); } else { transform = glm::translate(transform, glm::vec3(0, 1, 0)); @@ -326,3 +306,81 @@ RendererSectionData ParseSection(World * world, Vector sectionPosition) return data; } + +unsigned char SectionsData::GetLight(const Vector & pos) const { + const Vector directions[] = { + Vector(0,0,0), + Vector(1,0,0), + Vector(-1,0,0), + Vector(0,1,0), + Vector(0,-1,0), + Vector(0,0,1), + Vector(0,0,-1), + }; + + unsigned char value = 0; + + for (const Vector &dir : directions) { + Vector vec = pos + dir; + unsigned char dirValue = 0; + + if (vec.x < 0 || vec.x > 15 || vec.y < 0 || vec.y > 15 || vec.z < 0 || vec.z > 15) { + if (vec.x < 0) + dirValue = east.GetBlockLight(Vector(15, vec.y, vec.z)); + if (vec.x > 15) + dirValue = west.GetBlockLight(Vector(0, vec.y, vec.z)); + if (vec.y < 0) + dirValue = bottom.GetBlockLight(Vector(vec.x, 15, vec.z)); + if (vec.y > 15) + dirValue = top.GetBlockLight(Vector(vec.x, 0, vec.z)); + if (vec.z < 0) + dirValue = south.GetBlockLight(Vector(vec.x, vec.y, 15)); + if (vec.z > 15) + dirValue = north.GetBlockLight(Vector(vec.x, vec.y, 0)); + } + else + dirValue = section.GetBlockLight(vec); + + value = _max(value, dirValue); + } + return value; +} + +unsigned char SectionsData::GetSkyLight(const Vector & pos) const { + const Vector directions[] = { + Vector(0,0,0), + Vector(1,0,0), + Vector(-1,0,0), + Vector(0,1,0), + Vector(0,-1,0), + Vector(0,0,1), + Vector(0,0,-1), + }; + + unsigned char value = 0; + + for (const Vector &dir : directions) { + Vector vec = pos + dir; + unsigned char dirValue = 0; + + if (vec.x < 0 || vec.x > 15 || vec.y < 0 || vec.y > 15 || vec.z < 0 || vec.z > 15) { + if (vec.x < 0) + dirValue = east.GetBlockSkyLight(Vector(15, vec.y, vec.z)); + if (vec.x > 15) + dirValue = west.GetBlockSkyLight(Vector(0, vec.y, vec.z)); + if (vec.y < 0) + dirValue = bottom.GetBlockSkyLight(Vector(vec.x, 15, vec.z)); + if (vec.y > 15) + dirValue = top.GetBlockSkyLight(Vector(vec.x, 0, vec.z)); + if (vec.z < 0) + dirValue = south.GetBlockSkyLight(Vector(vec.x, vec.y, 15)); + if (vec.z > 15) + dirValue = north.GetBlockSkyLight(Vector(vec.x, vec.y, 0)); + } + else + dirValue = section.GetBlockSkyLight(vec); + + value = _max(value, dirValue); + } + return value; +} diff --git a/src/RendererSectionData.hpp b/src/RendererSectionData.hpp index 42e1a06..134eef6 100644 --- a/src/RendererSectionData.hpp +++ b/src/RendererSectionData.hpp @@ -5,9 +5,24 @@ #include #include "Vector.hpp" +#include "Section.hpp" class World; +struct SectionsData { + Section section; + Section west; + Section east; + Section top; + Section bottom; + Section north; + Section south; + + unsigned char GetLight(const Vector &pos) const; + + unsigned char GetSkyLight(const Vector &pos) const; +}; + struct RendererSectionData { std::vector models; std::vector textures; @@ -18,4 +33,4 @@ struct RendererSectionData { bool forced = false; }; -RendererSectionData ParseSection(World *world, Vector sectionPosition); \ No newline at end of file +RendererSectionData ParseSection(const SectionsData §ions); \ No newline at end of file diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 64cdffc..50d1fce 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -28,7 +28,15 @@ void RendererWorld::WorkerFunction(size_t workerId) { if (result != sections.end()) { if (result->second.GetHash() != gs->world.GetSection(result->first).GetHash() || forced) { sectionsMutex.unlock(); - auto data = std::make_unique(ParseSection(&gs->world, vec)); + SectionsData sections; + sections.section = gs->world.GetSection(vec); + sections.west = gs->world.GetSection(vec + Vector(1, 0, 0)); + sections.east = gs->world.GetSection(vec + Vector(-1, 0, 0)); + sections.top = gs->world.GetSection(vec + Vector(0, 1, 0)); + sections.bottom = gs->world.GetSection(vec + Vector(0, -1, 0)); + sections.north = gs->world.GetSection(vec + Vector(0, 0, 1)); + sections.south = gs->world.GetSection(vec + Vector(0, 0, -1)); + auto data = std::make_unique(ParseSection(sections)); data->forced = true; renderDataMutex.lock(); renderData.push(std::move(data)); @@ -44,7 +52,15 @@ void RendererWorld::WorkerFunction(size_t workerId) { } else { sectionsMutex.unlock(); - auto data = std::make_unique(ParseSection(&gs->world, vec)); + SectionsData sections; + sections.section = gs->world.GetSection(vec); + sections.west = gs->world.GetSection(vec + Vector(1, 0, 0)); + sections.east = gs->world.GetSection(vec + Vector(-1, 0, 0)); + sections.top = gs->world.GetSection(vec + Vector(0, 1, 0)); + sections.bottom = gs->world.GetSection(vec + Vector(0, -1, 0)); + sections.north = gs->world.GetSection(vec + Vector(0, 0, 1)); + sections.south = gs->world.GetSection(vec + Vector(0, 0, -1)); + auto data = std::make_unique(ParseSection(sections)); data->forced = true; renderDataMutex.lock(); renderData.push(std::move(data)); -- cgit v1.2.3