1 # ***** BEGIN GPL LICENSE BLOCK *****
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # ***** END GPL LICENCE BLOCK *****
20 # (c) 2011 Phil Cote (cotejrp1)
23 "name": "Mesh Pyramid",
24 "author": "Phil Cote, cotejrp1, (http://www.blenderaddons.com)",
26 "blender": (2, 63, 0),
27 "location": "View3D > Add > Mesh",
28 "description": "Create an egyption-style step pyramid",
29 "warning": "", # used for warning icon and text in addons panel
30 "category": "Add Mesh",
36 from bpy
.props
import FloatProperty
, IntProperty
38 from mathutils
import Quaternion
, Vector
39 from bpy_extras
.object_utils
import AddObjectHelper
, object_data_add
42 def create_step(width
, base_level
, step_height
, num_sides
):
48 quat_angles
= [(cur_side
/num_sides
) * PI2
49 for cur_side
in range(num_sides
)]
51 quaternions
= [Quaternion(axis
, quat_angle
)
52 for quat_angle
in quat_angles
]
54 init_vectors
= [Vector([rad
, 0, base_level
])] * len(quaternions
)
56 quat_vector_pairs
= list(zip(quaternions
, init_vectors
))
57 vectors
= [quaternion
* vec
for quaternion
, vec
in quat_vector_pairs
]
58 bottom_list
= [(vec
.x
, vec
.y
, vec
.z
) for vec
in vectors
]
59 top_list
= [(vec
.x
, vec
.y
, vec
.z
+step_height
) for vec
in vectors
]
60 full_list
= bottom_list
+ top_list
66 split the blocks up. Credit to oremj for this one.
67 http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python
70 returned_list
= [l
[i
:i
+n
] for i
in range(0, len(l
), n
)]
75 def get_connector_pairs(lst
, n_sides
):
76 # chop off the verts that get used for the base and top
79 lst
= split_list(lst
, n_sides
)
82 def add_pyramid_object(self
, context
):
86 cur_width
= self
.width
88 for i
in range(self
.num_steps
):
89 verts_loc
= create_step(cur_width
, height_offset
, self
.height
,
91 height_offset
+= self
.height
92 cur_width
-= self
.reduce_by
93 all_verts
.extend(verts_loc
)
95 mesh
= bpy
.data
.meshes
.new("Pyramid")
98 for v_co
in all_verts
:
105 def add_faces(n
, block_vert_sets
):
106 for bvs
in block_vert_sets
:
107 for i
in range(self
.num_sides
-1):
108 bm
.faces
.new([bvs
[i
], bvs
[i
+n
], bvs
[i
+n
+1], bvs
[i
+1]])
109 bm
.faces
.new([bvs
[n
-1], bvs
[(n
*2)-1], bvs
[n
], bvs
[0]])
112 # get the base and cap faces done.
113 bm
.faces
.new(bm
.verts
[0:self
.num_sides
])
114 bm
.faces
.new(bm
.verts
[-self
.num_sides
:])
117 block_vert_sets
= split_list(bm
.verts
, self
.num_sides
)
118 add_faces(self
.num_sides
, block_vert_sets
)
120 # connector faces between faces and faces of the block above it.
121 connector_pairs
= get_connector_pairs(bm
.verts
, self
.num_sides
)
122 add_faces(self
.num_sides
, connector_pairs
)
126 res
= object_data_add(context
, mesh
, operator
=self
)
129 class AddPyramid(bpy
.types
.Operator
, AddObjectHelper
):
130 '''Add a mesh pyramid'''
131 bl_idname
= "mesh.primitive_steppyramid_add"
133 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
136 num_sides
= IntProperty(
138 description
= "How many sides each step will have",
139 min = 3, max = 20, default
=4)
140 num_steps
= IntProperty(
141 name
="Number of Steps",
142 description
="How many steps for the overall pyramid",
143 min=1, max=20, default
=10)
145 width
= FloatProperty(
146 name
="Initial Width",
147 description
="Initial base step width",
151 height
= FloatProperty(
153 description
="How tall each step will be",
157 reduce_by
= FloatProperty(
158 name
="Reduce Step By",
159 description
= "How much to reduce each succeeding step by",
160 min=.01, max = 2.0, default
= .20)
163 def execute(self
, context
):
164 add_pyramid_object(self
, context
)
168 def menu_func(self, context):
169 self.layout.operator(AddPyramid.bl_idname, icon='PLUGIN')
173 bpy.utils.register_class(AddPyramid)
174 bpy.types.INFO_MT_mesh_add.append(menu_func)
178 bpy.utils.unregister_class(AddPyramid)
179 bpy.types.INFO_MT_mesh_add.remove(menu_func)
181 if __name__ == "__main__":