#!BPY

"""
Name: 'Pipe'
Blender: 248
Group: 'AddMesh'
"""
__author__ = ["Luis Sergio S. Moura Jr."]
__version__ = '0.3'
__url__ = ["http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Add/Pipe"]
__bpydoc__ = """

Usage:

Pipe Mesh

This script lets the user create a new primitive. A pipe. Receives as input the 
inner radius, outer radius and the number of divisions. It consists in a hollow cone.

This script was inspired in opendimension.org's tutorial

0.3 - 2007-07-25 by Luis Sergio<br />
- removed leftover debug instructions
- added radial divisions

0.2 - 2007-07-25 by Luis Sergio<br />
- added height divisions as requested on blenderartists forum thread http://blenderartists.org/forum/showthread.php?t=101571
- normals are corrected

0.1 - 2007-07-24 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


# The actual function that generates the vectors and faces for the pipe
# PARAMETERS:
#	V_DIVISIONS	Vertical divisions
#	H_DIVISIONS	Height divisions
#	R_DIVISIONS	Radial divisions
#	INNER_RADIUS	Inner radius
#	OUTER_RADIUS	Outer radius
#	HEIGHT		Pipe height
def add_pipe(V_DIVISIONS, H_DIVISIONS, R_DIVISIONS, INNER_RADIUS, OUTER_RADIUS, HEIGHT):
	verts = []
	faces = []
	# Number of vertices in each division
	divvcount = (H_DIVISIONS + 1) * 2 + (R_DIVISIONS - 1) * 2
	# Total number of vertices
	vcount = divvcount * V_DIVISIONS

	# Create Vertices
	for hdiv in range(V_DIVISIONS):
		degree = hdiv * 2 * math.pi / V_DIVISIONS
		mulx = math.sin(degree)
		muly = math.cos(degree)
		# step between height divisions
		step = HEIGHT / H_DIVISIONS

		# step between section divisions
		sstep = (OUTER_RADIUS - INNER_RADIUS) / R_DIVISIONS

		for vdiv in range(H_DIVISIONS + 1):
			verts.append([mulx * OUTER_RADIUS, muly * OUTER_RADIUS, -HEIGHT/2 + step * vdiv]);
			verts.append([mulx * INNER_RADIUS, muly * INNER_RADIUS, -HEIGHT/2 + step * vdiv]);

		# section division vertices
		for sdiv in range(R_DIVISIONS):
			if (sdiv > 0):
				verts.append([mulx * (OUTER_RADIUS - sstep * sdiv), muly * (OUTER_RADIUS - sstep * sdiv), -HEIGHT/2]);
				verts.append([mulx * (OUTER_RADIUS - sstep * sdiv), muly * (OUTER_RADIUS - sstep * sdiv), HEIGHT/2]);
	
	# Create Faces
	for hdiv in range(V_DIVISIONS):
		start = hdiv * divvcount
		nextstart = start + divvcount
		if (nextstart >= vcount):
			nextstart = 0

		for vdiv in range(H_DIVISIONS * 2):
			# We have to draw the sequence differently because of our normals. They must point outside of the pipe.
			if ((vdiv % 2) == 0):
				# OUTER FACES
				faces.append([start + vdiv, start + vdiv + 2, nextstart + vdiv + 2, nextstart + vdiv]);
			else:
				# INNER FACES
				faces.append([start + vdiv + 2, start + vdiv, nextstart + vdiv, nextstart + vdiv + 2]);


		if (R_DIVISIONS == 1):
			# Bottom faces
			faces.append([start+1 , start, nextstart, nextstart+1])
			# Top faces
			faces.append([start + divvcount - 2, start + divvcount - 1, nextstart + divvcount - 1, nextstart + divvcount - 2]);
		else:
			# number of vertices on the sides (excluding the ones created between the inner radius and outer radius)
			sidevcount = (H_DIVISIONS + 1) * 2
			for inf in range(R_DIVISIONS):
				if (inf == 0):
					# First faces
					faces.append([start + sidevcount, start, nextstart, nextstart + sidevcount])
					faces.append([start + sidevcount - 2, start + sidevcount + 1, nextstart + sidevcount + 1, nextstart + sidevcount - 2])
				else:
					if (inf == (R_DIVISIONS - 1)):
						# Last faces
						faces.append([start + 1, start + divvcount - 2, nextstart + divvcount - 2, nextstart + 1])
						faces.append([start + divvcount - 1, start + sidevcount - 1, nextstart + sidevcount - 1, nextstart + divvcount - 1])
					else:
						xx = (inf - 1) * 2
						# Middle faces
						faces.append([start + sidevcount + xx + 2, start + sidevcount + xx, nextstart + sidevcount + xx, nextstart + sidevcount + xx + 2])
						faces.append([start + sidevcount + xx + 1, start + sidevcount + xx + 3, nextstart + sidevcount + xx + 3, nextstart + sidevcount + xx + 1])
	
	return verts,faces

# main function (window handle and input variables)
def main():
	pipeInnerInput = Blender.Draw.Create(1.0)
	pipeOuterInput = Blender.Draw.Create(2.0)
	pipeDivInput = Blender.Draw.Create(16)
	pipeHDivInput = Blender.Draw.Create(1)
	pipeRDivInput = Blender.Draw.Create(1)
	pipeHeightInput = Blender.Draw.Create(1.0)
	
	block = []
	block.append(("Inner radius:", pipeInnerInput, 0.01, 100, "the inner radius"))
	block.append(("Outer radius:", pipeOuterInput, 0.01, 100, "the outer radius"))
	block.append(("Divisions:", pipeDivInput, 4, 100, "number of divisions"))
	block.append(("Height:", pipeHeightInput, 1.00, 100, "the height of the pipe"))
	block.append(("Height divisions:", pipeHDivInput, 1, 100, "number of height divisions"))
	block.append(("Radial divisions:", pipeRDivInput, 1, 100, "number of radial divisions"))
	
	if not Blender.Draw.PupBlock("Lay pipe", block):
		return
	
#	Generates the mesh
	verts, faces = add_pipe(pipeDivInput.val, pipeHDivInput.val, pipeRDivInput.val, pipeInnerInput.val, pipeOuterInput.val, pipeHeightInput.val)

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

# call our main function	
main()
