//
//
#include <GL/glut.h>    // Header File For The GLUT Library 
#include <GL/gl.h>	// Header File For The OpenGL32 Library
#include <GL/glu.h>	// Header File For The GLu32 Library
#include <unistd.h>     // Header File For sleeping.
#include <math.h>

/* ASCII code for the escape key. */
#define ESCAPE 27

/* The number of our GLUT window */
int window; 

/* rotation angle for the triangle. */
float rtri = 0.0f;
float spvx=0.0;
float spvy=0.0;
float spvz=0.0;
float spx=0.3;
float spxx=0.0;
float spy=0.1;
float spz=0.005;
float spzz=0.0;
float theta=0.0;
float thetai=0.0;
float r=0.0;
float yad=2.0;
float xad=2.4;
float spyy;
int flag;
/* rotation angle for the quadrilateral. */
float rquad = 0.0f;

/* A general OpenGL initialization function.  Sets all of the initial parameters. */
void InitGL(int Width, int Height)	        // We call this right after our OpenGL window is created.
{
  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);		// This Will Clear The Background Color To Black
  glClearDepth(1.0);				// Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);				// The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);			// Enables Depth Testing
  glShadeModel(GL_SMOOTH);			// Enables Smooth Color Shading

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();				// Reset The Projection Matrix

  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	// Calculate The Aspect Ratio Of The Window

  glMatrixMode(GL_MODELVIEW);
}

/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
  if (Height==0)				// Prevent A Divide By Zero If The Window Is Too Small
    Height=1;

  glViewport(0, 0, Width, Height);		// Reset The Current Viewport And Perspective Transformation

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
  glMatrixMode(GL_MODELVIEW);
}

void DrawSphere(float x, float y, float z, float radius)
{
  GLUquadricObj *pSphere = gluNewQuadric();
  glPushMatrix();
  glTranslatef(x,y,z);
  gluSphere(pSphere, radius, 45, 45);
    glPopMatrix();
     gluDeleteQuadric(pSphere);
}


/* The main drawing function. */
void DrawGLScene()
{


  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// Clear The Screen And The Depth Buffer
  glLoadIdentity();				// Reset The View
  glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
            GLfloat light_pos[]={3.0,0.0,0.0,3.0};
   glLightfv(GL_LIGHT0,GL_AMBIENT, light_pos);
            glEnable(GL_BLEND);
 glEnable ( GL_DEPTH_TEST );
   glTranslatef(-1.2,-1.5,-6.0);		// Move Left 1.5 Units And Into The Screen 6.0
   //  glRotatef(rtri,0.0f,1.0f,0.0f);
    glColor3f(0.0,1.0,0.0);
    // thetai=atan(spz/spx);
    //r=sqrt(spx*spx+spz*spz);

    //spxx=r*cos(thetai+theta);
    //spzz=r*sin(thetai+theta);
    //theta=-(3.1416/180)*rtri;
    spvx=spvx-spx*0.05;
    spvz=spvz+spz*0.05;
    spy=spx*spx-spz*spz+0.07;
    spyy=spx*spx+0.07;
    //spy=spx*spx+0.1;
    spx=spx+spvx*0.1;
    spz=spz+spvz*0.1;
    theta=(3.1456/180)*rtri;
    r=sqrt(spx*spx);
    DrawSphere(r*cos(theta)*spx/sqrt(spx*spx),spyy+yad,r*sin(theta),0.06);
    DrawSphere(spx+xad,spy+yad,spz,0.06);
    if(spy*spy>2){spz=0.01;spvz=0;spy=0.1;}
     
    //spx=spxx;
    //spz=spzz;
     int i;
     int j;

     float x=-1.05;
     float y=-4.0;
     float z=-1.05;


     glDisable(GL_LIGHTING);
   
     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    
     glEnable(GL_CULL_FACE);


  glBegin(GL_POLYGON);
     //glTranslatef(0.0,-6.0,-6.0);
      z=-1.05;
      for(j=0;j<=40;j++){
      z+=0.05;
      glColor3f(1.0,1.0,1.0);
      glVertex3f(-1.0+xad,-1.0+yad,z);
      x=-1.05;
      for(i=0;i<=40;i++){  
      glColor3f(2*x,0.0,1.0);
      x+=0.05;
      y=x*x-z*z;
      if(z<0)glColor3f(0.5,1.0,1.0);
      if(i==0)glColor3f(1.0,1.0,1.0);
      if(i==40)glColor3f(1.0,1.0,1.0);
      if(j==0)glColor3f(1.0,1.0,1.0);     
      if(j==40)glColor3f(1.0,1.0,1.0);
      glVertex3f(x+xad,y+yad,z);}
      glColor3f(1.0,1.0,1.0);
      glVertex3f(1.0+xad,-1.0+yad,z);}

      x=-1.05;
      z=-1.05;
      for(j=0;j<=40;j++){
      x+=0.05;
      glColor3f(1.0,1.0,1.0);
      glVertex3f(x+xad,-1.0+yad,-1.0);
      z=-1.05;
      for(i=0;i<=40;i++){  
      glColor3f(2*z,0.0,1.0);
      z+=0.05;
      y=x*x-z*z;
      if(z<0)glColor3f(0.5,1.0,1.0);
      if(i==0)glColor3f(1.0,1.0,1.0);     
      if(i==40)glColor3f(1.0,1.0,1.0);
      if(j==0)glColor3f(1.0,1.0,1.0);     
      if(j==40)glColor3f(1.0,1.0,1.0);
      glVertex3f(x+xad,y+yad,z);}
      glColor3f(1.0,1.0,1.0);
      glVertex3f(x+xad,-1.0+yad,1.0);}


      glEnd(); 











     glRotatef(rtri,0.0,1.0,0.0);

    
     glBegin(GL_POLYGON);
     //glTranslatef(0.0,-6.0,-6.0);
     z=-1.05;
      for(j=0;j<=40;j++){
      z+=0.05;
      glColor3f(1.0,1.0,1.0);
      glVertex3f(-1.0,-2.0+yad,z);
      x=-1.05;
      for(i=0;i<=40;i++){  
      glColor3f(2*x,0.0,1.0);
      x+=0.05;
      y=x*x-z*z;
      if(z<0)glColor3f(0.5,1.0,1.0);
      if(i==0)glColor3f(1.0,1.0,1.0);
      if(i==40)glColor3f(1.0,1.0,1.0);
      if(j==0)glColor3f(1.0,1.0,1.0);     
      if(j==40)glColor3f(1.0,1.0,1.0);
      glVertex3f(x,y+yad,z);}
      glColor3f(1.0,1.0,1.0);
      glVertex3f(1.0,-2.0+yad,z);}

      x=-1.05;
      z=-1.05;
      for(j=0;j<=40;j++){
      x+=0.05;
      glColor3f(1.0,1.0,1.0);
      glVertex3f(x,-2.0+yad,-1.0);
      z=-1.05;
      for(i=0;i<=40;i++){  
      glColor3f(2*z,0.0,1.0);
      z+=0.05;
      y=x*x-z*z;
      if(z<0)glColor3f(0.5,0.8,1.0);
      if(i==0)glColor3f(1.0,1.0,1.0);     
      if(i==40)glColor3f(1.0,1.0,1.0);
      if(j==0)glColor3f(1.0,1.0,1.0);     
      if(j==40)glColor3f(1.0,1.0,1.0);
      glVertex3f(x,y+yad,z);}
      glColor3f(1.0,1.0,1.0);
      glVertex3f(x,-2.0+yad,1.0);}


      glEnd(); 

      




      //      glRotatef(rtri,0.0f,1.0f,0.0f);		// Rotate The Triangle On The Y axis 

   
 					// we're done with the polygon (smooth color interpolation)

   //  glLoadIdentity();				// make sure we're no longer rotated.
  //  glTranslatef(1.5f,0.0f,-6.0f);		// Move Right 3 Units, and back into the screen 6.0
	
  //glRotatef(rquad,1.0f,0.0f,0.0f);		// Rotate The Quad On The X axis 
  // draw a square (quadrilateral)
  //glColor3f(0.5f,0.5f,1.0f);			// set color to a blue shade.
  // glBegin(GL_QUADS);				// start drawing a polygon (4 sided)
  //glVertex3f(-1.0f, 1.0f, 0.0f);		// Top Left
  //glVertex3f( 1.0f, 1.0f, 0.0f);		// Top Right
  // glVertex3f( 1.0f,-1.0f, 0.0f);		// Bottom Right
  //glVertex3f(-1.0f,-1.0f, 0.0f);		// Bottom Left	
  //glEnd();					// done with the polygon

  rtri+=1.0;					// Increase The Rotation Variable For The Triangle
  rquad-=15.0f;					// Decrease The Rotation Variable For The Quad 
  //  spx+=0.005;
  // swap the buffers to display, since double buffering is used.
   glutSwapBuffers();
}

/* The function called whenever a key is pressed. */
void keyPressed(unsigned char key, int x, int y) 
{
    /* sleep to avoid thrashing this procedure */
    usleep(100);

    /* If escape is pressed, kill everything. */
    if (key == ESCAPE) 
    { 
	/* shut down our window */
	glutDestroyWindow(window); 
	
	/* exit the program...normal termination. */
	exit(0);                   
    }
}

int main(int argc, char **argv) 
{  
  /* Initialize GLUT state - glut will take any command line arguments that pertain to it or 
     X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */  
  glutInit(&argc, argv);  

  /* Select type of Display mode:   
     Double buffer 
     RGBA color
     Alpha components supported 
     Depth buffer */  
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);  

  /* get a 640 x 480 window */
  glutInitWindowSize(640, 480);  

  /* the window starts at the upper left corner of the screen */
  glutInitWindowPosition(0, 0);  

  /* Open a window */  
  window = glutCreateWindow("Paul rf");  

  /* Register the function to do all our OpenGL drawing. */
  glutDisplayFunc(&DrawGLScene);  

  
  /* Go fullscreen.  This is as soon as possible. */
  //glutFullScreen();

  /* Even if there are no events, redraw our gl scene. */
  glutIdleFunc(&DrawGLScene);

  /* Register the function called when our window is resized. */
  glutReshapeFunc(&ReSizeGLScene);

  /* Register the function called when the keyboard is pressed. */
  glutKeyboardFunc(&keyPressed);

  /* Initialize our window. */
  InitGL(640, 480);
  
  /* Start Event Processing Engine */  
  glutMainLoop();  

  return 1;
}
