# Extrude faces of an icosphere from a python script

I have an array of values and I need to extrude each face - faces[i] - of an icosphere with the amount of arr[i] in the direction of it's normal.

I managed to extrude the face I have selected by hand and managed to get the list of all faces of the mesh, but can't find a way to combine these solutions.

• Share what you have so far. – iKlsR Jan 18 '15 at 22:00
• list(bpy.context.object.data.polygons) seems to give the faces. And bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate={ "constraint_orientation": 'NORMAL', "value": (x, y, z)}) extrudes the face that is selected. – mzdravkov Jan 18 '15 at 23:37

bmesh.ops.extrude_discrete_faces takes a list of faces and extrudes them, leaving them in the original place with new joining geometry. If we take the ['faces'] part of the data returned by extrude_discrete_faces we have a list of faces that have been extruded, these are the 'original' faces only, not the extra joining faces.

For each of these extruded faces we take the face normal and multiply it by the distance you wish to move the face and use that in bmesh.ops.translate to position them where you want.

import bpy
import bmesh

# sample set for cube
extrude_values = [0.1,0.2,0.3,0.4,0.5,0.6]

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

extrude_faces = bmesh.ops.extrude_discrete_faces(bm, faces=bm.faces)['faces']

for f_idx in range(len(extrude_faces)):
dr = extrude_faces[f_idx].normal * extrude_values[f_idx]
bmesh.ops.translate(bm, verts=extrude_faces[f_idx].verts, vec=dr)

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


I would solve this problem by doing a LOT of analytic geometry and avoid bpy.ops as much as possible (because bpy.ops has cooties). In fact, part of what you want I already did in my spikify script for the azathoth boogie animation.

In my case I was interpolating between the triangle of the icosphere face and the degenerate tip of the spike. Here's an excerpt:

def fab_layer(verts, base_indices, layer, max_layers, max_radius):

vavg = average( [ verts[vi] for vi in base_indices])

tip = vavg * max_radius / vavg.magnitude

rval_vi = []

for i in range(len(base_indices)):
v0 = verts[base_indices[i]]
v1 = (v0 * (max_layers-layer) + tip*layer ) / max_layers
idx = len(verts)
rval_vi.append(idx)
verts.append(v1)

return rval_vi


If you can mathematically decide what it means to "extrude" for your application (which will likely be different than mine) then you can come up with your own code.