Archived

This topic is now archived and is closed to further replies.

MARS_999

Vertex Arrays problem with rendering correctly

Recommended Posts

MARS_999    1627
I am now using Vertex Arrays to render my terrain engine. I have a question about when I go to use glDrawArrays() my terrain is all FUBAR! Now when I initialize the terrain data I am not doing this 1,3,5,7 0,2,4,6 for vertex data. I am using GL_TRIANGLE_STRIP. I am just putting data in my struct
struct Vertex
{
float x;
float y;
float z;
};
Vertex terrain[256][256] = {0};

for(int z = 0; z < 256; z++)
{
for(int x = 0; x < 256; x++)
{
terrain[z][x].x = x;
terrain[z][x].y = //height value for height map

terrain[z][x].z = z;
}
}
shouldn''t I be aligning the data so that the next element terrain[0][0] = vertex 0; terrain[0][1] = vertex 1; terrain[0][2] = vertex 2; terrain[0][3] = vertex 3; terrain[0][4] = vertex 0; ect... Thanks

Share this post


Link to post
Share on other sites
Trienco    2555
"for(int z = 0; z < 256; z++) {
for(int x = 0; x < 256; x++) {"

*cough* never use strips if you dont know exactly what youre doing. in a strip every new vertex will form a triangle with the last two points (the last edge), so obviously you cant just jump from one edge to the other and even less can you just traverse one single row at a time and expect any meaningful results.

you really have to understand how strips work first before you try to do something, thats in addition requiring a few tricks to even work as a strip. take a piece of paper, make a lot of dots and connect them like a strip would... then after finally getting a light to medium headache, begin asking yourself why the hell it has to be strips, when the speed difference is minor anyway and using indexed arrays would be a much better thing to spend time on.

just dont throw a lot of vertices in any random order at your strip and expect it to work. work it out on paper first or go through the whole experience. every second row upside down, jagged edges, total garbage on screen, a few access violations, a terrain that first looks ok but has strange lines all over the place, small vertical triangles where the terrain builds a small gap, ect. etc.

so i would really suggest you forget strips for now, first do the less worthless (compared to the work) optimizations and if you really need 84 instead of 83.5 fps you can still change to strips.

else, have a very close look at strips (changing winding order) and degenerate triangles, because thats the only way you will ever get to render more than one row in a single strip.

Share this post


Link to post
Share on other sites
MARS_999    1627
I do know how to use strips I have them working in my engine with hard coded glVertex3f() using loops. I am trying to convert it over to arrays to speed up my engine beings I have gone from 75fps to 22fps using multitexturing. Sorry if I come off as rude but I do know how to use them when I use glVertex3f() I am asking why my terrain mesh looks like long white blocks of lines? Is it because I don't have the vertex data arranged so terrain[0][0].x terrain[0][0].y terrain[0][0].z = point 0
on the strip vertex and
terrain[0][1].x terrain[0][1].y terrain[0][1].z = point 1 terrain[0][2].x terrain[0][2].y terrain[0][1].z = point 2 terrain[0][3].x terrain[0][3].y terrain[0][3].z = point 3

terrain[0][4].x terrain[0][4].y terrain[0][4].z = point 0 on next triangle???
and so forth

Or is it because I am using glDrawArrays() that I am getting garbage?

Also if I am to use glDrawElements() how can I get to use floats? I don't want to use GL_UNSIGNED_INT for my data type!

[edited by - Mars_999 on August 10, 2003 9:31:32 PM]

Share this post


Link to post
Share on other sites
skremon    122
quote:
Also if I am to use glDrawElements() how can I get to use floats? I don''t want to use GL_UNSIGNED_INT for my data type!

Please see the Red Book for details, glDrawElements only takes an index pointer that contains integer indices of type GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT OR GL_UNSIGNED_INT only.

quote:
Or is it because I am using glDrawArrays() that I am getting garbage?

If your loop works but vertex array doesn''t then most probably you didn''t initialize your vertex array properly!

Share this post


Link to post
Share on other sites
Trienco    2555
try to drop 2d arrays and store the vertices in one straight array. might not be the reason if you can still see any pattern and im not sure if the compiler would turn it into a float*[] or if it would just index differently.

also: drawelements wants the info about your index-array and passing floats as index wouldnt make that much sense, would it? you give the info about your vertex array when you set the vertex pointer.

if you use drawarrays and pass the array the way you set it up, then no kind of primitive will work. what you are doing seems to be this:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

if you pass them in this order then all your getting is garbage. a strip would do this:

make a tri from 1/2/3 (which are on one line), then 2/3/4, again one line, then 3/4/5, a completely wrong triangle, maybe even facing the wrong direction. try using glvertex in the same order as you store them in the array and you should get the same garbage.

Share this post


Link to post
Share on other sites
MARS_999    1627
quote:
Original post by Trienco
try to drop 2d arrays and store the vertices in one straight array. might not be the reason if you can still see any pattern and im not sure if the compiler would turn it into a float*[] or if it would just index differently.

also: drawelements wants the info about your index-array and passing floats as index wouldnt make that much sense, would it? you give the info about your vertex array when you set the vertex pointer.

if you use drawarrays and pass the array the way you set it up, then no kind of primitive will work. what you are doing seems to be this:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

if you pass them in this order then all your getting is garbage. a strip would do this:

make a tri from 1/2/3 (which are on one line), then 2/3/4, again one line, then 3/4/5, a completely wrong triangle, maybe even facing the wrong direction. try using glvertex in the same order as you store them in the array and you should get the same garbage.


Ok, so now that you have confirmed my fears that the vertex data isn't aligned right. That would be why using gl_POINTS works fine. What about the parameter *indicies with glDrawElements()? Isn't that the pointer where I have all my vertex data stored? If not then what is it? Is this indices some kind of array that somehow says which vertexs to use from your vertex pointer? Now all of a sudden this whole vertex arrays subject is getting way more complicated than just using glVertex3f()! Thanks for your patients.

[edited by - Mars_999 on August 11, 2003 1:03:13 PM]

Share this post


Link to post
Share on other sites
python_regious    929
the DrawElements function takes a set of indices to the vertex set that you have defined using the *Pointer functions. So, the first vertex in the set would have an index of 0, and it would increase by one for each vertex.

Death of one is a tragedy, death of a million is just a statistic.

Share this post


Link to post
Share on other sites
Trienco    2555
index arrays are a nice thing for a few reasons:
-you dont have to send the whole vertex array
-you can reuse shared vertices
-indices are smaller than vertices

to keep the vertex array (because else you would have a ton of redundant vertices) you would have this like before

0 1 2 3 4
5 6 7 8 9
...

and an index array like this (a strip, but only one row, dont even try to just jump back to the left after finishing it)

0 5 1 6 2 7 3 8 4 9

Share this post


Link to post
Share on other sites
Arch@on    100
Use triangle strips only when you need them. Are you sure 256x256 terrain needs triangle strips? You could as well go with indexed trianle lists, since they are a) easier b) the performance drawback is almost non-existent.

Triangle strips are good for bigger landscapes, but can really turn into pain in the ass when you start dealing with things like triangle reduction. Where as creating indices for triangle lists is easy, with triangle strips you create patches that are connected together. Anyway, the size of your index list won't be that big perhaps 1/32th of the map size depending how you divide triangles.

There are three possible problems:
-Either your vertex data isn't aligned right, which is higly unlikely, if you can render with immediate mode(glVertex3f)
-Your indices are built wrong(most likely).
-Your data structure is bigger than the max of short or int.

I'm guessing you have mixture of latter.

Build your indices manually or look for code on this site how to build them for tri-strips. I have myself posted it a couple of times. But really, if you want to do yourself a favoir do it manually.

Edit: Also listen Trienco, he really knows his stuff.

[edited by - Captain Goatse on August 12, 2003 6:47:55 AM]

Share this post


Link to post
Share on other sites
MARS_999    1627
Ok I think I got the indices down because my terrain is rendering correctly now as a mesh. I added in texturing and now all is hell again! Urgh! I setup my texture array as such


struct TextureCoord
{
float x;
float y;
};

TextureCoord tex_coord[MAP_Z * MAP_X];

for(z = 0; z < MAP_Z * MAP_X; z++)
{
tex_coord[z].x = 0;
tex_coord[z].y = 0;
}

for(z = 0; z < MAP_Z * MAP_X; z++)
{
tex_coord[z].x = 0.0f;
tex_coord[z++].y = 0.0f;
tex_coord[z].x = 0.0f;
tex_coord[z++].y = 1.0f;
tex_coord[z].x = 1.0f;
tex_coord[z++].y = 0.0f;
tex_coord[z].x = 1.0f;
tex_coord[z].y = 1.0f;
}

glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, tex_coord);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, texture[GRASS]);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);




I get a texture to wrap to my triangles GL_TRIANGLE_STRIP) but it looks smeared?

And thanks for all the help. I do believe Trienco knows what he is talking about. I am learning this new way of doing things in OpenGL. I almost got it down except for the texturing now.

Share this post


Link to post
Share on other sites
Trienco    2555
the tex coords need to be in exactly the same order as your vertices. it might be easier/safer to handle them in the same loop as your vertices.

and the way you increase z i would really use a while loop instead. changing your counter variable all over the place will just result in confusion.

Share this post


Link to post
Share on other sites
MARS_999    1627
Do you mean my indices array or the vertex array? I am assuming you mean indicies beings that is the order in which the vertex data is going to be called correct?

Share this post


Link to post
Share on other sites
Trienco    2555
hehe, that depends on how to look at it.
if you have vertices in your vertex array like this
0 1 2 3 4 5

then the tex coords for them should also be
0 1 2 3 4 5

if they already are in the same order try to write a few lines down. are you still line by line left to right? because then for the first line you should NOT change the "y" of your texcoords, as the first line obviously is supposed to be the top edge of the texture. only your x should alternate every single step, y should only change with each line.

Share this post


Link to post
Share on other sites
MARS_999    1627
quote:
Original post by Trienco
hehe, that depends on how to look at it.
if you have vertices in your vertex array like this
0 1 2 3 4 5

then the tex coords for them should also be
0 1 2 3 4 5

if they already are in the same order try to write a few lines down. are you still line by line left to right? because then for the first line you should NOT change the "y" of your texcoords, as the first line obviously is supposed to be the top edge of the texture. only your x should alternate every single step, y should only change with each line.


Ok here is what I got. I have texturing going on now but for some reason it looks wrong?


//fill indices array with alignment for processing vertex array data

for(z = 0; z < MAP_Z - 1; z++)
{
for(x = 0; x < MAP_X; x++)
{
current_vertex = z * MAP_X + x;
indices[index++] = current_vertex;
indices[index++] = current_vertex + MAP_X;
}
}

//fill texture vertex array

for(z = 0; z < MAP_Z; z++)
{
for(x = 0; x < MAP_X; x++)
{
tex_coord[z][x].x = float(x % 2);
tex_coord[z][x].y = float(z % 2);
}
}
CalNormal();

glVertexPointer(3, GL_FLOAT, 0, terrain);
glTexCoordPointer(2, GL_FLOAT, 0, tex_coord);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);


Is that correct? In the texture array each element

tex_coord[0][0].x = 0.0f
tex_coord[0][0].y = 0.0f
tex_coord[0][1].x = 1.0f
tex_coord[0][1].y = 0.0f
tex_coord[0][2].x = 0.0f
tex_coord[0][2].y = 0.0f
tex_coord[0][3].x = 1.0f
tex_coord[0][3].y = 0.0f

then when I goto 2nd row
tex_coord[1][0].x = 0.0f
tex_coord[1][0].y = 1.0f
tex_coord[1][1].x = 1.0f
tex_coord[1][1].y = 1.0f
tex_coord[1][2].x = 0.0f
tex_coord[1][2].y = 1.0f
tex_coord[1][3].x = 1.0f
tex_coord[1][3].y = 1.0f

is that a correct algorithm?

Share this post


Link to post
Share on other sites
MARS_999    1627
Ok, now I got it to work. Trienco is right about 0,1,2,3 ect.. But I didn''t understand it at first and still don''t? Why would I give texture coordinates of 0,1,2,3,4 instead of the texture coordinates that you give glTexCoord2f(0.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); ect... I don''t understand how OpenGL can take texture coordnate 0,255 and use it like 0.0f, 1.0f? Thanks for the help so far and now I got the texturing up and running but still am confused.

Share this post


Link to post
Share on other sites
Trienco    2555
if you set the mode to repeat, then 21 is the same as 0 (and 1), 21.5 is the same as 0.5

the difference is simple: you have every vertex only once, while in immediate mode you could give the same vertex with different texcoords. but obviously one vertex cant have two values and opengl doesnt have a crystal ball telling it that you want it to be 1 for the quad you just did and 0 for the next quad youre doing.

Share this post


Link to post
Share on other sites