diff options
Diffstat (limited to 'src/RendererWorld.cpp')
-rw-r--r-- | src/RendererWorld.cpp | 129 |
1 files changed, 117 insertions, 12 deletions
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 0661b9a..c50ff44 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -1,6 +1,107 @@ #include "RendererWorld.hpp" #include "DebugInfo.hpp" +class Frustum { + enum FrustumSide + { + RIGHT = 0, + LEFT, + BOTTOM, + TOP, + BACK, + FRONT, + }; + + enum PlaneData + { + A = 0, + B, + C, + D, + }; + + glm::mat4 vp; + + float frustum[6][4]; + + void NormalizePlane(FrustumSide side) + { + float magnitude = (float)sqrt(frustum[side][A] * frustum[side][A] + + frustum[side][B] * frustum[side][B] + + frustum[side][C] * frustum[side][C]); + + frustum[side][A] /= magnitude; + frustum[side][B] /= magnitude; + frustum[side][C] /= magnitude; + frustum[side][D] /= magnitude; + } + +public: + Frustum() {} + + ~Frustum() {} + + void UpdateFrustum(const glm::mat4& vpmat) { + vp = vpmat; + return; + + float *clip = glm::value_ptr(vp); + + + frustum[RIGHT][A] = clip[3] - clip[0]; + frustum[RIGHT][B] = clip[7] - clip[4]; + frustum[RIGHT][C] = clip[11] - clip[8]; + frustum[RIGHT][D] = clip[15] - clip[12]; + NormalizePlane(RIGHT); + + + frustum[LEFT][A] = clip[3] + clip[0]; + frustum[LEFT][B] = clip[7] + clip[4]; + frustum[LEFT][C] = clip[11] + clip[8]; + frustum[LEFT][D] = clip[15] + clip[12]; + NormalizePlane(LEFT); + + frustum[BOTTOM][A] = clip[3] + clip[1]; + frustum[BOTTOM][B] = clip[7] + clip[5]; + frustum[BOTTOM][C] = clip[11] + clip[9]; + frustum[BOTTOM][D] = clip[15] + clip[13]; + NormalizePlane(BOTTOM); + + frustum[TOP][A] = clip[3] - clip[1]; + frustum[TOP][B] = clip[7] - clip[5]; + frustum[TOP][C] = clip[11] - clip[9]; + frustum[TOP][D] = clip[15] - clip[13]; + NormalizePlane(TOP); + + frustum[BACK][A] = clip[3] - clip[2]; + frustum[BACK][B] = clip[7] - clip[6]; + frustum[BACK][C] = clip[11] - clip[10]; + frustum[BACK][D] = clip[15] - clip[14]; + NormalizePlane(BACK); + + frustum[FRONT][A] = clip[3] + clip[2]; + frustum[FRONT][B] = clip[7] + clip[6]; + frustum[FRONT][C] = clip[11] + clip[10]; + frustum[FRONT][D] = clip[15] + clip[14]; + NormalizePlane(FRONT); + } + + //Return true, if tested point is visible + bool TestPoint(VectorF point) { + glm::vec4 p = vp * glm::vec4(point.glm(), 1); + glm::vec3 res = glm::vec3(p) / p.w; + return (res.x < 1 && res.x > -1 && res.y < 1 && res.y > -1 && res.z > 0); + for (int i = 0; i < 6; i++) + { + if (frustum[i][A] * point.x + frustum[i][B] * point.y + frustum[i][C] * point.z + frustum[i][D] <= 0) + { + return false; + } + } + return true; + } +}; + void RendererWorld::WorkerFunction(size_t workerId) { EventListener tasksListener; @@ -87,6 +188,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) } RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) { + frustum = std::make_unique<Frustum>(); MaxRenderingDistance = 2; numOfWorkers = 2; @@ -297,9 +399,12 @@ void RendererWorld::Render(RenderState & renderState) { glUniform2f(windowSizeLoc, renderState.WindowWidth, renderState.WindowHeight); glCheckError(); + frustum->UpdateFrustum(projView); + sectionsMutex.lock(); + size_t culledSections = sections.size(); for (auto& section : sections) { - sectionsMutex.unlock(); + sectionsMutex.unlock(); std::vector<Vector> sectionCorners = { Vector(0, 0, 0), Vector(0, 0, 16), @@ -310,28 +415,28 @@ void RendererWorld::Render(RenderState & renderState) { Vector(16, 16, 0), Vector(16, 16, 16), }; - bool isBreak = true; - glm::mat4 vp = projection * view; - for (auto &it : sectionCorners) { - glm::vec3 point(section.second.GetPosition().x * 16 + it.x, - section.second.GetPosition().y * 16 + it.y, - section.second.GetPosition().z * 16 + it.z); - 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; + bool isVisible = false; + for (const auto &it : sectionCorners) { + VectorF point(section.second.GetPosition().x * 16 + it.x, + section.second.GetPosition().y * 16 + it.y, + section.second.GetPosition().z * 16 + it.z); + if (frustum->TestPoint(point)) { + isVisible = true; break; } } + double lengthToSection = (gs->player->pos - VectorF(section.first.x*16,section.first.y*16,section.first.z*16)).GetLength(); - if (isBreak && lengthToSection > 30.0f) { + if (!isVisible && lengthToSection > 30.0f) { sectionsMutex.lock(); + culledSections--; continue; } section.second.Render(renderState); sectionsMutex.lock(); } + this->culledSections = culledSections; sectionsMutex.unlock(); glCheckError(); } |