8
$\begingroup$

I'm trying to make a script to apply vertex normals based on selected faces. So far I have written the script and it works fine, but if I exit edit mode and then re-enter edit mode, the normals get automatically recalculated by blender and look wrong again. Is there some way to stop blender recalculating the normals when entering edit mode? I have set autosmooth on the model.

Here is the script:

import bpy
import bmesh
import mathutils

me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)

selected_verts = [v for v in bm.verts if v.select]
for v in selected_verts:
  # get all the selected faces linked to the vertex
  ls_faces = [f for f in v.link_faces if f.select]

  # set vertex normal to average of face normals
  if len(ls_faces) > 0:
    average_normal = mathutils.Vector()
    for f in ls_faces:
      average_normal += f.normal
    average_normal /= len(ls_faces)
    v.normal = average_normal

bmesh.update_edit_mesh(me, False, False)

enter image description here

Here are some images that show what the script is for (this kind of thing is very handy for game models, especially toon shaded models). The script appears to be working fine, but whenever I go back to edit mode after leaving it, the normals revert to how the object looks in the left image.

$\endgroup$
5
$\begingroup$

You want to use Mesh.normals_split_custom_set(normals).

Custom normals are always set per loop (i.e. face corners), but this utility set those per-vertex (it internally translates those 'vert normals' to loop ones).

Note that you have to set all normals for all vertices at once (basically because this is a rather heavy process, so setting it by vertex or loop would be inefficient), however you can set some normals to zero (0.0, 0.0, 0.0) vector to keep existing custom normals, or use default auto-computed ones.

Finally, you must be in Object mode currently, custom normals at BMesh level (Edit mode) are not yet supported really.

You can find some examples of that API in use in the new mesh_custom_normals_tools.py addon, as well as OBJ and FBX importers.

$\endgroup$
  • $\begingroup$ Thanks, this is exactly the answer I was looking for. I'll get to work on this as soon as I can! $\endgroup$ – MrFlamey Oct 10 '15 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.