# heightmap geometry normals

I can’t get my terrain to be properly lit, and my problem resides of course in the normals.

I generate the terrain with triangle strips, with the code:

``````for (int z = 0; z < tsize-1; z++)
{
glBegin(GL_TRIANGLE_STRIP);

for (int x=0; x < tsize-1; x++)
{
v_height = hmap.GetValue(x,z);
scaledHeight = v_height * h_scale;

glNormal3fv (normals[x*tsize+z]);
glVertex3f ((GLfloat) x,  scaledHeight, (GLfloat) z);

v_height = hmap.GetValue(x,z+1);
scaledHeight = v_height * h_scale;

glNormal3fv (normals[(x*tsize)+z+1]);
glVertex3f ((GLfloat)x, scaledHeight, (GLfloat)z+1);
}
glEnd();
}

``````

As you see, triangles are generated like this:

``````B\---D\---
| \  | \
|  \ |  \
|   \|   \
A----C---E-
``````

Tris are ABC, CDE…etc.

This triangles of course are generating a terrain geometry… and I need to calculate normals for it.

The method which I think should work is:

• For every vertex A choose neighbour vertices B and C that share the same triangle as A.
• Take vectors B-A and C-A, do cross product (B-A)x(C-A)
• Normalize cross product.
• We have our normal for the vertex.

But of course this generates very sharp lighting, so for I need to average more vectors in case of vertices that share more than one triangle.

``````M\---N\---O\---P
| \  | \  | \  |
|  \ |   \|  \ |
I\--\J----k\--\L
| \  | \  | \  |
|  \ |   \|  \ |
E\--\F\---G---\H
| \  | \  | \  |
|  \ |  \ |  \ |
A----B----C----D

Well, let's go for a little pseudocode:

IF VTX=A
N=NORM((E-A)x(B-A))

// this shares two triangles BEF and BFC
IF VTX=B
V1=(E-B)
V2=(F-B)
V3=(C-B)
VP=(V1xV2+V2xV3)/2
N=NORM(VP)

// a inner vertex like F shares triangles FIJ, FJG, BEF, BFC

and so on...
``````

Should this work or can I use another methods for smooth lighting?

At last, should my normals be 1 at Y (height) or must be multiplied by the height-scale of my terrain vertices?

thank you!

Hi,

At first sight, I don’t see anything wrong with the suggested method. Note that this can be simplified:

``````
(N-J)x(M-J) +
(M-J)x(I-J) +
(I-J)x(F-J) +
(F-J)x(G-J) +
(G-J)x(K-J) +
(K-J)x(N-J)

=

NxM-NxJ-JxM+JxJ +
MxI-MxJ-JxI+JxJ +
IxF-IxJ-JxF+JxJ +
FxG-FxJ-JxG+JxJ +
GxK-GxJ-JxK+JxJ +
KxN-KxJ-JxN+JxJ

=

NxM-NxJ+MxJ +
MxI-MxJ+IxJ +
IxF-IxJ+FxJ +
FxG-FxJ+GxJ +
GxK-GxJ+KxJ +
KxN-KxJ+NxJ

=

NxM + MxI + IxF + FxG + GxK + KxN

``````

This works if all your triangles have approximately the same area. If they don’t (many peaks) it’s better to use:

normalized(N-J) x normalized(M-J)

(N-J)x(M-J)

Your normals should always be normalized, so make sure that automatic normalization is enabled (or done manually in shader) or that your transformation matrices do not scale/skew your object.

Cheers,

N.

Thank you very much!!! Worksss!!! Looks very good and smooth.

Now I need to get some terrain LOD algorithm. What about clipmapping? It’s good and easy to implement?

My terrain is 1024x1024 pixels heightmap based (about 512x512 tris) to represent a 1.5km x 1.5km area.

I recently played with the isometric heightmaps, they may be a bit trickier to implement but provide better-looking results: ftp://ftp.cs.brown.edu/pub/techreports/05/cs05-14.pdf

For LOD I suggest you use geometrical mipmapping as described in this paper: ftp://ftp.cs.brown.edu/pub/techreports/05/cs05-14.pdf

Still, for your terrain you need no LOD. 512x512 tris are only 256k triangles, even older graphics card eat something like this for breakfest. Just load it into a static VBO and you should be fine.

I think for a 1.5km square area 512x512 tris seems to be a little constrained. What triangles per km scale are you using?

Now, just implementing VBOs…

Thanks!