//============================================================================= // // Glagen : a planet sized landscape generator // Copyright (C) 2002 Julien Guertault, Hugues Hiegel, Meng-Tih Lam // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // //============================================================================= // // Glagen : GPL LAndscape GENerator // // display.cc for Glagen : made by Zavie (Julien Guertault) // // www.glagen.org // //============================================================================= #include #include #include #ifndef DARWIN # include # include # include #else # include # include # include #endif #include "data_glagen.hh" #include "end.hh" #include "library.hh" #include "time.hh" #include "triangle.hh" bool pressed; int x; int y; int xold; int yold; static const GLfloat L0position[] = { 0.0, 1.0, -2.0, 0.0 }; static const GLfloat L0ambient[] = { 0.0, 0.0, 0.0, 1.0 }; static const GLfloat L0diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; static const GLfloat L0specular[] = { 1.0, 1.0, 1.0, 1.0 }; static const GLfloat Mshiny = 50; void display_frame () { Frame *o = &glagen.observer.frame; update_time (); glagen.step = glagen.step + 1; if (glagen.display_planet == true) library_caller (glagen.ref); glagen.step = glagen.step + 1; glagen.ref->Update_normal_visitor (); glagen.step = glagen.step + 1; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); // Third person view : the observer is represented by a frame if (glagen.third_view == true) { // View initialization in third person view mode gluPerspective(45, float(glagen.x) / float(glagen.y), 0.5, 8.0); gluLookAt (-4, 4, -4, 1, -1, 1, 0, 1, 0); // The frame representing the user's position if (glagen.light == true) glDisable(GL_LIGHTING); glBegin (GL_LINES); glColor3f(1.0, 1.0, 0.0); glVertex3f(o->Origin_X (), o->Origin_Y (), o->Origin_Z ()); glVertex3f(o->Origin_X () + o->Basis_X ().X () / 2, o->Origin_Y () + o->Basis_X ().Y () / 2, o->Origin_Z () + o->Basis_X ().Z () / 2); glColor3f(0.0, 1.0, 1.0); glVertex3f(o->Origin_X (), o->Origin_Y (), o->Origin_Z ()); glVertex3f(o->Origin_X () + o->Basis_Y ().X () / 2, o->Origin_Y () + o->Basis_Y ().Y () / 2, o->Origin_Z () + o->Basis_Y ().Z () / 2); glColor3f(1.0, 0.0, 1.0); glVertex3f(o->Origin_X (), o->Origin_Y (), o->Origin_Z ()); glVertex3f(o->Origin_X () + o->Basis_Z ().X () / 2, o->Origin_Y () + o->Basis_Z ().Y () / 2, o->Origin_Z () + o->Basis_Z ().Z () / 2); // Then the projection of the user's position on the planet's frame glColor3f(1.0, 1.0, 1.0); glVertex3f(0, 0, 0); glVertex3f(o->Origin_X (), o->Origin_Y (), o->Origin_Z ()); glColor3f(1.0, 0.0, 0.0); glVertex3f(0, 0, 0); glVertex3f(o->Origin_X (), 0, 0); glColor3f(0.0, 1.0, 0.0); glVertex3f(o->Origin_X (), 0, 0); glVertex3f(o->Origin_X (), o->Origin_Y (), 0); glColor3f(0.0, 0.0, 1.0); glVertex3f(o->Origin_X (), o->Origin_Y (), 0); glVertex3f(o->Origin_X (), o->Origin_Y (), o->Origin_Z ()); glEnd (); if (glagen.light == true) glEnable(GL_LIGHTING); } else { // View initialization in normal view if (glagen.x > glagen.y) gluPerspective(45 * float(glagen.y) / float(glagen.x), float(glagen.x) / float(glagen.y), glagen.observer.altitude / 2, glagen.observer.altitude + 1); else gluPerspective(45, float(glagen.x) / float(glagen.y), glagen.observer.altitude / 2, glagen.observer.altitude + 1); gluLookAt (o->Origin_X (), o->Origin_Y (), o->Origin_Z (), o->Origin_X () + o->Basis_Z ().X (), o->Origin_Y () + o->Basis_Z ().Y (), o->Origin_Z () + o->Basis_Z ().Z (), o->Basis_Y ().X (), o->Basis_Y ().Y (), o->Basis_Y (). Z ()); } // The light if (glagen.light == true) { glLightfv(GL_LIGHT0, GL_POSITION, L0position); glEnable(GL_LIGHTING); } // The line calling the planet's display is just here glagen.ref->Display (0); glagen.step = glagen.step + 1; if (glagen.light == true) glDisable (GL_LIGHTING); // // Uncomment those lines for an atmosphere === glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // for (int current = 1; current < 100; current ++) // { // glagen.ref->Display (current); // glagen.step = glagen.step + 1; // } // glDisable (GL_BLEND); // // glFlush (); // On echange les buffers glutSwapBuffers (); glutPostRedisplay(); } // // Simple keyboard events catching // void Keyboard (unsigned char key_stroke, int, int) { switch (key_stroke) { // Quit case 'q': case 'Q': case 27: end_all(); } } // // Other keyboard events catching // void Keyboard_Special (int key_stroke, int, int) { Frame *o = &glagen.observer.frame; float ox = o->Origin_X (); float oy = o->Origin_Y (); float oz = o->Origin_Z (); switch (key_stroke) { case GLUT_KEY_UP: o->Translate (o->Basis_Z () * glagen.observer.speed); glagen.observer.speed = glagen.observer.altitude / 50; glagen.observer.altitude = sqrtf (ox * ox + oy * oy + oz * oz) - 1; if (glagen.zoom) glagen.ref->Split_visitor (); glagen.step = glagen.step + 1; glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; break; case GLUT_KEY_DOWN: o->Translate (o->Basis_Z () * -glagen.observer.speed); glagen.observer.speed = glagen.observer.altitude / 50; glagen.observer.altitude = sqrtf (ox * ox + oy * oy + oz * oz) - 1; if (glagen.zoom) glagen.ref->Split_visitor (); glagen.step = glagen.step + 1; glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; break; case GLUT_KEY_LEFT: o->Translate (o->Basis_X () * glagen.observer.speed); glagen.observer.speed = glagen.observer.altitude / 50; glagen.observer.altitude = sqrtf (ox * ox + oy * oy + oz * oz) - 1; if (glagen.zoom) glagen.ref->Split_visitor (); glagen.step = glagen.step + 1; glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; break; case GLUT_KEY_RIGHT: o->Translate (o->Basis_X () * -glagen.observer.speed); glagen.observer.speed = glagen.observer.altitude / 50; glagen.observer.altitude = sqrtf (ox * ox + oy * oy + oz * oz) - 1; if (glagen.zoom) glagen.ref->Split_visitor (); glagen.step = glagen.step + 1; glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; break; case GLUT_KEY_PAGE_UP: o->Translate (o->Basis_Y () * glagen.observer.speed); glagen.observer.speed = glagen.observer.altitude / 50; glagen.observer.altitude = sqrtf (ox * ox + oy * oy + oz * oz) - 1; if (glagen.zoom) glagen.ref->Split_visitor (); glagen.step = glagen.step + 1; glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; break; case GLUT_KEY_PAGE_DOWN: o->Translate (o->Basis_Y () * -glagen.observer.speed); glagen.observer.speed = glagen.observer.altitude / 50; glagen.observer.altitude = sqrtf (ox * ox + oy * oy + oz * oz) - 1; if (glagen.zoom) glagen.ref->Split_visitor (); glagen.step = glagen.step + 1; glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; break; case GLUT_KEY_F1: if (glagen.mode == 1) glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); else { if (glagen.mode == 2) glPolygonMode (GL_FRONT_AND_BACK, GL_POINT); else glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); } glagen.mode++; if (glagen.mode > 3) glagen.mode = 1; glutPostRedisplay (); break; case GLUT_KEY_F2: glagen.depth_test = !glagen.depth_test; if (glagen.depth_test == true) glEnable (GL_DEPTH_TEST); else glDisable (GL_DEPTH_TEST); glutPostRedisplay (); break; case GLUT_KEY_F3: glagen.display_normal = !glagen.display_normal; break; case GLUT_KEY_F4: glagen.display_planet = !glagen.display_planet; break; case GLUT_KEY_F5: glagen.display_all = !glagen.display_all; break; case GLUT_KEY_F6: glagen.third_view = !glagen.third_view; break; case GLUT_KEY_F7: glagen.light = !glagen.light; break; } // { // float alt = glagen.observer.altitude * 12000000; // if (alt > 1000) // printf ("%.3f km\n", alt / 1000); // else // printf ("%.3f m\n", alt); // } } void reshape (int x, int y) { glagen.x = x; glagen.y = y; glViewport (0, 0, x, y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } void mouse(int button, int state, int x, int y) { // sleft button pressed if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) pressed = true; // left button released if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { pressed = false; if (glagen.zoom) glagen.ref->Split_visitor (); glagen.step = glagen.step + 1; glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; } xold = x; // saving position yold = y; } void mousemotion(int x, int y) { float angle[3]; if (pressed) // left button { angle[0] = (y - yold) / 100.0; angle[1] = (xold - x) / 100.0; angle[2] = 0; } else { angle[0] = 0; angle[1] = 0; angle[2] = (xold - x) / 50.0; } glagen.observer.frame.Rotate (angle[0], glagen.observer.frame.Basis_X ()); glagen.observer.frame.Rotate (angle[1], glagen.observer.frame.Basis_Y ()); glagen.observer.frame.Rotate (angle[2], glagen.observer.frame.Basis_Z ()); glagen.ref->Hide_visitor (); glagen.step = glagen.step + 1; glutPostRedisplay (); xold = x; yold = y; } void display(int *narg, char ***args) { // Glut glutInit (narg, *args); glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize (600, 600); glutCreateWindow ("Test Glagen"); // OpenGL glClearColor (0.0, 0.0, 0.0, 0.0); glColor3f (1.0, 1.0, 1.0); glEnable (GL_DEPTH_TEST); glagen.mode = 1; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Light glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glLightfv (GL_LIGHT0, GL_DIFFUSE, L0diffuse); glLightfv (GL_LIGHT0, GL_SPECULAR, L0specular); glLightfv (GL_LIGHT0, GL_AMBIENT, L0ambient); glEnable (GL_COLOR_MATERIAL); glDisable (GL_LIGHTING); // Events functions glutDisplayFunc (display_frame); glutKeyboardFunc (Keyboard); glutSpecialFunc (Keyboard_Special); glutReshapeFunc (reshape); glutMouseFunc (mouse); glutMotionFunc (mousemotion); // Glut main loop ;-) glutMainLoop (); return; }