/* taken from Listing 2.8 : A complex rib generating file  */
#include <stdio.h>
#include <ri.h>
#include <math.h>

#define ROOTFILENAME "hard"
#define RECURSION    4           /* Recursion level for fractal       */
#define NFRAMES      90          /* Number of frames in the animation */
#define WINDOWX      700         /* Width of the window               */
#define WINDOWY      700         /* Height of the window              */
#define PI           3.14159256  /* PI */

#define lerp(t, a, b) ( a + t * (b - a) ) /* Ken Perlin's lerp macro */
#define Deg2Rad(deg)  ( deg * (PI/180.0) )

main()
{
  RtInt frame;
  RtPoint from, to;
  RtFloat intensity, fov, fraction, yAngle, xAngle;
  char filename[20];
  
  RiBegin(RI_NULL);    /* Start the renderer */
  
  for (frame = 0; frame < NFRAMES; frame++) {
    fraction  = (float) frame / (float) NFRAMES;

    sprintf(filename, "%s_%d_%d.tif", ROOTFILENAME, RECURSION, frame );
    RiFrameBegin(frame);

    from[0] =  1.0; to[0] = 0.0;
    from[1] =  1.0; to[1] = 0.0;
    from[2] = -2.0; to[2] = 0.0;

    intensity = 1.5;

    RiLightSource("distantlight", "intensity", &intensity, "from", from, "to", to,RI_NULL);  
    
    /*** Viewing transformation ***/
    fov = 50; /* measured in degrees of the field of view */
    RiProjection("perspective", RI_FOV, (RtPointer) &fov, RI_NULL);
    RiTranslate(0.0, 0.0, 2.0);
    
    /*** Display information ***/
    RiDisplay(filename, RI_FILE, RI_RGB, RI_NULL);
    RiFormat((RtInt) WINDOWX, (RtInt) WINDOWY, -1.0); 
    RiShadingRate(1.0);

    /*** Geometry Begin ***/
    RiWorldBegin();
    
    RiSides((RtInt) 1);  /* Tells whether to render back-face polys */
    
    xAngle = 30.0;
    yAngle = lerp(fraction, 30.0, 120.0);
    RiRotate(yAngle, 0.0, 1.0, 0.0); 
    RiRotate(-xAngle, cos(Deg2Rad(yAngle)), 0.0, sin(Deg2Rad(yAngle)));

    /*** Surface information ***/
    /* Nothing now, this is just a geometry demo */

    /*** Geometry information ***/
    SC(RECURSION);

    RiWorldEnd();
    RiFrameEnd();
  }
  
  RiEnd();

  return 0;
}


SC(n)
  int n;
{
  if (n == 0) {
    UnitCube();
  } else {
    RiTransformBegin();
       RiScale(1.0/3.0, 1.0/3.0, 1.0/3.0);
       SC_Square(n);
       RiTranslate(0.0,0.0,-1.0);
       SC_Square(n);
       RiTranslate(0.0,0.0,2.0);
       SC_Square(n);
       RiTranslate(0.0,0.0,-1.0);
       RiRotate(-90.0,0.0,1.0,0.0);
       SC_Square(n);
       RiRotate(90.0,1.0,0.0,0.0);
       SC_Square(n);
    RiTransformEnd();
  }
}

SC_Square(n)
int n;
{
  RiTransformBegin();
    RiTranslate(1.0,1.0,0.0);
    SC(n-1);
    RiTranslate(-2.0,0.0,0.0);
    SC(n-1);
    RiTranslate(0.0,-2.0,0.0);
    SC(n-1);
    RiTranslate(2.0,0.0,0.0);
    SC(n-1);
  RiTransformEnd();
}