Skip to content
Snippets Groups Projects
Commit 6c19e6cf authored by Philip Cote's avatar Philip Cote
Browse files

Allow for anywhere from a 3 sided pyramid to 20 sided pyramid.

parent a6689e08
No related branches found
No related tags found
No related merge requests found
......@@ -22,7 +22,7 @@
bl_info = {
'name': 'Mesh Pyramid',
'author': 'Phil Cote, cotejrp1, (http://www.blenderaddons.com)',
'version': (0, 4),
'version': (0, 5),
"blender": (2, 6, 3),
'location': 'View3D > Add > Mesh',
'description': 'Create an egyption-style step pyramid',
......@@ -32,111 +32,133 @@ bl_info = {
import bpy
import bmesh
from bpy.props import IntProperty, FloatProperty
from bpy.props import FloatProperty, IntProperty
from math import pi
from mathutils import Quaternion, Vector
from bpy_extras.object_utils import AddObjectHelper, object_data_add
def makePyramid(initial_size, step_height, step_width, number_steps):
vert_list = []
face_list = []
cur_size = initial_size # how large each step will be overall
# b = buttom, t = top, f = front, b = back, l = left, r = right
x = y = z = 0
voffset = 0 # relative vert indices to help make faces fo each step
sn = 0 # step number
while sn < number_steps:
# bottom verts for this iteration
bfl = (x, y, z)
bfr = (x + cur_size, y, z)
bbl = (x, y + cur_size, z)
bbr = (x + cur_size, y + cur_size, z)
# top verts for this iteration.
tfl = (x, y, z + step_height)
tfr = (x + cur_size, y, z + step_height)
tbl = (x, y + cur_size, z + step_height)
tbr = (x + cur_size, y + cur_size, z + step_height)
# add to the vert buffer
vert_list.extend((bfl, bfr, bbl, bbr, tfl, tfr, tbl, tbr,))
def create_step(width, base_level, step_height, num_sides):
axis = [0,0,-1]
PI2 = pi * 2
rad = width / 2
quat_angles = [(cur_side/num_sides) * PI2
for cur_side in range(num_sides)]
quaternions = [Quaternion(axis, quat_angle)
for quat_angle in quat_angles]
init_vectors = [Vector([rad, 0, base_level])
for quat in quaternions]
quat_vector_pairs = list(zip(quaternions, init_vectors))
vectors = [quaternion * vec for quaternion, vec in quat_vector_pairs]
bottom_list = [(vec.x, vec.y, vec.z) for vec in vectors]
top_list = [(vec.x, vec.y, vec.z+step_height) for vec in vectors]
full_list = bottom_list + top_list
return full_list
def split_list(l, n):
"""
split the blocks up. Credit to oremj for this one.
http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python
"""
n *= 2
returned_list = [l[i:i+n] for i in range(0, len(l), n)]
return returned_list
# side faces
face_list.extend((
(voffset + 4, voffset + 5, voffset + 1, voffset + 0), # back
(voffset + 6, voffset + 7, voffset + 3, voffset + 2), # front
(voffset + 2, voffset + 6, voffset + 4, voffset + 0), # left
(voffset + 3, voffset + 7, voffset + 5, voffset + 1), # right
))
# horizontal connecting faces ( note: n/a for the first iteration ).
if voffset > 0:
face_list.extend((
(voffset - 4, voffset - 3, voffset + 1, voffset + 0), # connector front
(voffset - 2, voffset - 1, voffset + 3, voffset + 2), # back
(voffset - 4, voffset - 2, voffset + 2, voffset + 0), # left
(voffset - 3, voffset - 1, voffset + 3, voffset + 1), # right
))
# set up parameters for the next iteration
cur_size = cur_size - (step_width * 2)
x = x + step_width
y = y + step_width
z = z + step_height
sn = sn + 1
voffset = voffset + 8
voffset = voffset - 8 # remove extra voffset done on final iteration
face_list.extend((
(voffset + 6, voffset + 7, voffset + 5, voffset + 4), # cap the top.
(2, 3, 1, 0), # cap the bottom.
))
return vert_list, face_list
def get_connector_pairs(lst, n_sides):
# chop off the verts that get used for the base and top
lst = lst[n_sides:]
lst = lst[:-n_sides]
lst = split_list(lst, n_sides)
return lst
def add_pyramid_object(self, context):
verts, faces = makePyramid(self.initial_size, self.step_height,
self.step_width, self.number_steps)
bm = bmesh.new()
mesh = bpy.data.meshes.new(name="Pyramid")
for vert in verts:
bm.verts.new(vert)
for face in faces:
bm.faces.new([bm.verts[i] for i in face])
all_verts = []
height_offset = 0
cur_width = self.width
for i in range(self.num_steps):
verts_loc = create_step(cur_width, height_offset, self.height,
self.num_sides)
height_offset += self.height
cur_width -= self.reduce_by
all_verts.extend(verts_loc)
mesh = bpy.data.meshes.new("Pyramid")
bm = bmesh.new()
for v_co in all_verts:
bm.verts.new(v_co)
# do the sides.
n = self.num_sides
def add_faces(n, block_vert_sets):
for bvs in block_vert_sets:
for i in range(self.num_sides-1):
bm.faces.new([bvs[i], bvs[i+n], bvs[i+n+1], bvs[i+1]])
bm.faces.new([bvs[n-1], bvs[(n*2)-1], bvs[n], bvs[0]])
# get the base and cap faces done.
bm.faces.new(bm.verts[0:self.num_sides])
bm.faces.new(bm.verts[-self.num_sides:])
# side faces
block_vert_sets = split_list(bm.verts, self.num_sides)
add_faces(self.num_sides, block_vert_sets)
# connector faces between faces and faces of the block above it.
connector_pairs = get_connector_pairs(bm.verts, self.num_sides)
add_faces(self.num_sides, connector_pairs)
bm.to_mesh(mesh)
mesh.update()
res = object_data_add(context, mesh, operator=self)
bm.to_mesh(mesh)
mesh.update()
res = object_data_add(context, mesh, operator=self)
class AddPyramid(bpy.types.Operator, AddObjectHelper):
"""Add a Mesh Object"""
'''Add a mesh pyramid'''
bl_idname = "mesh.primitive_steppyramid_add"
bl_label = "Pyramid"
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
initial_size = FloatProperty(name="Initial Size", default=2.0,
min=0.0, max=20.0,
description="Set the initial size at the pyramid base")
step_height = FloatProperty(name="Step Height", default=0.1,
min=0.0, max=10.0,
description="How tall each of the steps will be")
step_width = FloatProperty(name="Step Width", default=0.1,
min=0.0, max=10.0,
description="How wide each step will be")
number_steps = IntProperty(name="Number Steps", default=10,
min=1, max=20,
description="Total number of steps")
num_sides = IntProperty(
name="Number Sides",
description = "How many sides each step will have",
min = 3, max = 20, default=4)
num_steps = IntProperty(
name="Number of Steps",
description="How many steps for the overall pyramid",
min=1, max=20, default=10)
width = FloatProperty(
name="Initial Width",
description="Initial base step width",
min=0.01, max=100.0,
default=2)
height = FloatProperty(
name="Height",
description="How tall each step will be",
min=0.01, max=100.0,
default=0.1)
reduce_by = FloatProperty(
name="Reduce Step By",
description = "How much to reduce each succeeding step by",
min=.01, max = 2.0, default= .20)
def execute(self, context):
add_pyramid_object(self, context)
......@@ -144,17 +166,16 @@ class AddPyramid(bpy.types.Operator, AddObjectHelper):
'''
def menu_func(self, context):
self.layout.operator(OBJECT_OT_add_pyramid.bl_idname,
text="Pyramid", icon="PLUGIN")
self.layout.operator(AddPyramid.bl_idname, icon='PLUGIN')
def register():
bpy.utils.register_class(OBJECT_OT_add_pyramid)
bpy.utils.register_class(AddPyramid)
bpy.types.INFO_MT_mesh_add.append(menu_func)
def unregister():
bpy.utils.unregister_class(OBJECT_OT_add_pyramid)
bpy.utils.unregister_class(AddPyramid)
bpy.types.INFO_MT_mesh_add.remove(menu_func)
if __name__ == "__main__":
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment