/**************************************************************************** Copyright (C) 2002-2006 Gilles Debunne (Gilles.Debunne@imag.fr) This file is part of the QGLViewer library. Version 2.2.4-1, released on December 12, 2006. http://artis.imag.fr/Members/Gilles.Debunne/QGLViewer libQGLViewer 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. libQGLViewer 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 libQGLViewer; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ // TP OpenGL: Joerg Liebelt, Serigne Sow #include "viewer.h" #include #include #include #include "quadtree.h" #include "water.h" #include "sky.h" #include "tree.h" using namespace std; // variables globales SKY mySky; QUADTREE myQuadtree; WATER myWater; TREE myTree; int currentHeightmap= 0; const int scaleFactor = 1; const int mapSize = 128; const float waterLevel = 0.15f; const int numTrees = 100; void Viewer::draw() { myQuadtree.ComputeView(); myQuadtree.Init(); qglviewer::Vec v = camera()->position(); myQuadtree.Update(v.x,v.y,v.z); //render le terrain myQuadtree.Render(); if (myTree.wantTree()) myTree.Render( ); if (mySky.wantSky()) { //le ciel mySky.Set( -0.5,-0.5,-0.5, 2.0f ); //mySky.Set( v.x,v.y,v.z, 1.0f ); mySky.Render( ); } if (myWater.wantWater()) { //mise a jour des polygons et normales de l'eau myWater.Update( 0.001f ); myWater.CalcNormals( ); //render le filet de l'eau a une hauteur de 15% glTranslatef( 0.0f, waterLevel, 0.0f ); myWater.Render( ); } } void Viewer::animate() { if (myWater.wantWater()) { //mise a jour des polygons et normales de l'eau myWater.Update( 0.001f ); myWater.CalcNormals( ); } } void Viewer::init() { // Restore previous viewer state. restoreStateFromFile(); // initialiser DrawInit(); // positioner la camera: a l'origine, regarder le centre de la scene (scene entre 0..1,0..1) // camera()->setPosition(0,myQuadtree.GetScaledHeightAtPoint( 0,0)/myQuadtree.sizeHeightMap,0); // camera()->lookAt(0.5,myQuadtree.GetScaledHeightAtPoint( (int)myQuadtree.sizeHeightMap/2, (int)myQuadtree.sizeHeightMap/2)/myQuadtree.sizeHeightMap,0.5); // Large scene dimension so that the sky is not clipped setSceneCenter(Vec(0.5,0.3,0.5)); setSceneRadius(2.0); showEntireScene(); setKeyDescription(Qt::Key_C, "Create a new random terrain"); setKeyDescription(Qt::Key_H, "Load height field from file"); setKeyDescription(Qt::Key_M, "Toggle wireframe mesh display"); setKeyDescription(Qt::Key_O, "Toggles shadows"); setKeyDescription(Qt::Key_W, "Toggles water"); setKeyDescription(Qt::Key_S, "Toggles sky"); setKeyDescription(Qt::Key_T, "Toggles trees"); setKeyDescription(Qt::Key_L, "Change light direction"); setKeyDescription(Qt::Key_X, "Toggles textures"); drawMesh = false; help(); startAnimation(); } bool Viewer::DrawInit( void ) { int numMultiTextures; glShadeModel( GL_SMOOTH ); //cacher les polygons individuels glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClearDepth( 1.0 ); // effacer z-tampon glDepthFunc( GL_LEQUAL ); // tester distance "egale ou plus petite" (eviter "switching") glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); //ameliorer l'affichage glEnable( GL_DEPTH_TEST ); //activer z-Buffer glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); //dessiner les polygones remplis sur les deux cotes glDisable( GL_TEXTURE_2D ); //disable two dimensional texture mapping glDisable( GL_LIGHTING ); //disable lighting glDisable( GL_BLEND ); // charger heightmap // bool res = myQuadtree.LoadHeightMap( "height128.raw", 128 ); // creer carte fractale bool res = myQuadtree.MakeTerrainFault( mapSize, 32, 25, 150, 10 ); //terrain initial plus lisse myQuadtree.SetHeightScale( scaleFactor/4.0f ); myQuadtree.SetSizeScale(scaleFactor); //preparer les textures //lire les textures de base if (!myQuadtree.LoadTile( LOWEST, "Data/lowest.jpg" ) || !myQuadtree.LoadTile( MEDIUM, "Data/medium.jpg" ) || !myQuadtree.LoadTile( HIGH, "Data/high.jpg" ) || !myQuadtree.LoadTile( HIGHEST, "Data/highest.jpg" )) printf("Base Texture load failed\n"); //lire la carte de detail if (!myQuadtree.LoadDetailMap( "Data/detailMap.jpg" )) printf("Detail Texture load failed\n"); //creer la texture complete, la sauvegarder myQuadtree.GenerateTextureMap( 2*mapSize ); //double precision de la carte d'hauteur //creer la carte d'ombrages myQuadtree.CalculateLighting( ); if (CheckExtension( "GL_ARB_multitexture" ) ) { glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &numMultiTextures); if(numMultiTextures > 1) { myQuadtree.DoMultitexturing(true); printf("Multitexturing available!\n"); } else { myQuadtree.DoMultitexturing(false); printf("No Multitexturing available on this card\n"); } } else { myQuadtree.DoMultitexturing(false); printf("No Multitexturing available on this card\n"); } myQuadtree.DoTexturing(true); myQuadtree.DoLighting(true); myQuadtree.SetDetailLevel( 50.0f/(mapSize/3)); myQuadtree.SetMinResolution( 10.0f/(mapSize/3)); myQuadtree.SetLightColor(1.0f,1.0f,1.0f); //initialiser l'eau myWater.Init( 1.0f*scaleFactor, scaleFactor/4.0f ); myWater.LoadReflectionMap( "Data/reflectionMap.jpg" ); myWater.SetColor(QColor(qRgba(64, 74, 168, 230))); //initialiser le ciel mySky.LoadTexture( SKY_FRONT, "Data/skyfront.jpg" ); mySky.LoadTexture( SKY_BACK, "Data/skyback.jpg" ); mySky.LoadTexture( SKY_RIGHT,"Data/skyright.jpg" ); mySky.LoadTexture( SKY_LEFT, "Data/skyleft.jpg" ); mySky.LoadTexture( SKY_TOP, "Data/skytop.jpg" ); mySky.LoadTexture( SKY_BOTTOM, "Data/skybottom.jpg" ); myTree.LoadTexture("Data/palmier.png"); myTree.initTrees(myQuadtree,numTrees,waterLevel*mapSize); return res; } bool Viewer::DrawShutdown() { myQuadtree.UnloadAllTextures( ); //..de base myQuadtree.UnloadTexture( ); //..texture complete bool res = myQuadtree.UnloadHeightMap( ); myQuadtree.Shutdown( ); return res; } //overload c,s,w,r,t void Viewer::keyPressEvent(QKeyEvent *e) { #if QT_VERSION < 0x040000 if (e->state() == Qt::NoButton) #else if (e->modifiers() == Qt::NoModifier) #endif switch (e->key()) { case Qt::Key_C : //recreer le terrain if (!myQuadtree.MakeTerrainFault( mapSize, 32, 0, 255, 3 )) printf("prob creer terrain\n"); myQuadtree.SetHeightScale( scaleFactor/4.0f ); //creer la texture complete, la sauvegarder myQuadtree.GenerateTextureMap( 2*mapSize ); //double precision de la carte d'hauteur myQuadtree.CalculateLighting( ); myTree.initTrees(myQuadtree,numTrees,waterLevel*mapSize); updateGL(); break; case Qt::Key_H : //charger la carte d'hauteur (dans le meme repertoire) if (!myQuadtree.LoadHeightMap( "height128.raw", mapSize )) printf("prob charger carte\n"); myQuadtree.SetHeightScale( scaleFactor/4.0f ); //creer la texture complete, la sauvegarder myQuadtree.GenerateTextureMap( 2*mapSize ); //double precision de la carte d'hauteur myQuadtree.CalculateLighting( ); myTree.initTrees(myQuadtree,numTrees,waterLevel*mapSize); updateGL(); break; case Qt::Key_M : //ne pas dessiner les polygones, mais les lignes seulement drawMesh = !drawMesh; if (drawMesh) glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); else glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); updateGL(); break; case Qt::Key_O: //switch affichage ombres if (myQuadtree.isLighted()) myQuadtree.DoLighting(false); else myQuadtree.DoLighting(true); updateGL(); break; case Qt::Key_W: //switch water myWater.switchWater(); updateGL(); break; case Qt::Key_S: //switch sky mySky.switchSky(); updateGL(); break; case Qt::Key_T: //switch trees myTree.switchTree(); updateGL(); break; case Qt::Key_L: //switch direction de lumiere (en pas de 45°) myQuadtree.StepLightingDirection(); myQuadtree.CalculateLighting( ); updateGL(); break; case Qt::Key_X : //switch affichage textures (detail+base) if (myQuadtree.isTexture()) myQuadtree.DoTexturing(false); else { //creer la texture complete, la sauvegarder myQuadtree.GenerateTextureMap( 2*mapSize ); //double precision de la carte d'hauteur myQuadtree.DoTexturing(true); } updateGL(); break; default: QGLViewer::keyPressEvent(e); //handler de la classe superieure } else QGLViewer::keyPressEvent(e); } //-------------------------------------------------------------- // CODE EXTERNE DE Evan Pipho (evan@codershq.com) , // .. permet de tester les capacites GL hardware de la carte graphique //-------------------------------------------------------------- bool Viewer::CheckExtension( char* szExtensionName ) { unsigned int uiNextExtension; char* szSupExt= ( char* )glGetString( GL_EXTENSIONS );; char* cEndExtensions; //find the end of the extension list cEndExtensions= szSupExt+strlen( szSupExt ); //search through the entire list while( szSupExtT e r r a i n V i e w e r"); text += "The resolution of the terrain is dynamically updated depending on the camera position.
"; text += "You can toggle the display of water (W), trees (T) and sky (S).

"; text += "Press X to switch texturing on and off.
"; text += "Press O to switch shading on and off.
"; text += "Press L to cycle through different light source positions (+45°).
"; text += "Press M to toggle wireframe mesh display.

"; text += "Press C to create a new fractal terrain.
"; text += "Press H to load a terrain from a heightmap-file height128.raw.
"; return text; }