// ----- Wagon 
#include "colors.inc" 
#include "metals.inc"
#include "woods.inc"
#include "transforms.inc"
#include "canvas.inc"

#declare wood1_texture = 
texture {
  T_Wood7 
  normal {bumps .5 scale .02 scale <1,1,2>}
  scale .5
  rotate -4*y
}

#declare iron_texture = 
texture {
  T_Brass_1A
  normal {bumps scale .02}
}

#declare wagon_width = 5;  

//#ifndef (wagon_distance)
//  #declare wagon_distance = 0;
//#end

// -------------------------------------------------------
// ----- wheels    

#declare rim_radius = 2;
#declare rim_thickness = .25;  //.4 
#declare hub_radius = .4;
#declare hub_thickness = .35;  //.25                           
#declare n_spokes = 10;
#declare spoke_radius = .05;
#declare half_axle = wagon_width/2 + .5;
#declare axle_radius = .2;   
#declare wheel_base = 8;

#declare wheel = 
union {
  // rim   
  difference {
    cylinder {
      <0, 0,  rim_thickness/2 + .01>,
      <0, 0, -rim_thickness/2 - .01>,
      rim_radius
    }
    cylinder {
      <0, 0,  rim_thickness/2 + .1>,
      <0, 0, -rim_thickness/2 - .1>,
      rim_radius - .1
    }                             
    texture {iron_texture}
  }
  
  difference {
    cylinder {
      <0, 0,  rim_thickness/2>,
      <0, 0, -rim_thickness/2>,
      rim_radius - .1
    }
    cylinder {
      <0, 0,  rim_thickness/2 + .01>,
      <0, 0, -rim_thickness/2 - .01>,
      rim_radius - .5
    }                             
    texture {wood1_texture rotate 90*y}
  }
  
  // hub
  cylinder {               
    <0, 0,  hub_thickness/2>,
    <0, 0, -hub_thickness/2>,
    hub_radius 
    texture {wood1_texture rotate 90*y}
  }
  
  // spokes
  #declare i = 0;
  #while (i < n_spokes)
  
    //#if (i=0)
    //  sphere{rim_radius*x, .5 pigment{Red}}
    //#end
           
    cylinder { 
      <0, 0, 0>,
      <rim_radius-.01, 0, 0>,
      spoke_radius                
      texture {iron_texture}
      rotate <0, 0, i*360/n_spokes>
    }
    #declare i = i + 1;
  #end 
}       
       
#declare axle =
cylinder {                
  <0, 0,  half_axle>,
  <0, 0, -half_axle>,
  axle_radius
  texture {wood1_texture}
}          

#macro RotateWheels(wagon_distance)
#declare wheels = 
union {
  // center beam
  box {
    < 1, 0.0,  0.5>,
    <-9, 0.5, -0.5> 
    texture {wood1_texture rotate 90*y}
  }  
  
  // front axle  
  box {    
    < 0.5, 0.0, 1.5>
    <-0.5,-0.5,-1.5>
    texture {wood1_texture rotate 90*y}
  }                                
  
  #declare rotation = degrees(wagon_distance/rim_radius);
  
  object {axle translate <0, -.5, 0>}
  object {wheel scale <.75, .75, 1> rotate -z*rotation/.75 translate<0, -.5,  half_axle>}
  object {wheel scale <.75, .75, 1> rotate -z*rotation/.75 translate<0, -.5, -half_axle>}
  
  // rear axle
  object {axle  translate<-wheel_base, 0,  0>}          
  object {wheel rotate -z*rotation translate<-wheel_base, 0,  half_axle>}
  object {wheel rotate -z*rotation translate<-wheel_base, 0, -half_axle>}  
  translate <0, -.25, 0>
}
#end             

// -------------------------------------------------------
// ----- wagon_body     
//      
//       D------------------C
// front  \                /  back
//         A--------------B       

#declare body_height = 2;                    
#declare ptA =   2;
#declare ptB = -10;
#declare ptC = -11;
#declare ptD =   3;
                   
#declare body_bottom =
polygon {
  4,                                    
  <ptA, -wagon_width/2> <ptA,  wagon_width/2>
  <ptB,  wagon_width/2> <ptB, -wagon_width/2>                            
  texture {wood1_texture rotate 90*y}
  rotate 90*x
}
                    
#declare body_side =
union {
  polygon {
    4,
    <ptA, 0> <ptB, 0>
    <ptC, body_height>
    <ptD, body_height>                            
    texture {wood1_texture rotate 90*y}
  }
  
  #declare i = 0;
  #while (i < 4)
    box {                       
      <1 -3*i +.2, 0,            .04>,
      <1 -3*i -.2, body_height, -.04>                              
      texture {
        T_Wood10 
        scale .5
        rotate 84*x
      }   
    }
    #declare i = i + 1;
  #end   
  
  box {                       
    <ptD-.2, body_height,      .05>,
    <ptC+.2, body_height -.25, -.05>                              
    texture {
      T_Wood10 
      scale .5
      rotate 84*y
    }   
  }
  box {                       
    <ptA-.1, 0,   .05>,
    <ptB+.1, .25, -.05>                              
    texture {
      T_Wood10 
      scale .5
      rotate 84*y
    }   
  }  
  
  box {                       
    <ptA+.04, 0,            .06>,
    <ptA-.20,  body_height, -.06>                              
    texture {
      T_Wood10 
      scale .5
      rotate 84*x
    }
    Shear_Trans(x, y+.5*x, z)      
  } 
  
  box {                       
    <ptB+.20,  0,            .06>,
    <ptB-.04, body_height, -.06>                              
    texture {
      T_Wood10 
      scale .5
      rotate 84*x
    }
    Shear_Trans(x, y-.5*x, z)      
  }
}            

#declare body_front =
union {
  #declare k = sqrt(2*2 + 1*1)/2;
  #declare a = degrees(atan2(2,1));
  polygon {
    4,
    <0,  wagon_width/2>
    <0, -wagon_width/2>
    <body_height, -wagon_width/2>
    <body_height,  wagon_width/2>
    rotate 90*x                           
    texture {wood1_texture}       
  }             
                
  // bottom beam
  box {    
    <0,    -.05,-wagon_width/2>
    <.25, .05, wagon_width/2>                  
    texture {wood1_texture} 
  }          
  // top beam
  box {    
    <body_height,    -.05,-wagon_width/2>
    <body_height-.25, .05, wagon_width/2>
    texture {
      T_Wood10 
      scale .5
      rotate 4*y
    }
  }  
  // right beam
  box {    
    <0,          -.05, wagon_width/2>
    <body_height, .05, wagon_width/2-.3>
    texture {
      T_Wood10 
      scale .5
      rotate 84*y
    }
  }
  // left beam
  box {    
    <0,          -.05, -wagon_width/2>
    <body_height, .05, -wagon_width/2+.3>
    texture {
      T_Wood10 
      scale .5
      rotate 84*y
    }
  }

  rotate 90*z                 
}     

#declare body_back =                   
union {
  triangle { 
    <ptB, 0,            wagon_width/2>
    <ptC, body_height,  wagon_width/2>
    <ptC, body_height, -wagon_width/2>
  }
  triangle {                        
    <ptC, body_height, -wagon_width/2>
    <ptB, 0, -wagon_width/2>
    <ptB, 0,  wagon_width/2>
  }                   
  texture {wood1_texture} 
}                         

#declare divider =  
box {                   
  <1 + 0.1, 0, -wagon_width/2>,
  <1 - 0.1, body_height,  wagon_width/2>                  
  texture {wood1_texture} 
}


#declare wagon_body =
union {               
  object{body_bottom}                             
  object{body_side translate  wagon_width/2 * z}
  object{body_side translate -wagon_width/2 * z}  
  object{body_front Shear_Trans(x, y+.5*x, z) translate  ptA*x} 
  object{body_front Shear_Trans(x, y-.5*x, z) translate ptB*x} 
  object{divider}  
}
    
// -------------------------------------------------------
// ----- seat
 
#declare seat_width = 4;
#declare seat =
union {
  #declare i = -1;
  #while (i <= 1)
    torus {
      .5, .05         
      rotate 90*x
      clipped_by {
        plane {
          <2, -1, 0>, .25
        }
      }                           
    texture {iron_texture}
      translate <.5, -.52, i*(seat_width/2 - .4)>
    }
    #declare i = i + 1;
  #end          
  box {                               
    <1,   0,  seat_width/2>,
    <0, .05, -seat_width/2>
    texture {
      T_Wood10
      scale .7
      rotate -4*y
    } 
  }         
  box {                               
    <1,   0,  seat_width/2>,
    <0, .05, -seat_width/2>
    texture {
      T_Wood10
      scale .7
      rotate -4*y
    }
    rotate 100*z     
  } 
  translate <ptD-1, body_height+.25, 0>
}    

// ----------------------------------------------------
// ----- total

#macro UpdateWagon(wagon_distance)
#declare wagon = 
union {           
  RotateWheels(wagon_distance)
  object {wheels}
  object {wagon_body} 
  object {seat} 
  object {canvas}
  translate 2.25*y
} 
#end         

UpdateWagon(0)