//      Copyright 2001 Andrew Bowcock


#declare C_now=clock*100;
#declare quality=10;
                                                                                                                

#declare C_pullback1start=10;       // view of electron within socket + wording
#declare C_plugrisestart=11;        // start of plug rise
#declare C_plugriseend=27;          // end of plug rise
#declare C_sos=34.4;                // start of switchon
#declare C_soe=35;                  // end of switchon
#declare C_dive1start=35;           // start of dive into wire
#declare C_epos1=35;                // start of electron sweep along 1st wire segment
#declare C_epos2=C_epos1+3.33;      // start of electron sweep along 2nd wire segment
#declare C_epos3=C_epos2+1.2;       // start of electron sweep along 3rd wire segment
#declare C_epos4=C_epos3+1.25;      //
#declare C_epos5=C_epos4+.634;      //
#declare C_epos6=C_epos5+21.24;     //
#declare C_plunge=C_epos5;
#declare C_impact=40.9;               // moment of impact with flex
#declare C_bend=45;                 // camera reaches bend inside flex
#declare C_bendend=52;
#declare C_showinside=50;           // moment when inside of PC becomes visible
#declare C_elecout=52.5;            // electron leaves flex and enters computer
#declare C_out=53;                  // moment of reemergence of camera into computer
#declare C_wait=58;                 // wait till this time, watching mainboard
#declare C_vidout=68;               // leaving PC in video lead
#declare C_leavescreen=71;          // camera begins to lift off screen
#declare C_showpic=75.5;            // see screen (pic starts moving)
#declare C_picstop=C_showpic+10.7;  // moment pictures stop moving
#declare C_dotsview=75;             // dots are in first view
#declare C_picview=80;              // picture fully in view
#declare C_deskview=85;             // PC, desk etc are in view
#declare C_zapview=90;              // view of zapper
#declare C_flyzap=97.9;             // death of fly
#declare C_end=100;                 // end


#include "BasicShapes.inc"
#include "fly.inc" 
#include "wording.inc"
#include "components.inc"
#include "atomlat.inc"
#include "colors.inc"
#include "office.inc"
#include "debug.inc"

#macro wording()
        showwords("Does life seem futile when you think  ","  that you are one of billions of people",3,6)
        showwords("and no-one gives a thought","for your toil ... ?",7,10)
        showwords("Spare a moment to think of each","of the countless trillions of electrons",12,15)
        showwords("as they do their           work","",16,24)
        showwords("                            day's","",16,17.5)
        slidein  ("nanosecond's",16,24)
#end

#macro wording1()
        marquee("... and your electron still doesn't rest, it's off on a deadly mission ...",3,13,C_now)
#end

#macro post(tn,t1,t2,p1,p2)             // float function of tn which starts smoothly at p1 and ends smoothly at p2
        #declare tnorm=(tn-t1)/(t2-t1);
        #if ((tn>=t1)&(tn<=t2)) #declare ret=p1+(p2-p1)*(3*tnorm*tnorm-2*tnorm*tnorm*tnorm); #end
        #if (tn<t1) #declare ret=p1; #end
        #if (tn>t2) #declare ret=p2; #end
        ret
#end

#macro vppost(tn,t1,t2,p1,p2,ex)        // vector function of tn (time now) which starts smoothly at p1 and ends smoothly at p2
                                        // movement can be shifted towards beginning or end using "ex"
        #declare pfactor=pow(post(tn,t1,t2,0,1),ex);
        <p1.x+(p2.x-p1.x)*pfactor,p1.y+(p2.y-p1.y)*pfactor,p1.z+(p2.z-p1.z)*pfactor>
#end

#macro inwire(time)
        #declare px=ol-410.25;
        #declare py=ow-340.06+(C_out-time);
        #declare pz=post(time,C_bend,C_bendend,926.21,930);
#end

#macro flightcamera()
        #declare skyvect=<0,0,1>;
        #if(clock>=0)
                #declare campos=<220,ow-13,181>;
                #declare lookpos=<220,ow-5,181>;
        #end
        #if(C_now>C_pullback1start)// start to move camera
                #declare campos=<100+120*cos(post(C_now,C_pullback1start,C_dive1start,0,3*pi/4)),
                                 ow-13-120*sin(post(C_now,C_pullback1start,C_dive1start,0,3*pi/4)),
                                 181>;
                #declare lookpos=<220,ow-5,181>;
        #end
        #if(C_now>C_dive1start)
                #declare campos=<15.147+(ol*.105-15.147)*(1-cos(post(C_now,C_dive1start,C_plunge,0,pi/2))),
                                ow-13-84.853+(-35-8+84.853)*(1-cos(post(C_now,C_dive1start,C_plunge,0,pi/2))),
                                181-174.5*sin(post(C_now,C_dive1start,C_plunge,0,pi/2))>;
                #declare lookpos=<post(C_now,C_dive1start,C_plunge,220,ol*.12+100),
                                post(C_now,C_dive1start,C_plunge,ow-5,ow-35),
                                181-174.5*sin(post(C_now,C_dive1start,C_plunge,0,pi/2))>;
        #end
        #if(C_now>C_impact)
                inwire(C_now)
                #declare campos=<px,py,pz>;
                inwire(C_now+.1)
                #declare lookpos=<px,py,pz-.06*(C_now-C_impact)/(C_wait-C_impact)>;
        #end
        #if(C_now>C_wait)
                inwire(C_wait)
                #declare P_arrive=<px,py,pz>;
                inwire(C_wait+.1)
                #declare P_lookstart=<px,py,pz-.06>;
                #declare P_lookstart=P_arrive+200*vnormalize(P_lookstart-P_arrive);
                #declare P_vidout=<ol-354.7,ow-600,869.8>;
                #declare ang=pi/12;
                #declare campos=<P_vidout.x+(P_arrive.x-P_vidout.x)*sin(post(C_now,C_wait,C_vidout,ang,pi))/sin(ang),
                                post(C_now,C_wait,C_vidout,P_arrive.y,P_vidout.y),
                                post(C_now,C_wait,C_vidout,P_arrive.z,P_vidout.z)>;
                #declare lookpos=<post(C_now,C_wait,C_vidout,P_lookstart.x,P_vidout.x+1.01),
                                 post(C_now,C_wait,C_vidout,P_lookstart.y,P_vidout.y),
                                 post(C_now,C_wait,C_vidout,P_lookstart.z,P_vidout.z)>;
                #declare skyvect=<sin(post(C_now,C_wait,C_vidout,0,pi)),
                                   post(C_now,(C_wait+C_vidout)/2,C_vidout,0,1),
                                   post(C_now,C_wait,C_vidout,1,0)>;
        #end
        #if ((C_now>C_vidout)&(C_now<=C_dotsview))
                #declare scrlift=6.4*pow(post(C_now,C_leavescreen,C_dotsview,0,1),1.4);
                #declare xpos=post(C_now,C_vidout-(C_dotsview-C_vidout)/2,C_dotsview,-14,0.15);
                #declare campos=vrotate(<xpos,9.5+scrlift,200.4>,z*120);
                #declare campos=campos+<ol-560,ow-460,990>;
                #declare lookpos=vrotate(<0,0,200>,z*120)+<ol-560,ow-460,990>;
                #declare skyvect=<-cos(post(C_now,C_vidout,(C_dotsview+C_vidout)/2,0,pi/2)),
                                  0,
                                  sin(post(C_now,C_vidout,(C_dotsview+C_vidout)/2,0,pi/2))>;
        #end
        #if ((C_now>C_dotsview)&(C_now<=C_picview))
                #declare P_camstart=vrotate(<0.15,9.5+6.4,200.4>,z*120)+<ol-560,ow-460,990>;
                #declare P_camend=<4410,3510,1210>;
                #declare campos=vppost(C_now,C_dotsview,C_picview,P_camstart,P_camend,2);
                #declare P_lookstart=vrotate(<0,0,200>,z*120)+<ol-560,ow-460,990>;
                #declare P_lookend=P_lookstart;
                #declare lookpos=vppost(C_now,C_dotsview,C_picview,P_lookstart,P_lookend,1);
                #declare skyvect=<0,0,1>;
        #end
        #if ((C_now>C_picview)&(C_now<=C_deskview))
                #declare P_camstart=<4410,3510,1210>;
                #declare P_camend=<3700,3200,1320>;
                #declare campos=vppost(C_now,C_picview,C_deskview,P_camstart,P_camend,1);
                #declare P_lookstart=vrotate(<0,0,200>,z*120)+<ol-560,ow-460,990>;
                #declare P_lookend=<4440,3340,1190>;
                #declare lookpos=vppost(C_now,C_picview,C_deskview,P_lookstart,P_lookend,1);
                #declare skyvect=<0,0,1>;
        #end
        #if ((C_now>C_deskview)&(C_now<=C_zapview))
                #declare P_camstart=<3700,3200,1320>;
                #declare P_camend=<3700,3200,1412>;
                #declare campos=vppost(C_now,C_deskview,C_zapview,P_camstart,P_camend,1);
                #declare P_lookstart=<4440,3340,1190>;
                #declare P_lookend=<4350,4000,1480>;
                #declare lookpos=vppost(C_now,C_deskview,C_zapview,P_lookstart,P_lookend,1);
                #declare skyvect=<0,0,1>;
        #end
        #if ((C_now>C_zapview)&(C_now<=C_end))
                #declare P_camstart=<3700,3200,1412>;
                #declare P_camend=<4465,3960,1510>;
                #declare campos=vppost(C_now,C_zapview,C_end,P_camstart,P_camend,1);
                #declare lookpos=<4350,4000,1480>;
                #declare skyvect=<0.05*sin((C_now-C_zapview)*3),0,1>;
        #end
        camera {
                location campos
                sky skyvect
                look_at lookpos
                }
#end


#macro lights1()
        light_source{<3000,3000,2500>,colour post(C_now,C_dotsview,C_end,1,.4)}
        #if (quality>3)
        light_source{<15,3900,500> colour post(C_now,C_dotsview,C_end,1,.4)}            //lights dark side of plug
        #else
        light_source{campos colour 1}                  //easy light for low quality
        #end

#end

#macro incomputerlights()               // used in flex and in computer
        light_source{campos colour .2}
        light_source{<ol-55,ow-400,1050> colour 2.5}  // behind PC shining in
        light_source{<ol-500,ow-450,910> colour rgb <1.3,1,1.1>}
#end

#macro moveplug()
        #declare py=200*cos(post(C_now,C_plugrisestart,C_plugriseend,0,pi/2));
        #declare pz=200*sin(post(C_now,C_plugrisestart,C_plugriseend,0,pi/2));
        object{mainplug() rotate <post(C_now,C_plugrisestart,C_plugriseend,90,0),-90,90>
                translate <200+10,ow-11-py,pz-5>
               }
        #declare theta=90;
        #declare phi=0;
        #declare xs=210;
        #declare ys=ow-17-py;
        #declare zs=pz-5;
        #declare leaddiameter=7;

        object{mainsocket(post(C_now,C_sos,C_soe,0,1)) rotate<0,-90,90> translate <200,ow,200>}

        union{
                object{wirepiece(210+187.5,ow-18,12)}
                object{wirepiece(ol*.1,ow-48,8.5) }
                object{wirepiece(ol*.12,ow-35,8.5) }
                object{wirepiece(ol*.13,ow-16.5,11.5)}
                object{wirepiece(ol*.5,ow-28,8.5) }
                object{wirepiece(ol*.9,ow-40,8.5) }
                object{wirepiece(ol*.9+100,ow-41,200) }
                object{wirepiece(ol-730,ow-50,600) }
                object{wirepiece(ol-530,ow-150,870) }
                object{wirepiece(ol-300,ow-200,840) }
                finish{phong .3}
                pigment{Orange}
             }
#end

#macro electron(time)
    #declare time=time-int(time);
    #declare sint=sin(2*pi*time);
    union{
        sphere{0,20+10*time pigment{rgbt <.2,.2,1,.9+time*.1>} finish{ambient rgb <.2,.2,.9>}hollow}
        sphere{0,5+15*time pigment{rgbt <.2,.2,1,.8+time*.1>} finish{ambient rgb <.2,.2,.9>}hollow}
        sphere{0,3+2*time pigment{rgbt <.2,.2,.8,.7+time*.1>}finish{ambient .6}hollow}
        sphere{0,2+1*time pigment{rgbt <.2,.2,.8,.6+time*.1>}finish{ambient .6}hollow}
        sphere{0,.5+1.5*time pigment{rgbt <.2,.2,.8,.2+time*.4>}finish{ambient 1.6-time}hollow}
        sphere{0,.5 pigment{rgbt <.2,.2,1,.2>}finish{ambient rgb 2}hollow}
        pigment{rgbt <0,0,1,1>}
        }
#end

#macro movelectron()
     #if((clock>=0)&(C_now<=C_epos1))
                object{electron(C_now/2)                       // electron in socket
                clipped_by{box{<-25,-2,-25><25,2,25>}}
                bounded_by{clipped_by}
                //scale .1
                translate <220,ow-5,181>}
      #end
     #if((C_now>C_epos1)&(C_now<=C_impact))
                #if ((C_now>C_epos1)&(C_now<=C_epos2))
                        #declare theta=90;
                        #declare phi=0;
                        #declare pstart=<210,3983,195>;
                        #declare pcentre=<0,-.9367,183.0515>;
                        #declare r=183.0541;
                        #declare theta2=-.0053;
                        #declare Alpha=91.3925; //l=3.33
                        #declare sweepangle=(C_now-C_epos1)/(C_epos2-C_epos1)*Alpha*pi/180;
                #end
                #if ((C_now>C_epos2)&(C_now<=C_epos3))
                        #declare theta=-1.3925;
                        #declare phi=359.6944;
                        #declare pstart=<397.5,3982,12>;
                        #declare pcentre=<0,-186.1347,-37.8792>;
                        #declare r=189.9499;
                        #declare theta2=4.5116;
                        #declare Alpha=32;     //l=1.2096
                        #declare sweepangle=(C_now-C_epos2)/(C_epos3-C_epos2)*Alpha*pi/180;
                #end
                #if ((C_now>C_epos3)&(C_now<=C_epos4))
                        #declare theta=5.005;
                        #declare phi=327.6199;
                        #declare pstart=<500,3952,8.5>;
                        #declare pcentre=<0,77.9366,8.1574>;
                        #declare r=78.3623;
                        #declare theta2=1.4665;
                        #declare Alpha=80.0973;   //l=1.255
                        #declare sweepangle=(C_now-C_epos3)/(C_epos4-C_epos3)*Alpha*pi/180;
                #end
                #if ((C_now>C_epos4)&(C_now<=C_epos5))
                        #declare theta=-5.0005;
                        #declare phi=47.1939;
                        #declare pstart=<600,3965,8.5>;
                        #declare pcentre=<650,3983,11.5>;
                        #declare r=59.0579;
                        #declare theta2=4.6645;
                        #declare Alpha=53.7537;   //l=.6348
                        #declare sweepangle=(C_now-C_epos4)/(C_epos5-C_epos4)*Alpha*pi/180;
                #end
                #if ((C_now>C_epos5)&(C_now<=C_epos6))
                        #declare theta=-.7485;
                        #declare phi=353.5231;
                        #declare pstart=<650,3983,11.5>
                        #declare pcentre=<0,8515.6766,-1166.8290>;
                        #declare r=8595.2451;
                        #declare theta2=1.707
                        #declare Alpha=12.3563;   //l=.6348
                        #declare sweepangle=(C_now-C_epos4)/(C_epos5-C_epos4)*Alpha*pi/180;
                #end
                object{
                        electron(C_now/2)                        // electron in flex
                        translate <r*sin(sweepangle),0,-r*cos(sweepangle)>
                        rotate<-theta2*180/pi,0,0>
                        translate pcentre
                        rotate<0,theta,0>
                        rotate<0,0,phi>
                        translate pstart
                       }
       #end             // end of period when camera is out of flex
       #if ((C_now>C_impact)&(C_now<=C_elecout))
                inwire(C_now+1)
                object{electron(C_now/2)
                clipped_by{box{<-25,-2,-25><25,2,25>}}
                bounded_by{clipped_by}
                scale .1
                translate <px,py,pz-3*pow(((C_now-C_impact)/(C_elecout-C_impact)),4)>}
       #end
       #if ((C_now>C_elecout)&(C_now<=C_vidout))
                #declare time=(C_now-C_elecout)/(C_vidout-C_elecout);       // normalized time during flight through PC
                #declare npts=15;
                #declare pe=array[npts] {<165,36,20>,<170,-10,0>,<170,-60,0>,<120,-60,0>,<170,-60,0><100,-80,0>,<120,-190,0><170,-190,0><190,-150,0><160,-150,0><160,-206,0><160,-206,10><210,-206,10><210,-206,24.8><280,-206,24.8>}
                #declare te=array[npts] {    0,         .1,          .2,        .25,         .3        .35        .4,       .45,         .51,          .6,         .7,         .75,           .8,          .88,             1}
                #declare tcount=0;
                #while ((te[tcount+1]<time)&(tcount<npts-2))
                        #declare tcount=tcount+1;
                #end
                #declare P_epos=<ol-575,ow-400,846>+pe[tcount]+(pe[tcount+1]-pe[tcount])*(time-te[tcount])/(te[tcount+1]-te[tcount]);
                object{electron(C_now/2) translate P_epos}
       #end
       #if ((C_now>C_vidout)&(C_now<=C_dotsview))
                #declare xpos=post(C_now,C_vidout-(C_dotsview-C_vidout)/3,C_dotsview,-11.8,1);
                #declare P_epos=vrotate(<xpos,8.8-(C_now-C_vidout)/30,200.4>,z*120);
                #declare P_epos=P_epos+<ol-560,ow-460,990>;

                object{electron(C_now/2)
                clipped_by{box{<-25,-2,-25><25,2,25>}}
                bounded_by{clipped_by}
                scale .1
                translate P_epos
                }
       #end
#end                

#macro movefly()
        #if (C_now<C_impact)
                #declare flypos=<C_now+230,ow-30-10*cos(clock*20),130+clock*300>;
                object{flyingfly(C_now/2) rotate z*90 translate flypos}
        #end
        #if (C_now>C_zapview-2)
                #declare P_flystart=<3712,3225,1400>;
                #declare P_flyend=<4465,4012,1500>;
                #declare P_flypos=vppost(C_now,C_zapview,C_end,P_flystart,P_flyend,1);
                #if (C_now<C_flyzap)
                        object{flyingfly(C_now/2) rotate z*135 translate P_flypos}
                #else  
                        object{burntfly() rotate z*135 translate P_flypos}
                #end
        #end
        
#end


        #debug "Office\n"    office()
        flightcamera()
        lights1()
        #if (C_now<C_picview)
                #debug "Electron\n"  movelectron() #end
        #if (C_now>=C_pullback1start)
                #debug "Furniture\n" furniture(C_now) #end
        #if ((C_now>=C_pullback1start)&(C_now<C_impact))
                #debug "Clutter1\n" clutter1() #end
        #if ((C_now>=C_pullback1start)&(C_now<C_impact))
                #debug "Clutter2\n" clutter2() #end
        #if (C_now>=C_pullback1start)
                #debug "Plug\n" moveplug() #end
        #if ((C_now>=C_pullback1start)&(C_now<C_impact))
                #debug "Fly\n" movefly() #end
        #if (C_now<C_plugriseend)
                #debug "Wording\n" wording() #end
        #if ((C_now>=C_impact)&(C_now<C_out))
                #declare visline=(campos.y-(ow-340))/(vnormalize(campos-lookpos).y);
                #debug "Atoms\n" atomlattice(campos,lookpos,C_now/2,visline,visline*5) #end
        #if ((C_now>=C_showinside)&(C_now<C_vidout))
                #debug "Inside of Computer\n" incomputerlights() incomp() #end
        #if ((C_now>=C_vidout)&(C_now<(C_dotsview+C_picview)/2))
                #declare tm=C_now-C_vidout;
                #declare P_scamstart=vrotate(<-10,9,200.5>,z*120)+<ol-560,ow-460,990>;
                #declare P_scentre=vrotate(<.1,9,200>,z*120)+<ol-560,ow-460,990>;
                #debug "Atoms\n" atomlattice2(P_scamstart,P_scentre,C_now/2,1+12*pow(post(C_now,C_leavescreen,C_picview,0,1),2))
                #end
        #if ((C_now>=C_vidout)&(C_now<C_picview))
                #debug "rgb dots\n" rgbdots(.1+.9*pow(post(C_now,C_showpic,(C_deskview+C_showpic)/2,0,1),6)) #end
        #if (C_now>=C_zapview-2)
                #debug "Fly\n" movefly() #end
        #if ((C_now>=97.9)&(C_now<97.95))
                #debug"Zap\n" object{zap() translate <4389,3917,1470>} #end
        #if (C_now>=C_picview)
                #debug "Clutter\n" clutter1() clutter2() #end
        
        debugpos("Campos",campos)
        debugpos("Lookpos",lookpos)
