
// POV-Ray Object File - Trumpet Sound Visualization
// created 23-Apr-06
// last update 23-Apr-06
// Copyright ©2006 Glenn McCarter (glenn@mccarters.net). Some rights reserved.
// This work is licensed under the Creative Commons Attribution License
// To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/
//
// Required #include files: "GIncludeRH.inc"
//
// Objects:
// TrumpetSoundGroup
//
//
// Intended scale is English system (inches)
// Uses RH coordinate reference system (Z=up)
//
// This file is intended to be included in another POV-Ray scene file,
// but can be rendered alone.
#ifndef (ThisIsMaster) // If this include file was not called by another, then
	#declare RenderMe = 0; // supress self-rendering of other include files
	#declare ThisIsMaster = 1;
	#include "GIncludeRH.inc"
	// renderable sub includes go here

	#declare RenderMe = 1;
#end

//===============================================
//             Includes
//===============================================

// non-renderable sub includes go here

//===============================================
//             Variables
//===============================================

#if (RenderMe = 1)
	#local Radios=0;
#end

//===============================================
//             Textures
//===============================================

//#declare TP = color rgb<1.00,0.94,.37>; // basic note color, too white
//#declare TP = color rgb<1.00,0.99,.17>; // basic note color, too greenish
#declare TP = color rgb<1.16,0.65,.17>; // basic note color
/*
#declare TrumpetNoteTexS =
	texture {
		pigment { TP }
		#if (Radios)
			finish { ambient 20 diffuse 0 }
		#else
//			finish { ambient 1 diffuse 0 }
			finish { ambient .3 diffuse 0.4 }
		#end
	}
*/
#macro TrumpetNoteTex(R,G,B,BaseHeight,NoteHeight,MaxTransparency)
//	texture {
//		pigment { EGP + <R,G,B> transmit 0.8 } // test
		#local TGray=(TP.red+TP.green+TP.blue)/3;
		pigment {
			gradient z
			color_map {
//				[ 0.05 TP + <R,G,B> transmit 1.0 ] // low z, transparent
//				[ 0.95 TP + <R,G,B> transmit MaxTransparency ] // high z, opaque

				[ 0.05 rgb<TGray,TGray,TGray>*(1-BaseHeight/60)+TP*(BaseHeight/60) + <R,G,B> transmit 1.0 ] // low z, transparent
				[ 0.95 rgb<TGray,TGray,TGray>*(1-BaseHeight/60)+TP*(BaseHeight/60) + <R,G,B> transmit MaxTransparency ] // high z, opaque

			}
			scale NoteHeight
			translate <0,0,-NoteHeight*0.1>
		}
		#if (Radios)
			finish { ambient 8+BaseHeight*0.2 diffuse 0.4 specular 0 }
		#else
			finish { ambient 0.8 diffuse 0.4 }
		#end
//	}
#end

#macro TSparkTex(Rad,BaseHeight)
//	texture {
		#local BP=color rgb<1,1,.1>;
		#local BGray=(BP.red+BP.green+BP.blue)/3;
//		pigment { rgb<BGray,BGray,BGray>*(1-BaseHeight/60)+BP*(BaseHeight/60) } // solid color
		pigment {
			cylindrical // y-axis, 1.0 at origin, zero at 1 unit away
			color_map {
				[ 0.1 rgb<BGray,BGray,BGray>*(1-BaseHeight/60)+BP*(BaseHeight/60) transmit 1.00] // edge is clear
				[ 0.8 rgb<BGray,BGray,BGray>*(1-BaseHeight/60)+BP*(BaseHeight/60) transmit 0.10 ] // center is dense
			}
			scale <Rad/1,20,Rad/1>
		}
		#if (Radios)
			finish { ambient 8+BaseHeight*0.2 diffuse 0.2 }
		#else
			finish { ambient 0.8 diffuse 0.2 }
		#end
//	}
#end

//===============================================
//             Macros
//===============================================

// This is John VanSickle's Reorient Macro:
#macro Reorient(Axis1,Axis2)
  #local vX1=vnormalize(Axis1);
  #local vX2=vnormalize(Axis2);
  #local vY=vnormalize(vcross(vX1,vX2));
#if (vlength(vY)>0)
  #local vZ1=vnormalize(vcross(vX1,vY));
  #local vZ2=vnormalize(vcross(vX2,vY));
  matrix < vX1.x, vY.x,vZ1.x, vX1.y,vY.y,vZ1.y, vX1.z,vY.z, vZ1.z, 0,0,0 >
  matrix < vX2.x,vX2.y,vX2.z, vY.x,vY.y, vY.z, vZ2.x,vZ2.y,vZ2.z, 0,0,0 >
#end
#end

//===============================================
//             Sounds
//===============================================

#declare TRS=seed(20495);

#declare TSpline1 =
	spline {
		natural_spline
	 -0.10,<1,0,-1>
		0.00,<0,0,0>
		0.10,<-0.7,0,1.2>
		0.20,<-1.0,0,2.5>
		0.30,<-1.1,0,4.0>
		0.40,<-1.2,0,5.7>
		0.50,<-1.0,0,7.2>
		0.60,<-0.7,0,9.0>
		0.70,<-0.4,0,10.3>
		0.80,<0.2,0,11.7>
		0.90,<0.7,0,13.2>
		1.00,<1.6,0,14.4>
		1.10,<2.6,0,15.5>
	}

#declare TSpline2 =
	spline {
		natural_spline
	 -0.10,<-0.3,0,-1.2>
		0.00,<0,0,0>
		0.10,<0.4,0,1.3>
		0.20,<0.7,0,2.8>
		0.30,<0.2,0,4.4>
		0.40,<-0.4,0,5.5>
		0.50,<-0.9,0,7.0>
		0.60,<-1.2,0,8.3>
		0.70,<-1.3,0,9.8>
		0.80,<-1.0,0,11.3>
		0.90,<-0.3,0,12.6>
		1.00,<0.6,0,13.4>
		1.10,<1.7,0,14.1>
	}

#declare TSpline3 =
	spline {
		natural_spline
	 -0.10,<1.5,0,-0.2>
		0.00,<0,0,0>
		0.10,<-1.3,0,0.6>
		0.20,<-2.0,0,1.8>
		0.30,<-2.4,0,3.3>
		0.40,<-2.2,0,5.0>
		0.50,<-1.8,0,6.3>
		0.60,<-1.2,0,7.8>
		0.70,<-0.4,0,9.0>
		0.80,<0.4,0,10.2>
		0.90,<1.4,0,11.4>
		1.00,<2.2,0,12.8>
		1.10,<2.6,0,14.4>
	}


#macro TSpline(Case)
	#switch (Case)
	#case (1)
		TSpline1
	#break
	#case (2)
		TSpline2
	#break
	#case (3)
		TSpline3
	#break
	#end
#end

#macro TNote(Case,Spheres,BaseHeight,MaxTransparency,MinSphRad,RadGrow,Spin,TRS) // TRS=TrumpetRandomSeed
	merge {
		#declare Rad=1.4;	
		#declare MaxN=Spheres;
		#declare AnglePerSphere=10;
		#local N=0;
		#while (N<MaxN)
			#local Theta=radians(N*AnglePerSphere);
			sphere {
				<0,0,0>,MinSphRad+N*RadGrow
//				translate <Rad*cos(Theta),Rad*sin(Theta),0> // constant radius
				translate <(.1+N*.008)*cos(Theta),(.1+N*.008)*sin(Theta),0> // increasing radius
				rotate z*Spin
				Reorient(<0,0,-1>,TSpline(Case)(N/MaxN)-TSpline(Case)((N+0.1)/MaxN))
				translate <TSpline(Case)(N/MaxN).x,TSpline(Case)(N/MaxN).y,TSpline(Case)(N/MaxN).z>
			}

			#if (mod(N,10)=0) // inline sparkles
				#declare SRad=0.1+rand(TRS)*0.28;
				sphere { <0,0,0>,SRad
					texture { TSparkTex(SRad,BaseHeight)  rotate <0,0,-20>}
					translate TSpline(Case)(N/Spheres)+<-N/MaxN*5+N/MaxN*rand(TRS)*10,-N/MaxN*5+N/MaxN*rand(TRS)*10,rand(TRS)*2>
				}
			#end

			#local N=N+1;
		#end

		// top sparkles
		#local TSC=0;
		#while (TSC<3+int(rand(TRS)*8))
			#declare SRad=0.2+rand(TRS)*0.38;
			sphere {
				<0,0,0>,SRad
//cylinder { <0,-3,0>,<0,3,0>,1 rotate <BaseHeight*0.3,0,-30> texture { TestWhiteTex } // test texture rot angles
				texture { TSparkTex(SRad,BaseHeight) rotate <BaseHeight*0.3,0,-30> }
				translate TSpline(Case)(1)+<-3+rand(TRS)*6,-3+rand(TRS)*6,-2+rand(TRS)*10>
			}
			#local TSC=TSC+1;
		#end

		texture { TrumpetNoteTex(0,0,0,BaseHeight,18,MaxTransparency) }
		no_shadow
//		no_reflection
	} // end union
#end

// TNote(Case,Spheres,BaseHeight,Transparency,MinSphRad,RadGrow,TrumpetRandomSeed)
#declare TrumpetSoundGroup =
	#union {
/*
		object { TNote(3,100, 1,0.69,0.3,0.010,seed(13059)) scale 0.65 rotate <0,-15,0> } // lowest
		object { TNote(2,140,16,0.42,0.2,0.005,seed(20250)) scale 0.80 rotate z*10 translate <9,16,16>}
		object { TNote(3,180,36,0.38,0.1,0.005,seed(93557)) scale 1.00 rotate z*30 translate <16,0,29>}
		object { TNote(2,140,49,0.29,0.1,0.005,seed(47358)) scale <-1.1,1.1,1.4> rotate z*0 translate <9,-6,49>}
		object { TNote(1,170,59,0.14,0.1,0.005,seed(13699)) scale 0.70 rotate z*10 translate <20,-10,66>} // highest
*/
		object { TNote(3,100, 1,0.69,0.3,0.010,0,seed(13059)) scale 0.65 rotate <0,-15,0> } // lowest
		object { TNote(2,140,16,0.42,0.2,0.005,0,seed(20250)) scale 0.80 translate <9,16,16>}
		object { TNote(3,180,36,0.38,0.1,0.005,180,seed(93557)) scale 1.00 translate <16,0,29>}
		object { TNote(2,140,49,0.29,0.1,0.005,0,seed(47358)) scale <1.1,1.1,1.4> translate <9,-6,49>}
		object { TNote(1,170,59,0.14,0.1,0.005,90,seed(13699)) scale 0.70 translate <20,-10,66>} // highest
	} // end union
		

//===============================================
//             Testing Area
//===============================================

#if (RenderMe = 1)

#local Radios=0;
global_settings {	max_trace_level 150 }
#declare TestSphere = sphere{ 0,12 pigment { color rgb<1,1,1> } }

	camera {
		perspective
		direction <0.0,     1.0,  0.0>
		sky       <0.0,     0.0,  1.0>  // Use right handed-system!
		up        <0.0,     0.0,  1.0>  // Where Z is up
		right     <1.33333, 0.0,  0.0>

		angle 44
		location  <1*Feet, -13*Feet, 5.5*Feet> // overall
		look_at <0*Feet,2*Feet,4*Feet>
//		location  <3*Feet, -1*Feet, 35*Feet> // top down
//		look_at <3*Feet,3*Feet,3*Feet>

	}

background { color rgb <0.276,0.567,0.982>*.97 } // sky blue
light_source
{ <12*Feet,-30*Feet,25*Feet>, 1.2
//  spotlight point_at <0,0*Feet,2*Feet> radius 25 falloff 36
}
light_source
{ <-140*Feet,-200*Feet,130*Feet>, <1.13,1.08,0.83>*1.3
//  spotlight point_at <0,0,2*Feet> radius 25 falloff 36
}

plane { z,-0 pigment { checker rgb <1,1,1>, rgb <1,1,1>*.75 } scale 1*Feet }

//#include "GRuler.inc" // for testing only
//object { TestSphere scale 1 translate <0,0,10> }

object { TrumpetSoundGroup scale 1 rotate z*0 translate <-3*Feet,0,18> }
//object { TrumpetSoundGroup scale 1 rotate z*-90 translate <0*Feet,0,18> }
//object { TrumpetSoundGroup scale 1 rotate x*40 translate <3*Feet,0,18> }
#end

