it's.. something..
This commit is contained in:
parent
989d402933
commit
47fe269c76
|
@ -0,0 +1,7 @@
|
|||
#version 110
|
||||
|
||||
varying vec2 uv_p;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(uv_p.xy, 0.5f, 1.0f);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<glm::vec3> &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__
|
||||
|
|
|
@ -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;i<CHUNK_N;i++)
|
||||
{
|
||||
for(int j=0;j<CHUNK_N;j++)
|
||||
{
|
||||
for(int k=0;k<CHUNK_N;k++)
|
||||
{
|
||||
m_cells[i][j][k] = new Cell();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Chunk::~Chunk()
|
||||
{
|
||||
for(int i=0;i<CHUNK_N;i++)
|
||||
for(int j=0;j<CHUNK_N;j++)
|
||||
for(int k=0;k<CHUNK_N;k++)
|
||||
if(m_cells[i][j][k])
|
||||
delete m_cells[i][j][k];
|
||||
// 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::destroyChunk()
|
||||
void Chunk::unload()
|
||||
{
|
||||
m_active = false;
|
||||
delete this;
|
||||
}
|
||||
|
||||
void Chunk::tick(GLfloat dtime)
|
||||
void Chunk::load()
|
||||
{
|
||||
if (!m_active) return;
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
void Chunk::draw(Camera* camera)
|
||||
void Chunk::generate()
|
||||
{
|
||||
if (!m_active) return;
|
||||
// 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() + 1.0f);
|
||||
|
||||
camera->shaderViewProjection(*shader);
|
||||
shader->setUniform("modelMatrix", m_model);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
|
||||
}
|
||||
|
||||
void Chunk::formFace(std::vector<Vertex> &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();
|
||||
}
|
||||
|
|
|
@ -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<Vertex> &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<Vertex> m_vertices;
|
||||
};
|
||||
#endif // __CHUNK_H__
|
||||
|
|
|
@ -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);
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;i<CHUNKS_W;i++)
|
||||
PlanetFace::~PlanetFace()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PlanetFace::draw(Camera* camera, Shader* shader)
|
||||
{
|
||||
if (m_chunks)
|
||||
{
|
||||
for(int j=0;j<CHUNKS_H;j++)
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
m_chunks->render(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;k<CHUNKS_D;k++)
|
||||
for (int z = 0; z < (int)chunkCount; z++)
|
||||
{
|
||||
m_chunks[i][j][k] = new Chunk(planet, this, x + i * CHUNK_N, j * CHUNK_N, z + k * CHUNK_N);
|
||||
m_chunks.push_back(new Chunk(m_face->getPlanet(), m_face, x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlanetFace::~PlanetFace()
|
||||
ChunkManager::~ChunkManager()
|
||||
{
|
||||
// Delete chunks
|
||||
for(int i=0;i<CHUNKS_W;i++)
|
||||
for(int j=0;j<CHUNKS_H;j++)
|
||||
for(int k=0;k<CHUNKS_D;k++)
|
||||
if(m_chunks[i][j][k])
|
||||
m_chunks[i][j][k]->destroyChunk();
|
||||
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;i<CHUNKS_W;i++)
|
||||
for(int j=0;j<CHUNKS_H;j++)
|
||||
for(int k=0;k<CHUNKS_D;k++)
|
||||
m_chunks[i][j][k]->draw(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;i<CHUNKS_W;i++)
|
||||
for(int j=0;j<CHUNKS_H;j++)
|
||||
for(int k=0;k<CHUNKS_D;k++)
|
||||
m_chunks[i][j][k]->tick(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Chunk*> m_chunks;
|
||||
std::vector<Chunk*> m_chunksVisible;
|
||||
|
||||
// Queues
|
||||
std::vector<Chunk*> m_chunkUnloadQueue;
|
||||
std::vector<Chunk*> m_chunkLoadQueue;
|
||||
std::vector<Chunk*> m_chunkGenerateQueue;
|
||||
std::vector<Chunk*> m_chunkRebuildQueue;
|
||||
std::vector<Chunk*> m_chunkRenderQueue;
|
||||
std::vector<Chunk*> 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__
|
||||
|
|
Loading…
Reference in New Issue