I have loose mesh elements within an object and I would like each loos element to be placed in its own vertex group.
2 Answers
Another take on this. Already had code that separated a mesh into vertex groups from seams,
import bpy
def island_verts(mesh):
import bmesh
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
bm = bmesh.from_edit_mesh(mesh)
bm.verts.ensure_lookup_table()
verts = [v.index for v in bm.verts]
vgs = []
while len(verts):
bm.verts[verts[0]].select = True
#bpy.ops.mesh.select_linked(delimit={'SEAM'})
bpy.ops.mesh.select_linked()
sv = [v.index for v in bm.verts if v.select]
vgs.append(sv)
for v in sv:
bm.verts[v].select = False
verts.remove(v)
bm.free() # prob not nec.
bpy.ops.object.mode_set(mode='OBJECT')
return vgs
# test run
obj = bpy.context.object
mesh = obj.data
vgs = island_verts(mesh)
for vg in vgs:
group = obj.vertex_groups.new()
group.name = "Island"
group.add(vg, 1.0, 'ADD')
-
1$\begingroup$ Thanks for the code. For some reason, though it adds a vertex group for each vertex $\endgroup$ Commented Nov 18, 2015 at 15:50
-
$\begingroup$ Test the code against the cube (1 vgroup) or suzanne (3 vgroups, the eyes are separate). Could be something to do with your mesh. Try using p in edit mode, separate by loose parts, my guess is you will end up with as many objects as vertex groups it added from running the script. Probably why it's crashing TLousky's code as well, too many bmesh instances. $\endgroup$ Commented Nov 18, 2015 at 16:10
-
$\begingroup$ As for some reason, when testing it now, it works. Thank you :) $\endgroup$ Commented Nov 19, 2015 at 16:14
-
$\begingroup$ I also get separate vert groups for each vertex, with both samples of code. Not sure if there is something that has changed with the API or with BMesh to cause it though. $\endgroup$ Commented Jan 18, 2017 at 4:33
-
$\begingroup$ Ah, found my problem and the solution is simple: the script actually looks for the object in edit mode to be in vertex select - if it is in edge or face select, that will not work, and you will get a vertgroup for every vertex then. Thank you for the examples, I want to set this as a tool now :D $\endgroup$ Commented Jan 18, 2017 at 4:43
Here's a script that iterates over each mesh island and assigns its vertices into a new vertex group.
EDIT - WARNING: After testing it appears that this solution is limited to around 1000 islands (due to Blender's max recursion limit). Use @batFINGER's solution if you have more vertex groups than that.
It's based on a recursive function since the blender API currently doesn't provide (as far as I know) any built in way to get all mesh islands.
import bpy, bmesh
def find_island_and_assign_vgroup( o, remaining ):
''' Recursive function that itertaes over mesh islands and assigns a new vertex group to each'''
if len( remaining ) > 0:
# Create bmesh object (must do this every time since vertex groups are created in object mode, which destroys the bm object
bpy.ops.object.mode_set( mode = 'EDIT' )
bm = bmesh.from_edit_mesh( o.data )
bm.verts.ensure_lookup_table()
bpy.ops.mesh.select_all( action = 'DESELECT' )
bm.verts[ list(remaining)[0] ].select = True
bm.select_flush( True )
bpy.ops.mesh.select_linked()
selected_verts = [ v.index for v in bm.verts if v.select ]
# Add to a new vertex group
bpy.ops.object.mode_set( mode = 'OBJECT' )
vg = o.vertex_groups.new()
vg.add( selected_verts, 1.0, 'ADD' )
# Remove this island's verts from the vert list
now_remaining = remaining - set( selected_verts )
bm.free()
find_island_and_assign_vgroup( o, now_remaining )
o = bpy.data.objects[ bpy.context.object.name ]
all_verts = set( range( len( o.data.vertices ) ) )
find_island_and_assign_vgroup( o, all_verts )
-
$\begingroup$ Thanks for the script. Unfortunately it crashes Blender for some reason. $\endgroup$ Commented Nov 18, 2015 at 16:01
-
$\begingroup$ Weird, worked for me. Can you upload a blendfile? blend-exchange.giantcowfilms.com $\endgroup$– TLouskyCommented Nov 18, 2015 at 16:03
-
1$\begingroup$ A bm.free() before the recursive call is probably a good idea, as that's what prob crashes your code on high loose part counts, given the OP's comment on the answers we've provided. $\endgroup$ Commented Nov 19, 2015 at 10:37
-
$\begingroup$ Makes sense, @batFINGER, will add and test it. $\endgroup$– TLouskyCommented Nov 19, 2015 at 10:39
-
$\begingroup$ It doesn't crash now, but actually that's not enough either, as blender sets a maximum recursion depth to ~1000 (stopped in vertex group 992 in the Suzanne X3 test you suggested). So appears like your solution is more robust. $\endgroup$– TLouskyCommented Nov 19, 2015 at 10:43