Skip to content

Commit

Permalink
Converted Mesh class to use an element buffer object to prevent verte…
Browse files Browse the repository at this point in the history
…x duplication, as this is more useful for my other projects.
  • Loading branch information
nitronoid committed Feb 22, 2018
1 parent c92c565 commit af61914
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 48 deletions.
22 changes: 18 additions & 4 deletions include/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,23 @@ class Mesh
//-----------------------------------------------------------------------------------------------------
void reset();
//-----------------------------------------------------------------------------------------------------
/// @brief Gets a pointer to the first data element in the indices array for use with openGL buffers.
/// @return A pointer to the first element in the indices array.
//-----------------------------------------------------------------------------------------------------
const GLushort *getIndicesData() const noexcept;
//-----------------------------------------------------------------------------------------------------
/// @brief Gets a pointer to the first data element in the vertex array for use with openGL buffers.
/// @return A pointer to the first element in vertex array.
/// @return A pointer to the first element in the vertex array.
//-----------------------------------------------------------------------------------------------------
const GLfloat* getVertexData() const noexcept;
//-----------------------------------------------------------------------------------------------------
/// @brief Gets a pointer to the first data element in the normal array for use with openGL buffers.
/// @return A pointer to the first element in normal array.
/// @return A pointer to the first element in the normal array.
//-----------------------------------------------------------------------------------------------------
const GLfloat* getNormalsData() const noexcept;
//-----------------------------------------------------------------------------------------------------
/// @brief Gets a pointer to the first data element in the UV array for use with openGL buffers.
/// @return A pointer to the first element in UV array.
/// @return A pointer to the first element in the UV array.
//-----------------------------------------------------------------------------------------------------
const GLfloat* getUVsData() const noexcept;
//-----------------------------------------------------------------------------------------------------
Expand All @@ -47,6 +52,11 @@ class Mesh
//-----------------------------------------------------------------------------------------------------
const GLfloat* getAttribData(const MeshAttributes::Attribute _attrib) const noexcept;
//-----------------------------------------------------------------------------------------------------
/// @brief Used to the the amount of face indices.
/// @return The size of our indices array.
//-----------------------------------------------------------------------------------------------------
int getNIndicesData() const noexcept;
//-----------------------------------------------------------------------------------------------------
/// @brief Used to the the amount of vertex data elements.
/// @return The size of our vertex array.
//-----------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -77,9 +87,13 @@ class Mesh
//-----------------------------------------------------------------------------------------------------
std::vector<glm::vec3> m_normals;
//-----------------------------------------------------------------------------------------------------
/// @brief m_uvs contains the UV's
/// @brief m_uvs contains the UVs
//-----------------------------------------------------------------------------------------------------
std::vector<glm::vec2> m_uvs;
//-----------------------------------------------------------------------------------------------------
/// @brief m_indices contains the indices
//-----------------------------------------------------------------------------------------------------
std::vector<GLushort> m_indices;

};

Expand Down
50 changes: 40 additions & 10 deletions include/MeshVBO.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,27 @@ class MeshVBO
void init();
//-----------------------------------------------------------------------------------------------------
/// @brief called to reset our buffers, removing data from them
/// @param [in] _size is the size in bytes of the data type we are storing, float would be 4 (probably).
/// @param [in] _nVert is the amount of elements of _size bytes that we should allocate for the,
/// @param [in] _indicesSize is the size in bytes of the data type used to store indices.
/// @param [in] _nIndices is the amount of elements of _indicesSize bytes that we should allocate for,
/// the indices in the Element Buffer Object.
/// @param [in] _dataSize is the size in bytes of the data type we are storing, float would be 4 (probably).
/// @param [in] _nVert is the amount of elements of _dataSize bytes that we should allocate for the,
/// vertices in the Vertex Buffer Object.
/// @param [in] _nNorm is the amount of elements of _size bytes that we should allocate for the,
/// @param [in] _nNorm is the amount of elements of _dataSize bytes that we should allocate for the,
/// normals in the Vertex Buffer Object.
/// @param [in] _nUV is the amount of elements of _size bytes that we should allocate for the,
/// @param [in] _nUV is the amount of elements of _dataSize bytes that we should allocate for the,
/// UV's in the Vertex Buffer Object.
//-----------------------------------------------------------------------------------------------------
void reset(const int _size, const int _nVert, const int _nUV, const int _nNorm);
void reset(
const unsigned char _indicesSize,
const int _nIndices,
const unsigned char _dataSize,
const int _nVert,
const int _nUV,
const int _nNorm
);
//-----------------------------------------------------------------------------------------------------
/// @brief called to add new data into the specified buffer.
/// @brief called to add new data into the specified section of the vertex buffer.
/// @param [in] _address is a pointer to the data we want to store.
/// @param [in] _section is the section of the buffer we should write our data to.
//-----------------------------------------------------------------------------------------------------
Expand All @@ -43,7 +53,7 @@ class MeshVBO
/// @brief called to get the size of each data element we are storing.
/// @return the size of the data elements in our buffer
//-----------------------------------------------------------------------------------------------------
int dataSize() const noexcept;
unsigned char dataSize() const noexcept;
//-----------------------------------------------------------------------------------------------------
/// @brief called to get the amount of data elements we are storing.
/// @return the number of data elements in our buffer
Expand All @@ -59,14 +69,25 @@ class MeshVBO
/// @return the offset in bytes of _section.
//-----------------------------------------------------------------------------------------------------
int offset(const MeshAttributes::Attribute _section) const noexcept;

//-----------------------------------------------------------------------------------------------------
/// @brief called to bind our buffers.
//-----------------------------------------------------------------------------------------------------
void use();
//-----------------------------------------------------------------------------------------------------
/// @brief called to add new index data into the element buffer.
/// @param [in] io_indices is a pointer to the index data.
//-----------------------------------------------------------------------------------------------------
void setIndices(const void *_indices);

private:
//-----------------------------------------------------------------------------------------------------
/// @brief The vertex buffer object that stores our data.
//-----------------------------------------------------------------------------------------------------
QOpenGLBuffer m_vbo;
QOpenGLBuffer m_vbo {QOpenGLBuffer::VertexBuffer};
//-----------------------------------------------------------------------------------------------------
/// @brief The element buffer object that stores our face indices.
//-----------------------------------------------------------------------------------------------------
QOpenGLBuffer m_ebo {QOpenGLBuffer::IndexBuffer};
//-----------------------------------------------------------------------------------------------------
/// @brief Current amount of data elements in each section of m_vbo.
//-----------------------------------------------------------------------------------------------------
Expand All @@ -76,9 +97,18 @@ class MeshVBO
//-----------------------------------------------------------------------------------------------------
int m_totalAmountOfData = 0;
//-----------------------------------------------------------------------------------------------------
/// @brief Current number of indices.
//-----------------------------------------------------------------------------------------------------
int m_numIndices = 0;
//-----------------------------------------------------------------------------------------------------
/// @brief Current size of the stored data members in the buffer.
//-----------------------------------------------------------------------------------------------------
int m_size = 0;
unsigned char m_dataSize = 0;
//-----------------------------------------------------------------------------------------------------
/// @brief Current size of the data type used to store indices.
//-----------------------------------------------------------------------------------------------------
unsigned char m_indicesSize = 0;


};

Expand Down
15 changes: 10 additions & 5 deletions src/DemoScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void DemoScene::writeMeshAttributes()
{
m_meshVBO.write(mesh.getAttribData(buff), buff);
}
m_meshVBO.setIndices(mesh.getIndicesData());
}
//-----------------------------------------------------------------------------------------------------
void DemoScene::setAttributeBuffers()
Expand Down Expand Up @@ -97,11 +98,14 @@ void DemoScene::generateNewGeometry()
{
makeCurrent();
m_meshIndex = (m_meshIndex + 1) % m_meshes.size();
auto& mesh = m_meshes[m_meshIndex];
m_meshVBO.reset(
sizeof(GLushort),
mesh.getNIndicesData(),
sizeof(GLfloat),
m_meshes[m_meshIndex].getNVertData(),
m_meshes[m_meshIndex].getNUVData(),
m_meshes[m_meshIndex].getNNormData()
mesh.getNVertData(),
mesh.getNUVData(),
mesh.getNNormData()
);
writeMeshAttributes();
setAttributeBuffers();
Expand All @@ -128,7 +132,8 @@ void DemoScene::renderScene()

m_materials[m_currentMaterial]->update();


glDrawArrays(GL_TRIANGLES, 0, m_meshes[m_meshIndex].getNVertData()/3);
m_meshVBO.use();
glDrawElements(GL_TRIANGLES, m_meshes[m_meshIndex].getNIndicesData(), GL_UNSIGNED_SHORT, nullptr);
// glDrawArrays(GL_TRIANGLES, 0, m_meshes[m_meshIndex].getNVertData()/3);
}
//-----------------------------------------------------------------------------------------------------
54 changes: 32 additions & 22 deletions src/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ void Mesh::load(const std::string &_fname, const size_t _meshNum)
aiProcess_FlipUVs);
const aiMesh* mesh = scene->mMeshes[_meshNum];

// Get the number of faces on the mesh
size_t numFaces = mesh->mNumFaces;
// Calculate the amount of vertices we will store (3 per face)
size_t numStored = numFaces * 3;
size_t numVerts = mesh->mNumVertices;

// Reserve memory in vectors to accomodate the incomming data
m_vertices.reserve(numStored * 3);
m_normals.reserve(numStored * 3);
m_uvs.reserve(numStored * 2);
m_vertices.reserve(numVerts);
m_normals.reserve(numVerts);
m_uvs.reserve(numVerts);

// Get access to the information we will store
auto& vertices = mesh->mVertices;
Expand All @@ -33,6 +31,22 @@ void Mesh::load(const std::string &_fname, const size_t _meshNum)
// Some meshes don't have UV's
bool hasTexCoords = mesh->HasTextureCoords(0);

for (size_t i = 0; i < numVerts; ++i)
{
auto& vert = vertices[i];
m_vertices.insert(m_vertices.end(), {vert.x,vert.y,vert.z});

auto& norm = normals[i];
m_normals.insert(m_normals.end(), {norm.x,norm.y,norm.z});

if (!hasTexCoords) continue;
// UV's only use the first two members
const auto& uv = hasTexCoords ? texCoords[i] : aiVector3D(0.0f, 0.0f, 0.0f);
m_uvs.insert(m_uvs.end(), {uv.x, uv.y});
}

// Get the number of faces on the mesh
size_t numFaces = mesh->mNumFaces;
// We iterate through faces not vertices,
// as the verts will be duplicated when used by more than one face.
for (size_t faceIndex = 0; faceIndex < numFaces; ++faceIndex)
Expand All @@ -43,33 +57,24 @@ void Mesh::load(const std::string &_fname, const size_t _meshNum)
{
// Get the index of the vertex, we use this for it's normals and UV's too
size_t vertInFace = face.mIndices[i];

// Get the vertex
auto& vert = vertices[vertInFace];
// Push it's values into our float vector
m_vertices.insert(m_vertices.end(), {vert.x,vert.y,vert.z});

// Do the same for normals
auto& normal = normals[vertInFace];
m_normals.insert(m_normals.end(), {normal.x,normal.y,normal.z});

// Lazy check for texCoords
if (!hasTexCoords) continue;

// UV's only use the first two members
const auto& uv = hasTexCoords ? texCoords[vertInFace] : aiVector3D(0.0f, 0.0f, 0.0f);
m_uvs.insert(m_uvs.end(), {uv.x, uv.y});
m_indices.push_back(vertInFace);
}
}
}

void Mesh::reset()
{
m_indices.clear();
m_vertices.clear();
m_normals.clear();
m_uvs.clear();
}

const GLushort *Mesh::getIndicesData() const noexcept
{
return &m_indices[0];
}

const GLfloat* Mesh::getVertexData() const noexcept
{
return &m_vertices[0].x;
Expand Down Expand Up @@ -99,6 +104,11 @@ const GLfloat *Mesh::getAttribData(const MeshAttributes::Attribute _attrib) cons
return data;
}

int Mesh::getNIndicesData() const noexcept
{
return static_cast<int>(m_indices.size());
}

int Mesh::getNVertData() const noexcept
{
return static_cast<int>(m_vertices.size()) * 3;
Expand Down
29 changes: 22 additions & 7 deletions src/MeshVBO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ void MeshVBO::init()
// Generate all our required buffers
m_vbo.create();
m_vbo.bind();
m_ebo.create();
m_ebo.bind();
}
//-----------------------------------------------------------------------------------------------------
void MeshVBO::reset(const int _size, const int _nVert, const int _nUV, const int _nNorm)
void MeshVBO::reset(const unsigned char _indicesSize, const int _nIndices, const unsigned char _dataSize, const int _nVert, const int _nUV, const int _nNorm)
{
{
using namespace MeshAttributes;
Expand All @@ -20,24 +22,36 @@ void MeshVBO::reset(const int _size, const int _nVert, const int _nUV, const int
}
m_totalAmountOfData = _nVert + _nNorm + _nUV;
// Track the size of our stored data
m_size = _size;
m_dataSize = _dataSize;
// For all the buffers, we bind them then clear the data pointer
m_vbo.bind();
m_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
m_vbo.allocate(m_size * m_totalAmountOfData);
m_vbo.allocate(m_dataSize * m_totalAmountOfData);

m_numIndices = _nIndices;
m_indicesSize = _indicesSize;
m_ebo.bind();
m_ebo.setUsagePattern(QOpenGLBuffer::StaticDraw);
m_ebo.allocate(_nIndices * m_indicesSize);
}
//-----------------------------------------------------------------------------------------------------
void MeshVBO::write(const void *_address, const MeshAttributes::Attribute _section)
{
// Bind the requested buffer, then set it's data pointer
m_vbo.bind();
m_vbo.write(offset(_section), _address, m_amountOfData[_section] * m_size);
m_vbo.write(offset(_section), _address, m_amountOfData[_section] * m_dataSize);
}
//-----------------------------------------------------------------------------------------------------
void MeshVBO::setIndices(const void* _indices)
{
m_ebo.bind();
m_ebo.write(0, _indices, m_numIndices * m_indicesSize);
}
//-----------------------------------------------------------------------------------------------------
int MeshVBO::dataSize() const noexcept
unsigned char MeshVBO::dataSize() const noexcept
{
// Returns the size the stored of data elements
return m_size;
return m_dataSize;
}
//-----------------------------------------------------------------------------------------------------
int MeshVBO::dataAmount() const noexcept
Expand All @@ -57,10 +71,11 @@ int MeshVBO::offset(const MeshAttributes::Attribute _section) const noexcept
int offset = 0;
for (size_t i = 0; i < _section; ++i)
offset += m_amountOfData[i];
return offset * m_size;
return offset * m_dataSize;
}
//-----------------------------------------------------------------------------------------------------
void MeshVBO::use()
{
m_vbo.bind();
m_ebo.bind();
}

0 comments on commit af61914

Please sign in to comment.