0
$\begingroup$

I would like to change all the normals of selected vertices in my scene to be (0,0,1). I am attempting to do this on a single mesh as a test scenario using the following code:

import bpy

mesh = bpy.context.object.data

selected_verts = [v for v in mesh.vertices if v.select]

for v in selected_verts:    
    print(f"Before Vertex Normal: {v.normal}")
    v.normal = [0,0,1]
    print(f"After Vertex Normal: {v.normal}")

When doing this, the value appears to change but the normal in the scene remains unchanged. Using Blender 2.83LTS

enter image description here

EDIT - subbed out the averaging routine for a Vector(0,0,1) - this works for my needs since all my Vectors are either UP or DOWN -

#Evaluate face Normals - if negative - flip
for obj in selected:
    bpy.ops.object.select_all(action='DESELECT')
    obj.select_set(True)
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.editmode_toggle()

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

    # Reference selected face indices
    bm.faces.ensure_lookup_table()
    selFaces = [ f.index for f in bm.faces if f.select ]

    # Positive vector
    up = Vector([0,0,1])

    # Calculate the dot products between the Up vector and each face normal
    dots = [ up.dot( bm.faces[i].normal ) for i in selFaces ]

    # Reversed faces have a negative dot product value
    reversedFaces = [ i for i, dot in zip( selFaces, dots ) if dot < 0 ]

    # Deselect all faces and (later) only select flipped faces as indication of change
    for f in bm.faces: f.select = False
    bm.select_flush( False )

    for i in reversedFaces:
        bm.faces[i].select = True
        bm.faces[i].normal_flip()  # Flip normal

    bm.select_flush( True )

    bpy.ops.object.editmode_toggle()

bpy.ops.object.select_all(action='DESELECT')
$\endgroup$
7
  • $\begingroup$ Most changes done on an object.data variable are only refreshed after the object mode is changed. I would suggest as a 1st check verifying that toggling out of edit mode does not update your scene. $\endgroup$
    – Ratt
    Apr 20 at 4:26
  • $\begingroup$ unfortunately, that doesn't seem to update the scene. i can verify they have changed with the print statement. however, after cycling through Object and Edit mode, they will eventually reset to the original position. bizarre - obviously, something with Blender happening auto-magically that I do not understand. $\endgroup$
    – DP Roberts
    Apr 20 at 14:27
  • $\begingroup$ I did find this - blender.stackexchange.com/questions/87106/… - which is a great routine. I wonder if it could be simplified to identify negative normals. I'm essentially on flat planes and want to know UP or DOWN on the normal. And if DOWN, flip. I'm an artist with limited python ability beyond scouring the internet for solutions. $\endgroup$
    – DP Roberts
    Apr 20 at 16:54
  • $\begingroup$ Did you see brockman's answer for custom normals $\endgroup$
    – Ratt
    Apr 20 at 19:21
  • $\begingroup$ yes, but i'm trying to export these for import into Unity and wasn't sure that data would import correctly. i probably should have just phrased this as - "Is there a way to assign all my face normals to (0,0,1)?" - that's all I really need to do. I will try experimenting with modifying the bmesh routine. $\endgroup$
    – DP Roberts
    Apr 20 at 22:35

Your Answer

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

Browse other questions tagged or ask your own question.