Sign in to follow this  
silvermace

Vanilla Vertex Arrays Crash For No Reason.

Recommended Posts

silvermace    634
Hi all, FYI, im running XPSP2, VC2003.NET, Radeon 9500 Pro, Cat 4.9. and im using C++ and nVidia's Cg 1.2 so here's the problem: when i load my terrain data as triangles it crashes when i render. the error is to the tune of "Access Violation 0x0000005 when attempting to read location 0x00000000" now the obvious thing there is to check that i'm not passing in any null pointers, i did. i disabled everything but vertex arrays and rendered, still got the problem. next thing i checked was that verticies and tc's etc were valid, they were. then i checked that all my indices were in range... and they are. odd stuff: there are around 7900 polygons, so ~23000 verts.. but when i render LESS than 5913 verticies ie. glDrawElements( GL_TRIANGLES, 5912, ... ) it renders without crashing. i check the index values for indicies past 5912, they are all valid. if you need code, i can supply, i can't really describe the problem any more than that until anyone wants some specifics. Thanks in Advance, Danu

Share this post


Link to post
Share on other sites
silvermace    634
To make things interesting....
if i break the glDrawElements call into a loop
ie. instead of
glDrawElements( GL_TRIANGLES, mesh.polyCount * 3, GL_UNSIGNED_INT, &mesh.polys[0] );
i do this:
for(int i=0; i<mesh.polyCount; i++)
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, &mesh.polys[i]);
it works.

WTF.

Share this post


Link to post
Share on other sites
overflowed_    194
It's not a vanilla vertex array if you're using a vector to store the data. I'm kinda wondering WHY you're doing that in the first place...

Try putting it all into a simple array:

eg:
Polygon *polys;

and somewhere in your init routines:
polys = new Polygon[polyCount];

And then just calling:
glDrawElements(GL_TRIANGLES, mesh.polyCount * 3, GL_UNSIGNED_INT, mesh.polys);

Betcha it'll work.

Share this post


Link to post
Share on other sites
silvermace    634
Quote:
Original post by overflowed_
It's not a vanilla vertex array if you're using a vector to store the data. I'm kinda wondering WHY you're doing that in the first place...

Try putting it all into a simple array:

eg:
Polygon *polys;

and somewhere in your init routines:
polys = new Polygon[polyCount];

And then just calling:
glDrawElements(GL_TRIANGLES, mesh.polyCount * 3, GL_UNSIGNED_INT, mesh.polys);

Betcha it'll work.
Vector is guaranteed by the standard to provide contiguous memory, betcha it won't make a difference.

PS. i will try it any way!

Share this post


Link to post
Share on other sites
silvermace    634
did element-by-element copy into a plane jane array, still crashed in the same place. here's the exact message
Unhandled exception at 0x692ae676 in Ignite.exe: 0xC0000005: Access violation reading location 0x00000000.
looks like a good 'ol NULL pointer exception, but i dunno where.. as i said all the data looks valid.
/continues to search..

Share this post


Link to post
Share on other sites
overflowed_    194
Try setting up some breakpoints ahead of the code you think is causing the problem, then put some watches on any possible pointers near the problem section.

Also, if you can post the entire vertex array section (everything for this particular render), there might be something as simple as a typo causing a problem.

Share this post


Link to post
Share on other sites
zedzeek    529
try this

glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glClientActiveTexture( GL_TEXTURE0 );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glClientActiveTexture( GL_TEXTURE1 );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );

and then draw it
u wont see anythihng but hopefully it wont crash, then comment out
glDisableClientState( GL_VERTEX_ARRAY ); + run it again etc

Share this post


Link to post
Share on other sites
silvermace    634
Quote:
Original post by overflowed_
Try setting up some breakpoints ahead of the code you think is causing the problem, then put some watches on any possible pointers near the problem section.

Also, if you can post the entire vertex array section (everything for this particular render), there might be something as simple as a typo causing a problem.
its crashing INSIDE the OpenGL driver, not in my code. ie. exception comes from
atioglxx.dll!692ae676()


i disabled everything but vertex arrays, still crashes, but when i disable everything, its fine. (nothing on the screen though :p)

my renderer flush function if anyone cares:

void RRenderer::flush()
{
CVector3 *ve = 0;
int r = 0;
int i = 0;
int normArrayActive = 0;

// reset client states
for(int i=0; i<8; i++)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
glActiveTexture( GL_TEXTURE0_ARB+i);
glDisable( GL_TEXTURE_2D );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
}

glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );

glCullFace( GL_FRONT );
glEnable( GL_CULL_FACE );
glMatrixMode( GL_MODELVIEW );

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

RCgInfo& cgc = CgContext;

//iterate through rendering objects
for( uint o=0; o<objects.size(); o++ )
{
RObject *co = &objects[o];
//iterate through meshes of current object
for( uint m=0; m<co->meshes.size(); m++ )
{
RMesh *cm = &co->meshes[m];
RPolygon* p = cm->polybuffer.get(0); //returns polybuffer.polys[0]
RVertexBuffer& vb = cm->vertbuffer;

RShader *sh = getShader( cm->shader );

if( sh == NULL && (Renderer.settings & GENERATION_GL15) ) //some kind of error
continue;

glPushMatrix();

if( cm->transfomMat != NULL )
glMultMatrixf( cm->transfomMat->entries );

if( sh != NULL )
{
//bind the decal texture
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glActiveTexture( GL_TEXTURE0_ARB);

// bind the texture coordinates
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, (GLvoid*) vb.getTc( RVertexBuffer::TEXCOORD0, 0) );
}

if( Renderer.settings & GENERATION_GL15 )
bindShader(cm->shader);

if( vb.get(RVertexBuffer::NORMAL, 0) ) {
glEnableClientState( GL_NORMAL_ARRAY );
normArrayActive = 1;

glNormalPointer( GL_FLOAT, 0, (GLvoid*) vb.get(RVertexBuffer::NORMAL, 0) );
}

if( vb.get(RVertexBuffer::TANGENT, 0) && dx9 ) { //send the tangent data through the color arrays
glColorPointer( 3, GL_FLOAT, 0, (GLvoid*) vb.get(RVertexBuffer::TANGENT, 0) );
} else {
glDisableClientState( GL_COLOR_ARRAY );
}

glPushAttrib( GL_LIGHTING_BIT );

if( cm->flags & RMesh::MESH_NOLIGHT ) {
glDisable( GL_LIGHTING );
}

int numElems = cm->polybuffer.polycount * 3;

CVector3 *pVerts = vb.get(RVertexBuffer::VERTEX, 0);

glVertexPointer( 3, GL_FLOAT, 0, (GLvoid*) pVerts );
glDrawElements( GL_TRIANGLES, numElems, GL_UNSIGNED_INT, (GLvoid*) p); // crashes here for no reason.

glPopAttrib();

glPopMatrix();

unbindShader(cm->shader);

}
}

glDepthFunc( GL_LEQUAL );
}



Share this post


Link to post
Share on other sites
silvermace    634
Hi Guys, i got it working, don't know what was wrong, i made a checklist on paper and rewrote the flush function :-/

thanks heaps to everyone that posted, rate++
-Danu

Share this post


Link to post
Share on other sites
zedzeek    529
>>i disabled everything but vertex arrays, still crashes, but when i disable everything, its fine. (nothing on the screen though :p)<<

though it might work, the problem was the you were trying to access a vertex that wasn't in the array;

quasi code
float verts[1][3];
glVertexPointer( 3, verts );
glDrawElement(0); will work but drawelement(1) wont. (*)

though with float verts[2][3]; both will work

(*) in this case cause of how compilers allocate memory both of these most likely will work (but in theory only the first should)

Share this post


Link to post
Share on other sites
silvermace    634
Quote:
Original post by zedzeek
>>i disabled everything but vertex arrays, still crashes, but when i disable everything, its fine. (nothing on the screen though :p)<<

though it might work, the problem was the you were trying to access a vertex that wasn't in the array;

quasi code
float verts[1][3];
glVertexPointer( 3, verts );
glDrawElement(0); will work but drawelement(1) wont. (*)

though with float verts[2][3]; both will work

(*) in this case cause of how compilers allocate memory both of these most likely will work (but in theory only the first should)


no, definatly not that, that was the first thing i checked, also note that i tried replacing it with a for loop, and that workd (See my first reply)

Share this post


Link to post
Share on other sites
Solias    564
Quote:
Original post by silvermace
To make things interesting....
if i break the glDrawElements call into a loop
ie. instead of
glDrawElements( GL_TRIANGLES, mesh.polyCount * 3, GL_UNSIGNED_INT, &mesh.polys[0] );
i do this:
for(int i=0; i<mesh.polyCount; i++)
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, &mesh.polys[i]);
it works.

WTF.


These are actually doing different things. The first one starts at element 0 and reads 3 * polyCount elements. The second one starts at element 0 and reads 3, then it starts at element 1 and reads 3, etc. It does this polyCount times. This means it only ever got to element polyCount + 2 (last one is i = polyCount - 1 and reads 3).

My guess is that the array actually wasn't polyCount * 3 elements long and you were trying to read past the end of it. But it could also have been any number of other things, hard to say without looking at more code.

In any case I'm glad you got it working, these memory errors can be subtle and really annoying.

Share this post


Link to post
Share on other sites
silvermace    634
Quote:
Original post by Solias
Quote:
Original post by silvermace
To make things interesting....
if i break the glDrawElements call into a loop
ie. instead of
glDrawElements( GL_TRIANGLES, mesh.polyCount * 3, GL_UNSIGNED_INT, &mesh.polys[0] );
i do this:
for(int i=0; i<mesh.polyCount; i++)
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, &mesh.polys[i]);
it works.

WTF.


These are actually doing different things. The first one starts at element 0 and reads 3 * polyCount elements. The second one starts at element 0 and reads 3, then it starts at element 1 and reads 3, etc. It does this polyCount times. This means it only ever got to element polyCount + 2 (last one is i = polyCount - 1 and reads 3).

My guess is that the array actually wasn't polyCount * 3 elements long and you were trying to read past the end of it. But it could also have been any number of other things, hard to say without looking at more code.

In any case I'm glad you got it working, these memory errors can be subtle and really annoying.


yea i thought that too at first, but i was right to begin with :)
say
polyCount = 5
polyCount * 3 = 15 verts

for i<polyCount
DrawElements(3, p[i]) // 3 verts

5 calls to drawelements * 3 verts per call = 15 verts.


[Edited by - silvermace on October 21, 2004 10:45:02 PM]

Share this post


Link to post
Share on other sites
zedzeek    529
solias is correct, they aint the same thing
i just wrote a small test app to prove it


int polys[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};

const int polyCount = 5;

void log_elements( int count, int *indices )
{
for ( int i=0; i<count; i++ )
printf( "%d ", indices[i] );
}

void test()
{
//glDrawElements( GL_TRIANGLES, polyCount * 3, GL_UNSIGNED_INT, &polys[0] );
log_elements( polyCount * 3, &polys[0] );

printf( "\n" );

for( int i=0; i<polyCount; i++ )
{
//glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, &mesh.polys[i]);
log_elements( 3, &polys[i] );
}

printf( "\n" );

}


the output is
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 3 2 3 4 3 4 5 4 5 6
hence the crash in the first version

--- taken from the opengl spec ---

The effect of
DrawElements (mode, count, type, indices);
is the same as the effect of the command sequence
if (mode, count, or type is invalid )
generate appropriate error
else { Begin(mode);
for (int i = 0; i < count ; i++)
ArrayElement(indices[i]);
End();
}

Share this post


Link to post
Share on other sites
Ysaneya    1383
Quote:

These are actually doing different things. The first one starts at element 0 and reads 3 * polyCount elements. The second one starts at element 0 and reads 3, then it starts at element 1 and reads 3, etc. It does this polyCount times. This means it only ever got to element polyCount + 2 (last one is i = polyCount - 1 and reads 3).


If i'm not mistaken, his original code was correct:

Quote:

To make things interesting....
if i break the glDrawElements call into a loop
ie. instead of
glDrawElements( GL_TRIANGLES, mesh.polyCount * 3, GL_UNSIGNED_INT, &mesh.polys[0] );
i do this:
for(int i=0; i<mesh.polyCount; i++)
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, &mesh.polys[i]);
it works.


...knowing that..

Quote:

struct Polygon {
uint a, b, c;
};

vector<Polygon> polys;


Take 3 triangles as an example:
{0 1 2} {3 4 5} {6 7 8}

The first drawElements will draw 3*3=9 elements: 0 1 2 3 4 5 6 7 8.

The second drawElements will be called 3 times, with 3 elements each:
- 3 elements starting at &mesh.polys[0], hence 0 1 2.
- 3 elements starting at &mesh.polys[1], hence 3 4 5.
- 3 elements starting at &mesh.polys[2], hence 6 7 8.
Result: 0 1 2 3 4 5 6 7 8, as in the first method.

The problem was likely elsewhere..

Y.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this