/*
   Example of plotting a spiral around a torus

   (c) February 2001, Steve Cunningham & Ken Brown
*/
#define OSX

#ifdef MAC
#include "glut.h"
#endif
#ifdef OSX
#include <GLUT/glut.h>
#endif
#ifdef UNIX
#include <GL/glut.h>
#endif
#ifdef PC
#include <GL/glut.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

static char ch; // the character from the keyboard that controls the rotation
typedef GLfloat point3[3];
typedef GLfloat color [4];

// function prototypes
void myinit(void);
void spiral(void);
void display(void);
void reshape(int,int);
void keyboard(unsigned char,int,int);

// initialize OpenGL and all necessary global variables
void myinit(void)
{
//      set up overall light data
        GLfloat light_position0[]={ 10.0, 10.0, 10.0, 1.0 };
        GLfloat light_position1[]={-10.0,-10.0,-10.0, 1.0 };
        GLfloat light_color[]   ={ 1.0, 1.0, 0.0, 1.0 };
        GLfloat ambient_color[] ={ 1.0, 1.0, 0.0, 1.0 };

        glClearColor( 0.0, 0.0, 1.0, 0.0 );
        glShadeModel(GL_SMOOTH); // use gourand shading
        glLightfv(GL_LIGHT0, GL_POSITION, light_position0 );
        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color );
        glLightfv(GL_LIGHT0, GL_SPECULAR, light_color );
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color );
        glLightfv(GL_LIGHT0, GL_POSITION, light_position1 );
        glLightfv(GL_LIGHT1, GL_AMBIENT, ambient_color );
        glLightfv(GL_LIGHT1, GL_SPECULAR, light_color );
        glLightfv(GL_LIGHT1, GL_DIFFUSE, light_color );

/* attributes */

        glEnable(GL_LIGHTING);   // so lighting models are used
        glEnable(GL_LIGHT0);     // we'll use LIGHT0
        glEnable(GL_LIGHT1);	 // and also LIGHT1
        glEnable(GL_DEPTH_TEST); // allow z-buffer display
}

void spiral(void)
{
		int i;
		float a=2.0, b=3.0, c=18.0, t;

		glBegin(GL_LINE_STRIP);
		t = 0.0;
		for ( i=0; i<=1000; i++ ) {
			glVertex3f((a*sin(c*t)+b)*cos(t), (a*sin(c*t)+b)*sin(t), a*cos(c*t));
			t = t + .00628318;	//	2*PI/1000
		}
		glEnd();
}

void display( void )
{
/* define a point data type */
    typedef GLfloat point3[3];

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    //  NOTE that we do not take ourselves back to the original raw-world state.
    //  We let the modelview matrix hold our global view of the model, and
    //  we modify it by including the new rotation each time a key is pressed
    
#define Angle 2.0

    switch(ch)
    {
        case 'w':
            glRotatef( Angle, 1.0, 0.0, 0.0); break;
        case 'q':
            glRotatef(-Angle, 1.0, 0.0, 0.0); break;
        case 's':
            glRotatef( Angle, 0.0, 1.0, 0.0); break;
        case 'a':
            glRotatef(-Angle, 0.0, 1.0, 0.0); break;
        case 'x':
            glRotatef( Angle, 0.0, 0.0, 1.0); break;
        case 'z':
            glRotatef(-Angle, 0.0, 0.0, 1.0); break;
    }

	spiral();

    glutSwapBuffers();
}

void reshape(int w,int h)
{
        glViewport(0,0,(GLsizei)w,(GLsizei)h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(60.0,(GLfloat)w/(GLfloat)h,1.0,30.0);
		glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        /*           eye point        center of view      up   */
        gluLookAt( 10.0,  10.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);

}

void keyboard(unsigned char key, int x, int y)
{

        switch (key)
        {
        case 'w' :     // rotate around X; i = positive, j = negative
        case 'q' :
        case 's' :    // rotate around Y; k = positive, m = negative
        case 'a' :
        case 'x' :    // rotate around Z; a = positive, s = negative
        case 'z' :
           ch = key; break;
        }
        glutPostRedisplay(); /* perform display again */
}

int main(int argc, char** argv)
{
/* Standard GLUT initialization */
        glutInit(&argc,argv);
        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(500,500);
        glutInitWindowPosition(70,70);
        glutCreateWindow("Parametric Curve");
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);
        glutKeyboardFunc(keyboard); // enable keyboard callback

        myinit();
        glutMainLoop();

        return 0;
}
