Skip to main content
gamedev.net
🔒 Locked

glDrawElements

Started by AfroFire 9 replies 3.7k views
Original Post
AfroFire
AfroFire
I'm having a difficult time getting my glDrawElements(...) to draw properly. What I do is load my map data in to an array that looks like this


GLdouble **vertexArray;
vertexArray = new GLdouble*[map_info->w * map_info->h];

//... blah blah

    for(int k = 0; k < map_info->h; k++)
    {   
        for(int i = 0; i < map_info->w; i++)
        {
                vertexArray[i+(k*map_info->h)] = new GLdouble[3]; 
                vertexArray[i+(k*map_info->h)][0] = i; // x 
                vertexArray[i+(k*map_info->h)][1] = avg*INTENSITY; // y (height)
                vertexArray[i+(k*map_info->h)][2] = k; // z
        }
    }

Now, this array is fine - If I place the vertexes in to a display list they draw out perfectly. Now I create an index array:

    GLubyte *indexArray;
    indexArray = new GLubyte[map_info->w * map_info->h];

    for(int k = 0; k < map_info->h; k++)
    {   
        for(int i = 0; i < map_info->w; i++)
        {
                vertexArray[i+(k*map_info->h)] = new GLdouble[3]; 
                vertexArray[i+(k*map_info->h)][0] = i; // x 
                vertexArray[i+(k*map_info->h)][1] = avg*INTENSITY; // y (height)
                vertexArray[i+(k*map_info->h)][2] = k; // z

                indexArray[i+(k*map_info->h)] = i+(k*map_info->h); // Index Array...
        }
    }

and every frame I call

    glVertexPointer((map_info->w-1) * (map_info->h-1)*3, GL_DOUBLE, 0, vertexArray);

    glDrawElements(GL_POINTS, (map_info->w * map_info->h), GL_UNSIGNED_BYTE, indexArray);


And the program crashes a glDrawElements. I've been working on this for days and I am at my wits end, if anyone could help I would be mighty greatful. Thank you mucho.
AfroFire | Brin"The only thing that interferes with my learning is my education."-Albert Einstein
smitty1276
smitty1276
I have to go to bed, so this isn't the thorough analysis that your looking for... but will your indices fit in an unsigned byte (0-255)?

EDIT:

Also, the vertex array needs to be just that.. an ARRAY... you are giving it an array of arrays. Instead of allocating an array of 3 bytes to each vertex, just allocate the entire array at the beginning in contiguous memory.

GLdouble *vertexArray = new GLdouble[width*height*3];

Another problem...

glVertexPointer's first argument should be 3 (3 components, x, y, z... type GL_DOUBLE... with 0 space between them).

OK, now I'm going to bed. Sorry if I missed something.
Mr Lane
Mr Lane
I am surpized you dont need: glEnableClientState(GL_VERTEX_ARRAY);


EDIT: This was a thread I made some time ago when I was starting with vertex arrays. I learned more in this than anywhere else.

http://www.gamedev.net/community/forums/topic.asp?topic_id=326648
Gorax
Gorax
Quote:
Original post by Mr Lane
I am surpized you dont need: glEnableClientState(GL_VERTEX_ARRAY);


EDIT: This was a thread I made some time ago when I was starting with vertex arrays. I learned more in this than anywhere else.

http://www.gamedev.net/community/forums/topic.asp?topic_id=326648


It wouldn't crash if that was missing, it just wouldn't work.
xinvar
xinvar
smitty1276 is right about the two problems. You are using an array of arrays, which 1. makes indexing (possibly) slower and takes more memory, and 2. glVertexPointer takes a pointer to the vertices, not a pointer to pointers, and it (possibly) crashed your program. glVertexPointer reads in the data, and when glDrawElements(GL_POINTS,...) executes on the data, it crashed.

ps if you had spent 10 minutes reading the specifications, you wouldn't have made this mistake.
AfroFire
AfroFire
I did enable GL_VERTEX_POINTER

and I have had this working before, but I made the mistake of overwriting it without backing it up when I had another idea. I've spent many hours reading over everything and simply overlooked the "3" that was missing.

Anyways at the moment with those changes made - now my points are drawing in an incorrect way - is there anything else?

edit:

Actually what it appears to be doing is drawing all my points directly on a line that is about 128 vertexes long (my image is 128x128)

So I have 128 x 128 squished in to 128 x 1. But still I have 128 * 128 points.
AfroFire | Brin"The only thing that interferes with my learning is my education."-Albert Einstein
AfroFire
AfroFire
Im not understanding how an index array will comprehend which points it needs to load.


Theoretically speaking (as far as I can tell (which isn't much apparently)) if all I do is create an indexArray of 128*128 - and go from 1 to 16384 then it should just automatically draw 1 GL_POINT every 3 #s in my vertexArray. Right?

AfroFire | Brin"The only thing that interferes with my learning is my education."-Albert Einstein
dimebolt
dimebolt
Quote:
Original post by AfroFire
Im not understanding how an index array will comprehend which points it needs to load.


Theoretically speaking (as far as I can tell (which isn't much apparently)) if all I do is create an indexArray of 128*128 - and go from 1 to 16384 then it should just automatically draw 1 GL_POINT every 3 #s in my vertexArray. Right?


First, as pointed out before, you should change the type of your index array to unsigned short (unsigned byte is not big enough to fit 16384). Secondly, also pointed out before, I would not use a GLdouble **vertexArray; but a simple single dimensional array: GLdouble *vertexArray; and fill it using:
vertexArray[i * 3 +(k * map_info->h * 3)]vertexArray[i * 3 +(k * map_info->h * 3) + 1]vertexArray[i * 3 +(k * map_info->h * 3) + 2]

And finally, if you fill the indices with numbers going up from 0 to 16384, there is absolutely no added value to using them, as they will just draw all the vertices in line, just as your example without indices. You should write a routine that detects duplicate vertices (i.e. vertices that share the same x, y, z coordinates, the same normal, texcoords, etc.), creates a new vertex array (and normal array, texcoord array, etc.) and generates an index list of width x height indices that mimics the original array by pointing to the new list without duplicates. I can post my own code that does exactly that if you wish, but it's old and not very well written, so I doubt if it will be much use :)

Tom
AfroFire
AfroFire
Tom - Code would be helpful

By the way - I adjusted the arrays earlier, and it didn't help much - however I took the advice of changing from ubyte to ushort and it finished showing ALL of my vertices - thank you for that - however it draws them very similar to a cube - i thought it was kind of funny so here is a picture:

1021x767


Again, thanks a lot everyone, almost done with this durned thing.

AfroFire | Brin"The only thing that interferes with my learning is my education."-Albert Einstein
AfroFire
AfroFire
Alright, it's fixed - After adjusting the way I was filling the array to what you said Tom

Major kudos to you man - thanks a bunch :)

Another major thing was, as posted above, the changing to unsigned short.
AfroFire | Brin"The only thing that interferes with my learning is my education."-Albert Einstein
dimebolt
dimebolt
Quote:
Original post by AfroFire
Tom - Code would be helpful

By the way - I adjusted the arrays earlier, and it didn't help much - however I took the advice of changing from ubyte to ushort and it finished showing ALL of my vertices - thank you for that - however it draws them very similar to a cube - i thought it was kind of funny so here is a picture:

1021x767


Again, thanks a lot everyone, almost done with this durned thing.

Ok, then here it goes:
typedef std::vector<math::vector3D> vector_array;vector_array        org_vertices;vector_array        org_normals;vector_array        new_vertices;vector_array        new_normals;std::vector<ushort> new_indices;bool   found;ushort idx, i, j;if (org_vertices.size() != org_normals.size())    exit_with_error("vertex array and normal array not of same size!");// detect duplicates and fill the new buffers with unduplicated verticesfor (i = 0; i < org_vertices.size(); i++){    found = false;    for (j = 0; j < new_vertices.size(); j++)    {	// check if both vertex and normal are equal:	if (org_vertices == new_vertices[j] &&            org_normals == new_normals[j])	{	    found = true;	    // duplicate found at index 'j' of the new arrays	    idx   = j;	    break;	}    }	    if (!found)    {        // the index should be the index of the new vertex	idx = new_vertices.size();        // no duplicate found, add vertex and normal to the new arrays        new_vertices.push_back(org_vertices);        new_normals.push_back(org_normals);    }    // assign the index    new_indices.push_back(idx);}

I took the liberty of making it a bit more readable, but that means it may not be entirely correct anymore if I messed up something. It might also be possible to do it more efficiently, this algorithm is O(N^2). Anyway, this should make the idea clear enough.

Tom

[Edited by - dimebolt on September 27, 2005 5:57:39 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.