00001 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 #include "Display.h"
00026 
00027 #include <cstdlib>
00028 #include <cmath>
00029 
00030 #include "Constants.h"
00031 #include "Accum.h"
00032 #include "Jitter.h"
00033 
00039 void display_timer(int value) {
00040   Display::instance()->timer(value);
00041 }
00042 
00043 Display* Display::_instance = NULL;
00044 
00045 Display::Display() : _world(12, 12, 2) {
00046   
00047   _center_x = (GLint) (_world.getWidth() / 2) * CELL_SIZE;
00048   _center_y = 0;
00049   _center_z = (GLint) (_world.getHeight() / 2) * CELL_SIZE;
00050 
00051   
00052   _camera_x = (GLint) _center_x;
00053   _camera_y = (GLint) HEIGHT_MAX / 4;
00054   _camera_z = (GLint) _center_z + 3 * CELL_SIZE;
00055 
00056   
00057   _near = 0.1;
00058   _far = HORIZON;
00059 
00060   
00061   _fovy = 45.0;
00062 
00063   
00064   _timer = true;
00065   glutTimerFunc(REDISPLAY_NB_MILLI_SEC, display_timer, 0);
00066 }
00067 
00068 GLfloat Display::focal_distance() {
00069   return sqrt((_camera_x - _center_x) * (_camera_x - _center_x) +
00070               (_camera_y - _center_y) * (_camera_y - _center_y) +
00071               (_camera_y - _center_y) * (_camera_y - _center_y));
00072 }
00073 
00074 void Display::translate_camera(GLfloat  inc_x, GLfloat  inc_z) {
00075   GLfloat tmp_x = _center_x + inc_x;
00076   GLfloat tmp_z = _center_z + inc_z;
00077 
00078   if(tmp_x > 0.0 && tmp_x < (_world.getWidth() - 1.0) * CELL_SIZE &&
00079       tmp_z > 0.0 && tmp_z < (_world.getHeight() - 1.0) * CELL_SIZE) {
00080     _camera_x += inc_x;
00081     _center_x = tmp_x;
00082     _camera_z += inc_z;
00083     _center_z = tmp_z;
00084     glutPostRedisplay();
00085   }
00086 }
00087 
00088 void Display::move_camera(GLfloat  inc_y) {
00089   GLfloat tmp_y = _camera_y + inc_y;
00090 
00091   if(tmp_y >= HEIGHT_MIN && tmp_y <= HEIGHT_MAX) {
00092     _camera_y += inc_y;
00093     glutPostRedisplay();
00094   }
00095 }
00096 
00097 void Display::zoom_camera(GLfloat  inc) {
00098   GLfloat tmp = focal_distance();
00099 
00100   if(_camera_y + inc >= HEIGHT_MIN && _camera_y + inc <= HEIGHT_MAX) {
00101     _camera_x = ((_camera_x - _center_x) * (1 + inc / tmp)) + _center_x;
00102     _camera_y = ((_camera_y - _center_y) * (1 + inc / tmp)) + _center_y;
00103     _camera_z = ((_camera_z - _center_z) * (1 + inc / tmp)) + _center_z;
00104     glutPostRedisplay();
00105   }
00106 }
00107 
00108 void Display::rotate_camera(GLfloat  inc) {
00109   GLfloat tmp = _camera_x;
00110   _camera_x = ((_camera_x - _center_x) * cos(inc) -
00111     (_camera_z - _center_z) * sin(inc)) + _center_x;
00112   _camera_z = ((tmp - _center_x) * sin(inc) +
00113     (_camera_z - _center_z) * cos(inc)) + _center_z;
00114   glutPostRedisplay();
00115 }
00116 
00117 Display::~Display() {
00118   destroy();
00119 }
00120 
00121 Display* Display::instance() {
00122   if(_instance == NULL) {
00123     _instance = new Display();
00124   }
00125 
00126   return _instance;
00127 }
00128 
00129 void Display::destroy() {
00130   if(_instance != NULL) {
00131     delete _instance;
00132     _instance = NULL;
00133   }
00134 }
00135 
00136 void Display::init() {
00137   
00138   GLfloat mat_specular[]   = {1.0, 1.0, 1.0, 1.0};
00139   GLfloat mat_shininess[]  = {100.0};
00140   GLfloat white_light[]    = {1.0, 1.0, 1.0, 1.0};
00141   GLfloat light_position[] = {
00142     _world.getWidth() / 2.0,
00143     HEIGHT_MAX,
00144     _world.getHeight() / 2.0,
00145     0.0
00146   };
00147 
00148   
00149   glClearColor(0.0, 0.0, 0.0, 1.0);
00150 
00151   
00152   glShadeModel(GL_FLAT);
00153 
00154   
00155   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
00156   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
00157 
00158   
00159   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
00160   glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
00161   glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
00162 
00163   
00164   glEnable(GL_LIGHTING);
00165   glEnable(GL_LIGHT0);
00166 
00167   
00168   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00169   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
00170 
00171   
00172   glEnable(GL_COLOR_MATERIAL);
00173 
00174   
00175   glClearDepth(1.0);
00176   glDepthFunc(GL_LESS);
00177   glEnable(GL_DEPTH_TEST);
00178 
00179   
00180   glEnable(GL_AUTO_NORMAL);
00181   glEnable(GL_NORMALIZE);
00182 }
00183 
00184 void Display::quit() {
00185 
00186 }
00187 
00188 void Display::timer(int value) {
00189   _world.iteration();
00190   glutPostRedisplay();
00191   if(_timer) {
00192     
00193     glutTimerFunc(REDISPLAY_NB_MILLI_SEC, display_timer, 0);
00194   }
00195 }
00196 
00197 void Display::draw() {
00198   GLint viewport[4];
00199   GLdouble ratio;
00200   int nb_steps = j[ANTIALIASING_LEVEL].nb;
00201   GLdouble step = 1.0 / nb_steps;
00202   jitter_point* jp = j[ANTIALIASING_LEVEL].jitter_points;
00203   int jitter;
00204 
00205   
00206   glGetIntegerv(GL_VIEWPORT, viewport);
00207   
00208   ratio = (GLdouble) viewport[2] / (GLdouble) viewport[3];
00209 
00210   
00211   glClear(GL_ACCUM_BUFFER_BIT);
00212   for(jitter = 0; jitter < nb_steps; jitter++) {
00213     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00214 
00215     
00216     
00217     accPerspective(_fovy, ratio, _near, _far,
00218                    jp[jitter].x, jp[jitter].y,
00219                    0.0, 0.0, 1.0);
00220 
00221     
00222     glMatrixMode(GL_MODELVIEW);
00223     
00224     
00225     glLoadIdentity();
00226     
00227     gluLookAt(_camera_x, _camera_y, _camera_z,
00228               _center_x, _center_y, _center_z,
00229               0.0, 1.0, 0.0);
00230 
00231     
00232     glColor3ub((GLubyte) (0.7 * COLOR_MAX), COLOR_MAX, COLOR_MAX);
00233     glPushMatrix();
00234     glTranslatef(_center_x, _center_y + 0.01 * CELL_SIZE, _center_z);
00235     glRotatef(90.0, 1.0, 0.0, 0.0);
00236     glutSolidTorus (0.03 * CELL_SIZE, 0.75 * CELL_SIZE,
00237       CELL_SIZE, 5 * CELL_SIZE);
00238     glPopMatrix();
00239 
00240     
00241     _world.draw();
00242 
00243     
00244     glAccum(GL_ACCUM, step);
00245   }
00246 
00247   
00248   glAccum(GL_RETURN, 1.0);
00249 
00250   
00251   glutSwapBuffers();
00252 }
00253 
00254 void Display::reshape(int width, int height) {
00255   
00256   if (height == 0)
00257     height = 1;
00258 
00259   
00260   glViewport(0, 0, width, height);
00261 
00262   
00263   glMatrixMode(GL_PROJECTION);
00264 
00265   
00266   glLoadIdentity();
00267   gluPerspective(_fovy, (float) width / height, _near, _far);
00268 
00269   
00270   glMatrixMode(GL_MODELVIEW);
00271 }
00272 
00273 void Display::inputKey(unsigned char key, int x, int y) {
00274   GLint specialKey = glutGetModifiers();
00275 
00276   switch(key) {
00277     case TRANSLATE_LEFT :
00278       translate_camera(-CELL_SIZE, 0.0);
00279       break;
00280     case TRANSLATE_RIGHT :
00281       translate_camera(CELL_SIZE, 0.0);;
00282       break;
00283     case TRANSLATE_UP :
00284       translate_camera(0.0, -CELL_SIZE);
00285       break;
00286     case TRANSLATE_DOWN :
00287       translate_camera(0.0, CELL_SIZE);
00288       break;
00289     case ZOOM_IN :
00290       if(specialKey == GLUT_ACTIVE_CTRL) {
00291         move_camera(MOVE_UP_SPEED);
00292       } else {
00293         zoom_camera(-ZOOM_SPEED);
00294       }
00295       break;
00296     case ZOOM_OUT :
00297       if(specialKey == GLUT_ACTIVE_CTRL) {
00298         move_camera(-MOVE_UP_SPEED);
00299       } else {
00300         zoom_camera(ZOOM_SPEED);
00301       }
00302       break;
00303     case ROTATE_LEFT :
00304       rotate_camera(-ROTATE_ANGLE);
00305       break;
00306     case ROTATE_RIGHT :
00307       rotate_camera(ROTATE_ANGLE);
00308       break;
00309     case PAUSE :
00310       if(_timer) {
00311         _timer = false;
00312       } else {
00313         _timer = true;
00314         
00315         glutTimerFunc(REDISPLAY_NB_MILLI_SEC, display_timer, 0);
00316       }
00317       break;
00318     case VALIDATE :
00319       _world.addGodsGift((unsigned int) _center_z / CELL_SIZE,
00320         (unsigned int) _center_x / CELL_SIZE);
00321       glutPostRedisplay();
00322       break;
00323   }
00324 }
00325 
00326 void Display::inputMouse(int button, int state, int x, int y) {
00327   GLint specialKey = glutGetModifiers();
00328 
00329   
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348   if(state == GLUT_DOWN) {
00349     switch(button) {
00350       case GLUT_UP_BUTTON :
00351         if(specialKey == GLUT_ACTIVE_CTRL) {
00352           move_camera(MOVE_UP_SPEED);
00353         } else {
00354           zoom_camera(-ZOOM_SPEED);
00355         }
00356         break;
00357       case GLUT_DOWN_BUTTON :
00358         if(specialKey == GLUT_ACTIVE_CTRL) {
00359           move_camera(-MOVE_UP_SPEED);
00360         } else {
00361           zoom_camera(ZOOM_SPEED);
00362         }
00363         break;
00364       case GLUT_LEFT_BUTTON :
00365         if(specialKey == GLUT_ACTIVE_CTRL) {
00366           rotate_camera(-ROTATE_ANGLE);
00367         } else {
00368           _world.iteration();
00369           glutPostRedisplay();
00370         }
00371         break;
00372       case GLUT_RIGHT_BUTTON :
00373         if(specialKey == GLUT_ACTIVE_CTRL) {
00374           rotate_camera(ROTATE_ANGLE);
00375         }
00376         break;
00377     }
00378   }
00379 }