3
$\begingroup$

I have loose mesh elements within an object and I would like each loos element to be placed in its own vertex group.

$\endgroup$

2 Answers 2

4
$\begingroup$

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')
$\endgroup$
5
  • 1
    $\begingroup$ Thanks for the code. For some reason, though it adds a vertex group for each vertex $\endgroup$
    – dimitarsp
    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$
    – batFINGER
    Commented Nov 18, 2015 at 16:10
  • $\begingroup$ As for some reason, when testing it now, it works. Thank you :) $\endgroup$
    – dimitarsp
    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
1
$\begingroup$

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.

enter image description here

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 )
$\endgroup$
6
  • $\begingroup$ Thanks for the script. Unfortunately it crashes Blender for some reason. $\endgroup$
    – dimitarsp
    Commented Nov 18, 2015 at 16:01
  • $\begingroup$ Weird, worked for me. Can you upload a blendfile? blend-exchange.giantcowfilms.com $\endgroup$
    – TLousky
    Commented 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$
    – batFINGER
    Commented Nov 19, 2015 at 10:37
  • $\begingroup$ Makes sense, @batFINGER, will add and test it. $\endgroup$
    – TLousky
    Commented 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$
    – TLousky
    Commented Nov 19, 2015 at 10:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .