Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating normals for a height map

I have a small problem calculating normals for my heightmap. It has a strange behavior. At the higher and the lower points the normals are fine, but in the middle they seem wrong. They are lighted by a point light. Problem

UNFIXED SOURCE REMOVED

EDIT: Tried 2 new approaches:

This is per-face-normal. It looks fine but you see the single faces.

Position normal = crossP(vectorize(pOL, pUR), vectorize(pOR, pUL));

I also tried to do it per-vertex this way, but also with a strange output.

enter image description here

This is the suggestion Nico made:

It looks also rather odd. Maybe there is a mistake how I calculate the helping points.

UNFIXED SOURCE REMOVED

enter image description here

EDIT 2: Definition of my points: OL,OR,UL,UR are the corner vertices of the plane that is to be drawn.

                postVertPosZ1 postVertPosZ2
preVertPosX1         pOL           pOR         postVertPosX1
preVertPosX2         pUL           pUR         postVertPosX2
                 preVertPosZ1  preVertPosZ2

EDIT3:

I solved it now. It was a stupid mistake: I forgot to multiply the y value of the helping Vertices with the height Multiplier and had to change some values.

It is beautiful now. enter image description here

like image 274
Eskalior Avatar asked Nov 16 '15 13:11

Eskalior


1 Answers

There are lots of ways to solve this problem. I haven't encountered yours. I suggest using central differences to estimate partial derivatives of the height field. Then use the cross product to get the normal:

Each vertex normal can be calculated from its four neighbors. You don't need the plane plus its neighbors:

  T
L O R
  B

O is the vertex for which you want to calculate the normal. The other vertices (top, right, bottom, left) are its neighbors. Then we want to calculate the central differences in the horizontal and vertical direction:

             /           2           \
horizontal = | height(R) - height(L) |
             \           0           /

             /           0           \
vertical   = | height(B) - height(T) |
             \           2           /

The normal is the cross product of these tangents:

normal = normalize(cross(vertical, horizontal))
                   / / height(L) - height(R) \ \
       = normalize | |           2           | |
                   \ \ height(T) - height(B) / /

Note that these calculations assume that your x-axis is aligned to the right and the z-axis down.

like image 124
Nico Schertler Avatar answered Nov 06 '22 02:11

Nico Schertler