# ***** BEGIN GPL LICENSE BLOCK ***** # # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # ***** END GPL LICENCE BLOCK ***** # (c) 2011 Phil Cote (cotejrp1) ''' bl_info = { 'name': 'Mesh Pyramid', 'author': 'Phil Cote, cotejrp1, (http://www.blenderaddons.com)', 'version': (0, 5), "blender": (2, 63, 0), 'location': 'View3D > Add > Mesh', 'description': 'Create an egyption-style step pyramid', 'warning': '', # used for warning icon and text in addons panel 'category': 'Add Mesh'} ''' import bpy import bmesh 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 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])] * len(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 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): 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) class AddPyramid(bpy.types.Operator, AddObjectHelper): '''Add a mesh pyramid''' bl_idname = "mesh.primitive_steppyramid_add" bl_label = "Pyramid" bl_options = {'REGISTER', 'UNDO', 'PRESET'} 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) return {'FINISHED'} ''' def menu_func(self, context): self.layout.operator(AddPyramid.bl_idname, icon='PLUGIN') def register(): bpy.utils.register_class(AddPyramid) bpy.types.INFO_MT_mesh_add.append(menu_func) def unregister(): bpy.utils.unregister_class(AddPyramid) bpy.types.INFO_MT_mesh_add.remove(menu_func) if __name__ == "__main__": register() '''