I have use case where I need split a large mesh into small pieces. When I select and separate each of the desired pieces separately, the consolidation of the indices of the large mesh (i.e. building new packed vertex and face lists) takes alot of time. The consolidation is not really necessary in my use case, as I will be splitting off more pieces right away. If I mark all the different split regions using different materials and separate by material, the runtime suggest to me that this approach is also splitting of the regions piece by piece and consolidating the larger mesh in each iteration. So what is the most efficient way to tackle this problem?


2 Answers 2


The general case can get pretty messy, but if you just want to copy geometry and materials you can start from the code at http://web.purplefrog.com/~thoth/blender/python-cookbook/split-copy-mesh.html . It splits the mesh according to the material. It avoids bpy.ops and instead uses mesh.from_python to build the geometry of each fragment from a subset of the original.

Here is a copy of the relevant section:

import bpy
from math import *
from mathutils import *

def split_copy_mesh(obj, discriminant):

    accumulator = {}

    for polygon in obj.data.polygons:
        tag = discriminant(polygon)

        acc = accumulator.get(tag)
        if acc is None:
            acc = {
                "vertMap": {}
            accumulator[tag] = acc

        face = []
        for vi in polygon.vertices:
            vi2 = acc["vertMap"].get(vi)
            if vi2 is None:
                verts = acc["verts"]
                vi2 = len( verts )
                acc["vertMap"][vi] = vi2

    rval = []
    for tag,acc in accumulator.items():

        mesh = bpy.data.meshes.new(tag)
        mesh.from_pydata(acc["verts"], [], acc["faces"])

        for mat in obj.data.materials:

        for i in range(len(mesh.polygons)):
            mesh.polygons[i].material_index = acc["materials"][i]

        obj = bpy.data.objects.new(tag, mesh)

    return rval

#fabricate_test_mesh(bpy.context.scene, 3, 8)
copies = split_copy_mesh(bpy.data.objects['multisphere'], lambda p: "m%d"%p.material_index)

for obj in copies:
    obj.location = (5,0,0)

If you want to preserve modifiers or uv maps, or shape keys or other information, you will have to add more code to copy this information from the original mesh.


This can be done by separating the big mesh into small meshes using the below script:

import bpy
ob = bpy.data.objects['MyMesh'] #### replace MyMesh with the name of your Mesh object
ob.select = True
bpy.context.scene.objects.active = ob


If the object has no loose parts and you know the list of faces to separate then you can loop on them then separate using selection using the script below which I tested and it is working:

import bpy
ob = bpy.data.objects['MyMesh'] #### replace MyMesh with the name of your Mesh object
ob.select = True
bpy.context.scene.objects.active = ob
faces_to_separate = [0,2,4,6,8,10] #### add the list of faces you want to separate
mesh = ob.data
for face in mesh.polygons:
    if face.index in faces_to_separate:
        face.select = True
  • $\begingroup$ @ideasman42 sorry, I updated my answer. $\endgroup$
    – Tak
    Feb 6, 2017 at 2:29
  • 1
    $\begingroup$ This wont work if ob is hidden, or its layer isn't visible - better to pass in a custom context. $\endgroup$
    – ideasman42
    Feb 6, 2017 at 2:37
  • $\begingroup$ I don't understand your suggestion. Just to clarify: The input mesh has no loose elements, it's a connected mesh that is to be split in specific parts. I know the indices of the faces that go into the split meshes and right now assign different materials to those faces and separate using the 'MATERIAL' type. $\endgroup$
    – DrPepperJo
    Feb 8, 2017 at 12:36
  • $\begingroup$ @DrPepperJo answer updated to separate using a list of faces $\endgroup$
    – Tak
    Feb 8, 2017 at 23:32
  • 1
    $\begingroup$ I have voted down because you don't get what DrPepperJo is asking for and so your reply is irrelevant - the task is to separate a mesh EFFICIENTLY, which can't be achieved by calling the separate() method on the each iteration. Try to test your script in a case when you need to split a mesh to thousand objects, this can take even an hour or more. $\endgroup$ Jul 12, 2019 at 8:47

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.