6
$\begingroup$

This is a python question. What I want is a function that takes a mesh M and a bounding box B (This bounding box can be axis aligned or on an arbitrary angle. This detail isn't important, which ever is easier to implement, so it's okay to restrict B to be an axis aligned box if it helps) I want a new mesh M' that is subdivided so that M' fits perfectly into the bounding box B. To make it more clear, if a polygon P in mesh M is partially inside B and outside B, then that polygon needs to be split into P1 to Pn, and only the polygons inside B are returned; the rest are discarded.

I want this to be non-destructive, so M' shouldn't be added to the scene, nor should M be changed in anyway. I just want a new mesh that's not a part of the scene, so that I can export it. I already know how to split polygons by planes and implement this from scratch, however, I want to know how much of this is already implemented/not implemented for me within blender's libraries. It seems non-trivial to do this from scratch, and just using my linear algebra knowledge.

$\endgroup$
3
  • 1
    $\begingroup$ If I understand correctly, you want only the part of the mesh which intersects the bounding box? You could try using a boolean modifier $\endgroup$
    – gandalf3
    Apr 15, 2014 at 22:00
  • $\begingroup$ @gandalf3 yes, but in addition, if a polygon P in mesh M is partially inside B and outside B, then that polygon needs to be split into P1 to Pn, and only the polygons inside B are returned; the rest are discarded. $\endgroup$ Apr 15, 2014 at 22:04
  • $\begingroup$ @gandalf3 boolean modifier seems like exactly what I want. I just need to look up the blender API for it. Thanks! $\endgroup$ Apr 15, 2014 at 22:17

1 Answer 1

5
$\begingroup$

This slices a mesh object into axis-aligned parts (changing the active object):

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):
        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):
        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)])

for i in range(-10, 10):
        ret = bmesh.ops.bisect_plane(bm, geom=bm.verts[:]+bm.edges[:]+bm.faces[:], plane_co=(0,0,i), plane_no=(0,0,1))
        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')

The separate operator is needed, but you could write the bmesh to a new mesh datablock and temporarily bind it to a new object and run this operator. Then unlink it from the scene and delete, keeping the sliced mesh. Bmesh syntax in short:

bm = bmesh.new()
bm.from_mesh(me) # or from_object(ob, scene)
#...
me2 = bpy.data.meshes.new("Sliced")
bm.to_mesh(me2)
#...
$\endgroup$
3
  • $\begingroup$ I like this more than using boolean modifier. Thanks! $\endgroup$ Apr 15, 2014 at 22:33
  • $\begingroup$ sorry, one more question. Where is bmesh.ops.bisect_plane and bmesh.ops.split_edges documented? And how did you know that 'geom_cut' are the edges that were added? I can't seem to find the behavior of these functions anywhere on the docs =/ $\endgroup$ Apr 16, 2014 at 1:23
  • $\begingroup$ You can find it here: blender.org/documentation/blender_python_api_2_70a_release/… $\endgroup$
    – CodeManX
    Apr 16, 2014 at 8:50

You must log in to answer this question.

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