1
$\begingroup$

I created this example, where I only have 1 object that contains 2 cubes (mesh). These cubes respectively have a vertex group,1 UV Map and share 4 materials.

  • Vertex group "Cube1" white and green
  • Vertex group "Cube2" red and yellow

I was wondering if there was a way to create 2 new objects. I found this example to iterate at the vertices mesh of a respective group of vertices, but I was wondering if it was possible, to create 2 new objects, iterating also to the materials, since it is necessary to iterate the C.object.data I would have everything I believe available. Anyone have any suggestions of how to do such a thing? Keeping in mind that I would like 2 items with 2 materials and its UV map per item as a result.

I add a detail that I had omitted but I took for granted. Objects must be separated according to the group of vertices

enter image description here

$\endgroup$
0
2
$\begingroup$

Dupe n Delete

Similarly to another answer re materials and "normalizing" material slots (removing unused), can use a default dictionary with a list of the vertices of each vertex group, then remove others from from a dupe for each group.

Ultimately this would be better if could split using bmesh, but as of now cannot set a split target to another mesh or bmesh instance.

Note this will split based on vertex group. Vertices that are members of more than one group will be in each split off object. Vertices not assigned to any group will not be split off into new object.

Using copy on both the object and the mesh brings along all data.

import bpy
from collections import defaultdict
import bmesh

context = bpy.context

ob = context.object
me = ob.data
vgs = ob.vertex_groups[:]
col = context.collection
rg = defaultdict(set)

for v in me.vertices:
    for g in v.groups:
        rg[vgs[g.group]].add(v.index)

bm = bmesh.new()
all_verts = set(range(len(me.vertices)))

for vg, verts in rg.items():
    if not verts:
        continue #  no empty vg mesh
    oc = ob.copy()
    oc.name = vg.name
    me = oc.data = oc.data.copy()
    bm.from_mesh(me)
    bm.verts.ensure_lookup_table()
    bmesh.ops.delete(bm,
        geom=list(bm.verts[i] for i in (all_verts - verts)),
        context='VERTS',
        )
    bm.to_mesh(me)
    bm.clear()
    for g in oc.vertex_groups:
        if g.name != vg.name:
            oc.vertex_groups.remove(g)       
    col.objects.link(oc)

Note I haven't bothered to remove materials, as mentioned this is similar to a previous script used in one of your answers, to test what materials are on a face and remove.

Alternatively, instead of copying a new mesh each time, copy the bmesh and write to a new mesh. Once again will have to deal with materials, using all faces left after delete operator, to check which materials are assigned to faces of a particular vertex group.

See Delete all materials that aren't assigned to a face?

If the material is data (mesh) linked, can append to the Mesh.materials collection instead of using the slot operators.

import bpy
from collections import defaultdict
import bmesh

context = bpy.context

ob = context.object
me = ob.data
vgs = ob.vertex_groups[:]
col = context.collection
rg = defaultdict(set)

for v in me.vertices:
    for g in v.groups:
        rg[vgs[g.group]].add(v.index)

bm = bmesh.new()
all_verts = set(range(len(me.vertices)))
bm.from_mesh(me)
for vg, verts in rg.items():
    if not verts:
        continue #  no empty vg mesh
    oc = ob.copy()
    oc.name = vg.name
    oc.data = bpy.data.meshes.new(vg.name)
    bmc = bm.copy()
    bmc.verts.ensure_lookup_table()
    bmesh.ops.delete(bmc,
        geom=list(bmc.verts[i] for i in (all_verts - verts)),
        context='VERTS',
        )
    bmc.to_mesh(oc.data)
    bmc.free()
    for g in oc.vertex_groups:
        if g.name != vg.name:
            oc.vertex_groups.remove(g)       
    col.objects.link(oc)
$\endgroup$
2
  • $\begingroup$ This looks good but has a problem, I have tried to deal with an object with with many groups of vertices and it seems very slow, although I must say that it does its job. $\endgroup$
    – Noob Cat
    Mar 5 '20 at 17:01
  • $\begingroup$ I'm trying to understand what your script does, but I noticed (correct me if I'm wrong), copy the whole object and then delete what is not needed with bmesh.ops? Couldn't you think of doing a construction operation from 0? That is, it takes the materials on the faces, the UV and polygons, vertices, edges. And from this create a new object instead of copying the whole context object? I would just like to understand whether to abandon the idea or proceed further studying $\endgroup$
    – Noob Cat
    Mar 5 '20 at 19:23

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.