Texturing a vertex list?

Started by
4 comments, last by Farfadet 16 years, 11 months ago
Hi. I'm attempting to texture a heightmap in GLUT. the heightmap is made using an array of height values in an 80x80 1-dimensional array. I've been trying to use glTexCoordPointer() but when I run it, as soon as it tries to render the windo, it crashes. Here's the relevant code(in init()): glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); setupVertices(); glVertexPointer(3,GL_FLOAT,0,vertices); glNormalPointer(GL_FLOAT,0,normals); glTexCoordPointer(1, GL_FLOAT, 0, terrainPoints); in my setupVertices() function, I have at the bottom: terrainPoints[0] = vertices[0]; terrainPoints[1] = vertices[1]; terrainPoints[2] = vertices[2]; terrainPoints[3] = vertices[237]; terrainPoints[4] = vertices[238]; terrainPoints[5] = vertices[239]; terrainPoints[6] = vertices[18960]; terrainPoints[7] = vertices[18961]; terrainPoints[8] = vertices[18962]; terrainPoints[9] = vertices[19197]; terrainPoints[10] = vertices[19198]; terrainPoints[11] = vertices[19199]; I manually chose the vertice elements which had the four corner values. Thing is, I have no idea if what I am doing is right. I can texture coordinates just fine, but using a vertex list, I can't access the vertice drawing code and so can't texture each polygon. I would appreciate it if someone could give me a rough guide to how to texture a vertex list!
Advertisement
You're trying to texture your mesh by just providing the texture coordinates at the 4 corners of your terrain grid ; that's not how it works. Using arrays or not, you still have to provide at each vertex of each of your polygons the vertex coordinates, the texture coordinates and the normal. If you have one texture for your terrain, and no sharp edges between your polygons, this amounts to providing 1 texture coordinates (u,v) and one normal at each vertex, so your texture and normal arrays should be the same size as your vertex array. Computing the texture coordinates should be easy though, simply take (X,Y) of each vertex and divide respectively by your terrain width and height so the texture coordinates are clamped between 0 and 1.
Quote:Original post by Farfadet
You're trying to texture your mesh by just providing the texture coordinates at the 4 corners of your terrain grid ; that's not how it works. Using arrays or not, you still have to provide at each vertex of each of your polygons the vertex coordinates, the texture coordinates and the normal. If you have one texture for your terrain, and no sharp edges between your polygons, this amounts to providing 1 texture coordinates (u,v) and one normal at each vertex, so your texture and normal arrays should be the same size as your vertex array. Computing the texture coordinates should be easy though, simply take (X,Y) of each vertex and divide respectively by your terrain width and height so the texture coordinates are clamped between 0 and 1.


Where do I get the normals? Do I use the vertex normals and put them in the same array as the texture coordinates?

As it stands, I'm putting in the x/WIDTH then z/WIDTH where x and z are the coordinates of the current vertex. the third point is the corresponding height value in an array (A heightmap).

for (x=0;x<WIDTH;x++)
for (z=0;z<WIDTH;z++)
{
terrainPoints[offset++] = (float)x/WIDTH;
terrainPoints[offset++] = (float)z/WIDTH;
terrainPoints[offset++] = height[x*WIDTH+z];

}

So my terrainPoints array first three points would looks something like this:

assume x = 0.0, z = 0.0 and y = 3.0;

terrainPoints[0] = 0.0
terrainPoints[1] = 0.0
terrainPoints[2] = 3.0

and so on.

This leaves me with a weird-looking terrain, like it's covered in kaleidoscopic patterns.

Have I done this right?

With openGL you're supposed to compute the normals yourself at each vertex. It's done by averaging the normals of the faces that share the vertex (or better, the weighted average considering the angle of each face at the vertex). Since you have a very regular mesh, I guess you can simplify this and get the normal at a vertex just by comparing the height at the vertex with the heights of the 8 surrounding vertices, but I didn't work out the math. Anyhow, you need to store those normal vectors in a separate array, just like textures and vertices.
Your vertex array buildup looks OK, but how do you use this data for rendering ?
This is in my init() function:

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

setupVertices();

glVertexPointer(3,GL_FLOAT,0,vertices);
glNormalPointer(GL_FLOAT,0,normals);
glTexCoordPointer(1, GL_FLOAT, 0, terrainPoints);

vertices, normals and terrainPoints are all calculated within setupVertices(). I believe the code already finds the vertex normals, and is stored in the normals[] array.

The code finds all the corresponding face normals for each vertex and uses them to fill up the normals array. Unfortunately that code isn't mine so I can only tell you what it does, not specifically how it does it, although if I tried I could figure out how it worked.
Let's assume your normals are OK, somewhere in your code you must be dereferencing the arrays, something like
glBegin(GL_QUADS)
glArrayElement(...)
glArrayElement(...)
glArrayElement(...)
glArrayElement(...)
glEnd

if the indices of the glArrayElement calls are not correct, this could be an explanation of the kaleidoscopic pattern you're mentioning

This topic is closed to new replies.

Advertisement