// Persistence of Vision Ray Tracer Scene Description File
// File:	Tree.pov
// Vers:	3.01 Watcom Win32
// Desc:	Object Definition Code for an LParser-like Tree
// Date:	February 27, 1997
// Auth:	Sonya Roberts
// Note:	To change the appearance of the tree, modify the settings at the beginning
//		of the file.  If you want to create a number of different trees, create multiple
//		copies of this file with different settings, and number the Leaf and Tree #declare
//		statements (i.e., in TREE1.pov have Leaf1 and Tree1 objects).
//		Please note that you will need to #declare the variables True=1 and False=0 in your main
//		.POV file (or just leave in the definitions that are here).
//
//		Textures for tree components are all set within this file.  Textures include a bark
//		texture for the tree, the leaf color, the fruit colour, and the flower colour.
//		These are just simple non-realistic textures at the moment - have fun coming up
//		with good ones to really use ;)

// ==== Standard Includes ====
#declare True=1
#declare False=0

#declare Tree=
object {
	#debug "Creating Tree "
	// ---- SET UP VARIABLES AND PIECES OF TREE
	#declare MaxSplits=4		// Maximum number of forks in a section of Tree (minimum of 1)
	#declare MinSplits=3		// Minimum number of forks in a section of Tree (minimum of 1)
	#declare IncSplits=1		// To Increase Max. Splits near Branch Tips, Make > 1 - KEEP IT SMALL!
	#declare BaseLen=1		// Base Length (length of smallest twig - determines scale of tree)
	#declare LengthInc=1.2		// Factor By Which to Increase Base Length
	#declare MinXDeg=35		// Minimum X-rotation of forks
	#declare MaxXDeg=55		// Maximum X-rotation of forks
	#declare IncXDeg=0		// Number of degrees to increment X by at each level
	#declare MinYDeg=0		// Minimum Y-rotation of forks
	#declare MaxYDeg=360		// Maximum Y-rotation of forks		// NOTE: 2nd-Level Branches always based on 360 degrees
	#declare IncYDeg=0		// Number of degrees to increment Y by at each level
	#declare MinZDeg=0		// Minimum Z-rotation of forks		// Z-rotations highly optional - not required at all
	#declare MaxZDeg=0		// Maximum Z-rotation of forks
	#declare IncZDeg=0		// Number of degrees to increment Z by at each level
	#declare PlusMinus=20		// Angle of change of terminal fork
	#declare SD1=seed(2)		// Seed for random numbers - changing only this will create a different tree of the same species
	#declare SD2=seed(1997)		// Seed for additional randum numbers - so tree shape won't change from optional code
	#declare BallJoint=True		// Turns on and off the spheres used to smooth intersections of the branches and trunks
	#declare BallLevels=2		// Maximum Number of Levels to smooth when BallJoint=True (integer from 1 to 5 inclusive)
	#declare LeafNum=3		// Number of Leaves (not counting leaf object at tip of twig)
	#declare LeafRosette=False	// If true, leaves are arranged in rosette around twig rather than spiral up twig
	#declare LeafRandRot=False	// Rotate the leaves around the twig at random angles (cannot be combined with LeafRosette)
	#declare Tip=1			// Select either 1=Leaf, 2=Fruit, or 3=Flower

	#if (Tip=2)
		#declare FruitTexture=
		texture {
			pigment {color Red}
			finish {
				ambient .5
				phong .3
			}
		}
		#declare Fruit=
		object {
			sphere {<0,.095,0>,.1}
			texture {FruitTexture}
			scale <BaseLen,BaseLen,BaseLen>
		}
	#end

	#if (Tip=3)
		#declare PetalNum=5
		#declare FlowerTexture=
		texture {
			pigment {
				gradient z
				color_map {
					[0	color White]
					[.25	color White]
					[1	color Orchid]
				}
			}
			finish {
				ambient .25
			}
		}
		#declare FlowerPetal=
		object {
			sphere {<0,0,.095>,.1}
			texture {FlowerTexture	scale <.2,.2,.2>}
			scale <4/PetalNum,.01,1.5>
		}
		#declare Flower=
		object {
			union {
				sphere {
					<0,0,0>,.075
					scale <1,.25,1>
					pigment {color Yellow}
				}
				#declare P1=1
				#while (P1<=PetalNum)
					object {
						FlowerPetal
						rotate z*25
						rotate x*-20
						translate <0,0,.04>
						rotate y*((360/PetalNum)*P1)
					}
					#declare P1=P1+1
				#end
			}
			scale <BaseLen,BaseLen,BaseLen>
		}
	#end

	#declare Leaf=
	object {
		sphere {<0,0,.195>,.2}
		scale <.75,.1,1.5>
		pigment {color PaleGreen}
		scale <BaseLen,BaseLen,BaseLen>
	}

	#declare TreeBarkTexture=
	texture {
		pigment {color Tan}
		normal {
			bumps .6
			scale <.05,.1,.05>
		}
	}


	// ---- ASSEMBLE ELEMENTS OF TREE ----
	union {
		cone {<0,0,0>,BaseLen,<0,BaseLen*(LengthInc*5),0>,BaseLen/2}
		#if (BallJoint=True & BallLevels>=1)
			sphere {<0,BaseLen*(LengthInc*5),0>,BaseLen/2}
		#end
		#declare Loop1=int((rand(SD1)*((MaxSplits-MinSplits-1)+.9999999999))+MinSplits)	// How many forks?
		#declare Loop1Count=1
		#while (Loop1Count <= Loop1)
			#debug "."
			union {
				cone {<0,0,0>,BaseLen/2,<0,BaseLen*(LengthInc*4),0>,BaseLen/4}
				#if (BallJoint=True & BallLevels>=2)
					sphere {<0,BaseLen*(LengthInc*4),0>,BaseLen/4}
				#end
				#declare Loop2=int((rand(SD1)*(((MaxSplits*IncSplits)-MinSplits-1)+.9999999999))+MinSplits)	// How many forks?
				#declare Loop2Count=1
				#while (Loop2Count <= Loop2)
					#debug "."
					union {
						cone {<0,0,0>,BaseLen/4,<0,BaseLen*(LengthInc*3),0>,BaseLen/8}
						#if (BallJoint=True & BallLevels>=3)
							sphere {<0,BaseLen*(LengthInc*3),0>,BaseLen/8}
						#end
						#declare Loop3=int((rand(SD1)*(((MaxSplits*IncSplits*IncSplits)-MinSplits-1)+.9999999999))+MinSplits)
						#declare Loop3Count=1
						#while (Loop3Count <= Loop3)
							#debug "."
							union {
								cone {<0,0,0>,BaseLen/8,<0,BaseLen*(LengthInc*2),0>,BaseLen/16}
								#if (BallJoint=True & BallLevels>=4)
									sphere {<0,BaseLen*(LengthInc*2),0>,BaseLen/16}
								#end
								#declare Loop4=int((rand(SD1)*(((MaxSplits*IncSplits*IncSplits*IncSplits)-MinSplits-1)+.9999999999))+MinSplits)
								#declare Loop4Count=1
								#while (Loop4Count <= Loop4)
									#debug "."
									union {
										cone {<0,0,0>,BaseLen/16,<0,BaseLen*LengthInc,0>,BaseLen/32}
										#if (BallJoint=True & BallLevels>=5)
											sphere {<0,BaseLen*LengthInc,0>,BaseLen/32}
										#end
										#declare Loop5=int((rand(SD1)*(((MaxSplits*IncSplits*IncSplits*IncSplits*IncSplits)-MinSplits-1)+.9999999999))+MinSplits)
										#declare Loop5Count=1
										#while (Loop5Count <= Loop5)
											#debug "."
											union {
												cone {<0,0,0>,BaseLen/32,<0,BaseLen,0>,BaseLen/64}
												#switch (Tip)
													#case (1)
														object {Leaf	rotate x*-90	translate <0,BaseLen,0>}
													#break
													#case (2)
														object {Fruit	translate <0,BaseLen,0>}
													#break
													#case (3)
														object {Flower	translate <0,BaseLen,0>}
													#break
												#end
												#declare LNum=1
												#while (LNum<=LeafNum)
													object {
														Leaf
														rotate x*-MinXDeg
														rotate y*((MaxYDeg/LeafNum)*LNum)
														#if (LeafRosette)
															rotate y*((MaxYDeg/LeafNum)*LNum)
															translate <0,BaseLen*.6,0>
														   #else
														     	#if (LeafRandRot)
																rotate y*(rand(SD2)*360)
															   #else
																rotate y*((MaxYDeg/LeafNum)*LNum)
															#end
															translate <0,(BaseLen/(LeafNum+1))*LNum,0>
														#end
													}
													#declare LNum=LNum+1
												#end
												#if (Loop5Count<Loop5)
													rotate x*((rand(SD1)*((MaxXDeg+(IncXDeg*4))-(MinXDeg+(IncXDeg*4))))+(MinXDeg+(IncXDeg*4)))
													rotate y*((rand(SD1)*((MaxYDeg+(IncYDeg*4))-(MinYDeg+(IncYDeg*4))))+(MinYDeg+(IncYDeg*4)))
													rotate z*((rand(SD1)*((MaxZDeg+(IncZDeg*4))-(MinZDeg+(IncZDeg*4))))+(MinZDeg+(IncZDeg*4)))
												   #else
													rotate x*((rand(SD1)*(PlusMinus*2))-PlusMinus)
													rotate y*((rand(SD1)*(PlusMinus*2))-PlusMinus)
													rotate z*((rand(SD1)*(MinZDeg*2))-MinZDeg)
												#end
												translate <0,(BaseLen*LengthInc)*(Loop5Count/Loop5),0>
											}
											#declare Loop5Count = Loop5Count+1
										#end
										#if (Loop4Count<Loop4)
											rotate x*((rand(SD1)*((MaxXDeg+(IncXDeg*3))-(MinXDeg+(IncXDeg*3))))+(MinXDeg+(IncXDeg*3)))
											rotate y*((rand(SD1)*((MaxYDeg+(IncYDeg*3))-(MinYDeg+(IncYDeg*3))))+(MinYDeg+(IncYDeg*3)))
											rotate z*((rand(SD1)*((MaxZDeg+(IncZDeg*3))-(MinZDeg+(IncZDeg*3))))+(MinZDeg+(IncZDeg*3)))
										   #else
											rotate x*((rand(SD1)*(PlusMinus*2))-PlusMinus)
											rotate y*((rand(SD1)*(PlusMinus*2))-PlusMinus)
											rotate z*((rand(SD1)*(MinZDeg*2))-MinZDeg)
										#end
										translate <0,(BaseLen*(LengthInc*2))*(Loop4Count/Loop4),0>
									}
									#declare Loop4Count = Loop4Count+1
								#end
								#if (Loop3Count<Loop3)
									rotate x*((rand(SD1)*((MaxXDeg+(IncXDeg*2))-(MinXDeg+(IncXDeg*2))))+(MinXDeg+(IncXDeg*2)))
									rotate y*((rand(SD1)*((MaxYDeg+(IncYDeg*2))-(MinYDeg+(IncYDeg*2))))+(MinYDeg+(IncYDeg*2)))
									rotate z*((rand(SD1)*((MaxZDeg+(IncZDeg*2))-(MinZDeg+(IncZDeg*2))))+(MinZDeg+(IncZDeg*2)))
								   #else
									rotate x*((rand(SD1)*(PlusMinus*2))-PlusMinus)
									rotate y*((rand(SD1)*(PlusMinus*2))-PlusMinus)
									rotate z*((rand(SD1)*(MinZDeg*2))-MinZDeg)
								#end
								translate <0,(BaseLen*(LengthInc*3))*(Loop3Count/Loop3),0>
							}
							#declare Loop3Count = Loop3Count+1
						#end
						#if (Loop2Count<Loop2)
							rotate x*((rand(SD1)*((MaxXDeg+IncXDeg)-(MinXDeg+IncXDeg)))+(MinXDeg+IncXDeg))
							rotate y*((rand(SD1)*((MaxYDeg+IncYDeg)-(MinYDeg+IncYDeg)))+(MinYDeg+IncYDeg))
							rotate z*((rand(SD1)*((MaxZDeg+IncZDeg)-(MinZDeg+IncZDeg)))+(MinZDeg+IncZDeg))
						   #else
							rotate x*((rand(SD1)*(PlusMinus*2))-PlusMinus)
							rotate y*((rand(SD1)*(PlusMinus*2))-PlusMinus)
							rotate z*((rand(SD1)*(MinZDeg*2))-MinZDeg)
						#end
						translate <0,(BaseLen*(LengthInc*4))*(Loop2Count/Loop2),0>
					}
					#declare Loop2Count = Loop2Count+1
				#end
				#if (Loop1Count<Loop1)
					rotate x*((rand(SD1)*(MaxXDeg-MinXDeg))+MinXDeg)
					rotate y*(rand(SD1)*360)
					rotate z*((rand(SD1)*(MaxZDeg-MinZDeg))+MinZDeg)
				   #else
					rotate x*((rand(SD1)*(PlusMinus*2))-PlusMinus)
					rotate y*((rand(SD1)*(PlusMinus*2))-PlusMinus)
					rotate z*((rand(SD1)*(MinZDeg*2))-MinZDeg)
				#end
				translate <0,(BaseLen*(LengthInc*5))*(Loop1Count/Loop1),0>
			}
			#declare Loop1Count = Loop1Count+1
			#debug "\n"
		#end
	}
	texture {TreeBarkTexture}
}
