How to cut a mesh into smaller pieces with python? I have a big terrain object, I'm trying to write a script that cut it in smaller pieces and then I will export the pieces to other formats. This is required by a game engine because the mesh, if not subdivided at export time, is not properly culled, resulting in slow rendering.

I tried to use bpy.ops.view3d.select_border() but it fails with message:

RuntimeError: Operator bpy.ops.view3d.select_border.poll() expected a view3d region


A search revealed that select_border must be called from 3d view, probably by clicking a button. But this is not a generalized script, it is specific to this model, I will rewrite parts of it if I need it for another model. I want to run it from text editor directly.

The only solution I can see for now is to iterate every vertex of the selected object and if they are inside the defined tile size, then duplicate, separate, export, delete, and repeat moving one tile to the left, starting at object dimensions[0] / 2 * -1, dimensions[1] / 2 * -1. Iterate vertices and select them can be done from text editor.

Is there a more convenient way of doing this?
I don't think hijacking select_border() is a good approach. You could use the new bisect_plane() bmesh operator to slice your mesh.

Here's a straightforward script that slices a mesh into an aligned grid:

import bpy, bmesh
from bpy import context as C

bpy.ops.object.mode_set(mode='EDIT')

bm = bmesh.from_edit_mesh(C.object.data)

edges = []

for i in range(-10, 10, 2):
        ret = bmesh.ops.bisect_plane(bm, geom=bm.verts[:]+bm.edges[:]+bm.faces[:], plane_co=(i,0,0), plane_no=(-1,0,0))
        bmesh.ops.split_edges(bm, edges=[e for e in ret['geom_cut'] if isinstance(e, bmesh.types.BMEdge)])

for i in range(-10, 10, 2):
        ret = bmesh.ops.bisect_plane(bm, geom=bm.verts[:]+bm.edges[:]+bm.faces[:], plane_co=(0,i,0), plane_no=(0,1,0))
        bmesh.ops.split_edges(bm, edges=[e for e in ret['geom_cut'] if isinstance(e, bmesh.types.BMEdge)])


bmesh.update_edit_mesh(C.object.data)

bpy.ops.mesh.separate(type='LOOSE')
bpy.ops.object.mode_set(mode='OBJECT')