/*---------------------------------------------------------------------------
Name: objects.c (for use with space.c)
Author: Christopher Huyler
Date: April 30, 2002
Description:
OpenGL objects and variables
----------------------------------------------------------------------------*/
#include <math.h>
#include <GL/glut.h>
#include <stdlib.h>

// global variables ----------------------------------------------------------
// an object structure contains xyz and angle coordinates
struct objStruct {
    GLfloat xpos;
    GLfloat ypos;
    GLfloat zpos;
    GLfloat h_angle;
    GLfloat v_angle;
};

// define variables for the crane
struct objStruct crane = {0,-20,0,90,1};
int holding = 1,
    crane_state = 0;
GLfloat crane_tie[16];

// define variables for the robot
struct objStruct robot1 = {0.0,0.0,0.0,0.0,0.0};
int rand_num1;              // storage for a random number to make robot turn
struct objStruct robot2 = {5.0,0.0,5.0,0.0,0.0};
int rand_num2;

// define variables for a space ship
struct objStruct ship = {0,0,-525,0,0};
GLfloat wing_angle = -45;           // current angle of the wings
float blink = 0;                    // blinking marker lights on/off

// define variables for an elevator
GLUquadricObj *p;                   // pointer to quadric object
GLfloat elevator_height = 0,
        e_angle = 0;
int     e_count = 20;

// define variables for tie-fighters
GLfloat tie_angle = 180,
        tie_spin = 90,
        tie_incr = -1;

// a tesselated polygon ------------------------------------------------------
void myTessPolygon(float x1, float y1,float x2, float y2) {
    float div = .1;
    float i,j;
    for(i=x1;i<x2-div;i+=div) {
        for(j=y1;j<y2-div;j+=div) {
            glBegin(GL_POLYGON);
              glNormal3f(0,1,0);
              glVertex3f(i,0,j);
              glVertex3f(i+div,0,j);
              glVertex3f(i+div,0,j+div);
              glVertex3f(i,0,j+div);
            glEnd();
        }
    }
}

// draw a cube using my tesselate function -----------------------------------
void mySolidCube(float dim) {
    glPushMatrix();     // top
      glTranslatef(0.0,dim/2,0.0);
      glRotatef(180,0.0,0.0,1.0);
      myTessPolygon(-dim/2.0,-dim/2,dim/2,dim/2);
    glPopMatrix();
    glPushMatrix();     // bottom
      glTranslatef(0.0,-dim/2,0);
      myTessPolygon(-dim/2,-dim/2,dim/2,dim/2);
    glPopMatrix();
    glPushMatrix();     // front
      glTranslatef(0.0,0.0,dim/2);
      glRotatef(-90,1.0,0.0,0.0);
      myTessPolygon(-dim/2,-dim/2,dim/2,dim/2);
    glPopMatrix();
    glPushMatrix();     // back
      glTranslatef(0.0,0.0,-dim/2);
      glRotatef(90,1.0,0.0,0.0);
      myTessPolygon(-dim/2,-dim/2,dim/2,dim/2);
    glPopMatrix();
    glPushMatrix();     // left
      glTranslatef(-dim/2,0.0,0.0);
      glRotatef(-90,0.0,0.0,1.0);
      myTessPolygon(-dim/2,-dim/2,dim/2,dim/2);
    glPopMatrix();
    glPushMatrix();      // right
      glTranslatef(dim/2,0.0,0.0);
      glRotatef(90,0.0,0.0,1.0);
      myTessPolygon(-dim/2,-dim/2,dim/2,dim/2);
    glPopMatrix();
}

// shear along x or y axis ---------------------------------------------------
void myglShearf(GLfloat x, GLfloat y, GLfloat z) {
    GLfloat m[16];
    int i;
    for(i=0;i<16;i++) m[i] = 0.0;
    m[0] = m[5] = m[10] = m[15] = 1.0;
    m[4] = x;
    m[1] = y;
    glMultMatrixf(m);
}

// draw a large doorway ------------------------------------------------------
void draw_doorway() {
    glPushMatrix();
      glColor3f(.8,.8,.8); // color = gray
      glTranslatef(0.0,13.25,0.0);
      glScalef(20.0,2.5,20.0);
      glutSolidCube(1.0);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(-8.75,6.0,0.0);
      glScalef(2.5,12.0,20.0);
      glutSolidCube(1.0);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(8.75,6.0,0.0);
      glScalef(2.5,12.0,20.0);
      glutSolidCube(1.0);
    glPopMatrix();
}

// draw spaceport hangar -----------------------------------------------------
void draw_hangar(GLfloat x,GLfloat y,GLfloat z) {
    materials(&grayPlasticMaterials);
    glPushMatrix();
      glColor3f(.8,.8,.8); // color = gray
      glTranslatef(x,y,z); // center
      // draw base
      glPushMatrix();
        glTranslatef(0.0,-2.5,0.0);
        glScalef(100.0,5.0,100.0);
        glutSolidCube(1.0);
      glPopMatrix();
      // draw left wall
      glPushMatrix();
        glTranslatef(-47.5,0.0,0.0);
        myglShearf(.5,0.0,0.0);
        glTranslatef(0.0,15.0,0.0);
        glScalef(5.0,30.0,100.0);
        glutSolidCube(1.0);
      glPopMatrix();
      // draw right wall
      glPushMatrix();
        glTranslatef(+47.5,0.0,0.0);
        myglShearf(-.5,0.0,0.0);
        glTranslatef(0.0,15.0,0.0);
        glScalef(5.0,30.0,100.0);
        glutSolidCube(1.0);
      glPopMatrix();
      // draw ceiling
      glPushMatrix();
        glTranslatef(0.0,32.5,0.0);
        glScalef(70.0,5.0,100.0);
        glutSolidCube(1.0);
      glPopMatrix();
      // draw back wall
      glPushMatrix();
        glTranslatef(0.0,15.0,52.5);
        glScalef(100.0,40.0,5.0);
        glutSolidCube(1.0);
      glPopMatrix();
      // draw front wall
      glPushMatrix();
        glTranslatef(0.0,27.5,-52.5);
        glScalef(100.0,15.0,5.0);
        glutSolidCube(1.0);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(-40.0,7.5,-52.5);
        glScalef(20.0,25.0,5.0);
        glutSolidCube(1.0);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(40.0,7.5,-52.5);
        glScalef(20.0,25.0,5.0);
        glutSolidCube(1.0);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(0.0,-2.5,-52.5);
        glScalef(60.0,5.0,5.0);
        glutSolidCube(1.0);
      glPopMatrix();
      // draw left door
      glPushMatrix();
        glTranslatef(-35.0,0.0,25.0);
        glRotatef(90.0,0.0,1.0,0.0);
        draw_doorway();
      glPopMatrix();
      // draw right door
      glPushMatrix();
        glTranslatef(35.0,0.0,25.0);
        glRotatef(90.0,0.0,1.0,0.0);
        draw_doorway();
      glPopMatrix();
      // draw platform
      glPushMatrix();
        glTranslatef(-35.0,13.25,-5.0);
        glScalef(20.0,2.5,40.0);
        glutSolidCube(1.0);
      glPopMatrix();
      // draw observation deck
      glPushMatrix();
        glTranslatef(0.0,17.5,45.0);
        glPushMatrix();
          glTranslatef(0.0,-1.25,0.0);
          glScalef(40.0,2.5,10.0);
          glutSolidCube(1.0);
        glPopMatrix();
        glPushMatrix();
          glTranslatef(18.75,6.0,0.0);
          glScalef(2.5,12.0,10.0);
          glutSolidCube(1.0);
        glPopMatrix();
        glPushMatrix();
          glTranslatef(-18.75,6.0,0.0);
          glScalef(2.5,12.0,10.0);
          glutSolidCube(1.0);
        glPopMatrix();
        glPushMatrix();
          glTranslatef(0.0,2.5,-3.75);
          glScalef(35.0,5.0,2.5);
          glutSolidCube(1.0);
        glPopMatrix();
      glPopMatrix();
    glPopMatrix();
}

// draw an elevator cylinder -------------------------------------------------
void draw_elevator(GLfloat x, GLfloat y, GLfloat z) {
   materials(&yellowMaterials);
   glPushMatrix();
     glTranslatef(x,y,z);
     glPushMatrix();
       glRotatef(-90.0,1.0,0.0,0.0);
       gluCylinder(p,5.0,5.0,1.0,20,2);
     glPopMatrix();
     glPushMatrix();
       glTranslatef(0.0,1.0,0.0);
       glRotatef(-90.0,1.0,0.0,0.0);
       gluDisk(p,0.0,5.0,20,5);
     glPopMatrix();
     glPushMatrix();
       glRotatef(+90.0,1.0,0.0,0.0);
       gluDisk(p,0.0,5.0,20,5);
     glPopMatrix();
   glPopMatrix();
}

// draw a tie fighter at x,y,z -----------------------------------------------
void draw_tiefighter(GLfloat x,GLfloat y,GLfloat z) {
  glPushMatrix();
    glTranslatef(x,y,z);
      glScalef(.5,.5,.5);
      materials(&grayPlasticMaterials);
      glutSolidSphere(3.0,6,5);
      materials(&blackMaterials);
      glutWireSphere(3.01,6,5);
      materials(&grayPlasticMaterials);
    glPushMatrix();
      glTranslatef(0.0,0.0,-5.0);
      materials(&blackMaterials);
      gluCylinder(p,1.0,1.0,10.0,20,2);
    glPopMatrix();
    glScalef(1.0,1.2,1.0);
    glRotatef(90,0.0,0.0,1.0);
    glPushMatrix();
      glTranslatef(0.0,0.0,5.0);
        materials(&blackMaterials);
        glutSolidCone(8.0,0.0,6,2);
        materials(&grayPlasticMaterials);
        glutWireCone(8.01,0.01,6,1);
      glTranslatef(0.0,0.0,-0.01);
      glRotatef(180,1.0,0.0,0.0);
        materials(&blackMaterials);
        glutSolidCone(8.0,0.0,6,2);
        materials(&grayPlasticMaterials);
        glutWireCone(8.01,.01,6,1);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(0.0,0.0,-5.0);
        materials(&blackMaterials);
        glutSolidCone(8.0,0.0,6,2);
        materials(&grayPlasticMaterials);
        glutWireCone(8.01,0.01,6,1);
      glTranslatef(0.0,0.0,-0.01);
      glRotatef(180,1.0,0.0,0.0);
        materials(&blackMaterials);
        glutSolidCone(8.0,0.0,6,2);
        materials(&grayPlasticMaterials);
        glutWireCone(8.01,.01,6,1);
    glPopMatrix();
  glPopMatrix();
}

void draw_support(int x, int y, int z) {
    materials(&blackMaterials);

    glPushMatrix();
      glTranslatef(x,y,z);
      glPushMatrix();
        glScalef(10.0,.5,.8);
        glutSolidCube(1.0);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(0.0,5.0,0.0);
        glScalef(10.0,.5,.8);
        glutSolidCube(1.0);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(0.0,2.5,0.0);
        glPushMatrix();
          glRotatef(30.0,0.0,0.0,1.0);
          glScalef(10.0,.5,.5);
          glutSolidCube(1.0);
        glPopMatrix();
        glPushMatrix();
          glRotatef(-30,0.0,0.0,1.0);
          glScalef(10.0,.5,.5);
          glutSolidCube(1.0);
        glPopMatrix();
      glPopMatrix();
    glPopMatrix();
}

void draw_scaffolding() {
   int i,j;
   glPushMatrix();
     glTranslatef(-40.0,23.0,30);
     for(i=0;i<3;i++) {
       glPushMatrix();
         for(j=0;j<8;j++) {
           draw_support(0.0,0.0,0.0);
           glTranslatef(10.0,0.0,0.0);
         }
       glPopMatrix();
       glTranslatef(0.0,0.0,-30.0);
     }
   glPopMatrix();
}

// functions to draw the crane -----------------------------------------------
void draw_claw(void) {
    glPushMatrix();
      glScalef(0.5,1.0,3.5);
      glutSolidCube(1.0);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(0.0,-.5,1.5);
      glScalef(0.5,3.0,0.5);
      glTranslatef(0.0,-.5,0.0);
      glutSolidCube(1.0);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(0.0,-.5,-1.5);
      glScalef(0.5,3.0,0.5);
      glTranslatef(0.0,-.5,0.0);
      glutSolidCube(1.0);
    glPopMatrix();
}
void draw_crane(GLfloat x, GLfloat y, GLfloat z) {
    materials(&yellowMaterials);
    glPushMatrix();
      glTranslatef(x,29.0,-15.0);
      glPushMatrix();
        glScalef(4.0,2.0,34.0);
        glutSolidCube(1.0);
      glPopMatrix();
      glTranslatef(0.0,-2.0,z);
      glRotatef(crane.h_angle,0.0,1.0,0.0);
      glPushMatrix();
        glScalef(1.0,1.0,1.0);
        glutSolidDodecahedron();
      glPopMatrix();
      materials(&blackMaterials);
      glPushMatrix();
        glTranslatef(0.5,0.0,0.0);
        glScalef(.1,-y,.1);
        glRotatef(90,1.0,0.0,0.0);
        gluCylinder(p,1.0,1.0,1.0,8,8);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(-.5,0.0,0.0);
        glScalef(.1,-y,.1);
        glRotatef(90,1.0,0.0,0.0);
        gluCylinder(p,1.0,1.0,1.0,8,8);
      glPopMatrix();
      glTranslatef(0.0,y,0.0);
      glutSolidTorus(.25,.45,8,16);
      materials(&yellowMaterials);
      glTranslatef(0.0,-0.5,0.0);
      if(holding) glGetFloatv(GL_MODELVIEW_MATRIX,crane_tie);
      glPushMatrix();
        glScalef(6.0,1.0,1.0);
        glutSolidCube(1.0);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(-crane.v_angle,-.25,0.0);
        draw_claw();
      glPopMatrix();
      glPushMatrix();
        glTranslatef(crane.v_angle,-.25,0.0);
        draw_claw();
      glPopMatrix();
    glPopMatrix();
}

// draw a robot droid --------------------------------------------------------
void draw_droid() {
    glScalef(0.25,0.25,0.25);
    glPushMatrix();
      glRotatef(-20,1.0,0.0,0.0);
      glPushMatrix();
        glTranslatef(0.0,1.0,0.0);
        glRotatef(-90,1.0,0.0,0.0);
        materials(&whiteShineyMaterials);
        gluCylinder(p,2.2,2.2,5.0,20,2);
      glPopMatrix();
      glPushMatrix();
        glTranslatef(0.0,6.0,0.0);
        materials(&steelMaterials);
        glutSolidSphere(2.0,16,16);
        glRotatef(-90.0,1.0,0.0,0.0);
        materials(&bluePlasticMaterials);
        glutSolidCone(2.2,0.0,20,1);
      glPopMatrix();
    glPopMatrix();
    glPushMatrix();
      glTranslatef(2.5,2.5,-2.0);
      glRotatef(20.0,1.0,0.0,0.0);
      glScalef(1.0,5.0,1.0);
      glutSolidCube(1.0);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(-2.5,2.5,-2.0);
      glRotatef(20.0,1.0,0.0,0.0);
      glScalef(1.0,5.0,1.0);
      glutSolidCube(1.0);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(0.0,1.0,0.0);
      glRotatef(-20.0,1.0,0.0,0.0);
      glScalef(1.0,2.0,1.0);
      glutSolidCube(1.0);
    glPopMatrix();
}

// functions to draw a space ship --------------------------------------------
void draw_wing() {
    materials(&whiteShineyMaterials);
    glBegin(GL_POLYGON);  // top
      glNormal3f(0,1,0);
      glVertex3f(0.0,1.0,-8.0);
      glVertex3f(0.0,1.0,6.0);
      glVertex3f(18.0,0.5,4.0);
      glVertex3f(18.0,0.5,-4.0);
    glEnd();
    glBegin(GL_POLYGON);  // bottom
      glNormal3f(0,-1,0);
      glVertex3f(0.0,-1.0,-8.0);
      glVertex3f(18.0,-0.5,-4.0);
      glVertex3f(18.0,-0.5,4.0);
      glVertex3f(0.0,-1.0,6.0);
    glEnd();
    glBegin(GL_POLYGON); // left
      glNormal3f(-1,0,0);
      glVertex3f(0.0,1.0,-8.0);
      glVertex3f(0.0,-1.0,-8.0);
      glVertex3f(0.0,-1.0,6.0);
      glVertex3f(0.0,1.0,6.0);
    glEnd();
    glBegin(GL_POLYGON); // back
      glNormal3f(0,0,-1);
      glVertex3f(0.0,1.0,-8.0);
      glVertex3f(18.0,0.5,-4.0);
      glVertex3f(18.0,-0.5,-4.0);
      glVertex3f(0.0,-1.0,-8.0);
    glEnd();
    glBegin(GL_POLYGON); // front
      glNormal3f(0,0,1);
      glVertex3f(0.0,1.0,6.0);
      glVertex3f(0.0,-1.0,6.0);
      glVertex3f(18.0,-0.5,4.0);
      glVertex3f(18.0,0.5,4.0);
    glEnd();
    glBegin(GL_POLYGON); // right
      glNormal3f(1,0,0);
      glVertex3f(18.0,0.5,4.0);
      glVertex3f(18.0,-0.5,4.0);
      glVertex3f(18.0,-0.5,-4.0);
      glVertex3f(18.0,0.5,-4.0);
    glEnd();
    materials(&whiteShineyMaterials);

}
void draw_head() {
    GLfloat off[] = {0.0,0.0,0.0,1.0};
    GLfloat on[] = {0.6,0.6,0.6,1.0};
    materials(&whiteShineyMaterials);
      glRotatef(20,1.0,0.0,0.0);
      glBegin(GL_POLYGON);   //back
        glNormal3f(0,0,-1);
        glVertex3f(-5.0,2.5,0.0);
        glVertex3f(5.0,2.5,0.0);
        glVertex3f(5.0,-2.5,0.0);
        glVertex3f(-5.0,-2.5,0.0);
      glEnd();
      glBegin(GL_POLYGON);  // top
        glNormal3f(0,1,0);
        glVertex3f(5.0,2.5,0.0);
        glVertex3f(-5.0,2.5,0.0);
        glNormal3f(0,1,1);
        glVertex3f(-3.0,0.0,9.0);
        glVertex3f(3.0,0.0,9.0);
      glEnd();
      glBegin(GL_POLYGON);  // bottom
        glNormal3f(0,-1,0);
        glVertex3f(-5.0,-2.5,0.0);
        glVertex3f(5.0,-2.5,0.0);
        glNormal3f(0,-1,1);
        glVertex3f(3.0,-2.5,9.0);
        glVertex3f(-3.0,-2.5,9.0);
      glEnd();
      glBegin(GL_POLYGON);  // left
        glNormal3f(-1,0,0);
        glVertex3f(-5.0,2.5,0.0);
        glVertex3f(-5.0,-2.5,0.0);
        glVertex3f(-3.0,-2.5,9.0);
        glVertex3f(-3.0,0.0,9.0);
      glEnd();
      glBegin(GL_POLYGON);  // right
        glNormal3f(1,0,0);
        glVertex3f(5.0,2.5,0.0);
        glVertex3f(3.0,0.0,9.0);
        glVertex3f(3.0,-2.5,9.0);
        glVertex3f(5.0,-2.5,0.0);
      glEnd();
      glBegin(GL_POLYGON);  // front
        glNormal3f(0,1,1);
        glVertex3f(3.0,0.0,9.0);
        glVertex3f(-3.0,0.0,9.0);
        glNormal3f(0,-1,1);
        glVertex3f(-3.0,-2.5,9.0);
        glVertex3f(3.0,-2.5,9.0);
      glEnd();
      glPushMatrix();
        materials(&bluePlasticMaterials);
        glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,on);
        glTranslatef(0.0,-1.0,9.0);
        glutSolidSphere(1,12,12);
        glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,off);
      glPopMatrix();
}
void draw_ship(GLfloat wing_angle) {
    GLfloat off[] = {0.0,0.0,0.0,1.0};
    GLfloat on[] = {0.6,0.6,0.6,1.0};
     glPushMatrix();
       glScalef(.75,.75,.75);
       glTranslatef(0.0,6.5,0.0);
       glPushMatrix();
         glScalef(12.0,6.0,18.0);
         materials(&steelMaterials);
         glutSolidCube(1.0);
       glPopMatrix();
       glPushMatrix();
         glTranslatef(6.0,0.0,0.0);
         glRotatef(wing_angle,0.0,0.0,1.0);
         glTranslatef(2.0,0.0,0.0);
         glPushMatrix();
           glRotatef(45,0.0,0.0,1.0);
           glScalef(4.0,4.0,16.0);
           materials(&steelMaterials);
           glutSolidCube(1.0);
         glPopMatrix();
         glPushMatrix();
           glTranslatef(0.0,-2.0,0.0);
           draw_wing();
           materials(&darkYellowMaterials);
           if(blink>3)
                glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,on);
           glTranslatef(17.5,0.5,0.0);
           glutSolidSphere(.5,8,8);
           glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,off);
         glPopMatrix();
       glPopMatrix();
       glPushMatrix();
         glTranslatef(-6.0,0.0,0.0);
         glRotatef(-wing_angle,0.0,0.0,1.0);
         glTranslatef(-2.0,0.0,0.0);
         glRotatef(180,0.0,0.0,1.0);
         glPushMatrix();
           glRotatef(45,0.0,0.0,1.0);
           glScalef(4.0,4.0,16.0);
           materials(&steelMaterials);
           glutSolidCube(1.0);
         glPopMatrix();
         glPushMatrix();
           glTranslatef(0.0,2.0,0.0);
           draw_wing();
           materials(&darkYellowMaterials);
           if(blink>3)
                glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,on);
           glTranslatef(17.5,-0.5,0.0);
           glutSolidSphere(.5,8,8);
           glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,off);
         glPopMatrix();
       glPopMatrix();
       glPushMatrix();
         glTranslatef(0.0,3.0,0.0);
         glRotatef(90,0.0,0.0,1.0);
         draw_wing();
           materials(&darkYellowMaterials);
           if(blink>3)
                glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,on);
           glTranslatef(18.0,0.0,3.0);
           glutSolidSphere(.5,8,8);
           glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,off);
       glPopMatrix();
       glPushMatrix();
         glTranslatef(0.0,0.0,9.0);
         draw_head();
       glPopMatrix();
     glPopMatrix();
}

