# use python to randomly inset each face, bmesh?

I would like to create some interesting shapes with a script. I'm still pretty new to python and I'm having trouble understanding how to get BMesh to behave the way I want. Here is what I'm trying to accomplish.

1. Randomly inset faces a random length, with some not being inset at all.

2. Advanced function: randomly inset again excluding the 4 faces around original insets (if that makes sense)

import bpy
import bmesh
from random import randint, random

obj = bpy.context.active_object

bm = bmesh.new()
bm.from_mesh(obj.data,face_normals=True)

for faces in bm.faces:
if randint(0,1) > 0:
bmesh.ops.inset_region(bm, faces=bm.faces, thickness=0.4, depth=randint(0,1))

bm.to_mesh(obj.data)
bm.free()
obj.data.update()


Here is an idea of what I'm going for generated from a cube.

## 1 Answer

You can't loop through bm.faces, because you are creating more faces in the loop, which are also iterated over. Instead make a copy of the faces

faces_copy = [f for f in bm.faces]


Now, your code would give us the following result.

Notable problems - Insets, even at 0 depth. - Your example image shows and inset with 0 depth and then a random extrusion.

Let's implement that. Luckily, after a inset_region operation, the face index stays the same so we can simply extrude it by insetting another time and moving the face's vertices along the face normal.

bmesh.ops.inset_region(bm, faces = [face], thickness=0.4, depth=0)
bmesh.ops.inset_region(bm, faces = [face], thickness=0, depth=0)
bmesh.ops.translate(bm, verts = face.verts, vec = face.normal)


Now lets add the randomness:

import random
#[...]

bmesh.ops.inset_region(bm, faces = [face], thickness=random.uniform(0.1, 0.9), depth=0)
bmesh.ops.inset_region(bm, faces = [face], thickness=0, depth=0)
bmesh.ops.translate(bm, verts = face.verts, vec = face.normal * random.uniform(0.1, 4))


### Iterations

We need to catch the newly "extruded" faces. Luckily inset_region returns geometry. We can create a new face list like this:

geom = bmesh.ops.inset_region(bm, faces = [face], thickness=0, depth=0)
new_faces = geom['faces'] # list of bmesh faces


Create an empty list for the new faces. After the insetting and extrusion, we'll add the active face and the extruded side faces.

new_faces.extend(geom['faces'])
new_faces.append(face)


Complete code (with two iterations):

import bpy
import bmesh
import random
from mathutils import Vector

obj = bpy.context.active_object

bm = bmesh.new()
bm.from_mesh(obj.data,face_normals=True)

# faces, which could be extruded
faces_copy = [f for f in bm.faces]
new_faces = []
# number of iterations goes here
for i in range(0, 2):
for face in faces_copy:
do_inset = random.randint(0,1)
if do_inset:
bmesh.ops.inset_region(bm, faces = [face], thickness=random.uniform(0.1, 0.9), depth=0)
geom = bmesh.ops.inset_region(bm, faces = [face], thickness=0, depth=0)
bmesh.ops.translate(bm, verts = face.verts, vec = face.normal * random.uniform(0.1, 4))
new_faces.extend(geom['faces'])
new_faces.append(face)
faces_copy = new_faces
new_faces = []

bm.to_mesh(obj.data)
bm.free()
obj.data.update()


The concept is pretty cool, but it already show, that we need to implement a method to take the faces size into account before using bmesh.ops.translate.

• You are amazing! Thank you so much for your help. I had been spending days looking at other peoples code and documentation to try and understand this. Thank you for taking time to explain everything. May 7 '18 at 22:58
• @adminbromo You're welcome, I fiddled around a bit more with it and tried to add an intersection detection. It's not ready to be included in the answer, but may it'll help you anyways. May 7 '18 at 23:01
• Unless i'm missing something, you can copy a list by taking a "full slice" e.g. faces_copy = bm.faces[:]; probably better than a list comprehension. May 8 '18 at 3:26
• @StarWeaver Feel free to edit. I didn't use the slice notation since OP mentioned being new to python and it's even less clear what happens there. Also bm.faces is a BMFaceSeq and understanding why the list notation works on a collection is also not very beginner-friendly. May 8 '18 at 10:28
• Are there any resources that would help a new user like myself understand bmesh (or blender scripting in general). I have an okay understanding of python. Where I have trouble is understanding syntax and how to move things around within lists. I guess what I'm asking, are there any best practices or resources that you would recommend. One of the problems I run into is older versions of code that don't line up with newer versions. Especially when working with things like pie menus etc... Please don't feel like you need to answer this, I figured I would ask. Thanks again! May 8 '18 at 13:18