From 47fe269c7668e18b37476b792b22bef804112f4e Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Wed, 6 Jun 2018 21:11:17 +0300 Subject: [PATCH] it's.. something.. --- data/shaders/chunk.frag | 7 + data/shaders/chunk.vert | 16 ++ src/Application.cpp | 21 ++- src/Camera.cpp | 7 +- src/Camera.h | 3 +- src/planet/Chunk.cpp | 238 +++++++++++++++++++++++++--- src/planet/Chunk.h | 54 ++++++- src/planet/Planet.cpp | 20 +-- src/planet/Planet.h | 7 +- src/planet/PlanetFace.cpp | 320 +++++++++++++++++++++++++++++++++++--- src/planet/PlanetFace.h | 55 ++++++- 11 files changed, 667 insertions(+), 81 deletions(-) create mode 100644 data/shaders/chunk.frag create mode 100644 data/shaders/chunk.vert diff --git a/data/shaders/chunk.frag b/data/shaders/chunk.frag new file mode 100644 index 0000000..724589a --- /dev/null +++ b/data/shaders/chunk.frag @@ -0,0 +1,7 @@ +#version 110 + +varying vec2 uv_p; + +void main(void) { + gl_FragColor = vec4(uv_p.xy, 0.5f, 1.0f); +} diff --git a/data/shaders/chunk.vert b/data/shaders/chunk.vert new file mode 100644 index 0000000..bd068c1 --- /dev/null +++ b/data/shaders/chunk.vert @@ -0,0 +1,16 @@ +#version 110 + +attribute vec3 position; +attribute vec3 normal; +attribute vec2 uv; +varying vec2 uv_p; + +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; +uniform mat4 modelMatrix; + +void main(void) { + gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0); + + uv_p = vec2(clamp(uv.x + normal.x, 0.0, 1.0), uv.y); +} diff --git a/src/Application.cpp b/src/Application.cpp index 2f49443..98d0c45 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -224,7 +224,15 @@ void Application::run() glEnable(GL_DEPTH_TEST); - Planet* pl = new Planet(glm::vec3(0.0f,0.0f,0.0f), 20); + Planet* pl = new Planet(glm::vec3(0.0f,0.0f,0.0f), 10); + // Create the shader and link them together + Shader& chunkShader = Shader::createShader("data/shaders/chunk.vert", "data/shaders/chunk.frag"); + chunkShader.linkShaders(); + + // Set attribute arrays + chunkShader.setAttribute("position", 3, GL_FALSE, 8, 0, GL_FLOAT); + chunkShader.setAttribute("normal", 3, GL_TRUE, 8, 3, GL_FLOAT); + chunkShader.setAttribute("uv", 2, GL_FALSE, 8, 6, GL_FLOAT); // END TEST CODE @@ -252,12 +260,19 @@ void Application::run() glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles -> 6 squares + pl->tick(m_camera, deltaTime); + + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + + pl->draw(m_camera, &chunkShader); + + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + + // END TEST CODE update(deltaTime); - pl->tick(deltaTime); render(); - pl->draw(m_camera); // Update window with OpenGL rendering SDL_GL_SwapWindow(m_window); diff --git a/src/Camera.cpp b/src/Camera.cpp index ccbbbdb..2862865 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -61,9 +61,9 @@ glm::mat4 Camera::getViewMatrix() return glm::lookAt(m_position, m_position + m_front, m_up); } -void Camera::updateFrustum(void) +void Camera::updateFrustum(glm::mat4 modelMatrix) { - const glm::mat4 mvp = getViewMatrix() * m_projection; + const glm::mat4 mvp = getViewMatrix() * m_projection * modelMatrix; // Extract the clipping planes; right, left, far, near, top, bottom m_planes[0] = mvp[3] - mvp[0]; @@ -227,7 +227,6 @@ void Camera::updateProjection(void) // Recalculate the projection matrix glm::vec2 screenDims = Application::getInstance().getScreenDimensions(); m_projection = glm::perspective(getFOV(), (GLfloat)screenDims.x/(GLfloat)screenDims.y, 0.1f, 100.0f); - updateFrustum(); } void Camera::updateCameraVectors(void) @@ -243,6 +242,4 @@ void Camera::updateCameraVectors(void) // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement. m_right = glm::normalize(glm::cross(m_front, m_worldUp)); m_up = glm::normalize(glm::cross(m_right, m_front)); - - updateFrustum(); } diff --git a/src/Camera.h b/src/Camera.h index 25b5f56..4a10e83 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -57,6 +57,8 @@ public: int frustumContainsSphere(const glm::vec3 &position, const double radius) const; int frustumContainsBox(const glm::vec3 &min, const glm::vec3 &max) const; int frustumContainsPolygon(const std::vector &points) const; + + void updateFrustum(glm::mat4 modelMatrix); private: glm::vec3 m_position; glm::vec3 m_front; @@ -83,6 +85,5 @@ private: void updateCameraVectors(void); void updateProjection(void); - void updateFrustum(void); }; #endif // __CAMERA_H__ diff --git a/src/planet/Chunk.cpp b/src/planet/Chunk.cpp index 93f8675..faacad6 100644 --- a/src/planet/Chunk.cpp +++ b/src/planet/Chunk.cpp @@ -1,6 +1,51 @@ #include "Chunk.h" #include "planet/PlanetFace.h" +const glm::vec3 FACE_VERTEX[6][4] = { + // Bottom + { + glm::vec3(1.0, 0.0, 0.0), + glm::vec3(1.0, 0.0, 1.0), + glm::vec3(0.0, 0.0, 1.0), + glm::vec3(0.0, 0.0, 0.0) + }, + // Top + { + glm::vec3(0.0, 1.0, 0.0), + glm::vec3(0.0, 1.0, 1.0), + glm::vec3(1.0, 1.0, 1.0), + glm::vec3(1.0, 1.0, 0.0) + }, + // Left + { + glm::vec3(0.0, 0.0, 1.0), + glm::vec3(0.0, 1.0, 1.0), + glm::vec3(0.0, 1.0, 0.0), + glm::vec3(0.0, 0.0, 0.0) + }, + // Right + { + glm::vec3(1.0, 0.0, 0.0), + glm::vec3(1.0, 1.0, 0.0), + glm::vec3(1.0, 1.0, 1.0), + glm::vec3(1.0, 0.0, 1.0) + }, + // Back + { + glm::vec3(1.0, 0.0, 1.0), + glm::vec3(1.0, 1.0, 1.0), + glm::vec3(0.0, 1.0, 1.0), + glm::vec3(0.0, 0.0, 1.0) + }, + // Front + { + glm::vec3(0.0, 0.0,0.0), + glm::vec3(0.0, 1.0,0.0), + glm::vec3(1.0, 1.0,0.0), + glm::vec3(1.0, 0.0,0.0) + } +}; + Chunk::Chunk(Planet* planet, class PlanetFace* face, int x, int y, int z) : m_planet(planet), m_planetFace(face), @@ -10,40 +55,189 @@ Chunk::Chunk(Planet* planet, class PlanetFace* face, int x, int y, int z) : m_dirty(false), m_active(true) { - // Create cells - for(int i=0;isetBuffers(m_vao, m_vbo, 0); + shader->use(); + + m_model = glm::translate(glm::mat4(1.0f), this->getAbsolutePosition() + 1.0f); + + camera->shaderViewProjection(*shader); + shader->setUniform("modelMatrix", m_model); + + glDrawArrays(GL_TRIANGLES, 0, m_vertices.size()); +} + +void Chunk::formFace(std::vector &vertices, glm::vec3 position, CellFace face) +{ + // Positions + auto P = [&](const glm::vec3& p) { + const glm::vec3 pp = (position + p); + return pp; + }; + + const glm::vec3 pos[4] = { + P(FACE_VERTEX[face][0]), P(FACE_VERTEX[face][1]), + P(FACE_VERTEX[face][2]), P(FACE_VERTEX[face][3]), + }; + + glm::vec3 normal = glm::cross(pos[2] - pos[0], pos[3] - pos[1]); + + vertices.push_back({pos[0], normal, {0.0, 1.0}}); + vertices.push_back({pos[1], normal, {0.0, 0.0}}); + vertices.push_back({pos[2], normal, {1.0, 0.0}}); + vertices.push_back({pos[0], normal, {0.0, 1.0}}); + vertices.push_back({pos[2], normal, {1.0, 0.0}}); + vertices.push_back({pos[3], normal, {1.0, 1.0}}); +} + +void Chunk::rebuildMesh() +{ + bool lDefault = true; + m_dirty = false; + m_vertices.clear(); + + for (int x = 0; x < CHUNK_SIZE; x++) + { + for (int y = 0; y < CHUNK_SIZE; y++) + { + for (int z = 0; z < CHUNK_SIZE; z++) + { + if(m_cells[x][y][z].isSolid() == false) + { + continue; + } + + bool faceLeft = lDefault; + if(x > 0) + faceLeft = !m_cells[x-1][y][z].isSolid(); + + bool faceRight = lDefault; + if(x < CHUNK_SIZE - 1) + faceRight = !m_cells[x+1][y][z].isSolid(); + + bool faceBottom = lDefault; + if(y > 0) + faceBottom = !m_cells[x][y-1][z].isSolid(); + + bool faceTop = lDefault; + if(y < CHUNK_SIZE - 1) + faceTop = !m_cells[x][y+1][z].isSolid(); + + bool faceBack = lDefault; + if(z > 0) + faceBack = !m_cells[x][y][z-1].isSolid(); + + bool faceFront = lDefault; + if(z < CHUNK_SIZE - 1) + faceFront = !m_cells[x][y][z+1].isSolid(); + + glm::vec3 cellPos = glm::vec3(x, y, z); + + if (faceBottom) + formFace(m_vertices, cellPos, CELL_FACE_BOTTOM); + if (faceTop) + formFace(m_vertices, cellPos, CELL_FACE_TOP); + if (faceLeft) + formFace(m_vertices, cellPos, CELL_FACE_LEFT); + if (faceRight) + formFace(m_vertices, cellPos, CELL_FACE_RIGHT); + if (faceFront) + formFace(m_vertices, cellPos, CELL_FACE_FRONT); + if (faceBack) + formFace(m_vertices, cellPos, CELL_FACE_BACK); + } + } + } + + if (m_vbo) + glDeleteBuffers(1, &m_vbo); + if (m_vao) + glDeleteBuffers(1, &m_vao); + + m_emptyChunk = m_vertices.size() == 0; + + if (m_emptyChunk) + return; + + // Generate buffers + glGenVertexArrays(1, &m_vao); + glBindVertexArray(m_vao); + + glGenBuffers(1, &m_vbo); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * m_vertices.size(), &(m_vertices[0]), GL_STATIC_DRAW); + + //std::cout << "rebuilt " << m_cx << "; " << m_cy << "; " << m_cz << "; " << std::endl; +} + +bool Chunk::isDetailedEnough(Camera* camera) +{ + // TODO: Level of detail on mesh + return true; +} + +const glm::vec3 Chunk::getAbsolutePosition() +{ + return getPosition() + m_planetFace->getPosition(); } diff --git a/src/planet/Chunk.h b/src/planet/Chunk.h index 2454863..e709f07 100644 --- a/src/planet/Chunk.h +++ b/src/planet/Chunk.h @@ -5,12 +5,28 @@ #include "planet/Planet.h" #include "Camera.h" -#define CHUNK_N 32 +#define CHUNK_SIZE 8 + +struct Vertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 uv; +}; struct Cell { - glm::vec3 position; GLuint internalId; + bool isSolid() + { + return true; + } +}; + +enum CellFace { + CELL_FACE_BOTTOM, CELL_FACE_TOP, + CELL_FACE_LEFT, CELL_FACE_RIGHT, + CELL_FACE_FRONT, CELL_FACE_BACK }; class Chunk @@ -19,21 +35,47 @@ class Chunk Chunk(Planet* planet, class PlanetFace* face, int x, int y, int z); ~Chunk(); - void destroyChunk(); + void unload(); + void load(); + void generate(); - void tick(GLfloat dtime); - void draw(Camera* camera); + void rebuildMesh(); + + inline const glm::vec3 getPosition() const { return glm::vec3(m_cx, m_cy, m_cz); } + const glm::vec3 getAbsolutePosition(); + inline int getX() const { return m_cx; } + inline int getY() const { return m_cy; } + inline int getZ() const { return m_cz; } + + inline bool isLoaded() const { return m_active; } + inline bool isRedrawRequired() const { return m_dirty; } + inline bool isGenerated() const { return m_generated; } + + inline bool shouldRender() const { return !m_emptyChunk && m_active && m_generated; } + + inline glm::mat4 getModelMatrix() const { return m_model; } + + bool isDetailedEnough(Camera* camera); + + void draw(Camera* camera, Shader* shader); + void updateFlags(); private: + void formFace(std::vector &vertices, glm::vec3 position, CellFace face); + Planet* m_planet; class PlanetFace* m_planetFace; + glm::mat4 m_model; bool m_dirty; bool m_active; + bool m_generated; + bool m_emptyChunk; int m_cx, m_cy, m_cz; GLuint m_vao, m_vbo; - Cell* m_cells[CHUNK_N][CHUNK_N][CHUNK_N]; + Cell*** m_cells; + std::vector m_vertices; }; #endif // __CHUNK_H__ diff --git a/src/planet/Planet.cpp b/src/planet/Planet.cpp index 1f96876..c08062d 100644 --- a/src/planet/Planet.cpp +++ b/src/planet/Planet.cpp @@ -17,18 +17,18 @@ Planet::~Planet() } } -void Planet::draw(Camera* camera) +void Planet::draw(Camera* camera, Shader* shader) { - for (int i = 0; i < 6; i++) - { - m_faces[i]->draw(camera); - } + //for (int i = 0; i < 6; i++) + //{ + m_faces[FACE_TOP]->draw(camera, shader); + //} } -void Planet::tick(GLfloat dtime) +void Planet::tick(Camera* camera, GLfloat dtime) { - for (int i = 0; i < 6; i++) - { - m_faces[i]->tick(dtime); - } + //for (int i = 0; i < 6; i++) + //{ + m_faces[FACE_TOP]->tick(camera, dtime); + //} } diff --git a/src/planet/Planet.h b/src/planet/Planet.h index 534a131..29d6ebf 100644 --- a/src/planet/Planet.h +++ b/src/planet/Planet.h @@ -15,8 +15,11 @@ class Planet inline void setLightDirection(glm::vec3 lightDir) { m_lightDir = lightDir; } inline glm::vec3 getLightDirection() const { return m_lightDir; } - void tick(GLfloat dtime); - void draw(Camera* camera); + inline float getRadius() const { return m_radius; } + inline glm::vec3 getPosition() const { return m_position; } + + void tick(Camera* camera, GLfloat dtime); + void draw(Camera* camera, Shader* shader); private: glm::vec3 m_position; float m_radius; diff --git a/src/planet/PlanetFace.cpp b/src/planet/PlanetFace.cpp index 5cb142e..fc44d1e 100644 --- a/src/planet/PlanetFace.cpp +++ b/src/planet/PlanetFace.cpp @@ -2,10 +2,11 @@ #include "planet/Planet.h" PlanetFace::PlanetFace(Planet* planet, const unsigned int face) : - m_planet(planet), m_face(face) + m_planet(planet), m_face(face), m_pos(glm::vec3(0.0f, 0.0f, 0.0f)) { // Set face normal depending on face - switch (m_face) { + switch (m_face) + { case Face::FACE_BOTTOM: m_normal = glm::vec3(0.0f, -1.0f, 0.0f); break; @@ -25,42 +26,313 @@ PlanetFace::PlanetFace(Planet* planet, const unsigned int face) : m_normal = glm::vec3(0.0f, 0.0f, 1.0f); break; } + m_chunks = new ChunkManager(this, planet->getRadius()); +} - // Create chunks - for(int i=0;irender(camera, shader); + + glDisable(GL_CULL_FACE); + } +} + +void PlanetFace::tick(Camera* camera, GLfloat dtime) +{ + if (m_chunks) + { + m_chunks->update(camera, dtime); + } +} + +// ******** // +// CHUNKS // +// ******** // + +ChunkManager::ChunkManager(PlanetFace* face, GLuint chunkCount) : m_face(face) +{ + m_forceVisibilityUpdate = true; + for (int x = 0; x < (int)chunkCount; x++) + { + for (int y = 0; y < (int)chunkCount; y++) { - for(int k=0;kgetPlanet(), m_face, x, y, z)); } } } } -PlanetFace::~PlanetFace() +ChunkManager::~ChunkManager() { - // Delete chunks - for(int i=0;idestroyChunk(); + for(auto iterator = m_chunks.begin(); iterator != m_chunks.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + delete pChunk; + } } -void PlanetFace::draw(Camera* camera) +void ChunkManager::update(Camera* camera, GLfloat dtime) { - for(int i=0;idraw(camera); + updateUnload(); + + updateLoad(); + + updateRebuild(); + + updateGenerate(); + + updateFlags(); + + updateVisibility(camera); + + updateRender(camera); } -void PlanetFace::tick(GLfloat dtime) +Chunk* ChunkManager::getChunk(int x, int y, int z) { - for(int i=0;itick(dtime); + for(auto iterator = m_chunks.begin(); iterator != m_chunks.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + + if (pChunk->getX() == x && pChunk->getY() == y && pChunk->getZ() == z) + return pChunk; + } + + return NULL; +} + +void ChunkManager::updateUnload() +{ + // Unload any chunks + for(auto iterator = m_chunkUnloadQueue.begin(); iterator != m_chunkUnloadQueue.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + + if(pChunk->isLoaded()) + { + pChunk->unload(); + + m_forceVisibilityUpdate = true; + } + } + + // Clear the unload list (every frame) + m_chunkUnloadQueue.clear(); +} + +void ChunkManager::updateLoad() +{ + int lNumOfChunksLoaded = 0; + + for(auto iterator = m_chunkLoadQueue.begin(); iterator != m_chunkLoadQueue.end() && + (lNumOfChunksLoaded != ASYNC_NUM_CHUNKS_PER_FRAME); ++iterator) + { + Chunk* pChunk = (*iterator); + + if(pChunk->isLoaded() == false) + { + if(lNumOfChunksLoaded != ASYNC_NUM_CHUNKS_PER_FRAME) + { + pChunk->load(); + + // Increase the chunks loaded count + lNumOfChunksLoaded++; + + m_forceVisibilityUpdate = true; + } + } + } + + // Clear the load list (every frame) + m_chunkLoadQueue.clear(); +} + +void ChunkManager::updateRebuild() +{ + // Rebuild any chunks that are in the rebuild chunk list + int lNumRebuiltChunkThisFrame = 0; + for(auto iterator = m_chunkRebuildQueue.begin(); iterator != m_chunkRebuildQueue.end() && + (lNumRebuiltChunkThisFrame != ASYNC_NUM_CHUNKS_PER_FRAME); ++iterator) + { + Chunk* pChunk = (*iterator); + + if(pChunk->isLoaded() && pChunk->isGenerated()) + { + if(lNumRebuiltChunkThisFrame != ASYNC_NUM_CHUNKS_PER_FRAME) + { + pChunk->rebuildMesh(); + + // If we rebuild a chunk, add it to the list of chunks that need their render flags updated + // since we might now be empty or surrounded + m_chunkFlagsQueue.push_back(pChunk); + + // Also add our neighbours since they might now be surrounded too (If we have neighbours) + Chunk* pChunkXMinus = getChunk(pChunk->getX()-1, pChunk->getY(), pChunk->getZ()); + Chunk* pChunkXPlus = getChunk(pChunk->getX()+1, pChunk->getY(), pChunk->getZ()); + Chunk* pChunkYMinus = getChunk(pChunk->getX(), pChunk->getY()-1, pChunk->getZ()); + Chunk* pChunkYPlus = getChunk(pChunk->getX(), pChunk->getY()+1, pChunk->getZ()); + Chunk* pChunkZMinus = getChunk(pChunk->getX(), pChunk->getY(), pChunk->getZ()-1); + Chunk* pChunkZPlus = getChunk(pChunk->getX(), pChunk->getY(), pChunk->getZ()+1); + + if(pChunkXMinus != NULL) + m_chunkFlagsQueue.push_back(pChunkXMinus); + + if(pChunkXPlus != NULL) + m_chunkFlagsQueue.push_back(pChunkXPlus); + + if(pChunkYMinus != NULL) + m_chunkFlagsQueue.push_back(pChunkYMinus); + + if(pChunkYPlus != NULL) + m_chunkFlagsQueue.push_back(pChunkYPlus); + + if(pChunkZMinus != NULL) + m_chunkFlagsQueue.push_back(pChunkZMinus); + + if(pChunkZPlus != NULL) + m_chunkFlagsQueue.push_back(pChunkZPlus); + + // Only rebuild a certain number of chunks per frame + lNumRebuiltChunkThisFrame++; + + m_forceVisibilityUpdate = true; + } + } + } + + // Clear the rebuild list + m_chunkRebuildQueue.clear(); +} + +void ChunkManager::updateFlags() +{ + for(auto iterator = m_chunkFlagsQueue.begin(); iterator != m_chunkFlagsQueue.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + pChunk->updateFlags(); + + } + + m_chunkFlagsQueue.clear(); +} + +void ChunkManager::updateGenerate() +{ + // Generate any chunks that have not already been generated + for(auto iterator = m_chunkGenerateQueue.begin(); iterator != m_chunkGenerateQueue.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + + if(pChunk->isLoaded() && pChunk->isGenerated() == false) + { + pChunk->generate(); + + if(pChunk->isGenerated()) + { + // Only force the visibility update if we actually generate the chunk, some chunks wait in the pre-generate stage... + m_forceVisibilityUpdate = true; + } + } + } + + // Clear the generate list (every frame) + m_chunkGenerateQueue.clear(); +} + +void ChunkManager::updateVisibility(Camera* camera) +{ + m_forceVisibilityUpdate = false; + + m_chunksVisible.clear(); + + for(auto iterator = m_chunks.begin(); iterator != m_chunks.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + + // TODO: Temporary distance limit + if (glm::abs(glm::length(camera->getPosition() - pChunk->getAbsolutePosition())) > 64.0f) + { + if (pChunk->isLoaded()) + { + m_chunkUnloadQueue.push_back(pChunk); + continue; + } + continue; + } + else + { + if (!pChunk->isLoaded()) + { + m_chunkLoadQueue.push_back(pChunk); + continue; + } + } + + // Generate chunk + if (!pChunk->isGenerated()) + { + m_chunkGenerateQueue.push_back(pChunk); + continue; + } + + if (pChunk->isRedrawRequired() || !pChunk->isDetailedEnough(camera)) + { + m_chunkRebuildQueue.push_back(pChunk); + continue; + } + + m_chunksVisible.push_back(pChunk); + } +} + +void ChunkManager::updateRender(Camera* camera) +{ + // Clear the render list each frame BEFORE we do our tests to see what chunks should be rendered + m_chunkRenderQueue.clear(); + + for(auto iterator = m_chunksVisible.begin(); iterator != m_chunksVisible.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + + if(pChunk != NULL) + { + if(pChunk->isLoaded() && pChunk->isGenerated()) + { + if(pChunk->shouldRender()) // Early flags check so we don't always have to do the frustum check... + { + // TODO: frustum culling + //glm::vec3 pos = pChunk->getAbsolutePosition(); + //glm::mat4 model = glm::translate(glm::mat4(1.0f), pos); + + //camera->updateFrustum(model); + //if(camera->frustumContainsBox(pos, pos + glm::vec3((float)CHUNK_SIZE))) + //{ + m_chunkRenderQueue.push_back(pChunk); + //} + } + } + } + } +} + +void ChunkManager::render(Camera* camera, Shader* shader) +{ + // Render only the chunks that should be rendered + for(auto iterator = m_chunkRenderQueue.begin(); iterator != m_chunkRenderQueue.end(); ++iterator) + { + Chunk* pChunk = (*iterator); + pChunk->draw(camera, shader); + } } diff --git a/src/planet/PlanetFace.h b/src/planet/PlanetFace.h index a28ca31..d786dcb 100644 --- a/src/planet/PlanetFace.h +++ b/src/planet/PlanetFace.h @@ -6,9 +6,7 @@ #include "Shader.h" #include "Camera.h" -#define CHUNKS_W 1 -#define CHUNKS_D CHUNKS_W -#define CHUNKS_H 32 +#define ASYNC_NUM_CHUNKS_PER_FRAME 8 enum Face { FACE_BOTTOM, FACE_TOP, @@ -17,14 +15,57 @@ enum Face { }; class Planet; +class PlanetFace; + +// PlanetFace Chunk Manager +class ChunkManager +{ + public: + ChunkManager(PlanetFace* face, GLuint chunkCount); + ~ChunkManager(); + + void update(Camera* camera, GLfloat dtime); + Chunk* getChunk(int x, int y, int z); + + void render(Camera* camera, Shader* shader); + private: + void updateUnload(); + void updateLoad(); + void updateGenerate(); + void updateRebuild(); + void updateFlags(); + void updateVisibility(Camera* camera); + void updateRender(Camera* camera); + + std::vector m_chunks; + std::vector m_chunksVisible; + + // Queues + std::vector m_chunkUnloadQueue; + std::vector m_chunkLoadQueue; + std::vector m_chunkGenerateQueue; + std::vector m_chunkRebuildQueue; + std::vector m_chunkRenderQueue; + std::vector m_chunkFlagsQueue; + + PlanetFace* m_face; + + int m_chunksLoaded = 0; + bool m_forceVisibilityUpdate; +}; + class PlanetFace { public: PlanetFace(Planet* planet, const unsigned int face = Face::FACE_BOTTOM); ~PlanetFace(); - void tick(GLfloat dtime); - void draw(Camera* camera); + void tick(Camera* camera, GLfloat dtime); + void draw(Camera* camera, Shader* shader); + + inline Planet* getPlanet() const { return m_planet; } + + inline const glm::vec3 getPosition() const { return m_planet->getPosition() + m_pos; } private: Planet* m_planet; unsigned int m_face; @@ -32,8 +73,6 @@ class PlanetFace glm::vec3 m_normal; glm::vec3 m_pos; - int x, z; - - Chunk* m_chunks[CHUNKS_W][CHUNKS_H][CHUNKS_D]; + ChunkManager* m_chunks; }; #endif // __PLANETFACE_H__