editing vertex normals (smoothgroups) script in the works

I just started a try at implement something like 3dsMax smoothgroups in blender.
Not very far jet, but the basics work.

here’s the code. I was wondering if someone else is working on the same thing?


# Edit vertex normals. Only works in edit mode with a Mesh.
# for now just a very basic implementation.
# I think it works like 3dsMax with two smooth groups
# first smoothgroup is the total mesh, second one is selected faces.
# 3D viewport is not automatically refreshed after this script runs, need to rotate the view to make it update.


import bpy
import bmesh


# Get the active mesh
me = bpy.context.object.data


# todo: use mesh ID-Property to store a lsit of integers that define faces in a smoothgrop


# Get a BMesh representation
smooth_group_bm = bmesh.new()   # create an empty BMesh
smooth_group_bm.from_mesh(me)   # fill it in from a Mesh
face_seq = smooth_group_bm.faces
for face in face_seq:
    if not face.select:
        #remove faces from that are not selected.
        # edges and verts stay. vertex indices should not be changed
        face_seq.remove(face)
smooth_group_bm.normal_update() # should smooth normals of the mesh with only the selected faces
vert_seq = smooth_group_bm.verts


bm = bmesh.new()
bm = bmesh.from_edit_mesh(me)


for vert in vert_seq:
    if vert.select:
        bm.verts[vert.index].normal = vert.normal
# todo: refresh 3d viewports. currently you have to rotate the view in order to see the changed vertex normals



Does the edit stay if you go in and out of Edit mode again?

The normal edit stays if you go out of edit mode, but is lost if you go back into edit mode. The edit is also lost if you edit the mesh.

I’m gona try saving the face selection as an ID-Property of the mesh, then the script can run again with the old selection (smoothgroup) to recalculate the normals after they are lost.

Blender seems to smooth the vertex normals automatically. If anyone knows how to disable this automatic smoothing that would be very nice.

Blender seems to smooth the vertex normals automatically. If anyone knows how to disable this automatic smoothing that would be very nice.

Blender auto-calcs normals you can’t disable it. You can, however, set shading of faces to flat or smooth and mark edges as sharp (e.g. to split sharp edges with edge split modifier).

as an ID-Property of the mesh

we don’t have ID props in python, we can only store object references as stringprops.

todo: refresh 3d viewports. currently you have to rotate the view in order to see the changed vertex normals

bmesh.update_edit_mesh(me)

thanks CoDEmanX
bmesh.update_edit_mesh(me) works great!

I think we do have ID Properties in python.
They are documented here: http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties

And saving the face selection in an integer list in the meshes id properties seems to work :slight_smile:


# save selected face indices as an ID-Property of the mesh
# can be seen in Custom Properties

import bpy
import bmesh


# Get the active mesh
me = bpy.context.object.data


face_selection_bm = bmesh.from_edit_mesh(me)
face_seq = face_selection_bm.faces
selected_face_indices = []
for face in face_seq:
    if face.select:
        selected_face_indices.append(face.index)
me["smooth_group_1"] = selected_face_indices


for index in me["smooth_group_1"]:
    print(index)

Next step will be to create a user interface…

I think we do have ID Properties in python.

Nope, that page is about adding attributes to IDProperty objects, not about adding ID-properties. There is no bpy.props.IDProperty!

finally got it to work, with a GUI :slight_smile:

It creates a panel called Smooth Groups in the object data of meshes. Click the + icon to add a smoothgroup, assign some faces to it, then press Smooth.
The smoothing is lost when entering edit mode or changing editing the mesh. Face selection is stored thow, so simply press Smooth again.
Feels a bit hacky because the script stores data in the custom properties of the mesh. If you don’t edit these properties everything should work fine.

hmm, the down side of this script is that if an edge split modifyer is added then the modifyer will do the smoothing again, and the smoothing by the script is lost. Workaround is to apply the edge split modifyer, but that’s destructive :frowning:

Is there actually ways to script modifyers in python? I would like to turn my script into a modifyer. Using it after an edge split modifyer would be very helpfull.

instead of

me[group.face_selection_name].to_list()

it might be possible to store the custom data in a bmesh layer, similar to how UV and Vcols are added with bmesh module.

Modifiers are hardcoded, you can’t script them.

good idea, thanks!

the tricky thing about bmesh custom data layers is that you need to get the layer handle back after loading .blend, but there is a way, i already managed this. Question is rather if the custom data itself stays and if it’s synced correctly…

Other than that, you could also use a CollectionProperty.

hmm, for me the bigger issue is to get the code to run after an edge split modifyer, without having to apply the modifyer.
Unfortunately I don’t see a way to do that without getting into the c code, and that’s beyond my capabilities at the moment.

bm.from_object(…, deform=True) ?

not sure if this works as expected in editmode. The funny thing: you can get bm from edit mesh, then do from_object and is_wrapped will still be true lol?!