2020-04-10 10:29:11 +00:00
|
|
|
#include "PlanetIndexBuffer.h"
|
|
|
|
|
2023-02-23 19:33:50 +00:00
|
|
|
PlanetIndexBuffer::PlanetIndexBuffer(
|
|
|
|
unsigned int resolution,
|
|
|
|
const unsigned int detailTop,
|
|
|
|
const unsigned int detailRight,
|
|
|
|
const unsigned int detailBottom,
|
|
|
|
const unsigned int detailLeft
|
|
|
|
) : m_resolution(resolution) {
|
|
|
|
TriangleFanList triangleFans;
|
|
|
|
|
|
|
|
// Build the patch body (without edges)
|
|
|
|
for (unsigned int x = 2; x < m_resolution - 1; x += 2)
|
|
|
|
{
|
|
|
|
for (unsigned int y = 2; y < m_resolution - 1; y += 2)
|
|
|
|
{
|
|
|
|
addTriangleFan(triangleFans);
|
|
|
|
addTriangleFanVertex(triangleFans, x, y);
|
|
|
|
addTriangleFanVertex(triangleFans, x + 1, y + 1);
|
|
|
|
addTriangleFanVertex(triangleFans, x, y + 1);
|
|
|
|
addTriangleFanVertex(triangleFans, x - 1, y + 1);
|
|
|
|
addTriangleFanVertex(triangleFans, x - 1, y);
|
|
|
|
addTriangleFanVertex(triangleFans, x - 1, y - 1);
|
|
|
|
addTriangleFanVertex(triangleFans, x, y - 1);
|
|
|
|
addTriangleFanVertex(triangleFans, x + 1, y - 1);
|
|
|
|
addTriangleFanVertex(triangleFans, x + 1, y);
|
|
|
|
addTriangleFanVertex(triangleFans, x + 1, y + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build all four edges
|
2023-02-24 13:34:40 +00:00
|
|
|
buildEdge(triangleFans, TOP, detailTop);
|
|
|
|
buildEdge(triangleFans, RIGHT, detailRight);
|
|
|
|
buildEdge(triangleFans, BOTTOM, detailBottom);
|
|
|
|
buildEdge(triangleFans, LEFT, detailLeft);
|
2023-02-23 19:33:50 +00:00
|
|
|
|
|
|
|
// Count the number of triangles and reserve three vertices per triangle
|
|
|
|
int triangleCount = 0;
|
|
|
|
for (unsigned int i = 0; i < triangleFans.size(); i++)
|
|
|
|
if (triangleFans[i].size() > 2)
|
|
|
|
triangleCount += triangleFans[i].size() - 2;
|
|
|
|
m_vertexCount = 3 * triangleCount;
|
|
|
|
|
|
|
|
// Create an index array
|
|
|
|
GLushort *indexData = new GLushort[m_vertexCount];
|
|
|
|
int n = 0;
|
|
|
|
for (unsigned int i = 0; i < triangleFans.size(); i++)
|
|
|
|
{
|
|
|
|
for (unsigned int j = 2; j < triangleFans[i].size(); j++)
|
|
|
|
{
|
|
|
|
indexData[n++] = triangleFans[i][0];
|
|
|
|
indexData[n++] = triangleFans[i][j-1];
|
|
|
|
indexData[n++] = triangleFans[i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate the index buffer object (IBO)
|
|
|
|
glGenBuffers(1, &m_ibo);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
|
|
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * m_vertexCount, indexData, GL_STATIC_DRAW);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
|
|
|
|
// Delete unnecessary data
|
|
|
|
triangleFans.clear();
|
|
|
|
delete[] indexData;
|
2020-04-10 10:29:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PlanetIndexBuffer::~PlanetIndexBuffer() {
|
2023-02-23 19:33:50 +00:00
|
|
|
glDeleteBuffers(1, &m_ibo);
|
2020-04-10 10:29:11 +00:00
|
|
|
}
|
|
|
|
|
2023-02-23 19:33:50 +00:00
|
|
|
void PlanetIndexBuffer::rotateIndices(unsigned int &x, unsigned int &y, const unsigned int rotation)
|
|
|
|
{
|
|
|
|
// Change the indices to match the given rotation
|
|
|
|
switch (rotation)
|
|
|
|
{
|
|
|
|
case TOP:
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
case RIGHT:
|
|
|
|
std::swap(x, y);
|
|
|
|
y = m_resolution - y;
|
|
|
|
return;
|
|
|
|
case BOTTOM:
|
|
|
|
x = m_resolution - x;
|
|
|
|
y = m_resolution - y;
|
|
|
|
return;
|
|
|
|
case LEFT:
|
|
|
|
std::swap(x, y);
|
|
|
|
x = m_resolution - x;
|
|
|
|
return;
|
|
|
|
}
|
2020-04-10 10:29:11 +00:00
|
|
|
}
|
|
|
|
|
2023-02-23 19:33:50 +00:00
|
|
|
// Creates and adds a triangle fan
|
|
|
|
void PlanetIndexBuffer::addTriangleFan(TriangleFanList &triangleFans)
|
|
|
|
{
|
|
|
|
triangleFans.push_back(TriangleFan());
|
|
|
|
}
|
|
|
|
|
|
|
|
// adds a vertex index to the most recently added triangle fan
|
|
|
|
void PlanetIndexBuffer::addTriangleFanVertex(TriangleFanList &triangleFans, unsigned int x, unsigned int y, const unsigned int rotation)
|
|
|
|
{
|
|
|
|
// Rotate and use the x and y indices
|
|
|
|
PlanetIndexBuffer::rotateIndices(x, y, rotation);
|
|
|
|
triangleFans.back().push_back(index1D(x,y));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlanetIndexBuffer::buildEdge(TriangleFanList &triangleFans, const unsigned int side, const unsigned int detail)
|
|
|
|
{
|
|
|
|
// If detail difference is 0 (default case) or too high
|
|
|
|
if (detail == 0 || detail > 4)
|
|
|
|
{
|
|
|
|
for (unsigned int x = 0; x < m_resolution - 1; x += 2)
|
|
|
|
{
|
|
|
|
addTriangleFan(triangleFans);
|
|
|
|
addTriangleFanVertex(triangleFans, x + 1, m_resolution - 1, side);
|
|
|
|
for (int d = -1; d <= 1; d++)
|
|
|
|
addTriangleFanVertex(triangleFans, x + 1 - d, m_resolution, side);
|
|
|
|
|
|
|
|
if (x > 0)
|
|
|
|
{
|
|
|
|
addTriangleFan(triangleFans);
|
|
|
|
addTriangleFanVertex(triangleFans, x, m_resolution, side);
|
|
|
|
for (int d = -1; d <= 1; d++)
|
|
|
|
addTriangleFanVertex(triangleFans, x + d, m_resolution - 1, side);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate step sizes; step = 2^detail
|
|
|
|
const int step = 1 << detail;
|
|
|
|
const int halfStep = step / 2;
|
|
|
|
|
|
|
|
unsigned int x = 0;
|
|
|
|
for (x = 0; x < m_resolution; x += step)
|
|
|
|
{
|
|
|
|
addTriangleFan(triangleFans);
|
|
|
|
addTriangleFanVertex(triangleFans, x, m_resolution, side);
|
|
|
|
addTriangleFanVertex(triangleFans, x + halfStep, m_resolution - 1, side);
|
|
|
|
addTriangleFanVertex(triangleFans, x + step, m_resolution, side);
|
|
|
|
|
|
|
|
if (x > 0)
|
|
|
|
{
|
|
|
|
addTriangleFan(triangleFans);
|
|
|
|
addTriangleFanVertex(triangleFans, x, m_resolution, side);
|
|
|
|
for (int d = -halfStep; d <= halfStep; d++)
|
|
|
|
addTriangleFanVertex(triangleFans, x + d, m_resolution - 1, side);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (step > 2)
|
|
|
|
{
|
|
|
|
addTriangleFan(triangleFans);
|
|
|
|
addTriangleFanVertex(triangleFans, 0, m_resolution, side);
|
|
|
|
for (int d = 1; d <= halfStep; d++)
|
|
|
|
addTriangleFanVertex(triangleFans, d, m_resolution - 1, side);
|
|
|
|
|
|
|
|
addTriangleFan(triangleFans);
|
|
|
|
addTriangleFanVertex(triangleFans, m_resolution, m_resolution, side);
|
|
|
|
for (int d = -halfStep; d <= -1; d++)
|
|
|
|
addTriangleFanVertex(triangleFans, m_resolution + d, m_resolution - 1, side);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GLsizei PlanetIndexBuffer::getVertexCount() const
|
|
|
|
{
|
|
|
|
return m_vertexCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
GLuint PlanetIndexBuffer::getIbo() const
|
|
|
|
{
|
|
|
|
return m_ibo;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int PlanetIndexBuffer::index1D(const unsigned int x, const unsigned int y) {
|
|
|
|
return ((x) + (y) * (m_resolution + 1));
|
2020-04-10 10:29:11 +00:00
|
|
|
}
|