I'm trying out the Vertex Arrays stuff but for some reason the glDrawElements command doesn't draw anything for me. I can draw using glBegin/glEnd and glDrawElements in between, but glDrawElements doesn't work. Here's a code snippet:
These arrays get set up in the constructor:
double points[100];
GLint indices[50];
for (int i=0; i < 50; i++){
points[2*i] = radius * cos(i*2*PI/50);
points[2*i + 1] = radius * sin(i*2*PI/50);
indices[i] = i;
}
Working code using only the points array with glArrayElement:
void GLCircle::draw()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, points);
glBegin(GL_POLYGON);
for (int i=0; i < 50; i++){
glArrayElement(i);
}
glEnd();
}
Also working code, using points array, specific indices accessed via indices array:
void GLCircle::draw()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, points);
glBegin(GL_POLYGON);
for (int i=0; i < 50; i++){
glArrayElement(indices[i]);
}
glEnd();
}
NON-working code, attempting to use glDrawElements:
void GLCircle::draw()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, points);
glDrawElements(GL_POLYGON, 4, GL_INT, indices);
}
Any advice? It's not entirely necessary for me to use it at this point, but it's disturbing that it doesn't work...
The 2nd parameter of glDrawElements is count, so shouldn't 4 be the numbers of indices (50)?
The parameters for
glDrawElements()
are as follows.. :
1st [mode] parameter is what kind of primitive to render.
2nd [count] parameter should be the number of elements to render. ie. the number of vertices
3rd [type] parameter should be the type of the value in the 4th parameter.. can ONLY be either
GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT or GL_UNSIGNED_INT
4th [indices] parameter is a pointer to where the indices are stored.
You can read more on this here..
I just faced the same problem.
Try GL_UNSIGNED_INT
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, indices);
Related
When I am trying to draw a line using legacy openGL , lines are drawing fine.
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINE_LOOP);
for (size_t idx = 0; idx < m_spline_cvs.size(); idx++) {
glVertex2f(m_cv_positions[0][idx].x,m_cv_positions[0][idx].y);
}
glEnd();
glDisable(GL_LINE_STIPPLE);
Correct Line Loop in Stipple mode
But when I am trying to use **glDrawArrays**. Something is going wrong?
std::vector <float> cv_tracker_target_line;
for (size_t idx = 0; idx < m_spline_cvs.size(); idx++) {
cv_tracker_target_line.push_back(m_cv_positions[0][idx].x);
cv_tracker_target_line.push_back(m_cv_positions[0][idx].y);
}
glEnable(GL_LINE_STIPPLE);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &cv_tracker_target_line[0]);
glDrawArrays(GL_LINE_LOOP, 0, cv_tracker_target_line.size());
glDisable(GL_LINE_STIPPLE);
glDisableClientState(GL_VERTEX_ARRAY);
Wrong Lines drawn not in loop
What am I doing wrong here?
The 3rd argument in glDrawArrays is the number of vertices, but not the number of elements (floats) in the array. Each vertex coordinate consists of 2 components (x, y):
glDrawArrays(GL_LINE_LOOP, 0, cv_tracker_target_line.size());
glDrawArrays(GL_LINE_LOOP, 0, cv_tracker_target_line.size() / 2);
I'm attempting to add a vertex buffer to the Mesh.cpp file of the pixel city procedural city-generating program. Part of the current code looks like this:
for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) {
glBegin (GL_QUAD_STRIP);
for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) {
glTexCoord2fv (&_vertex[*n].uv.x);
glVertex3fv (&_vertex[*n].position.x);
}
glEnd ();
}
This draws textures onto the rectangular sides of some of the buildings. Just going off the VBO tutorials I've found online, I attempt to convert this to use a vertex buffer like so (I store vboId in Mesh.h):
for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) {
void * varray = (char *) malloc(sizeof(GLfloat)*5*qsi->index_list.size());
GLfloat *p = (GLfloat*)varray;
int counter = 0;
for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) {
memcpy(&p[counter+0],&_vertex[*n].uv.x, sizeof(GLfloat)*2);
memcpy(&p[counter+2],&_vertex[*n].position.x, sizeof(GLfloat)*3);
counter+=5;
}
glGenBuffersARB(1, &vboId);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*5*qsi->index_list.size(), p, GL_STATIC_DRAW_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat)*5, (GLfloat*)0);
glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*5, (GLfloat*)2);
glDrawArrays(GL_QUAD_STRIP, 0, qsi->index_list.size());
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
free(varray);
}
However, this code simply doesn't work. Nothing is rendered. Sometimes, when I mess with the parameters into glTexCoordPointer or glVertexPointer, I really skewed/garbage data drawn on the screen (or the program crashes), but nothing that has even come close to remotely working.
Your vertex pointer is wrong. When using VBOs, the pointer is interpreted as the byte offset relative to the currently bound buffer. So, you need sizeof(GLfloat)*2 bytes as offset.
glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*5, (char*)0 +sizeof(GLfloat)*2);
As a side note: you could save the additional data copy if you would create the VBO with the correct size but NULL as the data pointer (which basically creates the data storage) and memory-map it with glMapBuffer(), completely avoivding the malloc()ed temporary buffer you use.
I use vectors to store vertex and normal data
vector<float> vertex;
vector<float> normal;
For example:
normal.push_back(-1);
normal.push_back(0);
normal.push_back(0);
vertex.push_back(BARRIER_RADIUS);
vertex.push_back(POLE_HEIGHT);
vertex.push_back(-POLE_RADIUS);
for (int i = POLE_POINTS, i >= 0; i--)
{
//add more vertex
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &vertex[0]);
glNormalPointer(GL_FLOAT, 0, &normal[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, vertex.size());
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
//Add some more + Draw some thing else the same way
What I've got from this is nothing. it doesn't draw anything onto the screen.
The previous version, which works, is as follow:
glNormal3f(-1, 0, 0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(BARRIER_RADIUS, POLE_HEIGHT, -POLE_RADIUS);
for ()
{
//add more vertex
glVertex3f(........);
}
glEnd();
//draw more the same way
Point me to where I've gone wrong.
You have defined vertex as a vector of float, but a geometric vertex consists of 3 floats, so that's a recipe for confusion. The number of vertices is not vertex.size(), but rather one third of that. I'm not sure if that's your only problem, but it's a problem.
You should have the same number of normals as vertices.
I have a vector of floats, this vector describes a set of triangles each triangle is described using 18 floats, first 3 are the first vertex, next 3 decribes the normal of the last vertex, and so on 3 times until describe each triangle.
i am using
std::vector< GLfloat >
to store all numbers, and this is my code to render the triangles
void Visualizer::draw3dModel()
{
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 6 * sizeof(GLfloat), this->vertexes->data() + 3);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), this->vertexes->data());
glPushMatrix();
glScalef(0.05f, 0.05f, 0.05f);
glColor3f(1,1,1);
glDrawArrays(GL_TRIANGLES, 0, this->vertexes->size());
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
this code actually works, but in certain moments I recreate the vector of floats with new triangles, it can be more or less triangles
before creating new triangles I clear the vector of vertexes, using this functions
std::vector< GLfloat >* MarchingCubesThread::getTriangles(float minvalue_scale)
{
this->generateTriangles(minvalue_scale);
for(unsigned int i=0; i < this->num_triangles; i++)
{
for(int j=0; j < 3; j++)
{
this->vertexes.push_back(this->triangles[i].p[j].x);
this->vertexes.push_back(this->triangles[i].p[j].y);
this->vertexes.push_back(this->triangles[i].p[j].z);
this->vertexes.push_back(this->triangles[i].norm.x);
this->vertexes.push_back(this->triangles[i].norm.y);
this->vertexes.push_back(this->triangles[i].norm.z);
}
}
return &(this->vertexes);
}
void MarchingCubesThread::generateTriangles(float minvalue_scale)
{
this->vertexes.clear();
this->triangles.clear();
this->triangles = MarchingCubesDataset(this->dataset->getMaxVal() * minvalue_scale, *(this->dataset), LinearInterp, this->num_triangles);
}
After playing around creating a new set of new triangles, the OpenGL render updates the mesh well, but in certain moments, I get some garbage triangles, and/or triangles that are from last iteration, and they should be cleared by calling this:
this->vertexes.clear();
this->triangles.clear();
here some screenshots taken in consecutive times:
any clues about what is happening here?, thank you
PD: for a complete source code, this is the public git repository on github:
https://github.com/joecabezas/MemoriaJoeCabezasCode/tree/visualizer
glDrawArrays expects not count of floats in your buffer, but count of vertices.
So correct call should be:
glDrawArrays(GL_TRIANGLES, 0, this->vertexes->size() / 6);
By letting glDrawArrays to draw 6 times more vertices you were displaying garbage after end of valid vector data, and sometimes it was data from previous iteration.
I recently switched from intermediate mode and have a new rendering process. There must be something I am not understanding. I think it has something to do with the indices.
Here is my diagram: Region->Mesh->Polygon Array->3 vertex indices which references the master list of vertices.
Here my render code:
// Render the mesh
void WLD::render(GLuint* textures, long curRegion, CFrustum cfrustum)
{
int num = 0;
// Set up rendering states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Set up my indices
GLuint indices[3];
// Cycle through the PVS
while(num < regions[curRegion].visibility.size())
{
int i = regions[curRegion].visibility[num];
// Make sure the region is not "dead"
if(!regions[i].dead && regions[i].meshptr != NULL)
{
// Check to see if the mesh is in the frustum
if(cfrustum.BoxInFrustum(regions[i].meshptr->min[0], regions[i].meshptr->min[2], regions[i].meshptr->min[1], regions[i].meshptr->max[0], regions[i].meshptr->max[2], regions[i].meshptr->max[1]))
{
// Cycle through every polygon in the mesh and render it
for(int j = 0; j < regions[i].meshptr->polygonCount; j++)
{
// Assign the index for the polygon to the index in the huge vertex array
// This I think, is redundant
indices[0] = regions[i].meshptr->poly[j].vertIndex[0];
indices[1] = regions[i].meshptr->poly[j].vertIndex[1];
indices[2] = regions[i].meshptr->poly[j].vertIndex[2];
// Enable texturing and bind the appropriate texture
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textures[regions[i].meshptr->poly[j].tex]);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &vertices[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].u);
// Draw
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices);
}
}
}
num++;
}
// End of rendering - disable states
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Sorry if I left anything out. And I really appreciate feedback and help with this. I would even consider paying someone who is good with OpenGL and optimization to help me with this.
There is no point in using array rendering if you're only rendering 3 vertices at a time. The idea is to send thousands through with a single call. That is, you render a single "Polygon Array" or "Mesh" with one call.