/* melite5b.c - visualizza un pianeta con relativo satellite in 3D * usando le primitive viste e anima pianeta e satellite con * moto rivoluzionario * * Autore: Andrea Fusiello, Andrea Colombari 2004 * * arrow keys - trasla la telecamera prospettica rispetto a x e y * SPACE key - accellera * - key - decellera * Escape Key - esce dal programma */ #include #include #include /* segue inclusione di una piccola libreria con alcune definizioni di tipo e utils */ #include "eliteutils.h" /* segue file .h dove si definisce la forma e le proprieta' del satellite */ #include "coriolis.h" /* Function Prototypes */ void initgfx( void ); void keyboard( GLubyte, GLint, GLint ); void specialkeys( GLint, GLint, GLint ); void drawScene( void ); void drawControlPanel(); void checkError( char * ); void printHelp( char * ); void reshape ( GLsizei, GLsizei ); void animate( void ); void visibility( GLint ); /* Global Definitions */ GLsizei width, height, ctrl_panel_height; GLdouble tx; GLdouble ty; GLdouble g_v; /* variabile per il conteggio dei frame per second */ static long g_frames=0; #define KEY_ESC 27 /* ascii value for the escape key */ #define CAM_SPEED_STEP 0.05f /* step di incremento velocita' */ #define CAM_MAX_SPEED 1.0f /* massima velocita' */ #define FOVx 8 /* field of fiew in x direction */ #define FOVy (3.0f*(FOVx/4.0f)) /* field of view in y direction with 4:3 proportion */ int main( int argc, char *argv[] ) { glutInit( &argc, argv ); width = glutGet( GLUT_SCREEN_WIDTH ) / 2; height = glutGet( GLUT_SCREEN_HEIGHT ) / 2; ctrl_panel_height = 50; glutInitWindowPosition( width / 2, height / 2 ); glutInitWindowSize( width, height ); /* aggiungiamo double buffering per le animazioni */ glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE ); glutCreateWindow( argv[0] ); initgfx(); glutKeyboardFunc( keyboard ); glutSpecialFunc( specialkeys ); glutDisplayFunc( drawScene ); /* aggiungiamo l'aggiornameto di width e height per il corretto aspect ratio */ glutReshapeFunc( reshape ); /* aggiungiamo la funzione per animare pianeta e satellite */ glutIdleFunc( animate ); /* aggiungiamo la funzione per gestire la visibilita' della finestra */ glutVisibilityFunc( visibility ); printHelp( argv[0] ); glutMainLoop(); return(0); } /* ----------------------------------------------------------*/ void printHelp( char *progname ) { fprintf(stdout, "\n%s - elite in 3D with rotating planet and satellite\n\n" "arrow keys - translate the perspective camera in x and y directions\n" "SPACE key - speed up\n" "- key - slow down\n" "Escape Key - exit the program\n\n", progname); } /* ----------------------------------------------------------*/ void initgfx( void ) { /* set clear color to black */ glClearColor( 0.0, 0.0, 0.0, 1.0 ); /* settaggi relativi alla visione in soggettiva del gioco */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( 45.0, (GLdouble) width / (GLdouble) (height-ctrl_panel_height), 1.0, 20.0 ); ty = 0; tx = 0; g_v = CAM_MAX_SPEED/2.0f; } /* ----------------------------------------------------------*/ void checkError( char *label ) { GLenum error; while ( (error = glGetError()) != GL_NO_ERROR ) printf( "%s: %s\n", label, gluErrorString(error) ); } /* ----------------------------------------------------------*/ void keyboard( GLubyte key, GLint x, GLint y ) { switch (key) { case ' ': if (g_v+CAM_SPEED_STEP <= CAM_MAX_SPEED) g_v+=CAM_SPEED_STEP; glutPostRedisplay(); break; case '-': if (g_v > 0) g_v-=CAM_SPEED_STEP; glutPostRedisplay(); break; case KEY_ESC: /* Exit when the Escape key is pressed */ fprintf(stdout, "\n"); exit(0); } } /* ----------------------------------------------------------*/ void specialkeys( GLint key, GLint u, GLint v ) { switch (key) { case GLUT_KEY_UP: ty += g_v; glutPostRedisplay(); break; case GLUT_KEY_DOWN: ty -= g_v; glutPostRedisplay(); break; case GLUT_KEY_LEFT: tx -= g_v; glutPostRedisplay(); break; case GLUT_KEY_RIGHT: tx += g_v; glutPostRedisplay(); break; } } /* ----------------------------------------------------------*/ void drawScene( void ) { static GLfloat darkgreen[] = { 0.0f, 0.25f, 0.0f }; /* ogni volta che disegno incremento il numero dei frame */ g_frames++; /* Do all your OpenGL rendering here */ /* cancelliamo il buffer video e lo z buffer */ glClear( GL_COLOR_BUFFER_BIT ); /* ------------------------------------------------------------------------- */ /* attiva il viewport principale */ glViewport( 0, ctrl_panel_height, width, height-ctrl_panel_height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); gluLookAt( tx, ty, 8.0, tx, ty, 0.0, 0.0, 1.0, 0.0 ); /* pianeta */ glPushMatrix(); glRotatef(glutGet(GLUT_ELAPSED_TIME)*0.012, 0.0, 0.0, 1.0); /* ruotante */ glColor3fv( darkgreen ); glutWireSphere( 1.5f, 15, 15 ); glPopMatrix(); /* satellite */ glPushMatrix(); glTranslatef( 2, 2, 0 ); glRotatef(glutGet(GLUT_ELAPSED_TIME)*0.012, 0.0, 0.0, 1.0); /* ruotante */ glColor3f( 0.7, 0.7, 0.7 ); drawEliteObject(coriolis_numberOfFaces, coriolis_vertex, coriolis_face, coriolis_material); glPopMatrix(); glPopMatrix(); /* ------------------------------------------------------------------------- */ /* Attiva il viewport del pannello, in basso */ glViewport( 0, 0, width, ctrl_panel_height); /* Salva la projection e costruisce una vista ortogonale */ glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); /* vista ortgogonale, con fattore d'aspetto corretto, in modo che non ci sia distorsone */ gluOrtho2D(0, (GLfloat) width/ctrl_panel_height, 0, 1); /* Salva la modelview e carica l'identita'*/ glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); drawControlPanel(); glPopMatrix(); /* ripristina la projection */ glMatrixMode(GL_PROJECTION); glPopMatrix(); checkError( "drawScene" ); glFlush(); /* per non vedere il frame buffer mentre viene disegnato evitando cosi' il "flicker problem" */ glutSwapBuffers(); } /* ----------------------------------------------------------*/ void drawControlPanel() { /* disegna il pannello di controllo in un vieport di altezza 1 e larghezza dipendente da quella della finestra */ GLfloat v; /* velocita' tra 0 e 1; */ GLint t; GLfloat xr, yr; /* coordinate radar */ /* barra della velocita' */ glLineWidth( 1 ); glColor3f( 0, 0, 1); glBegin( GL_LINE_LOOP ); /* quadrato */ glVertex2f(1, 0.5); glVertex2f(2, 0.5); glVertex2f(2, 0); glVertex2f(1, 0); glEnd(); v = (g_v)/(CAM_MAX_SPEED); if ( v < 0.8 ) glColor3f( 1, 1, 0); else glColor3f( 1, 0, 0); glBegin( GL_QUADS ); glVertex3f(1.05+1.0*v, 0, 0.1); glVertex3f(1.05+1.0*v, 0.5, 0.1); glVertex3f(1.05, 0.5, 0.1); glVertex3f(1.05, 0, 0.1); glEnd(); /* posizioniamo la scritta */ glColor3f( 0, 0, 1); glRasterPos2f(2.1, 0.1); renderBitmapString(GLUT_BITMAP_HELVETICA_18, "SP"); /* radar */ glColor3f( 0, 0, 1 ); glLineWidth( 0.2 ); glBegin( GL_LINES ); /* cerchio */ for(t=0; t<200; t++) glVertex3f(0.5+0.5*cos(t/200.0*2*PI), 0.5+0.5*sin(t/200.0*2*PI),0.1); glEnd(); /* crocetta */ glColor3f( 1, 1, 1); glLineWidth( 0.2 ); glBegin( GL_LINES); /* uso la z per disegnarla dietro */ glVertex3f(0.5, 0,-0.1); glVertex3f(0.5, 1,-0.1); glVertex3f(0, 0.5,-0.1); glVertex3f(1, 0.5,-0.1); glEnd(); /* punto rosso */ xr = -tx/(3*FOVx); yr = -ty/(3*FOVy); if (xr*xr+yr*yr <= 0.25) { glColor3f( 1.0f, 0.0f, 0.0f); glPointSize(4); glBegin(GL_POINTS); glVertex2f(0.5 + xr, 0.5+ yr); glEnd(); } } /* ----------------------------------------------------------*/ void reshape( GLsizei w, GLsizei h ) { /* aggiorniamo dimensioni con i valori correnti */ width = w; height = h; /* aggiornamento settaggi relativi alla visione in soggettiva del gioco */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( 45.0, (GLdouble) width / (GLdouble) (height-ctrl_panel_height), 1.0, 20.0 ); } /* ----------------------------------------------------------*/ void animate( void ) { long dtime; static long currentTime=0, previousTime=0; /* restituisce il tempo in ms da glutInit o dall'ultima chiamata */ currentTime = glutGet(GLUT_ELAPSED_TIME); dtime = currentTime - previousTime; /* questo serve per calcolare il fps ogni secondo (circa) */ if (dtime > 1000) { fprintf(stdout, "\r%d fps", (int)(1e3 * (double) g_frames/(double) dtime) ); fflush(stdout); g_frames = 0; previousTime = currentTime; } glutPostRedisplay(); } /* ----------------------------------------------------------*/ void visibility( int state ) { /* restart the animation function if we were * animated when the window was hidden */ if (state == GLUT_VISIBLE) { glutIdleFunc( animate ); } else { glutIdleFunc( NULL ); } } /* Credits: Riccardo Giannitrapani per la scrittura di bitmap Ben Humphrey (DigiBen@GameTutorials.com) per la texture e la classe camera Tutorial SGI (quello che c'e' sulla pagina web del lab) in generale */