Creating pockets using bmesh/python I'm trying to figure out how to create a pocket using bmesh (Python Console). The regular workflow to create the example below could be as follows —



Add a Cube in Object Mode, tab into Edit Mode and select an arbitrary Face. Then, use the following steps —


Extrude the selected Face
Scale the selected Face
Extrude the selected Face again
Translate the selected Face


The question is how to create the same result using bmesh? To get started in the Python Console,

import mathutils
import bmesh

me = bpy.context.edit_object.data
bm = bmesh.from_edit_mesh(me)


Let's just extrude an arbitrary Face and continue from there

f = bm.faces[2]  
d = bmesh.ops.extrude_discrete_faces(bm, faces=[f])
f = d['faces'][0]


Now f refers to the extruded Face. The next step is to scale the extruded Face. To keep things simple, let's assume the normal of the selected Face is parallel to the x-axis. The following code only works as intended if the cube is centered around the origin

bmesh.ops.scale(bm, vec=mathutils.Vector((1,.5,.5)), verts=f.verts)


because bmesh.ops.scale() seems to use the global (world) coordinates. Is it possibible to use local coordinates instead?

Another option might be to use bmesh.ops.inset_individual(), though unfortunately it does not create the 4 trapezoid Faces.

The last two steps are straightforward, just another bmesh.ops.extrude_discrete_faces() followed by bmesh.ops.translate().
This seems to work, in edit mode (for the simplicity of example)

import bpy
import bmesh

obj = bpy.context.edit_object
me = obj.data
bm = bmesh.from_edit_mesh(me)

face = [bm.faces.active]

bmesh.ops.inset_region(bm, faces=face, thickness=0.4)
bmesh.ops.inset_region(bm, faces=face, thickness=0, depth=-0.5)

bmesh.update_edit_mesh(me, True)




Regarding bmesh.ops.scale(), it takes a space argument which is a matrix to base the operation on. If you are comfortable generating matrices then that's probably enough, but if not then see this snippet.

Template can be found at TextEditor->Templates->Python->Bmesh Simple

import bpy
import bmesh
from mathutils import Vector, Matrix

# Get the active mesh
me = bpy.context.object.data
bm = bmesh.new()   # create an empty BMesh
bm.from_mesh(me)   # fill it in from a Mesh

bm.edges.ensure_lookup_table()
bm.verts.ensure_lookup_table()

e = bm.edges[0]

mid_invert = (e.verts[0].co + e.verts[1].co) * -0.5
edge_matrix = Matrix()
edge_matrix[0][3] = mid_invert[0]
edge_matrix[1][3] = mid_invert[1]
edge_matrix[2][3] = mid_invert[2]

factor = (0.5, 0.5, 0.5)
bmesh.ops.scale(bm, vec=factor, space=edge_matrix, verts=e.verts)

# Finish up, write the bmesh back to the mesh
bm.to_mesh(me)
bm.free()  # free and prevent further access


I'm almost positive that there is an easier way to construct the space matrix, given a simple 3-vector, rather than my verbose approach.