/* Lesson 3
 *
 * Third.c                Version 1.0
 *
 * Topics:  Setting up 3D view
 *          Triangle Meshes (a pyramid)
 *          Wireframes      (a cube)
 *          Multiple Windows
 *          Zbuffering      (if available)
 *       
*/

#include <gl.h>        /* the graphics library */
#include <device.h>    /* keyboard defines and others */

#define X   0
#define Y   1
#define Z   2
#define MAX 99

  /* the variables for polarview and perspective */
float view_distance, field_of_view, near_clipping_plane,
      far_clipping_plane, aspect_ratio, azim, inc, rotation;

typedef struct {                        /* structure for multiple windows, */
	int gid;				            
} WINDOWS;

WINDOWS wins[3];                       /* leave 0th spot empty */
int GrafixWindow, DataWindow;          /* names of windows */

     /* define some basic RGB colors */
int red[3]          = {255,0,0};
int green[3]        = {0,255,0};
int blue[3]         = {0,0,255};
int black[3]        = {0,0,0};
int white[3]        = {255,255,255};
int grey[3]         = {123,123,123};
int dark_grey[3]    = {25,25,25};
int yellow[3]       = {255,255,0};
int purple[3]       = {255,0,255};
int aqua[3]         = {0,255,255};

typedef struct {
     int rotation[3], num_of_vertex, vertex_order[MAX];
     float center[3], scale[3], matrix[MAX][3], color_table[MAX][3];
} OBJECT;

OBJECT pyramid;



    /* these are the points of the cube */              
int v0[3] = {-1, -1, -1};
int v1[3] = {-1, -1,  1};
int v2[3] = {-1,  1,  1};
int v3[3] = {-1,  1, -1};
int v4[3] = { 1, -1, -1};
int v5[3] = { 1, -1,  1};
int v6[3] = { 1,  1,  1};
int v7[3] = { 1,  1, -1};



int xrot, yrot, zrot, scaler, rotate_mode;

/********************************************************************/
main()
{
     
    initalize_graphics();   
    
    qdevice(RIGHTMOUSE);
    qdevice(MIDDLEMOUSE);
    qdevice(LEFTMOUSE);  
    
    while(!getbutton(ESCKEY)) {   /* Cycle through main loop until ESC key is pressed */

     winset(GrafixWindow);        /* Set the 'GrafixWindow' as the window to draw in */
      pushmatrix();               /* push in a new matrix to use */
        
        c3i(black);   clear();    /* clear the screen */
        zclear();                 /* clear the zbuffer */         
       
        do_perspective(); 
        
        check_for_user_input();   /* check the keyboard and mouse for input */
        rot(xrot, 'x'); rot(yrot, 'y'); rot(zrot, 'z');
        
        c3i(red);
        draw_bounding_cube();     /* draw a cube around our 3d space */

        draw_pyramid(); 
          
      popmatrix();                /* pop out of the last matrix */           
      swapbuffers();   
      
              
      winset(DataWindow);         /* Now set the 'DataWindow' as the window to draw in */
        pushmatrix();
          c3i(dark_grey);  clear();
          text_message();
        popmatrix();
        swapbuffers();
                
    }

}


/********************************************************************/
do_perspective()
{
    perspective(field_of_view, aspect_ratio, near_clipping_plane, far_clipping_plane);
    polarview(view_distance, azim, inc, rotation);
}


/********************************************************************/
draw_pyramid()
{
  register int i;
  
  pushmatrix();
  
    scale( pyramid.scale[0], pyramid.scale[1], pyramid.scale[2] );
    rot( pyramid.rotation[X], 'x' );
    rot( pyramid.rotation[Y], 'y' );
    rot( pyramid.rotation[Z], 'z' );
 
    bgntmesh();
    
     for(i=0; i < pyramid.num_of_vertex ; i++) {
           c3i( pyramid.color_table[ pyramid.vertex_order[i] ] );          
           v3f( pyramid.matrix[ pyramid.vertex_order[i] ] );	
	   }
	      
    endtmesh();
    
  popmatrix();
 
} 



/***********************************************************/
draw_bounding_cube()
{

    pushmatrix();
    
      scale( 100.0, 100.0, 100.0 );    
      linewidth(2);        /* set the line width to 2 */

        /* create a wireframe cube from the predefined points */
      bgnline();
          v3i(v0); v3i(v1); v3i(v2); v3i(v3);
          v3i(v0); v3i(v4); v3i(v5); v3i(v6);
          v3i(v7); v3i(v4); v3i(v5); v3i(v1);
          v3i(v2); v3i(v6); v3i(v7); v3i(v3);
      endline(); 
    
        
   popmatrix();
  
      /* draw and label the X, Y, and Z axis */

   pushmatrix();
    
    c3i(grey); 
    move(-10.0, 0.0, 0.0);
    draw( 50.0, 0.0, 0.0);
    
    move( 0.0, -10.0, 0.0);
    draw( 0.0,  50.0, 0.0);
    
    move( 0.0, 0.0, -10.0);
    draw( 0.0, 0.0,  50.0);

    c3i(white);
    cmov(30.0, 0.0, 0.0);
    charstr("x");
  
    cmov(0.0, 30.0, 0.0);
    charstr("y");
  
    cmov(0.0, 0.0, 30.0);
    charstr("z");
    
   popmatrix();
 
}




/********************************************************************/
text_message()
{
   pushmatrix();
      c3i(white);
      cmov2( 1.0, 195.0 );
      charstr("Iris Tutorial, Lesson 3");
      cmov2( 1.0, 190.0 );
      charstr("Press X, Y, or Z to rotate,");
      cmov2( 1.0, 185.0 );
      charstr("S for Scale");
      cmov2( 1.0, 180.0 );
      charstr("Shift keys to reverse,");
      cmov2( 1.0, 175.0 );
      charstr("R for rotate mode,");
      cmov2( 1.0, 170.0 );
      charstr("and ESC to quit");
   popmatrix();
}


/********************************************************************/
check_for_user_input()
{
  
   /* change the rotation values according to what keys or mouse buttons are pressed */
    
  if(getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY)) {
     if(getbutton(XKEY) ) xrot--;
     if(getbutton(YKEY) ) yrot--;
     if(getbutton(ZKEY) ) zrot--;
     if(getbutton(SKEY) ) scaler--;
  } else { 
     if(getbutton(XKEY) ) xrot++;
     if(getbutton(YKEY) ) yrot++;
     if(getbutton(ZKEY) ) zrot++;
     if(getbutton(SKEY) ) scaler++;
  }
  rot( pyramid.rotation[X], 'x' );
    rot( pyramid.rotation[Y], 'y' );
    rot( pyramid.rotation[Z], 'z' );

 if(getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY)) {
     if( getbutton(LEFTMOUSE)   && !getbutton(MIDDLEMOUSE) ) pyramid.rotation[X]--;
     if( getbutton(MIDDLEMOUSE) && !getbutton(RIGHTMOUSE) && !getbutton(LEFTMOUSE) ) pyramid.rotation[Y]--;
     if( getbutton(RIGHTMOUSE)  && !getbutton(MIDDLEMOUSE) ) pyramid.rotation[Z]--;
   } else { 
     if( getbutton(LEFTMOUSE)   && !getbutton(MIDDLEMOUSE) ) pyramid.rotation[X]++;
     if( getbutton(MIDDLEMOUSE) && !getbutton(RIGHTMOUSE) && !getbutton(LEFTMOUSE) ) pyramid.rotation[Y]++;
     if( getbutton(RIGHTMOUSE)  && !getbutton(MIDDLEMOUSE) )  pyramid.rotation[Z]++;
   }

     if( getbutton(MIDDLEMOUSE) && getbutton(RIGHTMOUSE) ) scaler++;
     if( getbutton(MIDDLEMOUSE) && getbutton(LEFTMOUSE)  ) scaler--;



  if(getbutton(RKEY) ) 
      rotate_mode = 1;

  if(rotate_mode) {
       xrot++; yrot++; zrot++; scaler++;
  }
  
    /* make sure the rotation values arn't greater then 360 */
  if( xrot > 360.0 ) xrot = 0.0;
  if( yrot > 360.0 ) yrot = 0.0;
  if( zrot > 360.0 ) zrot = 0.0;
  if( scaler > 100.0) scaler = -100.0;
  

}

/*******************************************************************/
initalize_graphics()
{

      /* open first window */
    keepaspect(1,1);
    prefposition(10, 990, 10, 990);     /* preset the window size, the format is */
                                        /* (x1,x2,y1,y2)                         */
    wins[1].gid =  winopen("");  /* Open first window */
    wintitle(" Iris Graphics Tutorial, Lesson 3 ");
    GrafixWindow = wins[1].gid;         /* Give the wind a unique name */   
    doublebuffer();                     /* Use doublebuffer mode */
    RGBmode();                          /* Use RGB color mode */
    gconfig();                          /* Configure the window */

    zbuffer(TRUE); 
    mmode(MVIEWING); 

    view_distance           = 200.0;     
    field_of_view           = 600.0;     
    near_clipping_plane     = 0.1;       
    far_clipping_plane      = 800.0;     
    aspect_ratio            = 1.0;       
    azim                    = 0.0;
    inc                     = 0.0;
    rotation                = 0.0;
   
    perspective(field_of_view, aspect_ratio, near_clipping_plane, far_clipping_plane);
    polarview(view_distance, azim, inc, rotation);


      /* open second window */
    keepaspect(1,1); 
    prefposition(1007, 1270, 10, 990);    
    wins[2].gid =  winopen("");
    wintitle("Data Window");
    DataWindow = wins[2].gid; 
    doublebuffer(); 
    RGBmode();
    gconfig();
    ortho2(0.0, 25.0, 0.0, 200.0);

     /* clear the windows */
    winset(GrafixWindow);
       c3i(black); clear(); swapbuffers();
       c3i(black); clear(); swapbuffers();
    winset(DataWindow);
       c3i(black); clear(); swapbuffers();
       c3i(black); clear(); swapbuffers();

    /* create the pyramid */
             
  pyramid.num_of_vertex = 6;
                           
  pyramid.rotation[X] = 0;
  pyramid.rotation[Y] = 0;
  pyramid.rotation[Z] = 0;
 
  pyramid.center[X] = 0.0;
  pyramid.center[Y] = 0.0;
  pyramid.center[Z] = 0.0; 
 
  pyramid.matrix[0][X] = 0.0;
  pyramid.matrix[0][Y] = 0.0;
  pyramid.matrix[0][Z] = 0.0;

  pyramid.matrix[1][X] = 2.0;
  pyramid.matrix[1][Y] = 0.0;
  pyramid.matrix[1][Z] = 0.0;

  pyramid.matrix[2][X] = 1.0;
  pyramid.matrix[2][Y] = 2.0;
  pyramid.matrix[2][Z] = 0.0;

  pyramid.matrix[3][X] = 1.0;
  pyramid.matrix[3][Y] = 0.0;
  pyramid.matrix[3][Z] = 2.0;

  pyramid.vertex_order[0] = 1;
  pyramid.vertex_order[1] = 2; 
  pyramid.vertex_order[2] = 3;
  pyramid.vertex_order[3] = 4;
  pyramid.vertex_order[4] = 1;
  pyramid.vertex_order[5] = 2;
      
  pyramid.scale[X] = 40.0;
  pyramid.scale[Y] = 40.0;
  pyramid.scale[Z] = 40.0;

  pyramid.color_table[0][X] = 255;
  pyramid.color_table[0][Y] = 0;
  pyramid.color_table[0][Z] = 0;
  
  pyramid.color_table[1][X] = 0;
  pyramid.color_table[1][Y] = 255;
  pyramid.color_table[1][Z] = 0;

  pyramid.color_table[2][X] = 0;
  pyramid.color_table[2][Y] = 0;
  pyramid.color_table[2][Z] = 255;

  pyramid.color_table[3][X] = 255;
  pyramid.color_table[3][Y] = 255;
  pyramid.color_table[3][Z] = 0;


 }

