Newsgroups: comp.graphics
From: sloan@willis.cis.uab.edu (Kenneth Sloan)
Subject: Surface Normals (summary)
Date: 6 Sep 91 02:00:35 GMT
Recall the assumptions: you are given a shared vertex, and its neighbors
in a polygonal (triangular) mesh. The problem is to estimate the surface
normal at the shared vertex. Here are the methods submitted in response
to my query, in roughly the order received:
 Method 0: `weightbyarea'

Add up the normals of each polygon sharing a vertex, then normalize.
While it was unstated by the people who submitted this method, it was
clear that the `normals of each polygon' have magnitudes which are
proportional to their areas (in some sense). If the `polygons' are
triangles, then these `weighted normals' are simply computed as the
crossproducts of the successive vectors formed by the shared vertex and
it's neighbors. Rearrange terms, optimize the code, and you get the
formula presented in many texts. A possible problem with this method is
that the result is independent of the location of the shared vertex. A
major advantage is that it can be made to run very fast.
 Method 1: `weightuniformly'

Add up normalized face normals, then normalize. This is more expensive,
unless you already compute and store (normalized) face normals for each
polygon (triangle). It is reported to work a bit better than
`weightbyarea'.
 Method 2: `least squares'

Fit a plane to all of the vertices. Variation: fit the plane to all of
the vertices *except* the shared vertex.
 Method 3: `eigenvalues'

Compute moments, form a scatter matrix, and extract eigenvalues and
eigenvectors. The eigenvector corresponding to the smallest eigenvalue
is the (unnormalized) surface normal. Variations as above  either with
or without the shared vertex.
 Method 4: `independent derivatives'

Intended only for dense meshes  use 2 independent directional
derivative estimators.
 Method 5: `weightbyangle'

Compute normalized face normals for the neighboring polygons, and weight
each normal by the angle formed at the shared vertex.
 Method 6: `weightbyinversearea'

As above, but weight the normals by inverse area. This method appears
to have been independently invented by myself and Andrew Glassner, circa
1985. I am particularly interested in pointers to published literature
which discusses this method. The idea here is that small triangles have
all of their vertices close to the shared vertex, and "know" more about
the local surface normal than the faroff vertices forming large
triangles. It turns out (see the forthcoming paper) that this is also
relatively easy to compute.
Thanks to all. (very) preliminary results indicate that
`weightbyarea' is the most accurate method. But, this is very
preliminary (i.e., see the forthcoming paper).
If there are any other methods out there that were `too obvious to
mention', I'd still like to hear about them.