Page 1 of 1

Vertex normals weighted by face area

PostPosted: Sat Aug 09, 2008 7:53 am
by Christian Walther
I had planned to do some modeling today, and ended up coding again... :lol:

I was trying to make shapes with flat faces and smoothly rounded edges, and noticed that they looked really crappy in Uru (top right cube in the following picture).

renormal.jpeg
renormal.jpeg (40.98 KiB) Viewed 1115 times

This is because to compute the vertex normals (that are exported by PyPRP), Blender averages the face normals of all adjacent faces of a vertex, which means that even the normals of the cube faces that are supposed to be flat are bent outward and the face is shaded as if it was curved (bottom right in the picture). What I want is the look at the top left, which is achieved by vertex normals as shown at the bottom left.

So I searched the web for a while and came to the conclusion that Blender just can't do that. It does not have the capability to let the user arbitrarily modify vertex normals. The normals can be modified from Python (which is how I got the screenshot), but they are reset to the default averaged normals again as soon as edit mode is left.

What to do? Since the normals can be modified at least temporarily, we could do that right before exporting, inside PyPRP. So that's what I did, and the result is available as revision 318 in my experimental branch http://svn.guildofwriters.com/pyprp/contrib/CWalther/experimental/.

With this extension, every object that has property renormal set to areaweighted, either as a Blender property or in AlcScript, has its normals recomputed. All other objects are left alone with their default Blender-computed normals. To compute a vertex normal, it still averages the face normals of the adjacent faces, but it does this weighted by the area of each face. That way, my big cube faces contribute the major part of the resulting normal, while the small bevel faces have little influence. Other algorithms could conceivably be added to this system in the future, such as weighting by some power of the face area or by the angles of the face corners, explicitly specified normals encoded in a vertex color layer, etc.

Perhaps some of you find this useful too. Testing and feedback is welcome!

Edit: For those who don't wan't to deal with Subversion and/or with the unstable trunk version of PyPRP, here is the relevant file from PyPRP 1.5.0 with just this modification applied - unzip and drop into your .blender/scripts folder (after renaming the existing one as a backup):
prp_DrawClasses.py-renormal-1.5.0.zip
(17.32 KiB) Downloaded 87 times

Re: Vertex normals weighted by face area

PostPosted: Sun Aug 10, 2008 2:47 pm
by Nadnerb
I like this feature a lot, and after playing with it for a while, I decided (as you did) that it really ought to be a feature of blender. :P Anyway, I've added it to the pyprp trunk.

Note: changed the alcscript property to read from the visual section of the object script.

Re: Vertex normals weighted by face area

PostPosted: Mon Aug 11, 2008 11:18 am
by Christian Walther
Cool, thanks! 8-)

Modifiable normals seem to be quite an often-requested feature in Blender, particularly from game artists and other low-poly modellers. I have not seen any sign of anyone working to implement it though.

Nadnerb wrote:Note: changed the alcscript property to read from the visual section of the object script.

Good point. It does break the symmetry between AlcScript and Blender property a bit, but as far as I see there isn't a lot of such symmetry in the rest of PyPRP to begin with, so that's probably OK.

:idea: Remind me to write some documentation in the wiki before 1.6 is released.

Re: Vertex normals weighted by face area

PostPosted: Tue Aug 12, 2008 5:55 am
by Jojon
Excellent!