Skip to content

Instantly share code, notes, and snippets.

@aaronjolson
Created February 9, 2019 16:38
Show Gist options
  • Save aaronjolson/4eda04dad798e06d897e2b18f779b958 to your computer and use it in GitHub Desktop.
Save aaronjolson/4eda04dad798e06d897e2b18f779b958 to your computer and use it in GitHub Desktop.
Script to create a spiral staircase in blender. As-is, it runs standalone, but it can easily be refactored to integrate it into a project
import bpy
import bmesh
# cleans out the rest of the objects from the scene and puts the cube in, essentially a fresh start, useful for debugging
bpy.ops.object.select_all(action='TOGGLE')
bpy.ops.object.select_all(action='TOGGLE')
bpy.ops.object.delete(use_global=False)
bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)
bpy.ops.mesh.primitive_cube_add(radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))
ob = bpy.data.objects['Cube']
# jump into edit mode with the cube object selected
bpy.ops.object.mode_set(mode='EDIT')
# get mesh data and save in variable
mesh = bmesh.from_edit_mesh(bpy.context.object.data)
# look at all of the faces of the cube, find the one that is 'facing' the positive direction on the y axis
for f in mesh.faces:
if f.normal.y == 1.0:
f.select = True
ur_face = f
# bmesh.ops.translate(mesh, vec=(0,2,0), verts=ur_face['geom'][-1].verts)
bmesh.ops.translate(mesh, vec=(0,2,0), verts=ur_face.verts)
# could do bpy.ops.mesh.select_all(action='DESELECT') instead
for f in mesh.faces:
f.select = False
for f in mesh.faces:
if f.normal.z == -1.0: # -1, since it is the bottom z normal face
f.select = True
ur_face = f
# vertically slim the cube
bmesh.ops.translate(mesh, vec=(0,0,1), verts=ur_face.verts) # translate z up, makes the bottom of the cube flush with the pivot point
# deselect all faces
for f in mesh.faces:
f.select = False
# widen the stair's corner length to remove gap
for v in mesh.verts:
if v.co.x == 1.0 and v.co.y == 3.0:
v.select = True
bpy.ops.transform.translate(value=(0.7, -0.20, 0), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True, use_accurate=False)
bpy.ops.mesh.select_all(action='DESELECT')
# create empty arrow object adn rotate it right
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.empty_add(type='ARROWS', view_align=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))
bpy.ops.transform.rotate(value=-0.35, axis=(0.0, 0.0, 1), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
bpy.ops.object.select_all(action='DESELECT')
# re-select cube, add an array modifier to it, set the empty object as an offset object
bpy.context.scene.objects.active = bpy.data.objects['Cube']
bpy.data.objects['Cube'].select = True
bpy.ops.object.modifier_add(type='ARRAY')
bpy.context.object.modifiers["Array"].relative_offset_displace[0] = 0.6
bpy.context.object.modifiers["Array"].relative_offset_displace[1] = -0.1
bpy.context.object.modifiers["Array"].relative_offset_displace[2] = 0.9
bpy.context.object.modifiers["Array"].count = 25
bpy.context.object.modifiers["Array"].use_object_offset = True
bpy.context.object.modifiers["Array"].offset_object = bpy.data.objects["Empty"]
bpy.context.object.modifiers["Array"].use_relative_offset = True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment