PDA

View Full Version : Smooth Vertex Normals with Crease Angle



skynet
11-23-2009, 03:41 PM
Hi,
I'm pondering how to create _good_ normals for any given triangulated mesh. The standard approach "just average all face normals that meet at a vertex" just doesn't cut it.
One common answer to this is "don't average normals of faces that meet at a sharp edge". Well, I want to compute vertex normals. One vertex can be shared by many faces, even ones that don't share an edge. So the edge-answer seems wrong to me.

I'm now doing:



1. weld the mesh
2. compute per-triangle face normals
2. for each vertex
build a list of triangles that index the vertex
3. for each vertex V's triangle-list
for each triangle T1 in the list
find all others T2 in the list
if ((T1 dot T2)<creaseAngle)
remember in T1 and T2 that they are allowed to be averaged at V
4. finally, average the normals that are allowed to be averaged
5. distribute the averaged normals to the faces they belong to


This works well for sharp features but unfortunately, there are cases where it just fails :-(

Is there some well known algorithm that handles all (most) cases?
I have been searching the web, but did't find anything useful.

ZbuffeR
11-23-2009, 04:49 PM
Instead of introducing a discontinuity (if < creaseangle) try taking in account the area of the face, as a weight for its normal, instead of blindly averaging.

This helped solve my problems on chamfered boxes.
With large square face, axis aligned, had each corner vertex shared with long thin rectangles and a very small triangle, the naive "just average all face normals that meet at a vertex" gave poor results.

skynet
11-23-2009, 04:57 PM
Yeah, tried that, but blindly weighting won't solve you even the simplest box. Discontinuities are absolutely wanted, but only where "it makes sense"... but that is what the algorithm has to find out... somehow.

CatDog
11-23-2009, 05:02 PM
It's been a while since I messed with this. In my opinion, there's not the one way to do it. If your input data is just a cloud of triangles, no more info given, you won't get satisfying results without at least building the adjacency graph, finding "good" edge loops and then using this edge info to find "good" vertex normals. There are plenty of ambiguous corner cases involved. Just think of an edge sharing more than two triangles for example. So this will fail, too. But separating surfaces by finding continuous edge loops gives at least visually pleasing results. And since you just generated the edges, you can use them for rendering, of course.

CatDog

skynet
11-23-2009, 05:12 PM
Mhhm, what is a edge loop? What makes it a "good one"?
Is it a (ordered) list of triangles that all meet at a vertex?
What would this algorithm do with the top vertex of a cone?

CatDog
11-23-2009, 06:00 PM
The term "edge loop" is normally used to describe an ordered sequence of triangle edges, where the first and last vertex are the same. In particular the outer boundary of a surface describes an edge loop and each inner boundary (aka hole) also describes an edge loop.
What I propose is to find sequences of edges within the adjacency graph, that could possibly be good edge loops. They are good, if they match some kind of criteria, for example that crease angle, but you can make this as complicated as you want. You just don't check it per edge, but try to find sequences of edges that match. Obviously, this problem is very hard to solve. It's route finding within the adjacency graph. But you didn't ask for fastest methods, did you? :)

The top vertex of a cone would (should) be detected as some kind of singularity - it's one of the corner cases. You detect the discontinuity at this vertex (some triangles forming a sharp angle) but you don't find any sharp triangle edges. So this vertex is an edge loop of it's own. It not only starts where it ends, but also has zero length.

Ah, this kind of stuff make programming fun. (But only if there's no deadline waiting for you. :) )

CatDog

ZbuffeR
11-24-2009, 01:59 AM
Discontinuities are absolutely wanted, but only where "it makes sense"
Then you will need to compute several normals per vertex when angle between adjacent faces is > 30 degrees or whatever threshold.

sammie381
12-06-2009, 01:18 AM
1. weld the mesh
2. compute per-triangle face normals
2. for each vertex
build a list of triangles that index the vertex
3. for each vertex V's triangle-list
for each triangle T1 in the list
find all others T2 in the list
if ((T1 dot T2)<creaseAngle)
remember in T1 and T2 that they are allowed to be averaged at V
4. finally, average the normals that are allowed to be averaged
5. distribute the averaged normals to the faces they belong to


A crease angle only makes sense between two triangles sharing an edge.
So, you probably shouldn't be testing two triangles that *don't* share an edge.