I am trying to optimize the drawing of my quads (currently using glBegin
and glEnd
), and I read that a VBO is a better way to do this. My issue is that I don't have a basic array of GLuint
with an index array, but rather custom classes to hold the values:
Location.hpp
: Holds x, y, and z info
class Location {
public:
Location(int x_, int y_, int z_);
~Location();
int x;
int y;
int z;
};
Face.hpp
: Holds 4 Location*
s that mark the corners
class Face {
public:
Face(Location* bl_, Location* br_, Location* tr_, Location* tl_); // Using point
Face(int bl_[3], int br_[3], int tr_[3], int tl_[3]); // Using {x, y, z} int array
~Face();
Location* bl = NULL; // Bottom Left
Location* br = NULL; // Bottom Right
Location* tr = NULL; // Top Right
Location* tl = NULL; // Top Left
};
My question, is that I have a vector of faces (std::vector<Face*> facesToRender;
) that I would like to display on the screen.
Right now I have a loop to do this:
Info:
The Chunk
class creates a facesToRender
and I believe this is where I can put a vboId
)
chunks
is an array of Chunk*
s
glPushMatrix();
for (int i = 0; i < chunks.size(); i++) {
Chunk* chunk = chunks[i];
for (int j = 0; j < chunk->facesToRender.size(); j++) {
Face* f = chunk->facesToRender[j];
srand(i); // Create a color per chunk
glColor3ub(rand()%255, rand()%255, rand()%255);
glBegin(GL_QUADS);
glVertex3i(f->bl->x, f->bl->y, f->bl->z);
glVertex3i(f->br->x, f->br->y, f->br->z);
glVertex3i(f->tr->x, f->tr->y, f->tr->z);
glVertex3i(f->tl->x, f->tl->y, f->tl->z);
glEnd();
}
}
glPopMatrix();
My question is how to process this facesToRender
vector into a VBO to have it display. I am a beginner at OpenGL and C++ (although I know other languages, so sorry if I made some big mistake with the classes).
If any additional info is needed please comment!
First of all you have to ensure that the vertex coordinates are in a contiguous and contiguous area in memory and are not fragmented into a lot of little pieces. Use Location bl, br, tr, tl
instead of Location *bl ...
and std::vector<Face>
instead of std::vector<Face*>
. Then you have a consecutive list of vertex coordinates which can be bound to a vertex buffer object:
class Face {
public:
Location bl;
Location br;
Location tr;
Location tl;
};
std::vector<Location> faces;
Create the vetrtex array object and bind the data
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, faces.size()*sizeof(*faces.data()), faces.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
Draw the mesh:
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glVertexPointer( 3, GL_INT, sizeof(Location), nullptr );
glEnableClientState( GL_VERTEX_ARRAY );
glPushMatrix();
for (int i = 0; i < chunks.size(); i++) {
Chunk* chunk = chunks[i];
for (int j = 0; j < chunk->facesToRender.size(); j++) {
Face* f = chunk->facesToRender[j];
srand(i); // Create a color per chunk
glColor3ub(rand()%255, rand()%255, rand()%255);
glDrawArrays(GL_QUADS, j*4, 4);
}
}
glPopMatrix();
glDisableClientState( GL_VERTEX_ARRAY );
As an alternative you can create a list of vertex coordinates and a list of faces which each contains the 4 indices of the corner coordinates.
std::vector<Location> vertices;
struct Face
{
int bl;
int br;
int tr;
int tl;
};
std::vector<Face> faces;
Indexed vertex cordiaten can be drawn by glDrawElements
.