PDA

View Full Version : Strange Sphere



Nivk
09-03-2001, 06:22 PM
This code draws a sphere but once i rotate it give me problems...is it my normals?? please help...




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

#define CUBE_SIZE 1.0
#define PI 3.14

static float scal = 1;
static float phi, theta;
static float axis =0;
static float incr = 0.;
static float u[3],v[3],nv[3];

/* non printable characters are better identified through defines like this */
#define ESCKEY 27
#define ARROW_LEFT 100
#define ARROW_RIGHT 102
#define ARROW_UP 101
#define ARROW_DOWN 103

/************************************************** ********************
This function is called only once in the very beginning.
It can initialize whatever is desired.
Right now, two angles are defined.
************************************************** *********************/

static void Init() {

GLfloat light0_position[] = {0.0f, 8.0f, 4.0f, 1.0f};
GLfloat light0_ambient[] = {0.3f,0.3f,0.3f,1.0f};
GLfloat light0_diffuse[] = {0.7f,0.7f,0.7f,1.0f};
GLfloat light0_specular[] = {1.0f,1.0f,1.0f,1.0f};
GLfloat mat_ambient[] = {0.5f,0.5f,0.5f,0.5f};
GLfloat mat_diffuse[] = {0.5f,0.5f,0.5f,0.5f};
GLfloat mat_specular[] = {0.8f,0.8f,0.8f,0.5f};
GLfloat mat_shininess[] = {50.0f}; /* define material brightness */

/* initialize light and material characteristics */
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);

glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
/* initialise depth, lighting and colour of material */
//glDepthFunc(GL_LEQUAL);
//glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glDisable(GL_CULL_FACE);
/* enable relevant characteristics of colour, lighting and depth of material */
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT0);
phi=20.0; theta=20.0;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

/************************************************** ********************
This function defines the object(s) to be drawn.
Now, for wire-frame drawing, only polylines and lines are used.
While drawing shaded polygons, do not forget to
define materials and lights in Init()
************************************************** *********************/
int Sphere ( float *X, float *Y, float *Z, float Phi, float Theta) {
*X = cos(Phi);
*Y = cos(Theta)*sin(Phi);
*Z = sin(Theta)*sin(Phi);
u[0] = -sin(Phi);
u[1] = cos(Theta)*cos(Phi);
u[2] = sin(Theta)*cos(Phi);

v[0] = 0;
v[1] = -sin(Theta)*sin(Phi);
v[2] = cos(Theta)*sin(Phi);

return 1;
}

int EllpiticCone( float *X, float *Y, float *Z, float Phi, float Theta) {

u[0]= (cos(Theta))/(2*PI);
u[1]= (sin(Theta))/(2*PI);
u[2]= 1/(2*PI);

v[0]= Phi*(sin(Theta))/(2*PI);
v[1]= Phi*(cos(Theta))/(2*PI);
v[2]= 0;

*X = (Phi*cos(Theta))/(2*PI);
*Y = (Phi*sin(Theta))/(2*PI);
*Z = Phi/(2*PI);

return 1;
}

int SweptContractedHypocycloid (float *X, float *Y, float *Z, float Phi, float Theta) {
u[0] = 0.1*(-3*(sin (Phi)) - (0.8*3)*sin(3*Phi));
u[1] = (0.2* cos (Theta) * (3*(cos (Phi)) - (3*0.8)*(cos(3*Phi))));
u[2] = (0.2* sin (Theta) * (3*(cos (Phi)) - (3*0.8)*(cos(3*Phi))));

v[0] = 0;
v[1] = -0.2*(sin (Theta))*(5+(3*sin (Phi)) - 0.8*sin(3*Phi));
v[2] = 0.2*(cos (Theta))*(5+(3*sin (Phi)) - 0.8*sin(3*Phi));

*X = 0.1*((3*cos(Phi)+0.8*cos(3*Phi)));
*Y = (0.2*(cos(Theta)))*(5+3*sin(Phi)-0.8*sin(3*Phi));
*Z = (0.2*(sin(Theta)))*(5+3*sin(Phi)-0.8*sin(3*Phi));
return 1;
}

void CalculateCrossProdnNormlize() {
float n[3], d;

n[0] = (u[1]*v[2]) - (v[1]*u[2]);
n[1] = (u[2]*v[0]) - (v[2]*u[0]);
n[2] = (u[0]*v[1]) - (v[0]*u[1]);

d = (n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
if ( d < (float) 0.00000001 )
d = (float) 100000000.0;
else {
d = (float) 1.0 / (sqrt (d));
}

nv[0] = n[0] * d;
nv[1] = n[1] * d;
nv[2] = n[2] * d;

}

int (*Surface) (float *, float *, float *, float, float) = Sphere;

void MakeObject( void ) {
float x, y, z , alpha, beta ;

/* Set color to red */
glColor3f(1.0, 0.0, 0.0);
/* Coordinate axes - three lines */
if(axis==0) {
// glShadeModel(GL_FLAT);
glBegin(GL_LINES);
/* CL_LINES defines segments of straight line connecting vertices v1 with v2,
v3 with v4, v5 with v6, etc. */
glVertex3f(-2.0*CUBE_SIZE,0,0);
glVertex3f(2.0*CUBE_SIZE,0,0);
glColor3f(.4,.5,.3);
glVertex3f(-2,0,0);
glVertex3f(-4,0,0);
glColor3f(.0, 1.0, 0.0);
glVertex3f(0,-2.0*CUBE_SIZE,0);
glVertex3f(0,2.0*CUBE_SIZE,0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0,0,-2.0*CUBE_SIZE);
glVertex3f(0,0,2.0*CUBE_SIZE);
glEnd();
}
/* Set color to blue */
glColor3f(0 ,0.55 , 1);
/* A cube - 1 polyline and three segments */

for (alpha=0; alpha<=2*PI; alpha+=PI/12) {

glBegin(GL_QUAD_STRIP);
for ( beta=-PI/2; beta <=PI/2; beta +=PI/12){

Surface (&amp;x, &amp;y, &amp;z, alpha, beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
Surface (&amp;x, &amp;y, &amp;z, alpha + PI/12, beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
}
glEnd();
}
/* for (alpha=0; alpha<=2*PI; alpha+=PI/12){
glBegin(GL_QUAD_STRIP);
for ( beta=0; beta <=2*PI; beta +=PI/12){
Surface (&amp;x, &amp;y, &amp;z, alpha, beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
Surface (&amp;x, &amp;y, &amp;z, alpha + (PI/6), beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
Surface (&amp;x, &amp;y, &amp;z, alpha - (PI/6), beta + (PI/6));
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
Surface (&amp;x, &amp;y, &amp;z, alpha + PI/6, beta + (PI/6));
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
}
glEnd();
}*/
}


/************************************************** *********************
Main Drawing Function.
It is called by the system to draw every next buffer with the maximum
speed available.
************************************************** **********************/

static void Draw( void ) {
glClearColor (0.3, 0.0, 0.5, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
phi=phi+incr;
if (phi>=360.0) phi=0.0;

/* This translation is done for the visualization transformation */
glTranslatef(0.0,0.0,-5.0*CUBE_SIZE);
/* The following are rotations done about Y followed by rotation about X */
glRotatef(theta, 1.0, 0.0, 0.0);
glRotatef(phi, 0.0, 1.0, 0.0);
/* This could be a scaling if you decide to scale. Right now we scale by 1,1,1 */
glScalef(scal,scal,scal);
/* Here, the MakeObject function is called. You have to change it first to draw
the requested objects */
MakeObject();
/* glFlush(); --> not used in GLUT */
glPopMatrix();
glutSwapBuffers();
}

/************************************************** ****************
Key-Pressed events handling
************************************************** *****************/

void Close(void) {
exit(0);
}


static void Rotate(void) { /* Toggle between rotation and stop rotation */
static float LastRotation = 1.;
if (incr >0.) {
LastRotation = incr; /* we save inc because it will have */
incr = 0.; /* different values later on */
}
else incr = LastRotation;

}

static void Axis(void) {
static float x = 1;
if (axis >0.) {
x = axis;
axis = 0.;
}
else axis = x;
}

/************************************************** ****************
In this function the projection transformation is defined.
Currently, it is perspective projection. It can be orthographic
projection as well if one uses the commented glOrtho instead of
glFrustum
************************************************** *****************/

void Reshape(GLsizei w, GLsizei h) {
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();

/* This glOrtho can be used in place of glFrustrum if
perspective projection is not desired.
glOrtho(-2.0*CUBE_SIZE, 2.0*CUBE_SIZE, -2.0*CUBE_SIZE, 2.0*CUBE_SIZE,
0.0*CUBE_SIZE, 10.0*CUBE_SIZE);
*/
glFrustum(-2.0*CUBE_SIZE, 2.0*CUBE_SIZE, -2.0*CUBE_SIZE, 2.0*CUBE_SIZE,
3.0*CUBE_SIZE, 40.0*CUBE_SIZE);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, w, h);
}

/************************************************** ****************
This function calls Draw if there is nothing else to call
************************************************** *****************/

static void Idle(void) {
glutPostRedisplay(); /* forces the redisplay to produce the animation */
}

/************************************************** ****************
This function deals with non printable characters key strokes (ESC, ...)
************************************************** *****************/

static void special(int c, int x, int y) {

printf("%d\n",c);

switch (c) {

case ESCKEY : Close();
break;
case ARROW_UP: theta-=3;
break;
case ARROW_DOWN: theta+=3;
break;
case ARROW_LEFT: phi-=3;
break;
case ARROW_RIGHT: phi+=3;
break;
}/* end switch() */
}

/************************************************** ****************
This function intercepts all key strokes and deals with normal characters
************************************************** *****************/

static void keyboard(unsigned char c, int x, int y) {

if ( (c >= 'a') &amp;&amp; (c < 'z') ) { /* convert lowercases in uppercases */
c -= ( ((int)'a') - ((int)'A') );
}


switch (c) {


case 'R' : printf("%d\n",c);
Rotate(); /* 'R' or 'r' keystroke starts/stops rotation */
break;
case 'X' : printf("%d\n",c);
Axis();
break;

default: special(c,x,y); /* it's perhaps a non printable character */

}

}

/************************************************** ****************
This is the main function.
It defines the display modes, the initial window position and its
size. It also defines the functions for Display, Reshape and for intercepting
key strokes in the keyboard.
************************************************** *****************/

void main( int argc, char *argv[] ) {

glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 480);
glutInitWindowPosition(80, 60);
glutCreateWindow("SC208 - Sample");

glutDisplayFunc(Draw);
glutReshapeFunc(Reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutIdleFunc(Idle);

Init();
glutMainLoop();

}

Bob
09-03-2001, 10:36 PM
It gives you problems? Ok, but what kind of problems, and what is suppose to happen? Without knowing whats wrong, and what is supposed to happen, we can't say much to help you.

Nivk
09-04-2001, 12:33 AM
It's suppose to rotate with the added lighting and specular but somehow the surface get distorted at certain point of rotation..i can't figure out why is this so...is it something to do with my normals?
Thanks http://www.opengl.org/discussion_boards/ubb/biggrin.gif

09-04-2001, 09:07 AM
I solve ur problem.

(1) Add these to ur init()
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

(2) Define ur PI to be more accurate
(3) Add
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
to clear your depth and color buffer


http://www.opengl.org/discussion_boards/ubb/mad.gif
////////////////////////////////////////////
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "glut.h"

#define CUBE_SIZE 1.0
#define PI 3.1415926535897932384626433832795 /* Approximation of PI */


static float scal = 1;
static float phi, theta;
static float axis =0;
static float incr = 0.;
static float u[3],v[3],nv[3];

/* non printable characters are better identified through defines like this */
#define ESCKEY 27
#define ARROW_LEFT 100
#define ARROW_RIGHT 102
#define ARROW_UP 101
#define ARROW_DOWN 103

/************************************************** ********************
This function is called only once in the very beginning.
It can initialize whatever is desired.
Right now, two angles are defined.
************************************************** *********************/

static void Init() {

GLfloat light0_position[] = {0.0f, 8.0f, 4.0f, 1.0f};
GLfloat light0_ambient[] = {0.3f,0.3f,0.3f,1.0f};
GLfloat light0_diffuse[] = {0.7f,0.7f,0.7f,1.0f};
GLfloat light0_specular[] = {1.0f,1.0f,1.0f,1.0f};
GLfloat mat_ambient[] = {0.5f,0.5f,0.5f,0.5f};
GLfloat mat_diffuse[] = {0.5f,0.5f,0.5f,0.5f};
GLfloat mat_specular[] = {0.8f,0.8f,0.8f,0.5f};
GLfloat mat_shininess[] = {50.0f}; /* define material brightness */

/* initialize light and material characteristics */
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);

glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
/* initialise depth, lighting and colour of material */
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
// glDisable(GL_CULL_FACE);
/* enable relevant characteristics of colour, lighting and depth of material */
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
phi=20.0; theta=20.0;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

/************************************************** ********************
This function defines the object(s) to be drawn.
Now, for wire-frame drawing, only polylines and lines are used.
While drawing shaded polygons, do not forget to
define materials and lights in Init()
************************************************** *********************/
int Sphere ( float *X, float *Y, float *Z, float Phi, float Theta) {
*X = cos(Phi);
*Y = cos(Theta)*sin(Phi);
*Z = sin(Theta)*sin(Phi);
u[0] = -sin(Phi);
u[1] = cos(Theta)*cos(Phi);
u[2] = sin(Theta)*cos(Phi);

v[0] = 0;
v[1] = -sin(Theta)*sin(Phi);
v[2] = cos(Theta)*sin(Phi);

return 1;
}

int EllpiticCone( float *X, float *Y, float *Z, float Phi, float Theta) {

u[0]= (cos(Theta))/(2*PI);
u[1]= (sin(Theta))/(2*PI);
u[2]= 1/(2*PI);

v[0]= Phi*(sin(Theta))/(2*PI);
v[1]= Phi*(cos(Theta))/(2*PI);
v[2]= 0;

*X = (Phi*cos(Theta))/(2*PI);
*Y = (Phi*sin(Theta))/(2*PI);
*Z = Phi/(2*PI);

return 1;
}

int SweptContractedHypocycloid (float *X, float *Y, float *Z, float Phi, float Theta) {
u[0] = 0.1*(-3*(sin (Phi)) - (0.8*3)*sin(3*Phi));
u[1] = (0.2* cos (Theta) * (3*(cos (Phi)) - (3*0.8)*(cos(3*Phi))));
u[2] = (0.2* sin (Theta) * (3*(cos (Phi)) - (3*0.8)*(cos(3*Phi))));

v[0] = 0;
v[1] = -0.2*(sin (Theta))*(5+(3*sin (Phi)) - 0.8*sin(3*Phi));
v[2] = 0.2*(cos (Theta))*(5+(3*sin (Phi)) - 0.8*sin(3*Phi));

*X = 0.1*((3*cos(Phi)+0.8*cos(3*Phi)));
*Y = (0.2*(cos(Theta)))*(5+3*sin(Phi)-0.8*sin(3*Phi));
*Z = (0.2*(sin(Theta)))*(5+3*sin(Phi)-0.8*sin(3*Phi));
return 1;
}

void CalculateCrossProdnNormlize() {
float n[3], d;

n[0] = (u[1]*v[2]) - (v[1]*u[2]);
n[1] = (u[2]*v[0]) - (v[2]*u[0]);
n[2] = (u[0]*v[1]) - (v[0]*u[1]);

d = (n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
if ( d < (float) 0.00000001 )
d = (float) 100000000.0;
else {
d = (float) 1.0 / (sqrt (d));
}

nv[0] = n[0] * d;
nv[1] = n[1] * d;
nv[2] = n[2] * d;

}

int (*Surface) (float *, float *, float *, float, float) = Sphere;

void MakeObject( void ) {
float x, y, z , alpha, beta ;

/* Set color to red */
glColor3f(1.0, 0.0, 0.0);
/* Coordinate axes - three lines */
if(axis==0) {
// glShadeModel(GL_FLAT);
glBegin(GL_LINES);
/* CL_LINES defines segments of straight line connecting vertices v1 with v2,
v3 with v4, v5 with v6, etc. */
glVertex3f(-2.0*CUBE_SIZE,0,0);
glVertex3f(2.0*CUBE_SIZE,0,0);
glColor3f(.4,.5,.3);
glVertex3f(-2,0,0);
glVertex3f(-4,0,0);
glColor3f(.0, 1.0, 0.0);
glVertex3f(0,-2.0*CUBE_SIZE,0);
glVertex3f(0,2.0*CUBE_SIZE,0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0,0,-2.0*CUBE_SIZE);
glVertex3f(0,0,2.0*CUBE_SIZE);
glEnd();
}
/* Set color to blue */
glColor3f(0 ,0.55 , 1);
/* A cube - 1 polyline and three segments */

for (alpha=0; alpha<=2*PI+PI/12; alpha+=PI/12) {

glBegin(GL_QUAD_STRIP);
for ( beta=-PI; beta <=PI+PI/12; beta +=PI/12){

Surface (&x, &y, &z, alpha, beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);

Surface (&x, &y, &z, alpha + PI/12, beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
}
glEnd();
}
/* for (alpha=0; alpha<=2*PI; alpha+=PI/12){
glBegin(GL_QUAD_STRIP);
for ( beta=0; beta <=2*PI; beta +=PI/12){
Surface (&x, &y, &z, alpha, beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
Surface (&x, &y, &z, alpha + (PI/6), beta);
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
Surface (&x, &y, &z, alpha - (PI/6), beta + (PI/6));
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
Surface (&x, &y, &z, alpha + PI/6, beta + (PI/6));
CalculateCrossProdnNormlize();
glNormal3fv(nv);
glVertex3f(x,y,z);
}
glEnd();
}*/
}


/************************************************** *********************
Main Drawing Function.
It is called by the system to draw every next buffer with the maximum
speed available.
************************************************** **********************/

static void Draw( void ) {
glClearColor (0.3, 0.0, 0.5, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
phi=phi+incr;
if (phi>=360.0) phi=0.0;

/* This translation is done for the visualization transformation */
glTranslatef(0.0,0.0,-5.0*CUBE_SIZE);
/* The following are rotations done about Y followed by rotation about X */
glRotatef(theta, 1.0, 0.0, 0.0);
glRotatef(phi, 0.0, 1.0, 0.0);
/* This could be a scaling if you decide to scale. Right now we scale by 1,1,1 */
glScalef(scal,scal,scal);
/* Here, the MakeObject function is called. You have to change it first to draw
the requested objects */
MakeObject();
/* glFlush(); --> not used in GLUT */
glPopMatrix();
glutSwapBuffers();
}

/************************************************** ****************
Key-Pressed events handling
************************************************** *****************/

void Close(void) {
exit(0);
}


static void Rotate(void) { /* Toggle between rotation and stop rotation */
static float LastRotation = 1.;
if (incr >0.) {
LastRotation = incr; /* we save inc because it will have */
incr = 0.; /* different values later on */
}
else incr = LastRotation;

}

static void Axis(void) {
static float x = 1;
if (axis >0.) {
x = axis;
axis = 0.;
}
else axis = x;
}

/************************************************** ****************
In this function the projection transformation is defined.
Currently, it is perspective projection. It can be orthographic
projection as well if one uses the commented glOrtho instead of
glFrustum
************************************************** *****************/

void Reshape(GLsizei w, GLsizei h) {
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();

/* This glOrtho can be used in place of glFrustrum if
perspective projection is not desired.
glOrtho(-2.0*CUBE_SIZE, 2.0*CUBE_SIZE, -2.0*CUBE_SIZE, 2.0*CUBE_SIZE,
0.0*CUBE_SIZE, 10.0*CUBE_SIZE);
*/
glFrustum(-2.0*CUBE_SIZE, 2.0*CUBE_SIZE, -2.0*CUBE_SIZE, 2.0*CUBE_SIZE,
3.0*CUBE_SIZE, 40.0*CUBE_SIZE);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, w, h);
}

/************************************************** ****************
This function calls Draw if there is nothing else to call
************************************************** *****************/

static void Idle(void) {
glutPostRedisplay(); /* forces the redisplay to produce the animation */
}

/************************************************** ****************
This function deals with non printable characters key strokes (ESC, ...)
************************************************** *****************/

static void special(int c, int x, int y) {

printf("%d\n",c);

switch (c) {

case ESCKEY : Close();
break;
case ARROW_UP: theta-=3;
break;
case ARROW_DOWN: theta+=3;
break;
case ARROW_LEFT: phi-=3;
break;
case ARROW_RIGHT: phi+=3;
break;
}/* end switch() */
}

/************************************************** ****************
This function intercepts all key strokes and deals with normal characters
************************************************** *****************/

static void keyboard(unsigned char c, int x, int y) {

if ( (c >= 'a') && (c < 'z') ) { /* convert lowercases in uppercases */
c -= ( ((int)'a') - ((int)'A') );
}


switch (c) {


case 'R' : printf("%d\n",c);
Rotate(); /* 'R' or 'r' keystroke starts/stops rotation */
break;
case 'X' : printf("%d\n",c);
Axis();
break;

default: special(c,x,y); /* it's perhaps a non printable character */

}

}

/************************************************** ****************
This is the main function.
It defines the display modes, the initial window position and its
size. It also defines the functions for Display, Reshape and for intercepting
key strokes in the keyboard.
************************************************** *****************/

void main( int argc, char *argv[] ) {

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 480);
glutInitWindowPosition(80, 60);
glutCreateWindow("SC208 - Sample");

glutDisplayFunc(Draw);
glutReshapeFunc(Reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutIdleFunc(Idle);

Init();
glutMainLoop();

}