From cfbcc73549bb75618d0ff6e9a09a195da79b9f35 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sat, 21 Mar 2020 17:58:23 +0200 Subject: [PATCH] get rid of the chunk shit, broken sphere.. --- CMakeLists.txt | 3 +- src/Application.cpp | 2 +- src/Camera.cpp | 2 +- src/planet/Chunk.cpp | 266 -------------------- src/planet/Chunk.h | 82 ------ src/planet/Planet.cpp | 16 +- src/planet/PlanetFace.cpp | 506 ++++++++++++++------------------------ src/planet/PlanetFace.h | 76 +++--- 8 files changed, 232 insertions(+), 721 deletions(-) delete mode 100644 src/planet/Chunk.cpp delete mode 100644 src/planet/Chunk.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 95289d7..0d73f02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ endif() add_executable(${VOXSPATIUM_EXECUTABLE} ${SOURCES}) # Include GL +set(OpenGL_GL_PREFERENCE "LEGACY") find_package(OpenGL REQUIRED) include_directories(${OPENGL_INCLUDE_DIR}) target_link_libraries(${VOXSPATIUM_EXECUTABLE} ${OPENGL_LIBRARIES}) @@ -38,7 +39,7 @@ target_link_libraries(${VOXSPATIUM_EXECUTABLE} ${OPENGL_LIBRARIES}) # Include GLEW find_package(GLEW REQUIRED) include_directories(${GLEW_INCLUDE_PATH}) -target_link_libraries(${VOXSPATIUM_EXECUTABLE} ${GLEW_LIBRARY}) +target_link_libraries(${VOXSPATIUM_EXECUTABLE} ${GLEW_LIBRARIES}) # Include SDL INCLUDE(FindPkgConfig) diff --git a/src/Application.cpp b/src/Application.cpp index 34c5a16..099ee13 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -160,7 +160,7 @@ void Application::run() Input::getInstance().setMouseCoords(m_width/2, m_height/2); glEnable(GL_DEPTH_TEST); - Planet* pl = new Planet(glm::vec3(0.0f,0.0f,0.0f), 4); + Planet* pl = new Planet(glm::vec3(0.0f,0.0f,0.0f), 128.0f); // Create the shader and link them together Shader& chunkShader = Shader::createShader("data/shaders/chunk.vert", "data/shaders/chunk.frag"); chunkShader.linkShaders(); diff --git a/src/Camera.cpp b/src/Camera.cpp index 2862865..9f9b480 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -226,7 +226,7 @@ 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); + m_projection = glm::perspective(getFOV(), (GLfloat)screenDims.x/(GLfloat)screenDims.y, 0.1f, 1000.0f); } void Camera::updateCameraVectors(void) diff --git a/src/planet/Chunk.cpp b/src/planet/Chunk.cpp deleted file mode 100644 index e613906..0000000 --- a/src/planet/Chunk.cpp +++ /dev/null @@ -1,266 +0,0 @@ -#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), - m_cx(x), - m_cy(y), - m_cz(z), - m_dirty(false), - m_active(true) -{ - -} - -Chunk::~Chunk() -{ - // Delete the buffers - deleteBuffers(); - - // Delete the cells - for (int i = 0; i < CHUNK_SIZE; ++i) - { - for (int j = 0; j < CHUNK_SIZE; ++j) - { - delete [] m_cells[i][j]; - } - - delete [] m_cells[i]; - } - delete [] m_cells; -} - -void Chunk::unload() -{ - m_active = false; - - // Make space in memory - m_vertices.clear(); - deleteBuffers(); - - // Next time the chunk loads, we'll have to regenerate it. - m_dirty = true; -} - -void Chunk::load() -{ - m_active = true; -} - -void Chunk::generate() -{ - // Populate cells with dummy data - m_cells = new Cell**[CHUNK_SIZE]; - for(int i = 0; i < CHUNK_SIZE; i++) - { - m_cells[i] = new Cell*[CHUNK_SIZE]; - - for(int j = 0; j < CHUNK_SIZE; j++) - { - m_cells[i][j] = new Cell[CHUNK_SIZE]; - } - } - m_generated = true; - m_dirty = true; -} - -void Chunk::updateFlags() -{ - // Figure out if we are a completely empty chunk - - //if(numVerts == 0 && numTriangles == 0) - //{ - // m_emptyChunk = true; - //} - - //m_emptyChunk = false; -} - -void Chunk::draw(Camera* camera, Shader* shader) -{ - if (!m_active || !m_vao || !m_vbo) - return; - - shader->setBuffers(m_vao, m_vbo, 0); - shader->use(); - - m_model = glm::translate(glm::mat4(1.0f), this->getAbsolutePosition()) * m_planetFace->getOrientation(); - - camera->shaderViewProjection(*shader); - shader->setUniform("modelMatrix", m_model); - - glDrawArrays(GL_TRIANGLES, 0, m_vertices.size()); -} - -void Chunk::formFace(std::vector &vertices, const glm::vec3 &position, CellFace face) -{ - // Calculate positions in mesh - auto P = [&](const glm::vec3& p) { - const glm::vec3 pp = (position + p); - return pp; - }; - - // Get the vertices of the selected face - 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]), - }; - - // Calculate normals - glm::vec3 normal = glm::cross(pos[2] - pos[0], pos[3] - pos[1]); - - // Construct face from triangles - 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() -{ - // Default visibility of a face - const bool faceDefault = true; - - // Don't update the chunk again until a change has occured - m_dirty = false; - - // Clear previous vertices - m_vertices.clear(); - - // Determine which cells should have which faces drawn - 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 = faceDefault; - if(x > 0) - faceLeft = !m_cells[x-1][y][z].isSolid(); - - bool faceRight = faceDefault; - if(x < CHUNK_SIZE - 1) - faceRight = !m_cells[x+1][y][z].isSolid(); - - bool faceBottom = faceDefault; - if(y > 0) - faceBottom = !m_cells[x][y-1][z].isSolid(); - - bool faceTop = faceDefault; - if(y < CHUNK_SIZE - 1) - faceTop = !m_cells[x][y+1][z].isSolid(); - - bool faceBack = faceDefault; - if(z > 0) - faceBack = !m_cells[x][y][z-1].isSolid(); - - bool faceFront = faceDefault; - 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); - } - } - } - - // Delete previous buffers - deleteBuffers(); - - 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); -} - -bool Chunk::isDetailedEnough(Camera* camera) -{ - // TODO: Level of detail on mesh - return true; -} - -void Chunk::deleteBuffers() -{ - if (m_vbo) - glDeleteBuffers(1, &m_vbo); - if (m_vao) - glDeleteBuffers(1, &m_vao); -} - -const glm::vec3 Chunk::getAbsolutePosition() -{ - return getPosition() + m_planetFace->getPosition(); -} diff --git a/src/planet/Chunk.h b/src/planet/Chunk.h deleted file mode 100644 index 0a24b4f..0000000 --- a/src/planet/Chunk.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef __CHUNK_H__ -#define __CHUNK_H__ - -#include "util/Common.h" -#include "planet/Planet.h" -#include "Camera.h" - -#define CHUNK_SIZE 16 - -struct Vertex -{ - glm::vec3 position; - glm::vec3 normal; - glm::vec2 uv; -}; - -struct Cell -{ - 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 -{ - public: - Chunk(Planet* planet, class PlanetFace* face, int x, int y, int z); - ~Chunk(); - - void unload(); - void load(); - void generate(); - - 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, const glm::vec3 &position, CellFace face); - void deleteBuffers(); - - 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; - std::vector m_vertices; -}; -#endif // __CHUNK_H__ diff --git a/src/planet/Planet.cpp b/src/planet/Planet.cpp index c08062d..cc06ecd 100644 --- a/src/planet/Planet.cpp +++ b/src/planet/Planet.cpp @@ -19,16 +19,16 @@ Planet::~Planet() void Planet::draw(Camera* camera, Shader* shader) { - //for (int i = 0; i < 6; i++) - //{ - m_faces[FACE_TOP]->draw(camera, shader); - //} + for (int i = 0; i < 6; i++) + { + m_faces[i]->draw(camera, shader); + } } void Planet::tick(Camera* camera, GLfloat dtime) { - //for (int i = 0; i < 6; i++) - //{ - m_faces[FACE_TOP]->tick(camera, dtime); - //} + for (int i = 0; i < 6; i++) + { + m_faces[i]->tick(camera, dtime); + } } diff --git a/src/planet/PlanetFace.cpp b/src/planet/PlanetFace.cpp index 7c8dd3d..3e40133 100644 --- a/src/planet/PlanetFace.cpp +++ b/src/planet/PlanetFace.cpp @@ -1,344 +1,196 @@ #include "planet/PlanetFace.h" -#include "planet/Planet.h" + +const glm::vec3 FACE_NORMALS[6] = { + glm::vec3(0.0f, -1.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f), + glm::vec3(-1.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 0.0f, -1.0f), + glm::vec3(0.0f, 0.0f, 1.0f) +}; + +PlanetFaceNode::PlanetFaceNode(Planet* planet, PlanetFace* face, glm::vec3 position, const unsigned int level) : + m_planet(planet), m_planetFace(face), m_pos(position), m_level(level), m_generated(false), m_dirty(true) +{ + glm::vec3 normal = face->getNormal(); + m_left = glm::vec3(normal.y, normal.z, normal.x); + m_forward = glm::cross(normal, m_left); + + if (level == 0) + { + float radius = m_planet->getRadius() / 2.0f; + m_pos = m_pos - (m_left * radius); + m_pos = m_pos - (m_forward * radius); + } +} + +PlanetFaceNode::~PlanetFaceNode() +{ + for (int i = 0; i < 4; i++) + { + delete m_children[i]; + } + + glDeleteBuffers(1, &m_vao); + glDeleteBuffers(1, &m_vbo); + glDeleteBuffers(1, &m_ebo); +} + +void PlanetFaceNode::tick(Camera* camera, GLfloat dtime) +{ + +} + +void PlanetFaceNode::draw(Camera* camera, Shader* shader) +{ + if (!m_generated) + return; + + shader->setBuffers(m_vao, m_vbo, m_ebo); + shader->use(); + + camera->shaderViewProjection(*shader); + shader->setUniform("modelMatrix", glm::translate(glm::mat4(1.0f), this->getAbsolutePosition())); + + glDrawElements(GL_TRIANGLES, m_indices, GL_UNSIGNED_INT, nullptr); +} + +void PlanetFaceNode::generate() +{ + if (m_generated) + return; + + std::vector vertices; + std::vector indices; + + float divisionLevel = (float)pow(2.0, m_level); + float radius = m_planet->getRadius(); + for (int i = 0; i < RESOLUTION; i++) + { + for (int j = 0; j < RESOLUTION; j++) + { + float iindex = i / (RESOLUTION - 1.0); + float jindex = j / (RESOLUTION - 1.0); + + // From the left and forward vectors, we can calculate an oriented vertex + glm::vec3 iv = ((m_left * iindex) * radius) / divisionLevel; + glm::vec3 jv = ((m_forward * jindex) * radius) / divisionLevel; + + // Add the scaled left and forward to the centered origin + glm::vec3 vertex = m_pos + (iv + jv); + + // Normalize and multiply by radius to create a spherical mesh + glm::vec3 vertNormal = glm::normalize(vertex); + glm::vec3 pos = vertNormal * radius; + + // Add + vertices.push_back({ pos, vertNormal, glm::vec2(j * (1.0 / RESOLUTION), i * (1.0 / RESOLUTION)) }); + } + } + + for (int gz = 0; gz < RESOLUTION - 1; gz++) + { + for (int gx = 0; gx < RESOLUTION - 1; gx++) + { + int topLeft = (gz * RESOLUTION) + gx; + int topRight = topLeft + 1; + int bottomLeft = ((gz + 1) * RESOLUTION) + gx; + int bottomRight = bottomLeft + 1; + + indices.push_back(topLeft); + indices.push_back(topRight); + indices.push_back(bottomLeft); + indices.push_back(bottomLeft); + indices.push_back(topRight); + indices.push_back(bottomRight); + } + } + + m_indices = indices.size(); + + glGenVertexArrays(1, &m_vao); + glBindVertexArray(m_vao); + + glGenBuffers(1, &m_vbo); + glGenBuffers(1, &m_ebo); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * m_indices, &(indices[0]), GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &(vertices[0]), GL_STATIC_DRAW); + + m_generated = true; + m_leaf = true; +} + +void PlanetFaceNode::subdivide() +{ + if (m_level == 4) + return; + + int lv = m_level + 1; + float radius = m_planet->getRadius(); + + glm::vec3 stepLeft = m_left * (radius / (float)pow(2, lv)); + glm::vec3 stepForward = m_forward * (radius / (float)pow(2, lv)); + + m_children[0] = new PlanetFaceNode(m_planet, m_planetFace, m_pos + stepForward, lv); + m_children[1] = new PlanetFaceNode(m_planet, m_planetFace, (m_pos + stepLeft) + stepForward, lv); + m_children[2] = new PlanetFaceNode(m_planet, m_planetFace, m_pos, lv); + m_children[3] = new PlanetFaceNode(m_planet, m_planetFace, (m_pos + stepLeft), lv); + + m_leaf = false; + this->dispose(); +} + +void PlanetFaceNode::merge() +{ + if (m_level == 0 && m_leaf) + return; + + for (int i = 0; i < 4; i++) + { + m_children[i]->merge(); + m_children[i]->dispose(); + delete m_children[i]; + } + + m_leaf = true; +} + +void PlanetFaceNode::dispose() +{ + m_generated = false; + glDeleteBuffers(1, &m_vao); + glDeleteBuffers(1, &m_vbo); + glDeleteBuffers(1, &m_ebo); +} + +bool PlanetFaceNode::isLeaf() +{ + return m_leaf; +} PlanetFace::PlanetFace(Planet* planet, const unsigned int face) : - m_planet(planet), m_face(face), m_pos(glm::vec3(0.0f, 0.0f, 0.0f)) + m_planet(planet), m_face(face) { - // Set face normal depending on face - switch (m_face) - { - case Face::FACE_BOTTOM: - m_normal = glm::vec3(0.0f, -1.0f, 0.0f); - break; - case Face::FACE_TOP: - m_normal = glm::vec3(0.0f, 1.0f, 0.0f); - break; - case Face::FACE_LEFT: - m_normal = glm::vec3(-1.0f, 0.0f, 0.0f); - break; - case Face::FACE_RIGHT: - m_normal = glm::vec3(1.0f, 0.0f, 0.0f); - break; - case Face::FACE_FRONT: - m_normal = glm::vec3(0.0f, 0.0f, -1.0f); - break; - case Face::FACE_BACK: - m_normal = glm::vec3(0.0f, 0.0f, 1.0f); - break; - } - m_chunks = new ChunkManager(this, planet->getRadius()); - - if (m_face < 2) - m_orientation = glm::rotate(glm::mat4(1.0f), (float)((face == FACE_BOTTOM ? 0.5 : -0.5) * M_PI), - glm::vec3(0.0f, 1.0f, 0.0f)); - else - m_orientation = glm::rotate(glm::mat4(1.0f), (float)(face * -0.5 * M_PI), glm::vec3(1.0f, 0.0f, 0.0f)); + m_normal = FACE_NORMALS[m_face]; + m_planetFace = new PlanetFaceNode(planet, this, m_normal * (m_planet->getRadius() / 2.0f), 0); + m_planetFace->generate(); } PlanetFace::~PlanetFace() { - + delete m_planetFace; } void PlanetFace::draw(Camera* camera, Shader* shader) { - if (m_chunks) - { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - m_chunks->render(camera, shader); - - glDisable(GL_CULL_FACE); - } + m_planetFace->draw(camera, shader); } 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 z = 0; z < (int)chunkCount; z++) - { - m_chunks.push_back(new Chunk(m_face->getPlanet(), m_face, x * CHUNK_SIZE, y * CHUNK_SIZE, z * CHUNK_SIZE)); - } - } - } -} - -ChunkManager::~ChunkManager() -{ - for(auto iterator = m_chunks.begin(); iterator != m_chunks.end(); ++iterator) - { - Chunk* pChunk = (*iterator); - delete pChunk; - } -} - -void ChunkManager::update(Camera* camera, GLfloat dtime) -{ - updateUnload(); - - updateLoad(); - - updateRebuild(); - - updateGenerate(); - - updateFlags(); - - updateVisibility(camera); - - updateRender(camera); -} - -Chunk* ChunkManager::getChunk(int x, int y, int z) -{ - 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: fix frustum culling - //glm::vec3 pos = pChunk->getAbsolutePosition(); - //glm::mat4 model = glm::translate(glm::mat4(1.0f), pos); - - //camera->updateFrustum(model); - //if(camera->frustumContainsBox(glm::vec3(0.0f), glm::vec3((float)CHUNK_SIZE / 2)) > 0) - //{ - 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); - } + m_planetFace->tick(camera, dtime); } diff --git a/src/planet/PlanetFace.h b/src/planet/PlanetFace.h index dd4d23e..5d0d936 100644 --- a/src/planet/PlanetFace.h +++ b/src/planet/PlanetFace.h @@ -2,56 +2,66 @@ #define __PLANETFACE_H__ #include "util/Common.h" -#include "planet/Chunk.h" +#include "planet/Planet.h" #include "Shader.h" #include "Camera.h" -#define ASYNC_NUM_CHUNKS_PER_FRAME 8 +#define RESOLUTION 128 -enum Face { +enum Face +{ FACE_BOTTOM, FACE_TOP, FACE_LEFT, FACE_RIGHT, FACE_FRONT, FACE_BACK }; +struct Vertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 uv; +}; + class Planet; class PlanetFace; -// PlanetFace Chunk Manager -class ChunkManager +class PlanetFaceNode { public: - ChunkManager(PlanetFace* face, GLuint chunkCount); - ~ChunkManager(); + PlanetFaceNode(Planet* planet, PlanetFace* face, glm::vec3 position, const unsigned int level); + ~PlanetFaceNode(); - void update(Camera* camera, GLfloat dtime); - Chunk* getChunk(int x, int y, int z); + void tick(Camera* camera, GLfloat dtime); + void draw(Camera* camera, Shader* shader); - void render(Camera* camera, Shader* shader); + void generate(); + void subdivide(); + void merge(); + void dispose(); + bool isLeaf(); + + inline Planet* getPlanet() const { return m_planet; } + inline PlanetFace* getPlanetFace() const { return m_planetFace; } + + inline glm::vec3 getAbsolutePosition() const { return m_planet->getPosition() + m_pos; } private: - void updateUnload(); - void updateLoad(); - void updateGenerate(); - void updateRebuild(); - void updateFlags(); - void updateVisibility(Camera* camera); - void updateRender(Camera* camera); + Planet* m_planet; + PlanetFace* m_planetFace; - std::vector m_chunks; - std::vector m_chunksVisible; + PlanetFaceNode* m_parent; + PlanetFaceNode* m_children[4]; - // 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; + unsigned int m_level; + bool m_dirty; + bool m_generated; + bool m_leaf; - PlanetFace* m_face; + GLuint m_ebo, m_vao, m_vbo; + int m_indices; - int m_chunksLoaded = 0; - bool m_forceVisibilityUpdate; + glm::vec3 m_pos; + glm::vec3 m_left; + glm::vec3 m_forward; }; class PlanetFace @@ -65,17 +75,13 @@ class PlanetFace inline Planet* getPlanet() const { return m_planet; } - inline const glm::vec3 getPosition() const { return m_planet->getPosition() + m_pos; } - inline const glm::mat4 getOrientation() const { return m_orientation; } + inline const glm::vec3 getNormal() const { return m_normal; } private: Planet* m_planet; unsigned int m_face; glm::vec3 m_normal; - glm::vec3 m_pos; - ChunkManager* m_chunks; - - glm::mat4 m_orientation; + PlanetFaceNode* m_planetFace; }; #endif // __PLANETFACE_H__