custom index buffers, broken neighbor detection
This commit is contained in:
parent
674887d5ce
commit
567dd856cb
|
@ -2,7 +2,8 @@
|
||||||
#include "planet/PlanetFace.h"
|
#include "planet/PlanetFace.h"
|
||||||
|
|
||||||
Planet::Planet(glm::vec3 position, float radius, PlanetNoiseParams &noiseParams) :
|
Planet::Planet(glm::vec3 position, float radius, PlanetNoiseParams &noiseParams) :
|
||||||
m_position(position), m_radius(radius), m_noise(noiseParams.frequency, noiseParams.amplitude, noiseParams.lacunarity, noiseParams.persistence)
|
m_position(position), m_radius(radius), m_noise(noiseParams.frequency, noiseParams.amplitude, noiseParams.lacunarity, noiseParams.persistence),
|
||||||
|
m_ibuffers(new PlanetIndexBuffer(15))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
|
@ -16,6 +17,7 @@ Planet::~Planet()
|
||||||
{
|
{
|
||||||
delete m_faces[i];
|
delete m_faces[i];
|
||||||
}
|
}
|
||||||
|
delete m_ibuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Planet::draw(Camera* camera, Shader* shader)
|
void Planet::draw(Camera* camera, Shader* shader)
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
|
||||||
|
#include "planet/PlanetIndexBuffer.h"
|
||||||
|
|
||||||
struct PlanetNoiseParams {
|
struct PlanetNoiseParams {
|
||||||
float frequency;
|
float frequency;
|
||||||
float amplitude;
|
float amplitude;
|
||||||
|
@ -14,6 +16,7 @@ struct PlanetNoiseParams {
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlanetFace;
|
class PlanetFace;
|
||||||
|
class PlanetFaceNode;
|
||||||
class Planet
|
class Planet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -29,10 +32,13 @@ class Planet
|
||||||
void tick(Camera* camera, GLfloat dtime);
|
void tick(Camera* camera, GLfloat dtime);
|
||||||
void draw(Camera* camera, Shader* shader);
|
void draw(Camera* camera, Shader* shader);
|
||||||
|
|
||||||
SimplexNoise& getNoise() { return m_noise; }
|
inline SimplexNoise& getNoise() { return m_noise; }
|
||||||
|
inline PlanetIndexBuffer* getBuffers() { return m_ibuffers; }
|
||||||
|
inline PlanetFace* getFace(const unsigned int face) { return m_faces[face]; }
|
||||||
|
|
||||||
glm::mat4 getTransformation();
|
glm::mat4 getTransformation();
|
||||||
private:
|
private:
|
||||||
|
PlanetIndexBuffer* m_ibuffers;
|
||||||
SimplexNoise m_noise;
|
SimplexNoise m_noise;
|
||||||
glm::vec3 m_position;
|
glm::vec3 m_position;
|
||||||
float m_radius;
|
float m_radius;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "planet/PlanetFace.h"
|
#include "planet/PlanetFace.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
// Correlates directly to Face enum
|
// Correlates directly to Face enum
|
||||||
const glm::vec3 FACE_NORMALS[6] = {
|
const glm::vec3 FACE_NORMALS[6] = {
|
||||||
|
@ -10,8 +11,8 @@ const glm::vec3 FACE_NORMALS[6] = {
|
||||||
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) :
|
PlanetFaceNode::PlanetFaceNode(Planet* planet, PlanetFace* face, glm::vec3 position, const unsigned int index, const unsigned int level) :
|
||||||
m_planet(planet), m_planetFace(face), m_pos(position), m_level(level), m_generated(false), m_dirty(true), m_leaf(true)
|
m_planet(planet), m_planetFace(face), m_pos(position), m_index(index), m_level(level), m_generated(false), m_dirty(true), m_leaf(true)
|
||||||
{
|
{
|
||||||
glm::vec3 normal = face->getNormal();
|
glm::vec3 normal = face->getNormal();
|
||||||
m_left = glm::vec3(normal.y, normal.z, normal.x);
|
m_left = glm::vec3(normal.y, normal.z, normal.x);
|
||||||
|
@ -23,6 +24,8 @@ PlanetFaceNode::PlanetFaceNode(Planet* planet, PlanetFace* face, glm::vec3 posit
|
||||||
m_pos = m_pos - (m_left * radius);
|
m_pos = m_pos - (m_left * radius);
|
||||||
m_pos = m_pos - (m_forward * radius);
|
m_pos = m_pos - (m_forward * radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlanetFaceNode::~PlanetFaceNode()
|
PlanetFaceNode::~PlanetFaceNode()
|
||||||
|
@ -35,36 +38,19 @@ PlanetFaceNode::~PlanetFaceNode()
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteBuffers(1, &m_vao);
|
|
||||||
glDeleteBuffers(1, &m_vbo);
|
|
||||||
glDeleteBuffers(1, &m_ebo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlanetFaceNode::tick(Camera* camera, GLfloat dtime, bool& tickUpdatedLOD, bool& tickGeneratedFace)
|
void PlanetFaceNode::tick(Camera* camera, GLfloat dtime)
|
||||||
{
|
{
|
||||||
if (tickUpdatedLOD == true || tickGeneratedFace == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// TODO: based on planet transform
|
// TODO: based on planet transform
|
||||||
float camToOrigin = glm::distance(camera->getPosition(), (m_planet->getPosition() + m_center));
|
float camToOrigin = glm::distance(camera->getPosition(), (m_planet->getPosition() + m_center));
|
||||||
float divisionLevel = (float)pow(2, m_level);
|
float divisionLevel = (float)pow(2, m_level);
|
||||||
float splitDistance = m_planet->getRadius() / divisionLevel;
|
float splitDistance = m_planet->getRadius() / divisionLevel;
|
||||||
|
if (camToOrigin < splitDistance * 1.5 && m_leaf) {
|
||||||
if (camToOrigin < splitDistance * 1.5 && m_leaf)
|
this->subdivide();
|
||||||
tickUpdatedLOD = this->subdivide();
|
|
||||||
else if (camToOrigin > splitDistance * 2 && !m_leaf)
|
|
||||||
tickUpdatedLOD = this->merge();
|
|
||||||
|
|
||||||
// TODO: fix weird vanishing meshes
|
|
||||||
|
|
||||||
if (tickUpdatedLOD)
|
|
||||||
return;
|
return;
|
||||||
|
} else if (camToOrigin > splitDistance * 2.0 && !m_leaf) {
|
||||||
if (m_leaf && m_generated == false)
|
this->merge();
|
||||||
{
|
|
||||||
tickGeneratedFace = true;
|
|
||||||
generate();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,13 +58,17 @@ void PlanetFaceNode::tick(Camera* camera, GLfloat dtime, bool& tickUpdatedLOD, b
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
m_children[i]->tick(camera, dtime, tickUpdatedLOD, tickGeneratedFace);
|
m_children[i]->tick(camera, dtime);
|
||||||
if (tickGeneratedFace || tickUpdatedLOD)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlanetFaceNode::setIndexBuffer(PlanetBufferIndex buf) {
|
||||||
|
PIB* indx = m_planet->getBuffers()->getBuffer(buf);
|
||||||
|
m_ebo = indx->ebo;
|
||||||
|
m_indices = indx->indices.size();
|
||||||
|
}
|
||||||
|
|
||||||
void PlanetFaceNode::draw(Camera* camera, Shader* shader)
|
void PlanetFaceNode::draw(Camera* camera, Shader* shader)
|
||||||
{
|
{
|
||||||
// TODO: occlusion culling
|
// TODO: occlusion culling
|
||||||
|
@ -109,7 +99,6 @@ void PlanetFaceNode::generate()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<Vertex> vertices;
|
std::vector<Vertex> vertices;
|
||||||
std::vector<unsigned int> indices;
|
|
||||||
|
|
||||||
float divisionLevel = (float)pow(2.0, m_level);
|
float divisionLevel = (float)pow(2.0, m_level);
|
||||||
float radius = m_planet->getRadius();
|
float radius = m_planet->getRadius();
|
||||||
|
@ -140,135 +129,16 @@ void PlanetFaceNode::generate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fanTop = true;
|
|
||||||
bool fanLeft = true;
|
|
||||||
bool fanRight = true;
|
|
||||||
bool fanBottom = true;
|
|
||||||
|
|
||||||
// Create indices for mesh
|
|
||||||
for (int gz = 0; gz < RESOLUTION - 1; gz++)
|
|
||||||
{
|
|
||||||
bool slantLeft = gz % 2 == 0;
|
|
||||||
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;
|
|
||||||
|
|
||||||
bool uTri1 = true;
|
|
||||||
bool uTri2 = true;
|
|
||||||
int tri1[3];
|
|
||||||
int tri2[3];
|
|
||||||
|
|
||||||
if (slantLeft)
|
|
||||||
{
|
|
||||||
tri1[0] = topLeft;
|
|
||||||
tri1[1] = bottomLeft;
|
|
||||||
tri1[2] = bottomRight;
|
|
||||||
tri2[0] = topLeft;
|
|
||||||
tri2[1] = bottomRight;
|
|
||||||
tri2[2] = topRight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tri1[0] = topLeft;
|
|
||||||
tri1[1] = bottomLeft;
|
|
||||||
tri1[2] = topRight;
|
|
||||||
tri2[0] = bottomLeft;
|
|
||||||
tri2[1] = bottomRight;
|
|
||||||
tri2[2] = topRight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fanTop && gz == 0)
|
|
||||||
{
|
|
||||||
if (gx % 2 == 0)
|
|
||||||
{
|
|
||||||
tri2[0] = topLeft;
|
|
||||||
tri2[1] = bottomRight;
|
|
||||||
tri2[2] = topRight + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uTri1 = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fanRight && gx == RESOLUTION - 2)
|
|
||||||
{
|
|
||||||
if (gz % 2 == 0)
|
|
||||||
{
|
|
||||||
tri2[0] = topRight;
|
|
||||||
tri2[1] = bottomLeft;
|
|
||||||
tri2[2] = bottomRight + RESOLUTION;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uTri2 = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fanBottom && gz == RESOLUTION - 2)
|
|
||||||
{
|
|
||||||
if (gx % 2 == 0)
|
|
||||||
{
|
|
||||||
tri2[0] = bottomLeft;
|
|
||||||
tri2[1] = bottomRight + 1;
|
|
||||||
tri2[2] = topRight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uTri1 = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fanLeft && gx == 0)
|
|
||||||
{
|
|
||||||
if (gz % 2 == 0)
|
|
||||||
{
|
|
||||||
tri1[0] = topLeft;
|
|
||||||
tri1[1] = bottomLeft + RESOLUTION;
|
|
||||||
tri1[2] = bottomRight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uTri1 = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uTri1)
|
|
||||||
{
|
|
||||||
indices.push_back(tri1[0]);
|
|
||||||
indices.push_back(tri1[1]);
|
|
||||||
indices.push_back(tri1[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uTri2)
|
|
||||||
{
|
|
||||||
indices.push_back(tri2[0]);
|
|
||||||
indices.push_back(tri2[1]);
|
|
||||||
indices.push_back(tri2[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
slantLeft = !slantLeft;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_indices = indices.size();
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &m_vao);
|
glGenVertexArrays(1, &m_vao);
|
||||||
glBindVertexArray(m_vao);
|
glBindVertexArray(m_vao);
|
||||||
|
|
||||||
glGenBuffers(1, &m_vbo);
|
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);
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &(vertices[0]), GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &(vertices[0]), GL_STATIC_DRAW);
|
||||||
|
|
||||||
m_generated = true;
|
m_generated = true;
|
||||||
|
setIndexBuffer(PlanetBufferIndex::Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlanetFaceNode::subdivide()
|
bool PlanetFaceNode::subdivide()
|
||||||
|
@ -282,12 +152,15 @@ bool PlanetFaceNode::subdivide()
|
||||||
glm::vec3 stepLeft = m_left * (radius / (float)pow(2, lv));
|
glm::vec3 stepLeft = m_left * (radius / (float)pow(2, lv));
|
||||||
glm::vec3 stepForward = m_forward * (radius / (float)pow(2, lv));
|
glm::vec3 stepForward = m_forward * (radius / (float)pow(2, lv));
|
||||||
|
|
||||||
|
m_children[TOP_LEFT] = new PlanetFaceNode(m_planet, m_planetFace, m_pos, TOP_LEFT, lv);
|
||||||
|
m_children[TOP_RIGHT] = new PlanetFaceNode(m_planet, m_planetFace, m_pos + stepForward, TOP_RIGHT, lv);
|
||||||
|
m_children[BOTTOM_RIGHT] = new PlanetFaceNode(m_planet, m_planetFace, (m_pos + stepLeft) + stepForward, BOTTOM_RIGHT, lv);
|
||||||
|
m_children[BOTTOM_LEFT] = new PlanetFaceNode(m_planet, m_planetFace, (m_pos + stepLeft), BOTTOM_LEFT, lv);
|
||||||
|
|
||||||
m_leaf = false;
|
m_leaf = false;
|
||||||
|
|
||||||
m_children[0] = new PlanetFaceNode(m_planet, m_planetFace, m_pos + stepForward, lv);
|
for (int i = 0; i < 4; i++)
|
||||||
m_children[1] = new PlanetFaceNode(m_planet, m_planetFace, (m_pos + stepLeft) + stepForward, lv);
|
m_children[i]->m_parent = this;
|
||||||
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);
|
|
||||||
|
|
||||||
this->dispose();
|
this->dispose();
|
||||||
|
|
||||||
|
@ -303,22 +176,19 @@ bool PlanetFaceNode::merge()
|
||||||
// Merge and dispose the children
|
// Merge and dispose the children
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
m_children[i]->merge();
|
|
||||||
m_children[i]->dispose();
|
m_children[i]->dispose();
|
||||||
delete m_children[i];
|
delete m_children[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're a leaf now
|
// We're a leaf now
|
||||||
m_leaf = true;
|
m_leaf = true;
|
||||||
|
generate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlanetFaceNode::dispose()
|
void PlanetFaceNode::dispose()
|
||||||
{
|
{
|
||||||
m_generated = false;
|
m_generated = false;
|
||||||
glDeleteBuffers(1, &m_vao);
|
|
||||||
glDeleteBuffers(1, &m_vbo);
|
|
||||||
glDeleteBuffers(1, &m_ebo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlanetFaceNode::isLeaf()
|
bool PlanetFaceNode::isLeaf()
|
||||||
|
@ -326,27 +196,141 @@ bool PlanetFaceNode::isLeaf()
|
||||||
return m_leaf;
|
return m_leaf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlanetFaceNode::getNeighbors() {
|
||||||
|
if (m_level == 0)
|
||||||
|
{
|
||||||
|
// The m_neighbors of root nodes never change
|
||||||
|
if (m_neighborTop != nullptr) return;
|
||||||
|
std::cout << m_planet->getFace(FACE_TOP)->getLODRoot() << std::endl;
|
||||||
|
switch (m_index)
|
||||||
|
{
|
||||||
|
// Front face
|
||||||
|
case FACE_FRONT:
|
||||||
|
m_neighborTop = m_planet->getFace(FACE_TOP)->getLODRoot();
|
||||||
|
m_neighborLeft = m_planet->getFace(FACE_LEFT)->getLODRoot();
|
||||||
|
m_neighborRight = m_planet->getFace(FACE_RIGHT)->getLODRoot();
|
||||||
|
m_neighborBottom = m_planet->getFace(FACE_BOTTOM)->getLODRoot();
|
||||||
|
break;
|
||||||
|
// Back face
|
||||||
|
case FACE_BACK:
|
||||||
|
m_neighborTop = m_planet->getFace(FACE_TOP)->getLODRoot();
|
||||||
|
m_neighborLeft = m_planet->getFace(FACE_RIGHT)->getLODRoot();
|
||||||
|
m_neighborRight = m_planet->getFace(FACE_LEFT)->getLODRoot();
|
||||||
|
m_neighborBottom = m_planet->getFace(FACE_BOTTOM)->getLODRoot();
|
||||||
|
break;
|
||||||
|
// Left face
|
||||||
|
case FACE_LEFT:
|
||||||
|
m_neighborTop = m_planet->getFace(FACE_TOP)->getLODRoot();
|
||||||
|
m_neighborLeft = m_planet->getFace(FACE_BACK)->getLODRoot();
|
||||||
|
m_neighborRight = m_planet->getFace(FACE_FRONT)->getLODRoot();
|
||||||
|
m_neighborBottom = m_planet->getFace(FACE_BOTTOM)->getLODRoot();
|
||||||
|
break;
|
||||||
|
// Right face
|
||||||
|
case FACE_RIGHT:
|
||||||
|
m_neighborTop = m_planet->getFace(FACE_TOP)->getLODRoot();
|
||||||
|
m_neighborLeft = m_planet->getFace(FACE_FRONT)->getLODRoot();
|
||||||
|
m_neighborRight = m_planet->getFace(FACE_BACK)->getLODRoot();
|
||||||
|
m_neighborBottom = m_planet->getFace(FACE_BOTTOM)->getLODRoot();
|
||||||
|
break;
|
||||||
|
// Top face
|
||||||
|
case FACE_TOP:
|
||||||
|
m_neighborTop = m_planet->getFace(FACE_BACK)->getLODRoot();
|
||||||
|
m_neighborLeft = m_planet->getFace(FACE_LEFT)->getLODRoot();
|
||||||
|
m_neighborRight = m_planet->getFace(FACE_RIGHT)->getLODRoot();
|
||||||
|
m_neighborBottom = m_planet->getFace(FACE_FRONT)->getLODRoot();
|
||||||
|
break;
|
||||||
|
// Bottom face
|
||||||
|
case FACE_BOTTOM:
|
||||||
|
m_neighborTop = m_planet->getFace(FACE_FRONT)->getLODRoot();
|
||||||
|
m_neighborLeft = m_planet->getFace(FACE_LEFT)->getLODRoot();
|
||||||
|
m_neighborRight = m_planet->getFace(FACE_RIGHT)->getLODRoot();
|
||||||
|
m_neighborBottom = m_planet->getFace(FACE_BACK)->getLODRoot();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_parent == nullptr) return;
|
||||||
|
|
||||||
|
switch (m_index)
|
||||||
|
{
|
||||||
|
// Top left corner
|
||||||
|
case TOP_LEFT:
|
||||||
|
if (m_parent->m_neighborTop != nullptr)
|
||||||
|
m_neighborTop = m_parent->m_neighborTop->m_children[BOTTOM_LEFT];
|
||||||
|
|
||||||
|
if (m_parent->m_children[TOP_RIGHT] != nullptr)
|
||||||
|
m_neighborRight = m_parent->m_children[TOP_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_children[BOTTOM_LEFT] != nullptr)
|
||||||
|
m_neighborBottom = m_parent->m_children[BOTTOM_LEFT];
|
||||||
|
|
||||||
|
if (m_parent->m_neighborLeft != nullptr)
|
||||||
|
m_neighborLeft = m_parent->m_neighborLeft->m_children[TOP_RIGHT];
|
||||||
|
break;
|
||||||
|
// Top right corner
|
||||||
|
case TOP_RIGHT:
|
||||||
|
if (m_parent->m_neighborTop != nullptr)
|
||||||
|
m_neighborTop = m_parent->m_neighborTop->m_children[BOTTOM_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_neighborRight != nullptr)
|
||||||
|
m_neighborRight = m_parent->m_neighborRight->m_children[TOP_LEFT];
|
||||||
|
|
||||||
|
if (m_parent->m_children[BOTTOM_RIGHT] != nullptr)
|
||||||
|
m_neighborBottom = m_parent->m_children[BOTTOM_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_children[TOP_LEFT] != nullptr)
|
||||||
|
m_neighborLeft = m_parent->m_children[TOP_LEFT];
|
||||||
|
break;
|
||||||
|
// Bottom right corner
|
||||||
|
case BOTTOM_RIGHT:
|
||||||
|
if (m_parent->m_children[TOP_RIGHT] != nullptr)
|
||||||
|
m_neighborTop = m_parent->m_children[TOP_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_neighborRight != nullptr)
|
||||||
|
m_neighborRight = m_parent->m_neighborRight->m_children[BOTTOM_LEFT];
|
||||||
|
|
||||||
|
if (m_parent->m_neighborBottom != nullptr)
|
||||||
|
m_neighborBottom = m_parent->m_neighborBottom->m_children[TOP_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_children[BOTTOM_LEFT] != nullptr)
|
||||||
|
m_neighborLeft = m_parent->m_children[BOTTOM_LEFT];
|
||||||
|
break;
|
||||||
|
// Bottom left corner
|
||||||
|
case BOTTOM_LEFT:
|
||||||
|
if (m_parent->m_children[TOP_RIGHT] != nullptr)
|
||||||
|
m_neighborTop = m_parent->m_children[TOP_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_children[BOTTOM_RIGHT] != nullptr)
|
||||||
|
m_neighborRight = m_parent->m_children[BOTTOM_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_neighborBottom != nullptr)
|
||||||
|
m_neighborBottom = m_parent->m_neighborBottom->m_children[TOP_RIGHT];
|
||||||
|
|
||||||
|
if (m_parent->m_neighborLeft != nullptr)
|
||||||
|
m_neighborLeft = m_parent->m_neighborLeft->m_children[BOTTOM_RIGHT];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PlanetFace::PlanetFace(Planet* planet, const unsigned int face) :
|
PlanetFace::PlanetFace(Planet* planet, const unsigned int face) :
|
||||||
m_planet(planet), m_face(face)
|
m_planet(planet), m_face(face)
|
||||||
{
|
{
|
||||||
m_normal = FACE_NORMALS[m_face];
|
m_normal = FACE_NORMALS[m_face];
|
||||||
m_planetFace = new PlanetFaceNode(planet, this, m_normal * (m_planet->getRadius() / 2.0f), 0);
|
m_lod = new PlanetFaceNode(planet, this, m_normal * (m_planet->getRadius() / 2.0f), face, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlanetFace::~PlanetFace()
|
PlanetFace::~PlanetFace()
|
||||||
{
|
{
|
||||||
delete m_planetFace;
|
delete m_lod;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlanetFace::draw(Camera* camera, Shader* shader)
|
void PlanetFace::draw(Camera* camera, Shader* shader)
|
||||||
{
|
{
|
||||||
m_planetFace->draw(camera, shader);
|
m_lod->draw(camera, shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlanetFace::tick(Camera* camera, GLfloat dtime)
|
void PlanetFace::tick(Camera* camera, GLfloat dtime)
|
||||||
{
|
{
|
||||||
// Do only one operation per tick, TODO: maybe allow more?
|
m_lod->tick(camera, dtime);
|
||||||
bool tickUpdatedLOD = false;
|
|
||||||
bool tickGeneratedFace = false;
|
|
||||||
m_planetFace->tick(camera, dtime, tickUpdatedLOD, tickGeneratedFace);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
|
||||||
#define RESOLUTION 61
|
#define RESOLUTION 15
|
||||||
|
|
||||||
enum Face
|
enum Face
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,12 @@ enum Face
|
||||||
FACE_FRONT, FACE_BACK
|
FACE_FRONT, FACE_BACK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LODFace
|
||||||
|
{
|
||||||
|
TOP_LEFT, TOP_RIGHT,
|
||||||
|
BOTTOM_RIGHT, BOTTOM_LEFT
|
||||||
|
};
|
||||||
|
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
|
@ -28,10 +34,10 @@ class PlanetFace;
|
||||||
class PlanetFaceNode
|
class PlanetFaceNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlanetFaceNode(Planet* planet, PlanetFace* face, glm::vec3 position, const unsigned int level);
|
PlanetFaceNode(Planet* planet, PlanetFace* face, glm::vec3 position, const unsigned int index, const unsigned int level);
|
||||||
~PlanetFaceNode();
|
~PlanetFaceNode();
|
||||||
|
|
||||||
void tick(Camera* camera, GLfloat dtime, bool& tickUpdatedLOD, bool& tickGeneratedFace);
|
void tick(Camera* camera, GLfloat dtime);
|
||||||
void draw(Camera* camera, Shader* shader);
|
void draw(Camera* camera, Shader* shader);
|
||||||
|
|
||||||
bool isLeaf();
|
bool isLeaf();
|
||||||
|
@ -46,13 +52,23 @@ class PlanetFaceNode
|
||||||
bool merge();
|
bool merge();
|
||||||
void dispose();
|
void dispose();
|
||||||
|
|
||||||
|
void setIndexBuffer(PlanetBufferIndex buf);
|
||||||
|
void getNeighbors();
|
||||||
|
|
||||||
Planet* m_planet;
|
Planet* m_planet;
|
||||||
PlanetFace* m_planetFace;
|
PlanetFace* m_planetFace;
|
||||||
|
|
||||||
PlanetFaceNode* m_parent;
|
PlanetFaceNode* m_parent;
|
||||||
PlanetFaceNode* m_children[4];
|
PlanetFaceNode* m_children[4];
|
||||||
|
|
||||||
|
PlanetFaceNode* m_neighborTop;
|
||||||
|
PlanetFaceNode* m_neighborRight;
|
||||||
|
PlanetFaceNode* m_neighborLeft;
|
||||||
|
PlanetFaceNode* m_neighborBottom;
|
||||||
|
|
||||||
|
unsigned int m_index;
|
||||||
unsigned int m_level;
|
unsigned int m_level;
|
||||||
|
|
||||||
bool m_dirty;
|
bool m_dirty;
|
||||||
bool m_generated;
|
bool m_generated;
|
||||||
bool m_leaf;
|
bool m_leaf;
|
||||||
|
@ -78,12 +94,13 @@ class PlanetFace
|
||||||
inline Planet* getPlanet() const { return m_planet; }
|
inline Planet* getPlanet() const { return m_planet; }
|
||||||
|
|
||||||
inline const glm::vec3 getNormal() const { return m_normal; }
|
inline const glm::vec3 getNormal() const { return m_normal; }
|
||||||
|
inline PlanetFaceNode* getLODRoot() { return m_lod; }
|
||||||
private:
|
private:
|
||||||
Planet* m_planet;
|
Planet* m_planet;
|
||||||
unsigned int m_face;
|
unsigned int m_face;
|
||||||
|
|
||||||
glm::vec3 m_normal;
|
glm::vec3 m_normal;
|
||||||
|
|
||||||
PlanetFaceNode* m_planetFace;
|
PlanetFaceNode* m_lod;
|
||||||
};
|
};
|
||||||
#endif // __PLANETFACE_H__
|
#endif // __PLANETFACE_H__
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
#include "PlanetIndexBuffer.h"
|
||||||
|
|
||||||
|
PlanetIndexBuffer::PlanetIndexBuffer(unsigned int resolution) : m_resolution(resolution) {
|
||||||
|
createBuffer(PlanetBufferIndex::Base);
|
||||||
|
createBuffer(PlanetBufferIndex::FixR, false, true, false, false);
|
||||||
|
createBuffer(PlanetBufferIndex::FixL, false, false, true, false);
|
||||||
|
createBuffer(PlanetBufferIndex::FixB, false, false, false, true);
|
||||||
|
createBuffer(PlanetBufferIndex::FixT, true, false, false, false);
|
||||||
|
createBuffer(PlanetBufferIndex::FixTR, true, true, false, false);
|
||||||
|
createBuffer(PlanetBufferIndex::FixTL, true, false, true, false);
|
||||||
|
createBuffer(PlanetBufferIndex::FixBR, false, true, false, true);
|
||||||
|
createBuffer(PlanetBufferIndex::FixBL, false, false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlanetIndexBuffer::~PlanetIndexBuffer() {
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
if (m_buffers[i] == nullptr) continue;
|
||||||
|
glDeleteBuffers(1, &m_buffers[i]->ebo);
|
||||||
|
m_buffers[i]->indices.clear();
|
||||||
|
delete m_buffers[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PIB* PlanetIndexBuffer::getBuffer(PlanetBufferIndex idx) {
|
||||||
|
return m_buffers[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlanetIndexBuffer::createBuffer(PlanetBufferIndex idx, bool fanTop, bool fanRight, bool fanLeft, bool fanBottom) {
|
||||||
|
PIB* buffer = new PIB();
|
||||||
|
// Create indices for mesh
|
||||||
|
for (unsigned int gz = 0; gz < m_resolution - 1; gz++)
|
||||||
|
{
|
||||||
|
bool slantLeft = gz % 2 == 0;
|
||||||
|
for (unsigned int gx = 0; gx < m_resolution - 1; gx++)
|
||||||
|
{
|
||||||
|
unsigned int topLeft = (gz * m_resolution) + gx;
|
||||||
|
unsigned int topRight = topLeft + 1;
|
||||||
|
unsigned int bottomLeft = ((gz + 1) * m_resolution) + gx;
|
||||||
|
unsigned int bottomRight = bottomLeft + 1;
|
||||||
|
|
||||||
|
bool uTri1 = true;
|
||||||
|
bool uTri2 = true;
|
||||||
|
unsigned int tri1[3];
|
||||||
|
unsigned int tri2[3];
|
||||||
|
|
||||||
|
if (slantLeft)
|
||||||
|
{
|
||||||
|
tri1[0] = topLeft;
|
||||||
|
tri1[1] = bottomLeft;
|
||||||
|
tri1[2] = bottomRight;
|
||||||
|
tri2[0] = topLeft;
|
||||||
|
tri2[1] = bottomRight;
|
||||||
|
tri2[2] = topRight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tri1[0] = topLeft;
|
||||||
|
tri1[1] = bottomLeft;
|
||||||
|
tri1[2] = topRight;
|
||||||
|
tri2[0] = bottomLeft;
|
||||||
|
tri2[1] = bottomRight;
|
||||||
|
tri2[2] = topRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fanTop && gz == 0)
|
||||||
|
{
|
||||||
|
if (gx % 2 == 0)
|
||||||
|
{
|
||||||
|
tri2[0] = topLeft;
|
||||||
|
tri2[1] = bottomRight;
|
||||||
|
tri2[2] = topRight + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uTri1 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fanRight && gx == m_resolution - 2)
|
||||||
|
{
|
||||||
|
if (gz % 2 == 0)
|
||||||
|
{
|
||||||
|
tri2[0] = topRight;
|
||||||
|
tri2[1] = bottomLeft;
|
||||||
|
tri2[2] = bottomRight + m_resolution;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uTri2 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fanBottom && gz == m_resolution - 2)
|
||||||
|
{
|
||||||
|
if (gx % 2 == 0)
|
||||||
|
{
|
||||||
|
tri2[0] = bottomLeft;
|
||||||
|
tri2[1] = bottomRight + 1;
|
||||||
|
tri2[2] = topRight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uTri1 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fanLeft && gx == 0)
|
||||||
|
{
|
||||||
|
if (gz % 2 == 0)
|
||||||
|
{
|
||||||
|
tri1[0] = topLeft;
|
||||||
|
tri1[1] = bottomLeft + m_resolution;
|
||||||
|
tri1[2] = bottomRight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uTri1 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uTri1)
|
||||||
|
{
|
||||||
|
buffer->indices.push_back(tri1[0]);
|
||||||
|
buffer->indices.push_back(tri1[1]);
|
||||||
|
buffer->indices.push_back(tri1[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uTri2)
|
||||||
|
{
|
||||||
|
buffer->indices.push_back(tri2[0]);
|
||||||
|
buffer->indices.push_back(tri2[1]);
|
||||||
|
buffer->indices.push_back(tri2[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
slantLeft = !slantLeft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenBuffers(1, &(buffer->ebo));
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * buffer->indices.size(), &(buffer->indices[0]), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
m_buffers[idx] = buffer;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __PLANETINDEXBUFFER_H__
|
||||||
|
#define __PLANETINDEXBUFFER_H__
|
||||||
|
|
||||||
|
#include "util/Common.h"
|
||||||
|
|
||||||
|
struct PIB {
|
||||||
|
GLuint ebo;
|
||||||
|
std::vector<uint> indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PlanetBufferIndex {
|
||||||
|
Base, FixR, FixL, FixB, FixT, FixTR, FixTL, FixBR, FixBL
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlanetIndexBuffer {
|
||||||
|
public:
|
||||||
|
PlanetIndexBuffer(unsigned int resolution);
|
||||||
|
~PlanetIndexBuffer();
|
||||||
|
|
||||||
|
PIB* getBuffer(PlanetBufferIndex idx);
|
||||||
|
private:
|
||||||
|
void createBuffer(PlanetBufferIndex idx, bool fanTop = false, bool fanRight = false, bool fanLeft = false, bool fanBottom = false);
|
||||||
|
PIB* m_buffers[9];
|
||||||
|
unsigned int m_resolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __PLANETINDEXBUFFER_H__
|
Loading…
Reference in New Issue