[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3639] trunk/py/scripts/addons/ add_mesh_extra_objects/add_mesh_pyramid.py: Allow for anywhere from a 3 sided pyramid to 20 sided pyramid.

Philip Cote cotejrp at gmail.com
Fri Jul 20 01:07:39 CEST 2012


Revision: 3639
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3639
Author:   cotejrp1
Date:     2012-07-19 23:07:39 +0000 (Thu, 19 Jul 2012)
Log Message:
-----------
Allow for anywhere from a 3 sided pyramid to 20 sided pyramid.

Modified Paths:
--------------
    trunk/py/scripts/addons/add_mesh_extra_objects/add_mesh_pyramid.py

Modified: trunk/py/scripts/addons/add_mesh_extra_objects/add_mesh_pyramid.py
===================================================================
--- trunk/py/scripts/addons/add_mesh_extra_objects/add_mesh_pyramid.py	2012-07-19 19:31:49 UTC (rev 3638)
+++ trunk/py/scripts/addons/add_mesh_extra_objects/add_mesh_pyramid.py	2012-07-19 23:07:39 UTC (rev 3639)
@@ -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,129 +32,150 @@
 
 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):
+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
 
-    vert_list = []
-    face_list = []
 
-    cur_size = initial_size  # how large each step will be overall
+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
+    
 
-    # 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)
+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
 
-        # 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)
+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()
 
-        # add to the vert buffer
-        vert_list.extend((bfl, bfr, bbl, bbr, tfl, tfr, tbl, tbr,))
-
+        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
-        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 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")
+        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)
     
-    for vert in verts:
-        bm.verts.new(vert)
-    
-    for face in faces:
-        bm.faces.new([bm.verts[i] for i in face])
-    
-    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")
+    
+    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) 
+    
 
-    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")
-
     def execute(self, context):
         add_pyramid_object(self, context)
         return {'FINISHED'}
 
 '''
 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__":



More information about the Bf-extensions-cvs mailing list