PDA

View Full Version : glDrawElements() draws only part of my mesh... :-x



rakesh_thp
11-06-2009, 02:22 AM
Hello..

I have recently shifted from Display lists to VBOs... It's a very nice thing in OpenGL i found to render huge amount of data smoothly..

Let me explain you the scenario.. I have maintained a list of triangle objects as


std::map<unsigned int, EObjects*> MeshElements

Thus, MeshElements contains all the triangles generated by the mesh generator. Now inorder to display, i call a routine first as shown below:


mVertexCount = MeshElements.size();

mVertices = new GLfloat[mVertexCount * 6];
mIndices = new GLuint[mVertexCount * 3];

int v_ind = 0, i_ind = 0;

for( std::map<unsigned int, EObjects*>::iterator it = MeshElements.begin(); it != MeshElements.end(); it++ )
{
EObjects *ob = (*it).second;
mVertices[v_ind] = ob->GetNodeOne().GetX(); v_ind++;
mVertices[v_ind] = ob->GetNodeOne().GetY(); v_ind++;
mIndices[i_ind] = ob->GetNodeOneIndex(); i_ind++;
mVertices[v_ind] = ob->GetNodeTwo().GetX(); v_ind++;
mVertices[v_ind] = ob->GetNodeTwo().GetY(); v_ind++;
mIndices[i_ind] = ob->GetNodeTwoIndex(); i_ind++;
mVertices[v_ind] = ob->GetNodeThree().GetX(); v_ind++;
mVertices[v_ind] = ob->GetNodeThree().GetY(); v_ind++;
mIndices[i_ind] = ob->GetNodeThreeIndex(); i_ind++;
}

glGenGuffersARB(BufferSize, BufferName);



where BufferSize and BufferName are declared globally as follows:



enum{
INDEX_OBJECT = 0,
POSITION_OBJECT = 1
};

static const int BufferSize = 2;
static GLuint BufferName[BufferSize];


Below is my rendering code:



glBindBufferARB( GL_ARRAY_BUFFER_ARB, BufferName[POSITION_OBJECT]);
glBufferDataARB( GL_ARRAY_BUFFER_ARB, mVertexCount * 6 * sizeof(float), mVertices, GL_STREAM_DRAW_ARB );
glVertexPointer(2, GL_FLOAT, 0, 0);

glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, BufferName[INDEX_OBJECT] );
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mVertexCount * 3 * sizeof(GLuint), mIndices, GL_STREAM_DRAW_ARB );

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_INDEX_ARRAY);

glDrawElements( GL_TRIANGLES, mVertexCount*3, GL_UNSIGNED_INT, NULL );

glDisableClientState(GL_INDEX_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);


This code is working fine.. But, only the outer part of the mesh is displayed.. the Inner part is not displayed.. I mean to say, if the mesh is of shape "D", it should have filled all the triangles in "D".. Instead of doing so, it is rather, drawing triangles only along the border of the shape "D" Inner part, triangles are not drawn..

Before using glDrawElements(), i was using glDrawArrays().. It also produced the same output.. So I used, GL_POINTS with glDrawArrays(), just to check if it is reading all the points.. In response to this test, it rendered all the points.. But when i said, GL_TRIANGLES, it is not rendering the inner part..

On the other hand, GL_POINTS with glDrawElements() is also rendering only at the boundaries.. Not inner part like glDrawArrays()..

Is something wrong with my code above..?? Please someone guide me properly..

Thanks in advance..

rakesh_thp
11-12-2009, 04:18 AM
Hello,

I'm sorry but is there no one who can give solution or atleast tell me whats the problem and where it lies..??

Thanks

Dark Photon
11-12-2009, 06:30 AM
Below is my rendering code:


...
glEnableClientState(GL_INDEX_ARRAY);
...
Where did you dig up this code? Check this out:

Common Mistakes -- glEnableClientState(GL_INDEX_ARRAY) (http://www.opengl.org/wiki/Common_Mistakes#glEnableClientState.28GL_INDEX_ARR AY.29)

Check out one of these tutorials. It should give you what you need:

* oZone3D.Net Tutorials: OpenGL Vertex Buffer Objects (http://www.ozone3d.net/tutorials/opengl_vbo.php)
* SongHo: OpenGL Vertex Buffer Object (VBO) (http://www.songho.ca/opengl/gl_vbo.html)

DmitryM
11-12-2009, 07:39 AM
Where do you get the geometry?
Some triangles may not be draw due to face culling.
Try to glDisable(GL_CULL_FACE) before drawing.

And add some checks at the end of the loading process to be sure you read the correct amount of data:


assert(i_ind == mVertexCount * 3);
assert(v_ind == mVertexCount * 6);

rakesh_thp
11-13-2009, 12:15 AM
Well that glIndexArrays() was just to try whether it will draw all elements.. It was my last alternative... :)

Anyhow it displays all points..

Displaying triangles with glDrawArrays() also not working.. Producing same output.. I also tried with glDisable(GL_CULL_FACE) as mentioned by one of the sir.. But my fortunate is not that good enough to produce the required out put.. I think no need to check the number of elements after loading.. Coz, the same code with


glDrawArrays( GL_POINTS, 0, mVertexCount * 3);

works fine... I mean all points are displayed.. If i replace it by


glDrawArrays( GL_TRIANGLES, 0, mVertexCount);

produces undesired output.. Only outside boundary is being displayed.. IT's very strange but true... :)

Any more suggestions..??

Thanks anyways

scratt
11-13-2009, 05:32 AM
Your mVertexCount count should be the same in both commands as it is a vertex count, literally.

So you should be using mVertexCount * 3 in both draw commands.

For example : glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) draws two triangles using 4 vertices and glDrawArrays(GL_TRIANGLES, 0, 3) draws one triangle using 3 vertices.

rakesh_thp
11-13-2009, 11:33 PM
oh is it..?? But part of mesh is displyed.. why is that so..?? if thats the case, then is there any method to build the array of vertices..?? like, in my case, I have stored the triangle objects in a list.. and each triangle object is have three members..

NodeOne
NodeTwo
NodeThree

Now if i want to build the vertices for VBO, how can i do it..?? As far as my mind worked i used the following logic.. :)


mVertexCount = MeshElements.size();

mVertices = new GLfloat[mVertexCount * 6];
mIndices = new GLuint[mVertexCount * 3];

int v_ind = 0, i_ind = 0;

for( std::map<unsigned int, EObjects*>::iterator it = MeshElements.begin(); it != MeshElements.end(); it++ )
{
EObjects *ob = (*it).second;
mVertices[v_ind] = ob->GetNodeOne().GetX(); v_ind++;
mVertices[v_ind] = ob->GetNodeOne().GetY(); v_ind++;
mIndices[i_ind] = ob->GetNodeOneIndex(); i_ind++;
mVertices[v_ind] = ob->GetNodeTwo().GetX(); v_ind++;
mVertices[v_ind] = ob->GetNodeTwo().GetY(); v_ind++;
mIndices[i_ind] = ob->GetNodeTwoIndex(); i_ind++;
mVertices[v_ind] = ob->GetNodeThree().GetX(); v_ind++;
mVertices[v_ind] = ob->GetNodeThree().GetY(); v_ind++;
mIndices[i_ind] = ob->GetNodeThreeIndex(); i_ind++;
}


Is there any change i should do there..???

Thanks

scratt
11-14-2009, 02:07 AM
oh is it..?? But part of mesh is displyed.. why is that so..??

Part of the mesh will be displayed as you have asked OpenGL to draw one third of the required vertices.

rakesh_thp
11-17-2009, 10:11 PM
so u mean to say, i got to use,



glDrawArrays( GL_TRIANGLES, 0, mVertexCount*3);


to get the proper output..???