Skip to content
Snippets Groups Projects
add_mesh_pyramid.py 5.86 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ***** 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 *****
    
    bl_info = {
        'name': 'Mesh Pyramid',
    
    Philip Cote's avatar
    Philip Cote committed
        'author': 'Phil Cote, cotejrp1, (http://www.blenderaddons.com)',
    
    Philip Cote's avatar
    Philip Cote committed
        "blender": (2, 6, 3),
    
        'location': 'View3D > Add > Mesh',
        'description': 'Create an egyption-style step pyramid',
    
        'warning': '',  # used for warning icon and text in addons panel
    
    Philip Cote's avatar
    Philip Cote committed
    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]) 
                                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
        
    
    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
    
            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)
    
    Philip Cote's avatar
    Philip Cote committed
        
    
    class AddPyramid(bpy.types.Operator, AddObjectHelper):
    
        bl_idname = "mesh.primitive_steppyramid_add"
    
    Brendon Murphy's avatar
    Brendon Murphy committed
        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'}
    
        self.layout.operator(AddPyramid.bl_idname, icon='PLUGIN')
    
        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()
    
    Guillermo S. Romero's avatar
    Guillermo S. Romero committed
    '''