// Persistence of Vision Ray Tracer Include File
// File: locker.inc
// Vers: 3.1
// Desc: School Locker 
// Date: 9/21/99 
// Auth: Ray Benajmin, Copyright 1999, all rights reserved.
//
// Scale 1 = 1 foot 

#ifndef(School_Locker_Inc)
#declare School_Locker_Inc = 1;

#ifndef(char_A)
    #include "chars.inc"
#end

#include "hinge.inc"

///////////////////////////////////////////////////////////////////////////////////////
// School Locker

// Scaling variables

#ifndef (Foot)
    #declare Foot = 1;
#end

#ifndef (Inch)
    #declare Inch = 1/12;
#end

// Defaults - just define these in the pov file before you include this file to change them.
#ifndef (LockerHeight)
    #declare LockerHeight = 6*Foot;
#end
#ifndef (LockerWidth)    
    #declare LockerWidth = 1*Foot;
#end
#ifndef (LockerDepth)    
    #declare LockerDepth = 1*Foot;
#end
#ifndef (BaseHeight)    
    #declare BaseHeight = 6*Inch;
#end    
#ifndef (EdgeWidth)
    #declare EdgeWidth = 1*Inch; // really the width of the frame, space between door and outside edge of locker
#end
#ifndef (MW)    
    #declare MW = Inch/16; // metal width
#end
#ifndef (Gap)    
    #declare Gap = Inch/8;
#end    

#ifndef (NumVents)
    #declare NumVents = 4;
#end
#ifndef (VentHeight)    
    #declare VentHeight = Inch/2;
#end
#ifndef (VentDepth)
    #declare VentDepth = Inch/2;
#end
#ifndef (VentWidth)
    #declare VentWidth = 6*Inch;
#end
#ifndef (VentSpacing)
    #declare VentSpacing = Inch/4;
#end

#ifndef (DoorOpenAngle)
    #declare DoorOpenAngle = 0; // in degrees
#end

#ifndef (RLockerSeed)
    #declare RLockerSeed = seed(2001);
#end

// this pigment has smudges and scratches to simulate wear and tear on the lockers
#declare P_Locker = pigment {
    granite
    color_map {
        [0.0 White]
        [0.07 White]
        [0.07 Gray50]
        [0.8 Gray50]
        [0.92 Black]
        [1.0 Gray10]
        }
    turbulence 1
    scale 6
    }

#declare T_Locker = texture {
    pigment {P_Locker}
    finish {Dull}
    normal {dents 1}
    }

///////////////// Make Locker Base Macro ////////////////
#macro MakeLockerBase()
    #local T_LockerBase = texture { T_Locker }
    #local LB_Width = LockerWidth-MW*2-Gap*3;
    #local LB_Height = BaseHeight-Gap;
    #local LB_Depth = LockerDepth-MW*2-Gap*2;
     
    box {<0,0,MW>, <LB_Width,LB_Height,LB_Depth> texture {T_LockerBase}}
        texture {T_LockerBase translate <rand(RLockerSeed),rand(RLockerSeed),rand(RLockerSeed)>
        translate <MW,0,0>
        }
#end // Macro

// locker door parameters are defined here since they are needed in the MakeLockerBody macro
#declare LDoorWidth = LockerWidth-EdgeWidth*2 - Gap*2;
#declare LDoorHeight = LockerHeight-BaseHeight-EdgeWidth-Gap*2;
#declare LDoorDepth = 1*Inch;

//////////// Make Locker Body Macro //////////////////////
#macro MakeLockerBody()
    #local LW = LockerWidth - Gap;
    #local LH = LockerHeight;
    #local LD = LockerDepth;

    difference {
        box {<0,0,0>, <LW,LH,LD>}
        // make it hollow
        box {<0,0,0>, <LW-MW*2,LH-MW*2,LD-MW*2>
            translate <MW,MW,MW>
            } // make it hollow
        // cut out the door
        box {<0,0,-.1>, <LockerWidth - 2*EdgeWidth,LDoorHeight+BaseHeight-EdgeWidth+Gap*2,.1>
            translate <EdgeWidth-Gap/2,EdgeWidth,0>
            }
        // texture, finish, etc.
        texture {T_Locker translate <rand(RLockerSeed),rand(RLockerSeed),rand(RLockerSeed)>}
        translate Gap/2*x
        }
    // add base
    object {
        MakeLockerBase()
        translate <Gap/2,0,0>
        }
#end // macro

/////// Locker Shelf ////////////
#declare Locker_Shelf = box {
    <MW,0,MW+Inch>, <LockerWidth-MW*2-Gap*3,Inch,LockerDepth-MW*2-Inch> 
    texture {T_Locker}
    }     

#declare Locker_Bar = cylinder {  //HMC
    <MW,0,LockerDepth/2>,<LockerWidth-MW*2-Gap*3,0,LockerDepth/2>, .5*Inch
    texture {T_Locker}
    }

/// Make Locker Macro /////////
//
// IDNumber - id number for the locker plate
// DoorOpenAngle - 0 = shut, 175 all the way open
//
#macro MakeLocker(IDNumber,DoorOpenAngle)

//////////////// Locker Door //////////////////////////

#local T_NumberPlate = texture {T_Silver_1A}
#local T_Vent = texture { T_Locker }

////////// Locker Number Plate ////////////

#local NP_W = 3*Inch;
#local NP_H = 1*Inch;
#local NP_D = Inch/16;
#local NP_cyl_rad = Inch/4;
#local NumberPlate_Pos = <LDoorWidth/2,LDoorHeight - EdgeWidth*2,0>;

#local NumberPlate = union {
    #local npcyl = cylinder {<0,0,0>, <0,0,-NP_D>, NP_cyl_rad}
    #local rivet_rad = Inch/8;
    box {<0,0,-NP_D>, <NP_W,NP_H,0>}
    object {npcyl translate <-NP_cyl_rad/2,NP_H/2,0>}
    object {npcyl translate <NP_W+NP_cyl_rad/2,NP_H/2,0>}
    // add rivets
    #local rivet = sphere {<0,0,0>, rivet_rad texture {Polished_Chrome}}
    object {rivet translate <0,NP_H/2,0>}
    object {rivet translate <NP_W,NP_H/2,0>}
    texture {T_NumberPlate}
    translate -NP_W/2*x
    }

////////// Vents ////////////

#local Vent = object {
    #local VentPart = union {
        sphere {<0,0,0> VentHeight}
        cylinder {<0,0,0>, <VentWidth,0,0>, VentHeight}
        sphere {<VentWidth,0,0>, VentHeight}
        }
    difference {
        object {VentPart}
        object {VentPart scale (VentHeight-MW)/VentHeight}
        clipped_by { plane {-y,0} plane{z,0}}
        bounded_by { clipped_by }
        }
    texture {T_Vent translate <rand(RLockerSeed),rand(RLockerSeed),rand(RLockerSeed)>}
    }


#local VentAssembly = union {
    #local y_offset = VentHeight + VentSpacing;
    #local ct = 0;
    #while (ct < NumVents)
        object {Vent translate y_offset*ct*y}
        #local ct = ct + 1;
    #end
    translate -VentWidth/2*x
    }


#local TotalVentHeight = VentHeight*NumVents + VentSpacing*(NumVents-1);
#local UpperVent_pos = <LDoorWidth/2,LDoorHeight-6*Inch,0>;
#local LowerVent_pos = <LDoorWidth/2,6*Inch,0>;

#local VentCutOut = box {<0,0,-.1>, <VentWidth,TotalVentHeight,.1> translate -VentWidth/2*x}

#local LD_Hinge_Rad = Inch/9;

#local LD_Hinge = object {
    #local len = LDoorHeight-2*Gap;
    #local hdiv = 40;
    #local tex = texture {T_Silver_1A}
    MakeHinge(len,LD_Hinge_Rad,hdiv,tex)
    }

////////// Lock ////////////////////
#local LP_Width = 2*Inch;     // lock plate width
#local LP_Height = 4*Inch;    // lock plate height
#local LP_Depth = Inch/16;    // lock plate depth

#local Lock_pos = <LDoorWidth-EdgeWidth/2-Gap-LP_Width,LDoorHeight/2,-LP_Depth>;
#local T_LockPlate = texture { T_Silver_3A }

#local T_Combo = texture {
    pigment {Gray10}
    }

#local T_Slider = texture {
    T_Silver_4B
    }                          
   
    
#local Lock_Slider = difference {
    #local LS_Width = Inch/4;
    #local LS_Depth = Inch;
    #local LS_Height = Inch;
    #local LS_Hole_Rad = Inch/4;
    
    box {<0,0,0>, <LS_Width,LS_Height,LS_Depth>}
    cylinder {<0,0,0>, <Inch,0,0>, LS_Hole_Rad 
        translate <-Inch/2,LS_Height/2,LS_Depth/2>
        }
    texture {T_Slider}
    translate <-LS_Width/2,-LS_Height,-LS_Depth>
    }
    
#local Lock_Knob = union {
    #local Knob_Rad = 3*Inch/4;
    cylinder {<0,0,0>, <0,Inch/8,0>, Knob_Rad texture {Polished_Chrome}}
    cone {<0,0,0>, Knob_Rad-Knob_Rad/8, <0,Inch/4,0>, Inch/4 texture {T_Combo} translate y*Inch/8}
    cylinder {<0,0,0>, <0,3*Inch/16,0>, Inch/4 texture {T_Silver_3A} translate (Inch/8+Inch/4)*y}
    rotate <-90,0,0> 
    }

#local Lock_Housing_Depth = 1*Inch-MW;
#local T_Lock_Housing = texture {T_Silver_3A}

#local Lock_Housing = difference {
    box {<0,0,0>, <LP_Width,LP_Height,Lock_Housing_Depth> texture {T_Lock_Housing}}
    box {<MW,MW,-MW>, <LP_Width-MW, LP_Height-MW,Lock_Housing_Depth-MW>
        pigment {Gray90}
        }
    }

#local Lock_Plate = difference {
    box {<0,0,0>, <LP_Width,LP_Height,LP_Depth>}
    // slot for slider
    box {<-Inch/16,0,-.1>, <Inch/16,1*Inch,.1> translate <LP_Width/2,LP_Height/2,0>}
    texture {T_LockPlate}
    }
        
#local Lock_Assembly = union {
    // housing
    object {Lock_Housing translate <0,0,0>}
    // lock plate
    union {
        object {Lock_Plate translate <0,0,Inch/8>}
        object {Lock_Knob translate <LP_Width/2,LP_Width/2,0>}
        object {Lock_Slider translate <LP_Width/2,LP_Height - 3*Inch/4,0>}
        translate z*Inch/2
        }
    translate <0,0,-Inch/16>
    }

#local Lock_Assembly_Cutout = box {<0,0,-.1>,<LP_Width,LP_Height,Inch>}

////////// Assemble Locker Door ///////////////
#local LockerDoor = union {
    difference {
        box {<0,0,0>, <LDoorWidth,LDoorHeight,LDoorDepth>}
        // make door hollow, sort of
        box {<MW,MW,MW>,<LDoorWidth-MW,LDoorHeight-MW,LDoorDepth+.1>}
        // cutout place for upper vents
        object {VentCutOut translate UpperVent_pos}
        // cutout place for lower vents
        object {VentCutOut translate LowerVent_pos}
        // cutout for lock assembly
        object {Lock_Assembly_Cutout translate Lock_pos}
        texture {T_Locker translate <rand(RLockerSeed),rand(RLockerSeed),rand(RLockerSeed)>}
        } // difference
    // bracing on back of door
    difference {
        box {<0,0,0>, <LDoorWidth,LDoorHeight,MW>}
        box {<Inch,Inch,-Inch>,<LDoorWidth-Inch,LDoorHeight-Inch,Inch>}
        texture {T_Locker translate <rand(RLockerSeed),rand(RLockerSeed),rand(RLockerSeed)>}
        translate <0,0,Inch-MW>
        } // difference
    // Number Plate
    object {NumberPlate translate NumberPlate_Pos}
    // upper vents
    object {VentAssembly translate UpperVent_pos}
    // lower vents
    object {VentAssembly translate LowerVent_pos}
    // Hinge
    object {LD_Hinge translate <-LD_Hinge_Rad/2,Gap,-LD_Hinge_Rad>}     
    // Lock
    object {Lock_Assembly translate Lock_pos}
    } // union


////// Assemble Locker /////////
union {
    MakeLockerBody()
    #local LW = LockerWidth - Gap;
    #local LH = LockerHeight;
    #local LD = LockerDepth;
    // add door
           
    #if (DoorOpenAngle = 0)
        #local Angle = rand(RLockerSeed)*5;
        #declare anglesOpen[ctr] = Angle;
    #else
        #local Angle = DoorOpenAngle;
        #declare anglesOpen[ctr] = Angle;
    #end
    
    #declare ctr=ctr+1;
    
    object {LockerDoor rotate <0,DoorOpenAngle,0> 
        translate <EdgeWidth+Gap,BaseHeight+Gap,0> 
        translate x*0
        }
    object {Locker_Shelf 
        translate <0,LockerHeight-1*Foot,0>
        texture {T_Locker translate <rand(RLockerSeed),rand(RLockerSeed),rand(RLockerSeed)>}
        } 
    object {Locker_Bar //HMC
        translate <0, LockerHeight-1*Foot-Foot/4,0>  
        texture {T_Locker translate <rand(RLockerSeed),rand(RLockerSeed),rand(RLockerSeed)>}
        }  
    }

#end // Macro

//////////////////////////////////////////////////////////////////////////////////////////////////
// Fire Extinguisher/Waste Can
//
// The fire extinguisher and waste can are incorporated in a locker unit

#declare ExtRad = 4*Inch;
#declare ExtH = 18*Inch;

#declare T_Ext_Body = texture {
    pigment { Red }
    finish { ambient .4 }
    }

// Fire Text
#declare T_FireText = texture {
    pigment {Red}
    }
    
#declare FireText = union {
    #local vertspace = 7;
    object {char_F translate vertspace*3*y}
    object {char_I translate vertspace*2*y}
    object {char_R translate vertspace*y}
    object {char_E}
    texture {T_FireText}
    scale 1/20
    }
        
// Trash Text
#declare T_TrashText = texture {
    pigment {Black}
    }
#declare TrashText = union {
    object {char_T}
    object {char_R translate 5*x}
    object {char_A translate 5*x*2}
    object {char_S translate 5*x*3}
    object {char_H translate 5*x*4}
    texture {T_TrashText}
    scale 1/40
    }
    
#declare Extinguisher = union {
    // body
    union {
        cylinder {<0,-ExtRad/2,0>, <0,ExtH,0>, ExtRad}
        sphere {<0,ExtH,0>, ExtRad}
        texture {T_Ext_Body}
        }
    // Add silver bands of mounting bracket
    #local Band = difference {
        cylinder {<0,0,0>, <0,1*Inch,0>, ExtRad + Inch/16}
        cylinder {<0,-Inch/10,0>, <0,Inch+Inch/10,0>, ExtRad}
        texture {Polished_Chrome}
        }
    object {Band translate <0,2*Inch,0>}
    object {Band translate <0,ExtH-2*Inch,0>}
    // Make origin bottom most point of bottom sphere
    translate <0,ExtRad,0>
    }
    
#declare ExtinguisherCan = union {
    #local MidPoint = BaseHeight+LDoorHeight/2;
    MakeLockerBody()
    box {<MW,0,0>, <LockerWidth-MW*2-Gap*3,Inch,LockerDepth-MW*2>
        texture {T_Locker}
        translate <0,MidPoint,0>
        }
    // Extinguisher
    object {Extinguisher translate <LockerWidth/2,MidPoint+3*Inch,LockerDepth/2>}

    #local PanelWidth = LockerWidth-EdgeWidth*2-Gap; 
    #local ExtDoorH = LockerHeight - EdgeWidth*2 - MidPoint;
    // Extinguisher Door
    union {
        // frame
        difference {
            box {<0,0,0>, <PanelWidth,ExtDoorH,Inch/2>}
            box {<EdgeWidth,EdgeWidth,-Inch>,<PanelWidth-EdgeWidth,ExtDoorH-EdgeWidth,Inch>}
            texture {T_Silver_3C}
            }
        // glass
        box {<0,0,0>, <PanelWidth-EdgeWidth*2,ExtDoorH-EdgeWidth*2,Inch/8>
            texture {T_Glass1}
            interior {I_Glass}
            translate <EdgeWidth,EdgeWidth,Inch/8>
            }
        // text
        object {FireText translate <PanelWidth/2,8*Inch,-Inch/16>}
        // handle
        // translation
        translate <EdgeWidth+Gap/3,MidPoint+EdgeWidth+Gap/3,Inch/16>
        }
    // Trash Can Panel
    #local TrashDoorHeight = 6*Inch;
    box {<0,BaseHeight+Gap/2,0>, <PanelWidth,MidPoint-TrashDoorHeight-Gap,MW>
        texture {T_Locker}
        translate (EdgeWidth+Gap/3)*x}
    // Trash Can Door
    union {
        box {<0,0,0>, <PanelWidth-Gap/2,TrashDoorHeight,MW> 
            texture {T_Silver_4B}
            }
        object {TrashText translate <1.5*Inch,2.5*Inch,-Inch/16>}
        translate <EdgeWidth+Gap/2,MidPoint-TrashDoorHeight,MW>
        }
    }
    
//////////////////////////////////////////////////////////////////////////////////////////////////

////////// Locker Row Macro ///////////
// startpos is number of locker widths "over" to start the row
// num is the number of lockers to make
// width is the width of each locker
// lockernumber is the starting number for the row of lockers (currently unused)
#macro MakeLockerRow(startpos,num,Width,lockernumber,OpenAngle)
    // Declare variables so they can be stolen for Heather Cousineau's sticker macro
    #declare anglesOpen = array[num]
    #declare ctr = 0;                
    #declare rowStart = startpos;   
    #declare lockerOpenAngle = OpenAngle;
    // ---
    #local ct = 0;
    #while (ct < num)
        object {
            MakeLocker(lockernumber,OpenAngle)
            translate <Width*(ct+startpos),0,-rand(RLockerSeed)*Gap+Gap/2>
            }
        #local ct = ct + 1;
    #end
//    bounded_by {box {<-Inch,0,-Inch/2>,<Width*ct+Inch,LockerHeight+Inch,LockerDepth+Inch>}}
#end

#end // ifndef


