
// POV-Ray Object File - Plumbing Pipes
// created 29-May-03
// last update 27-Jun-03
// ©2003 Glenn McCarter  ( glenn@mccarters.net )
//
// This file does not render.  #include "PipeGroup.inc" in another .pov file
// Required #include files: "GIncludeRH.inc"
//
// Objects:
// DisconnPiping // random horiz & vertical disconnected pipes
// RPipeTrackS(Nodes,Dia) // random piping, no elbows
// RPipeTrack(Nodes,Dia,MinLen,MaxLen,PSeed,PipePig) // random piping, includes elbows
// PipeTrackS(NodeArray,Nodes,Dia,PipeTexture) // you supply the array, no elbows
// PipeTrack(NodeArray,Nodes,Dia,PipeTexture) // with elbows
// PipeLoop(Xdim,Ydim,Dia,PipeTexture)
//
//
// Intended scale is English system (inches)
// Uses RH coordinate reference system (Z=up)
// Sky is up

#ifndef (ThisIsMaster) // now we know this include file was not called by another
	#declare RenderMe = 0; // supress self-rendering of other includes files
	#declare ThisIsMaster = 1;
	#include "GIncludeRH.inc"
	// renderable sub includes go here
	#declare RenderMe = 1;
#end

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

// non-renderable sub includes go here


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


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

#declare PipeTex = // default
	texture {
		pigment { color rgb<.999,.991,.979>*0.50 }
		finish { specular 0.53 roughness 0.24 }
	}
#declare CopperTex =
	texture {
		pigment { color rgb<0.875,0.592,0.247>*1.00 }
		finish { metallic specular 0.92 roughness 0.035 }
	}


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

#macro PipeSection(Dia,Length)
//	union {
		cylinder {
			<0,0,0>,<Length,0,0>,Dia/2
		}
//	} // end union
#end

#macro Elbow(Dia) // starts into +x, bending into +z
// Dia = main diameter of pipe
	union {
		difference {
			torus {
				1.5*Dia, Dia/2
			}
			box { <-3*Dia,-Dia,0>,<3*Dia,Dia,3*Dia> }
			box { <-3*Dia,-Dia,-3*Dia>,<0,Dia,3*Dia> }
			translate <0,0,1.5*Dia> // set end at x=0
		} // end difference
		cylinder { <-Dia/2,0,0>,<0,0,0>,0.6*Dia }
		cylinder { <-Dia/2,0,0>,<0,0,0>,0.6*Dia rotate y*90 translate <1.5*Dia,0,1.5*Dia> }
	} // end union
#end

#macro FlangedElbow(Dia) // starts into +x, bending into +z
// Dia = main diameter of pipe
	union {
		difference {
			torus {
				1.5*Dia, Dia/2
			}
			box { <-3*Dia,-Dia,0>,<3*Dia,Dia,3*Dia> }
			box { <-3*Dia,-Dia,-3*Dia>,<0,Dia,3*Dia> }
			translate <0,0,1.5*Dia> // set end at x=0
		} // end difference
		cylinder { <Dia/28,0,0>,<Dia/4,0,0>,0.8*Dia }
		cylinder { <-Dia/4,0,0>,<-Dia/28,0,0>,0.8*Dia }
		cylinder { <Dia/28,0,0>,<Dia/4,0,0>,0.8*Dia rotate y*90 translate <1.5*Dia,0,1.5*Dia> }
		cylinder { <-Dia/4,0,0>,<-Dia/28,0,0>,0.8*Dia rotate y*90 translate <1.5*Dia,0,1.5*Dia> }
		#declare BoltPos = 0;
		#while ( BoltPos < 360 )
			cylinder {
				<-Dia/4-Dia/6,0,0>,<Dia/4+Dia/6,0,0>,Dia/10
				translate <0,0,0.65*Dia>
				rotate x*BoltPos
			}
			#declare BoltPos = BoltPos + 24;
		#end
		#declare BoltPos = 0;
		#while ( BoltPos < 360 )
			cylinder {
				<-Dia/4-Dia/6,0,0>,<Dia/4+Dia/6,0,0>,Dia/10
				translate <0,0,0.65*Dia>
				rotate x*BoltPos
				rotate y*90 translate <1.5*Dia,0,1.5*Dia>
			}
			#declare BoltPos = BoltPos + 24;
		#end
	} // end union
#end

#macro RPipeTrackS(Nodes,Dia) // simple version, no elbows
// Nodes = total number of pipe sections
// Dia = main diameter of pipe
	#declare PA = array[Nodes][2]; // Pipe Array
	#declare RS=seed(31987);
	#declare StartPos = <0,0,0>;
	#declare PA[0][0] = StartPos;
//#debug concat("PA[0][0].x :",str(PA[0][0].x,5,0),"\n")
	#declare StartDir = <1,0,0>;
	#declare PA[0][1] = StartDir;
	union {
	#declare NodeN=1;
	#while ( NodeN < Nodes ) // ok, this section is crude, but it works!
		// reorient the next section of pipe to be 90-deg from the previous one
		#declare OldDir = PA[NodeN-1][1];
		#if (abs(OldDir.x)=1)
			#declare NewDir = vrotate(OldDir,<0,90,0>);
			#declare NewDir = vrotate(NewDir,<int(mod(4,rand(RS))*4)*90,0,0>);
		#end
		#if (abs(OldDir.y)=1)
			#declare NewDir = vrotate(OldDir,<0,0,90>);
			#declare NewDir = vrotate(NewDir,<int(mod(4,rand(RS))*4)*90,0>);
		#end
		#if (abs(OldDir.z)=1)
			#declare NewDir = vrotate(OldDir,<90,0,0>);
			#declare NewDir = vrotate(NewDir,<0,0,int(mod(4,rand(RS))*4)*90>);
		#end
		#declare PA[NodeN][1]=NewDir;
		#declare NewLength = <1,1,1>*(4*Feet+rand(RS)*24*Feet);
		#declare NewPos = PA[NodeN-1][0]+NewLength*NewDir;
		#declare PA[NodeN][0]=NewPos;
		cylinder {
			PA[NodeN-1][0],PA[NodeN][0],Dia/2
			texture { PipeTex }
		}
 		#declare NodeN = NodeN + 1;
	#end
	} // end union
#end

#macro RPipeTrack(Nodes,Dia,MinLen,MaxLen,PSeed,PipePig) // complex version, includes elbows
// Nodes = total number of pipe sections
// Dia = main diameter of pipe
// MinLen = minimum length of any pipe section
// MaxLen = maximum length of any pipe section
// PSeed = number to use as random seed
// PipePig = pigment for pipe texture
	#declare PA = array[Nodes][2]; // Pipe Array
	#declare RS=seed(PSeed);
//	#declare RS=seed(16951);
	#declare StartPos = <0,0,0>;
	#declare PA[0][0] = StartPos;
//#debug concat("PA[0][0].x :",str(PA[0][0].x,5,0),"\n")
	#declare StartDir = <1,0,0>;
	#declare PA[0][1] = StartDir;
	union {
//sphere { PA[0][0],Dia*.65 texture { PipeTex } } // for testing
	#declare NodeN=1;
	#while ( NodeN < Nodes ) // ok, this section is crude, but it works!
		// reorients the next section of pipe to be 90-deg from the previous one
//#debug concat("NodeN: ",str(NodeN,3,0),"\n")
		#declare OldDir = PA[NodeN-1][1];
		#if (abs(OldDir.x)=1)
			#declare NewDir = vrotate(OldDir,<0,90,0>);
			#declare NewDir = vrotate(NewDir,<int(mod(4,rand(RS))*4)*90,0,0>);
		#end
		#if (abs(OldDir.y)=1)
			#declare NewDir = vrotate(OldDir,<0,0,90>);
			#declare NewDir = vrotate(NewDir,<int(mod(4,rand(RS))*4)*90,0>);
		#end
		#if (abs(OldDir.z)=1)
			#declare NewDir = vrotate(OldDir,<90,0,0>);
			#declare NewDir = vrotate(NewDir,<0,0,int(mod(4,rand(RS))*4)*90>);
		#end
		#declare PA[NodeN][1]=NewDir;
		#declare NewLength = <1,1,1>*(MinLen+rand(RS)*MaxLen);
		#declare NewPos = PA[NodeN-1][0]+NewLength*NewDir;
		#declare PA[NodeN][0]=NewPos;
		cylinder {
			PA[NodeN-1][0]+1.5*Dia*NewDir,PA[NodeN][0]-1.5*Dia*NewDir,Dia/2
			texture { PipeTex pigment {PipePig} }
		}
		object { Elbow(Dia)
			texture { PipeTex pigment {PipePig} }
			rotate (vcross(x,OldDir))*90
//#debug concat("vcross: ",str(vcross(x,OldDir).x,3,0),str(vcross(x,OldDir).y,3,0),str(vcross(x,OldDir).z,3,0),"\n")
				#if (OldDir.x = -1) rotate z*180 #end // correct sign error
			#declare VS = vrotate(z,(vcross(x,OldDir)*90));
//#debug concat("VS: ",str(VS.x,3,0),str(VS.y,3,0),str(VS.z,3,0),"\n")
			rotate (vcross(VS,NewDir))*90 
//#debug concat("final rotate: ",str(((vcross(VS,NewDir))*90).x,3,0),str(((vcross(VS,NewDir))*90).y,3,0),str(((vcross(VS,NewDir))*90).z,3,0),"\n")
			#declare FS = vrotate(VS,(vcross(VS,NewDir))*90);
//#debug concat("FS: ",str(FS.x,3,0),str(FS.y,3,0),str(FS.z,3,0),"\n","\n")
				#if (FS.x != NewDir.x) rotate z*180 #end // correct sign error
				#if (FS.z != NewDir.z) rotate x*180 #end // correct sign error
			translate PA[NodeN-1][0]-OldDir*Dia*1.5
		}

 		#declare NodeN = NodeN + 1;
	#end
	} // end union
#end

#macro PipeTrackS(NodeArray,Dia,PipeTexture) // simple version, no elbows
// NodeArray = single dimensional array with all start, elbow, and end positions
// Dia = main diameter of pipe
// PipeTexture = texture for pipe
	#declare Nodes = dimension_size(NodeArray,1);
	#declare StartPos = <0,0,0>;
//	#declare PA[0] = StartPos;
//#debug concat("PA[0][0].x :",str(PA[0][0].x,5,0),"\n")
	#declare StartDir = <1,0,0>;
	union {
	#declare NodeN=1;
	#while ( NodeN < Nodes )
		cylinder {
			NodeArray[NodeN-1],NodeArray[NodeN],Dia/2
			texture { PipeTexture }
		}
 		#declare NodeN = NodeN + 1;
	#end
	} // end union
#end

#macro PipeTrack(NodeArray,Dia,PipeTexture) // with elbows
// NodeArray = single dimensional array with all start, elbow, and end positions
	#declare Nodes = dimension_size(NodeArray,1);
// Dia = main diameter of pipe
// PipeTexture = texture for pipe
//#debug concat("PA[0][0].x :",str(PA[0][0].x,5,0),"\n")
	#declare StartDir = <1,0,0>;
	union {
	#declare NodeN=1;
	#while ( NodeN < Nodes )
		cylinder {
			#declare NewDir = vnormalize(NodeArray[NodeN]-NodeArray[NodeN-1]);
			NodeArray[NodeN-1]+1.5*Dia*NewDir,NodeArray[NodeN]-1.5*Dia*NewDir,Dia/2
			texture { PipeTexture }
		}
 		#declare NodeN = NodeN + 1;
	#end
	#declare NodeN=1;
	#while ( NodeN < Nodes-1 )
		object { Elbow(Dia)
			texture { PipeTexture }
			#declare OldDir = vnormalize(NodeArray[NodeN]-NodeArray[NodeN-1]);
			#declare NewDir = vnormalize(NodeArray[NodeN+1]-NodeArray[NodeN]);
			rotate (vcross(x,OldDir))*90
//#debug concat("vcross: ",str(vcross(x,OldDir).x,3,0),str(vcross(x,OldDir).y,3,0),str(vcross(x,OldDir).z,3,0),"\n")
				#if (OldDir.x = -1) rotate z*180 #end // correct sign error
			#declare VS = vrotate(z,(vcross(x,OldDir)*90)); // new direction of far end of elbow
//#debug concat("VS: ",str(VS.x,3,0),str(VS.y,3,0),str(VS.z,3,0),"\n")
			rotate (vcross(VS,NewDir))*90 
//#debug concat("final rotate: ",str(((vcross(VS,NewDir))*90).x,3,0),str(((vcross(VS,NewDir))*90).y,3,0),str(((vcross(VS,NewDir))*90).z,3,0),"\n")
			#declare FS = vrotate(VS,(vcross(VS,NewDir))*90);
//#debug concat("FS: ",str(FS.x,3,0),str(FS.y,3,0),str(FS.z,3,0),"\n","\n")
				#if (FS.x != NewDir.x) rotate z*180 #end // correct sign errors
				#if (FS.z != NewDir.z) rotate x*180 #end // correct sign errors
				#if (NewDir.z=-1 & OldDir.x=0) rotate z*180 #end // correct sign errors
			translate NodeArray[NodeN]-OldDir*Dia*1.5
		}
 		#declare NodeN = NodeN + 1;
	#end
	} // end union
#end

#macro FlangedPipeTrack(NodeArray,Dia,PipeTexture) // with flanged elbows
// NodeArray = single dimensional array with all start, elbow, and end positions
	#declare Nodes = dimension_size(NodeArray,1);
// Dia = main diameter of pipe
// PipeTexture = texture for pipe
//#debug concat("PA[0][0].x :",str(PA[0][0].x,5,0),"\n")
	#declare StartDir = <1,0,0>;
	union {
	#declare NodeN=1;
	#while ( NodeN < Nodes )
		cylinder {
			#declare NewDir = vnormalize(NodeArray[NodeN]-NodeArray[NodeN-1]);
			NodeArray[NodeN-1]+1.5*Dia*NewDir,NodeArray[NodeN]-1.5*Dia*NewDir,Dia/2
			texture { PipeTexture }
		}
 		#declare NodeN = NodeN + 1;
	#end
	#declare NodeN=1;
	#while ( NodeN < Nodes-1 )
		object { FlangedElbow(Dia)
			texture { PipeTexture }
			#declare OldDir = vnormalize(NodeArray[NodeN]-NodeArray[NodeN-1]);
			#declare NewDir = vnormalize(NodeArray[NodeN+1]-NodeArray[NodeN]);
			rotate (vcross(x,OldDir))*90
//#debug concat("vcross: ",str(vcross(x,OldDir).x,3,0),str(vcross(x,OldDir).y,3,0),str(vcross(x,OldDir).z,3,0),"\n")
				#if (OldDir.x = -1) rotate z*180 #end // correct sign error
			#declare VS = vrotate(z,(vcross(x,OldDir)*90)); // new direction of far end of elbow
//#debug concat("VS: ",str(VS.x,3,0),str(VS.y,3,0),str(VS.z,3,0),"\n")
			rotate (vcross(VS,NewDir))*90 
//#debug concat("final rotate: ",str(((vcross(VS,NewDir))*90).x,3,0),str(((vcross(VS,NewDir))*90).y,3,0),str(((vcross(VS,NewDir))*90).z,3,0),"\n")
			#declare FS = vrotate(VS,(vcross(VS,NewDir))*90);
//#debug concat("FS: ",str(FS.x,3,0),str(FS.y,3,0),str(FS.z,3,0),"\n","\n")
				#if (FS.x != NewDir.x) rotate z*180 #end // correct sign errors
				#if (FS.z != NewDir.z) rotate x*180 #end // correct sign errors
				#if (NewDir.z=-1 & OldDir.x=0) rotate z*180 #end // correct sign errors
			translate NodeArray[NodeN]-OldDir*Dia*1.5
		}
 		#declare NodeN = NodeN + 1;
	#end
	} // end union
#end

#macro PipeLoop(Xdim,Ydim,Dia,PipeTexture)
	#declare MyArray =
	array[6]
	{<0,0,0>,<Xdim,0,0>,<Xdim,Ydim,0>,<0,Ydim,0>,<0,0,0>,<Xdim,0,0>
	}
	object { PipeTrack(MyArray,Dia,PipeTexture) }
#end

//===============================================
//             Objects
//===============================================

#declare RS=seed(20945);
#declare DisconnPiping =
	union {
		#local PQ=0;
		#while ( PQ < 400 )
			object { PipeSection(6,4*Feet+rand(RS)*20*Feet)
			texture { PipeTex }
			rotate <0,int(mod(4,rand(RS))*4)*90,int(mod(4,rand(RS))*4)*90>
			translate <-40*Feet+rand(RS)*80*Feet,-30*Feet+rand(RS)*60*Feet,-40*Feet+rand(RS)*80*Feet>
			}
			#local PQ=PQ+1;
		#end
	} // end union


//===============================================
//             Groups
//===============================================



//===============================================
//             For Testing Only
//===============================================

#if (RenderMe = 1)

global_settings {	max_trace_level 50 }
	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 35
//		location  <0*Feet, -100*Feet, 1500*Feet> // helicopter view
//		look_at <1*Feet,-40*Feet,8*Feet>
//		location  <300*Feet, -900*Feet, 180*Feet> // distant view
//		look_at <1*Feet,40*Feet,8*Feet>
		location  <11*Feet, -18*Feet, 6*Feet> // closer
		look_at <1*Feet,-0*Feet,2*Feet>
	}


light_source
{ <800*Feet,-700*Feet,1000*Feet>, 1.5
  spotlight point_at <0,0*Feet,2*Feet> radius 15 falloff 26
}
light_source
{ <-400*Feet,-200*Feet,300*Feet>, <1.13,1.08,0.83>*.8
  spotlight point_at <0,0,2*Feet> radius 15 falloff 26
}

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


//object { PipeGroup scale 1 rotate z*40 translate <0,0,0> }
//object { RPipeTrack(226,4,2*Feet,4*Feet,12270,rgb<.1,.1,1>) scale 3 rotate z*40 translate <12*Feet,0,9*Feet> }
//object { RPipeTrack(42,4,2*Feet,4*Feet,12270,rgb<1,1,1>) scale 2 rotate z*50 translate <-6*Feet,0,8*Feet> }
//object { Elbow(6) texture {PipeTex} scale 4 rotate z*40 translate <0,0,40> }  

#declare MyArray=
	array[18]
	{<0,0,0>,<0,0,20>,<20,0,20>,<20,-10,20>,
	<20,-10,10>,<20,10,10>,<20,10,40>,<0,10,40>,
	<0,-20,40>,<0,-20,30>,<15,-20,30>,<15,-5,30>,
	<40,-5,30>,<40,-5,20>,<55,-5,20>,<55,-40,20>,
	<30,-40,20>,<30,-40,0>

	}
//object { PipeTrack(MyArray,2,CopperTex) scale 1.4 translate <0,0,2> }
#declare FArray=
	array[6]
	{<0,0,0>,<0,0,20>,<40,0,20>,<40,40,20>,
	<40,40,80>,<-30,40,80>
	}
object { FlangedPipeTrack(FArray,8,CopperTex) scale 1.0 translate <0,0,2> }


//object { PipeLoop(60,20,2,CopperTex) translate <0,0,4> }

#end
