AlasdairRyan AlasdairRyan - 3 months ago 27
C++ Question

OpenGL Duplicating Vertex Arrays

I am looking for some clarification and some guidance regarding duplicating indices that are already in an array.I need to from what I gather duplicate indices so that I can render a cube (each side a different colour).
My cube is read in from a "OBJ" file.

Current Code

using std::vector;

vector<GLfloat>vertex;
vector<GLuint>faces;

GLubyte color1[] =
{
255,255,0,
255,255,0,
255,255,0,
255,255,0,

255,0,255,
255,0,255,
255,0,255,
255,0,255

};

struct OBJVertex
{
GLint f1;
GLint f2;
GLint f3;

GLfloat x;
GLfloat y;
GLfloat z;

}obj;

int OBJLoader::LoadOBJData(string filename)
{
ifstream f_obj;

string line;

f_obj.open(filename, ios::in);

while (!f_obj.eof())
{
getline(f_obj, line);

if (line.find("v") != line.npos)
{
sscanf_s(line.c_str(), "v %f %f %f ", &obj.x, &obj.y, &obj.z);
vertex.push_back(obj.x);
vertex.push_back(obj.y);
vertex.push_back(obj.z);
}
if (line.find("f ")!= line.npos)
{
sscanf_s(line.c_str(), "f %d %d %d ", &obj.f1, &obj.f2, &obj.f3);
obj.f1 = obj.f1 - 1;
obj.f2 = obj.f2 - 1;
obj.f3 = obj.f3 - 1;

faces.push_back(obj.f1);
faces.push_back(obj.f2);
faces.push_back(obj.f3);
}
}
return 0;
}
void OBJLoader::RenderOBJ()
{
glEnable(GL_DEPTH_TEST);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

glColorPointer(3, GL_UNSIGNED_BYTE, 0, color1);
glVertexPointer(3,GL_FLOAT, 0, &vertex[0]);

glDrawElements(GL_TRIANGLE_STRIP,faces.size(),GL_UNSIGNED_INT,&faces[0]);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}


Am I correct in thinking I need to bind both the vertex and colour array using glBindBuffer?

glBindBuffer(GL_ARRAY_BUFFER,vertex[0]);


I currently have a colour array setup named "color1",this colours the top and bottom faces of the cube after binding the first vertex and colour array am I correct in thinking I can create two more colour arrays for the remaining sides of the cube?

Idea?

glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

glColorPointer(3, GL_UNSIGNED_BYTE, 0, color1); // first colour array //
glVertexPointer(3,GL_FLOAT, 0, &vertex[0]);

glDrawElements(GL_TRIANGLE_STRIP, faces.size(), GL_UNSIGNED_INT,&faces[0]);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,vertex[0]);



glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

glColorPointer(3, GL_UNSIGNED_BYTE, 0, color2); // second colour array //
glVertexPointer(3,GL_FLOAT, 0, &vertex[0]);

glDrawElements(GL_TRIANGLE_STRIP, faces.size(), GL_UNSIGNED_INT,&faces[0]);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,vertex[0]);


----Update----

Sorry, but I made a colour array per face but it is just overwriting the previous array.Can someone explain what I have not done right?

GLubyte color1[] =
{
255,255,0,
255,255,0,
255,255,0,
255,255,0,

255,0,255,
255,0,255,
255,0,255,
255,0,255

};

GLubyte color2[] =
{
255,0,0,
255,0,0,
255,0,0,
255,0,0,

0,0,255,
0,0,255,
0,0,255,
0,0,255
};

GLubyte color3[] =
{
0,255,255,
0,255,255,
0,255,255,
0,255,255,

255,0,255,
255,0,255,
255,0,255,
255,0,255
};

GLubyte color4[] =
{
255,255,255,
255,255,255,
255,255,255,
255,255,255,

0,255,0,
0,255,0,
0,255,0,
0,255,0
};

void OBJLoader::RenderOBJ()
{
glEnable(GL_DEPTH_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, &vertex[0]);

glColorPointer(3, GL_UNSIGNED_BYTE, 0, color1);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, color2);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, color3);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, color4);

glDrawElements(GL_TRIANGLE_STRIP, faces.size(), GL_UNSIGNED_INT, &faces[0]);
glDrawElements(GL_TRIANGLE_STRIP, faces.size(), GL_UNSIGNED_INT, &faces[0]);
glDrawElements(GL_TRIANGLE_STRIP, faces.size(), GL_UNSIGNED_INT, &faces[0]);
glDrawElements(GL_TRIANGLE_STRIP, faces.size(), GL_UNSIGNED_INT, &faces[0]);

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}

Answer

In your case you don't need to bind a buffer at all since you send the index of your buffer directly into glColorPointer().

Think of it as sending a pointer to your buffer directly to OpenGL to read from. You can create more color buffers and simply change your glColorPointer().

glColorPointer(3, GL_UNSIGNED_BYTE, 0, color2);
//...
glColorPointer(3, GL_UNSIGNED_BYTE, 0, color3);

alternatively you can have all colors in one buffer called color and simply pass the right offset. assuming you had 72 components for three colors in a single buffer you can do.

glColorPointer(3, GL_UNSIGNED_BYTE, 0, &color[0]);
//...
glColorPointer(3, GL_UNSIGNED_BYTE, 0, &color[24]);
//...
glColorPointer(3, GL_UNSIGNED_BYTE, 0, &color[48]);

You only need to bind buffers if you pass a null pointer like this

//setup your array buffer
GLuint colorBuffID;
glGenBuffers(1, &colorBuffID);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffID);
glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(unsigned char), color1, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//...
//use your array buffer
glBindBuffer(GL_ARRAY_BUFFER, colorBuffID);
glColorPointer( 3, GL_UNSIGNED_BYTE, 0, (const void*)( 0 ) );
// draw the quad
glBindBuffer(GL_ARRAY_BUFFER, 0);

If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER target (see glBindBuffer) while a color array is specified, pointer is treated as a byte offset into the buffer object's data store. Also, the buffer object binding (GL_ARRAY_BUFFER_BINDING) is saved as color vertex array client-side state (GL_COLOR_ARRAY_BUFFER_BINDING).

Refer https://www.opengl.org/sdk/docs/man2/xhtml/glColorPointer.xml