#!BPY

"""
Name: 'N-Pyramid'
Blender: 248
Group: 'AddMesh'
"""
__author__= ['Luis Sergio S. Moura Jr.']
__url__ = ("http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Add/N-Pyramid")
__version__= '0.1'
__bpydoc__= '''\

N-Pyramid Mesh

This script lets the user create a new primitive: A pyramid. Receives as input the 
number of sides, number of steps, height of each step and distance of each step.

0.1 - 2009-06-25 by Luis Sergio<br />
- initial version
'''

# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (c) Luis Sergio S. Moura Jr., 2007
#
# 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------

# Importing modules
import BPyAddMesh
import Blender
import math

PI = 3.1415926535897932384626433832795

# This generates as many faces as needed to close up a sequence of vertices.
def faceGen(SIDES, offset = 0):
        faces = []
        if (SIDES % 2 == 0):
                # Pair number of faces. Let's make quads.
                start = 0
                end = SIDES - 1
                while (start < (end-1)):
                        faces.append([start + offset, start+1 + offset, end-1 + offset, end + offset])
                        start = start + 1
                        end = end - 1
        else:
                # Odd number of faces. Triangles it is!
                start = 0
                end = SIDES - 1
                while (start < (end - 1)):
                        faces.append([start + offset, start + 1 + offset, end + offset])
                        start = start + 1
                        if (start < (end - 1)):
                                faces.append([end - 1 + offset, end + offset, start + offset,])
                                end = end - 1
        return(faces)

def add_pyramid(SIDES, STEPS, HSIZE, WSIZE):
	verts = []
	faces = []

	rot_step = 2 * PI / SIDES
	h = STEPS * HSIZE

	for i in range(STEPS):
                # Helper vertex groups
                v0 = [] # Previous group of vertexes
                v1 = [] # First group of vertexes for this level
                v2 = [] # Second group of vertexes for this level
                for j in range(SIDES):
                        v = 2 * i * SIDES + j
                        v0.append(v - SIDES)
                        v1.append(v)
                        v2.append(v + SIDES)
                v0.append(2 * i * SIDES - SIDES)
                v1.append(2 * i * SIDES)
                v2.append(2 * i * SIDES + SIDES)
                
                # Create CAP
                for j in range(SIDES):
                        vx = (i+1) * WSIZE * math.cos(rot_step * j)
                        vy = (i+1) * WSIZE * math.sin(rot_step * j)
                        v = [vx, vy, h]
                        verts.append(v)

                # Create CAP Face(s)
                if (i == 0):
                        if (SIDES <= 4):
                                face = []
                                for j in range(SIDES):
                                        face.append(j)
                                faces.append(face)
                        else:
                                topfaces = faceGen(SIDES)
                                for f in topfaces:
                                        faces.append(f)
                else:
                        for j in range(SIDES):
                                face = [v1[j], v1[j+1], v0[j+1], v0[j]]
                                faces.append(face)
                        
                # Down one step
                h = h - HSIZE

                # Bottom side
                for j in range(SIDES):
                        vx = (i+1) * WSIZE * math.cos(rot_step * j)
                        vy = (i+1) * WSIZE * math.sin(rot_step * j)
                        v = [vx, vy, h]
                        verts.append(v)

                # Create SIDE Faces
                for j in range(SIDES):
                        face = [v2[j], v2[j+1], v1[j+1], v1[j]]
                        faces.append(face)

        return verts,faces


# main function (window handle and input variables)
def main():
	pyramidSides = Blender.Draw.Create(4)
	pyramidSteps = Blender.Draw.Create(10)
	PyramidHSize = Blender.Draw.Create(1.0)
	PyramidWSize = Blender.Draw.Create(0.5)
	
	block = []
	block.append(("Sides:", pyramidSides, 3, 100, "the number of sides"))
	block.append(("Steps:", pyramidSteps, 2, 100, "the number of steps"))
	block.append(("Step Height:", PyramidHSize, 0.01, 100, "height of each step"))
	block.append(("Step Width:", PyramidWSize, 0.01, 100, "width of the steps"))
	
	if not Blender.Draw.PupBlock("Create pyramid", block):
		return
	
#	Generates the mesh
	verts, faces = add_pyramid(pyramidSides.val, pyramidSteps.val, PyramidHSize.val, PyramidWSize.val)

#	Adds the mesh to the scene
	BPyAddMesh.add_mesh_simple('NPyramid', verts, [], faces)

# call our main function	
main()
