How does this normal() function works ?

The following function finds the normal to a terrain represented by a texture.
I found it somewhere online , it works but i couldn't understand the math behind it.
So , How (or Why ?) does it works ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//psuedo code
Vector2 normal(x,y)
{
    Vector2 avg;
    for(int w = -3; w <= 3; w++)
    {
      for(int h = -3; h <= 3; h++)
      {
        if(pixel is solid at (x+w,y+h) )
        {
          avg -= Vector2(w,h)
        }
      }
    }
    mod = hypot(avg.x,avg.y)
    return avg/mod //normalize assumes mod != 0
}

Last edited on
I don't know what this means:
 
avg -= (w,h)
I gave it some thought , it seems to take the weighted average of all the solid pixels and then reverse it ( by subtracting).
Although it still isn't quite clear , can someone help
Can you post the implementation of your Vector2 class please (at least the constructor)? It's impossible to tell otherwise.
┬┐what's a `solid' pixel?
┬┐which would be the solid pixels of a flat surface?
If I'm right, this looks like it's used to detect slopes or something? It's not a perfect method... and seems like it would only work in a very limited use case.

The idea looks to be pretty simple. Let's say you have a perfectly diagonal slope:

1
2
3
4
5
6
7
\     O
 \
  \
   \
    \
     \
C     \


With the 'C' part being "closed" and the 'O' part being open.

The routine looks at a 7x7 pixel square. 'avg' starts at the center point of the square... and the routine loops through the square with 'w' and 'h' represending each pixel's distance from the center.

Every time a pixel is solid... 'avg' gets pushed in the opposite direction. In the case of my simple example slope... 'avg' would get pushed very far up and to the right, into the "open space". It will get pushed equally far in both x and y because the number of solid pixels on the X and Y axis are equal.

For a shallower slope...such as this:

1
2
3
4
5
6
7
      O


_
 \_
   \_
C    \


'avg' will get pushed more "up" than right... because there are fewer solid pixels on the left side of the square.


Lastly, avg get normalized presumably to make it a unit vector. At which point you have a reasonably decent estimate of the surface normal.
Last edited on
Vector2 just holds two numbers x and y with suitable operator overloads.

A pixel is solid for a terrain map/image if it isn't transparent

@Disch
Thanks, it explains it.
Last edited on
Topic archived. No new replies allowed.