Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Blender MultiExtrude from Blender Artists Liero
################################################################################
# Repeats extrusion + rotation + scale for one or more faces #
################################################################################
bl_info = {
"name": "MExtrude",
"version": (1, 3, 0),
"blender": (2, 6, 8),
"location": "View3D > Tool Shelf",
"description": "Repeat extrusions from faces to create organic shapes",
'warning': '',
"category": "Mesh"}
import bpy, bmesh, random
from random import gauss
from math import radians
from mathutils import Euler
from bpy.props import FloatProperty, IntProperty
def vloc(self, r):
random.seed(self.ran + r)
return self.off * (1 + random.gauss(0, self.var1 / 3))
def vrot(self,r):
random.seed(self.ran + r)
return Euler((radians(self.rotx) + random.gauss(0, self.var2 / 3), \
radians(self.roty) + random.gauss(0, self.var2 / 3), \
radians(self.rotz) + random.gauss(0,self.var2 / 3)), 'XYZ')
def vsca(self, r):
random.seed(self.ran + r)
return self.sca * (1 + random.gauss(0, self.var3 / 3))
class MExtrude(bpy.types.Operator):
bl_idname = 'object.mextrude'
bl_label = 'MExtrude'
bl_description = 'Multi Extrude'
bl_options = {'REGISTER', 'UNDO'}
off = FloatProperty(name='Offset', min=-2, soft_min=0.001, \
soft_max=2, max=5, default=.5, description='Translation')
rotx = FloatProperty(name='Rot X', min=-85, soft_min=-30, \
soft_max=30, max=85, default=0, description='X rotation')
roty = FloatProperty(name='Rot Y', min=-85, soft_min=-30, \
soft_max=30, max=85, default=0, description='Y rotation')
rotz = FloatProperty(name='Rot Z', min=-85, soft_min=-30, \
soft_max=30, max=85, default=-0, description='Z rotation')
sca = FloatProperty(name='Scale', min=0.1, soft_min=0.5, \
soft_max=1.2, max =2, default=.9, description='Scaling')
var1 = FloatProperty(name='Offset Var', min=-5, soft_min=-1, \
soft_max=1, max=5, default=0, description='Offset variation')
var2 = FloatProperty(name='Rotation Var', min=-5, soft_min=-1, \
soft_max=1, max=5, default=0, description='Rotation variation')
var3 = FloatProperty(name='Scale Noise', min=-5, soft_min=-1, \
soft_max=1, max=5, default=0, description='Scaling noise')
num = IntProperty(name='Repeat', min=1, max=50, soft_max=100, \
default=5, description='Repetitions')
ran = IntProperty(name='Seed', min=-9999, max=9999, default=0, \
description='Seed to feed random values')
@classmethod
def poll(cls, context):
obj = context.object
return (obj and obj.type == 'MESH')
def draw(self, context):
layout = self.layout
column = layout.column(align=True)
column.label(text='Transformations:')
column.prop(self, 'off', slider=True)
column.prop(self, 'rotx', slider=True)
column.prop(self, 'roty', slider=True)
column.prop(self, 'rotz', slider=True)
column.prop(self, 'sca', slider=True)
column = layout.column(align=True)
column.label(text='Variation settings:')
column.prop(self, 'var1', slider=True)
column.prop(self, 'var2', slider=True)
column.prop(self, 'var3', slider=True)
column.prop(self, 'ran')
column = layout.column(align=False)
column.prop(self, 'num')
def execute(self, context):
obj = bpy.context.object
data, om = obj.data, obj.mode
bpy.context.tool_settings.mesh_select_mode = [False, False, True]
# bmesh operations
bpy.ops.object.mode_set()
bm = bmesh.new()
bm.from_mesh(obj.data)
sel = [f for f in bm.faces if f.select]
# faces loop
for i, of in enumerate(sel):
rot = vrot(self, i)
off = vloc(self, i)
of.normal_update()
# extrusion loop
for r in range(self.num):
nf = of.copy()
nf.normal_update()
no = nf.normal.copy()
ce = nf.calc_center_bounds()
s = vsca(self, i + r)
for v in nf.verts:
v.co -= ce
v.co.rotate(rot)
v.co += ce + no * off
v.co = v.co.lerp(ce, 1 - s)
# extrude code from TrumanBlending
for a, b in zip(of.loops, nf.loops):
sf = bm.faces.new((a.vert, a.link_loop_next.vert, \
b.link_loop_next.vert, b.vert))
sf.normal_update()
bm.faces.remove(of)
nf.select_set(True)
of = nf
for v in bm.verts: v.select = False
for e in bm.edges: e.select = False
bm.to_mesh(obj.data)
obj.data.update()
# restore user settings
bpy.ops.object.mode_set(mode=om)
if not len(sel):
self.report({'INFO'}, 'Select one or more faces...')
return{'FINISHED'}
class BotonME(bpy.types.Panel):
bl_label = 'Multi Extrude'
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
def draw(self, context):
layout = self.layout
layout.operator('object.mextrude')
def register():
bpy.utils.register_class(MExtrude)
bpy.utils.register_class(BotonME)
def unregister():
bpy.utils.unregister_class(MExtrude)
bpy.utils.unregister_class(BotonME)
if __name__ == '__main__':
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment