PDA

View Full Version : glDrawElements going out of bounds



nukem
10-18-2003, 06:37 PM
Let me start off my saying I know this is a bit off topic but Ive asked every where else and no one has been able to answer me. I am hoping someone here can.

It was recently suggested to me that I have a central rendering engine for all my other engines. I have sucessfully created this engine but while converting Q3BSPFace to my facetype, VertexBuffer I ran into some errors. The conversion of the facetypes themselves goes fine, its just when rendering them that the program crashes. What is happening is that when I call glDrawElements to render my face the count is set to faces[i]->meshvertcount but there are only lfaces[i].vertcount verts in each face. In plain english meshvertcount is bigger then vertcount for each face, so glDrawElements goes out of bounds. I tryed changing the number of verts to meshvertcount but I get the same results.

Here is the code

This is my Facetype VertexBuffer



struct VertexBuffer
{
~VertexBuffer()
{
if(vert)
{
delete [] vert;
}

if(normal)
{
delete [] normal;
}

if(texcoord)
{
delete [] texcoord;
}

if(lightmapcoord)
{
delete [] lightmapcoord;
}
}

Vect3* vert; //holds all the verts
Vect3* normal; //holds all the normals
Vect2* texcoord; //tolds the texture coords
Vect2* lightmapcoord; //holds the lightmap coords
int count; //the number of items in the top 4 arrays
BYTE colors[4]; //hold the color of the face(RGBA)
UINT* textureID; //the texture ID for the face
UINT* lightmapID; //the lightmap ID for the face
int type; //the type of face it is
int shaderindex; //the index for the shader
int index; //index
int meshvertcount; //the number of mesh verts
};


This is my conversion code



//alloc the memory
facecount = lfacecount;
faces = new VertexBuffer[facecount];

//go threw each face
for(int i=0;i<facecount;i++)
{
//put all the indices of each BSPFace into VertexBuffer
faces[i].meshvertcount = lfaces[i].meshvertcount;
faces[i].index = indexarray[lfaces[i].meshvertindex];

//copy the lightmap and texture IDs over
faces[i].textureID = &amp;texture[lfaces[i].textureID];
faces[i].lightmapID = &amp;lightmaps[lfaces[i].lightmapID];

//the the size of our coords
faces[i].count = lfaces[i].vertcount;

//alloc the memory for all our coords
faces[i].lightmapcoord = new Vect2[faces[i].count];
faces[i].normal = new Vect3[faces[i].count];
faces[i].texcoord = new Vect2[faces[i].count];
faces[i].vert = new Vect3[faces[i].count];

//here is where the problem may be
int k = 0;
//copy the values over
for(int j=lfaces[i].startvertindex;j<(lfaces[i].startvertindex+faces[i].count);j++,k++)
{
faces[i].lightmapcoord[k] = verts[j].lightmapcoord;
faces[i].normal[k] = verts[j].normal;
faces[i].texcoord[k] = verts[j].textcoord;
faces[i].vert[k] = verts[j].pos;
}
}

As you can see above I only copy the values from startvertindex to startvertindex+vertcount over to my face type. I dont understand how this is too few since im getting this number from BSPFace.

This is the code I use to render



//render the faces
void CRender::Render()
{
//go threw all the faces and render them
for(int i=0;i<facecount;i++)
{
//set the texture
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, *faces[i]->textureID);

//set the lightmaps up
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, *faces[i]->lightmapID);

//set the vertex pointer for each face
glVertexPointer(3, GL_FLOAT, sizeof(VertexBuffer), &amp;faces[i]->vert);
//assign texture pass to point to normal texture coords
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexBuffer), &amp;faces[i]->texcoord);
//assign lightmap pass to point
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexBuffer), &amp;faces[i]->lightmapcoord);
//draw it
//the problem is here
glDrawElements(GL_TRIANGLES, faces[i]->meshvertcount, GL_UNSIGNED_INT, &amp;faces[i]->index);
}
}

Since meshvertcount is always bigger then vertcount I always go out of bounds.

If it helps here (http://zonkbonk.virtualave.net/NuclearGraphics.zip) is the complete(linux, should work on any other os though) source.

I really cannt figure this one out, can someone please help me?

Thanks
Nuke

[This message has been edited by nukem (edited 10-19-2003).]

Cyranose
10-19-2003, 12:21 AM
I think the spec is not very clear on this, so it's a common problem: the 'count' parameter to glDrawElements should be the number of indices you're drawing, not the number of vertices or primitives. A variable named "mechvertexcount" may indeed be the number of indices, but it doesn't seem so from the name and your descriptions. I could be wrong.

Either way, if you're passing a count that's equal to or less than the actual number of indices, then you're probably _not_ going off the end of your index array into garbage. In that case, it's more likely that something's wonky with your indices themselves, meaning the index values could be pointing past the end of your vertex array, which could happen when you convert/move your vertices but don't (apparently) add or subtract an offset from the indices.

My suggestion is to write a simple analog to glDrawElements that verifies your contents:

For each index[i] (where 0 <= i < num_indices),
if index[i] >= num_vertices_bound, flag an error

Note: the index values and the num_vertices are all relative to what you bound via glVertexPointer et al, not per "face" or per call to glDrawElements.

Note2: indices should be unsigned. double check that too.

If I'm not too far from the mark in my wild-ass guesses, you'll find something out of whack there and can trace it back to how you build the index lists.

Hope that helps.

Avi


[This message has been edited by Cyranose (edited 10-19-2003).]

nukem
10-19-2003, 07:31 PM
I had basicly the same function before I converted BSPFace to my facetype. So the meshvertcount isnt the error, I think it was just misnamed in the gametutorials tutorial. I just realized that I am only passing one index to glDrawElements, should I be passing an array?

Cyranose
10-19-2003, 08:35 PM
Originally posted by nukem:
I am only passing one index to glDrawElements, should I be passing an array?

Yes.

nukem
10-20-2003, 03:43 PM
I am now passing all the indices from lfaces[i].meshvertindex to lfaces[i].meshvertindex+faces[i].meshvertcount and I get the same results. Here is what I changed the code to




//alloc the memory
facecount = lfacecount;
faces = new VertexBuffer[facecount];

//go threw each face
for(int i=0;i<facecount;i++)
{
//put all the indices of each BSPFace into VertexBuffer
faces[i].meshvertcount = lfaces[i].meshvertcount;
faces[i].indices = new int[lfaces[i].meshvertcount];

int k = 0;
for(int j=lfaces[i].meshvertindex;j<(lfaces[i].meshvertindex+faces[i].meshvertcount);j++,k++)
{
faces[i].indices[k] = indexarray[j];
}

//copy the lightmap and texture IDs over
faces[i].textureID = &amp;texture[lfaces[i].textureID];
faces[i].lightmapID = &amp;lightmaps[lfaces[i].lightmapID];

//the the size of our coords
faces[i].count = lfaces[i].vertcount;

//alloc the memory for all our coords
faces[i].lightmapcoord = new Vect2[faces[i].count];
faces[i].normal = new Vect3[faces[i].count];
faces[i].texcoord = new Vect2[faces[i].count];
faces[i].vert = new Vect3[faces[i].count];

k = 0;
//copy the values over
for(int j=lfaces[i].startvertindex;j<(lfaces[i].startvertindex+faces[i].count);j++,k++)
{
faces[i].lightmapcoord[k] = verts[j].lightmapcoord;
faces[i].normal[k] = verts[j].normal;
faces[i].texcoord[k] = verts[j].textcoord;
faces[i].vert[k] = verts[j].pos;
}
}

nukem
10-20-2003, 06:00 PM
Here is what im concerned about

lfaces[1407].meshvertindex+lfaces[1407]meshvertcount = 15012
lfaces[1407].meshvertcount = 72
lfaces[1407].meshvertindex = 14940
lfaces[1407].vertcount = 20
lfaces[1407].startvertindex = 7636
lfaces[1407].startvertindex+lfaces[1407].vertcount = 7656
lfaces[1407].startvertindex+faces[1407].meshvertcount = 7708

As you can see here meshvertcount is much higher then vertcount. Im not sure what this means. Should the number of indices I have be the same number of verts I have, or the way I have it with the number of meshverts there are. What am I doing wrong?

[This message has been edited by nukem (edited 10-20-2003).]

Cyranose
10-20-2003, 07:44 PM
I have no idea what these numbers mean. All I know is if you're calling

void glDrawElements(
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices)

Then you want "count" to be the number of elements in the _array_ of indices pointed to by "indices." In that array, the actual indices (unsigned integers in this case) must be within the scope of the vertex array bound in the glVertexPointer call or you will either render garbage or get an error.

I'll suggest again you write a function that iterates over the index array you pass to glDrawElements to verify that your indices are what they should be.

for each index[i], bound_vertex_array[index[i]]

should be valid and should be the actual vertex you expect it to be. Note: indices often need to be shifted when translating from one engine to another, depending on how the vertex arrays are built.

Other than that, I can't offer much else. Maybe someone else can, but this isn't really a question for the advanced board at this point. Best of luck,

Avi


[This message has been edited by Cyranose (edited 10-20-2003).]

nukem
10-21-2003, 08:08 PM
The number of indices I have and the count are the same number, so its not that. I think that problem is that I have to shift the indices, how would I figure out how much to shift? Is there some sort of formula I could see that gets x,y,z and creates an indice?

Thanks
nuke

MattS
10-22-2003, 03:20 AM
Looking through the code I can see that your indices are declared as an int (I assume you mean int*). When you pass the indices to glDrawElements you are saying GL_UNSIGNED_INT, which is not true. I think this may be causing your problem. Simply make the "int*" an "unsigned int*", oh yeah and cross fingers.

Matt

nukem
10-22-2003, 11:00 AM
I crossed my fingers and I still have the same error :\

[This message has been edited by nukem (edited 10-22-2003).]

Vasbin
10-23-2003, 07:19 AM
As i understand You load Quake3 maps, i can't help You, but i can give You a link to some examples: http://users.ox.ac.uk/~univ1234

May be this helps.
Vasbin