5
$\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$
  • 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 '14 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$ – spearmunkie Apr 15 '14 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$ – spearmunkie Apr 15 '14 at 22:17
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)
#...
| improve this answer | |
$\endgroup$
  • $\begingroup$ I like this more than using boolean modifier. Thanks! $\endgroup$ – spearmunkie Apr 15 '14 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$ – spearmunkie Apr 16 '14 at 1:23
  • $\begingroup$ You can find it here: blender.org/documentation/blender_python_api_2_70a_release/… $\endgroup$ – CodeManX Apr 16 '14 at 8:50

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.