# Set vertex normal in a stable manner with python

I wanted to set normals from a script, using this code (in a class method):

for face in modelMesh.polygons:
face.use_smooth = True  # normals have effect only if smooth shading
for i in range(len(self.vertices)):  # set normals here because they seem to be lost in some calulations
if self.normals[i] is not None:
modelMesh.vertices[i].normal = Vector(self.normals[i])
for loop in modelMesh.loops:
loop.normal = Vector(self.normals[loop.vertex_index])


however, if this sets the normals to the mesh's vertices, they are reset after using 'modelMesh.update()' or switching edit mode on and off (and btw it seems that the loop normals stay 'Vector((0,0,0))' whatever I try, even '.normal[:] = Vector((1,0,0))' and '.normal[:] = (1,0,0)')

is there a way so set vertex normals permanently using python? thanks in advance

I found it by observing two mesh importing add-ons, but I didn't understand how exactly it worked.

What I know is that it can only affect loop normals, not face nor vertex normals (so that won't help you if you have faces with "front" and "back" part swapped)

mesh.create_normals_split()

for face in mesh.polygons:
face.use_smooth = True  # loop normals have effect only if smooth shading ?

# <set normals (mesh.loops[ ? ].normal= ? )>

# create custom data to write normals correctly?
mesh.validate(clean_customdata=False)  # important to not remove loop normals here!
mesh.update()

clnors = array.array('f', [0.0] * (len(mesh.loops) * 3))
mesh.loops.foreach_get("normal", clnors)

mesh.polygons.foreach_set("use_smooth", [True] * len(mesh.polygons))

mesh.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3)))
mesh.use_auto_smooth = True
mesh.show_edge_sharp = True  # optionnal

• What I don't get... the "mesh.loops.foreach_get(..." seems to always return an array of 0.0... whatever the values in "foreach_set(...". Any idea? Mar 19 '17 at 12:15
• maybe update() -ing the mesh before that? I mean, your problem is precisely what I avoided with this piece of code by the way, to cover the 2% chance that you didn't see that, you must set the loop normals in the middle of the code. Hope it helps... Mar 26 '17 at 17:00