From: Bruce S. <Bru...@nc...> - 2010-01-26 22:36:44
|
Available at vpython.org: VPython 5.2 for Windows and Mac which adds a new feature for smoothing objects made of faces. After creating a faces object named (say) myfaces, myfaces.smooth() will average similar normals at a vertex and make the object look smoother. You must make sure that all vertices have nonzero normals before using the smooth function; a simple scheme is to make all the normals perpendicular to their respective faces and then let the smooth function adjust them for improved appearance. The issue that this addresses is that if you try to make a smooth-looking curved surface but adjacent faces have different normals, the surface has creases in it. Smoother appearance is obtained if similar normals at a vertex shared by two or more triangles are averaged and the average normal applied to all these triangle vertices. However, at a vertex shared between two surfaces with very different orientations, such as perpendicular surfaces, no such averaging should be applied. The new smoothing routine only averages shared normals if they don't differ too much in direction (about 18 degrees). The example program "faces_heightfield.py" has been revised to use the new smooth() function. Bruce Sherwood P.S. Maybe someone would find the algorithm interesting, and I'll describe it in terms of Python code, though it is implemented in C++ for speed: First pass: Construct a dictionary whose keys are vector positions of vertices and whose values are lists (or rather Python "sets") of indices of vectors in the faces pos (or normal) array. Second pass: For each key (spatial location of a vertex) in the dictionary, get the value (the set of indices of pos or normal vectors each of which corresponds to the same position in space). Pick an index in this set, evaluate its (normalized) normal, and one at a time take the dot product of this normal with the (normalized) normals of all the other members of the set, creating a list of indices for which the dot product of the normals is > 0.95 (so the normals differ in direction by no more than 18 degrees). For this subset, average their normals and assign them to this subset, then remove the subset from the larger set and repeat until the set is empty. This procedure assures that neighboring faces that don't differ much in orientation will not have a sharp crease between them, but neighboring faces that have very different orientations, including for example perpendicular faces, will have very different normals. There is an inappropriate bias in this scheme in that the starting normal for searching through the set might be an extreme one and therefore one might fail to identify the right bundle of normals to average. Maybe someone will think of an unbiased way to do the bundling. I can say that having tried the smooth() function on various objects made of many faces, the scheme seems to work pretty well. Another possibility would be to look at edges shared by triangles rather than at vertices shared by triangles. At the moment I don't see how to do that. |