1 /****************************************************************************
2 
3  Copyright (C) 2002-2014 Gilles Debunne. All rights reserved.
4 
5  This file is part of the QGLViewer library version 2.7.2.
6 
7  http://www.libqglviewer.com - contact@libqglviewer.com
8 
9  This file may be used under the terms of the GNU General Public License
10  versions 2.0 or 3.0 as published by the Free Software Foundation and
11  appearing in the LICENSE file included in the packaging of this file.
12  In addition, as a special exception, Gilles Debunne gives you certain
13  additional rights, described in the file GPL_EXCEPTION in this package.
14 
15  libQGLViewer uses dual licensing. Commercial/proprietary software must
16  purchase a libQGLViewer Commercial License.
17 
18  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
19  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 
21 *****************************************************************************/
22 
23 // TP OpenGL: Joerg Liebelt, Serigne Sow
24 #include "viewer.h"
25 
26 #include <math.h>
27 #include <qmessagebox.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 
31 #include "quadtree.h"
32 #include "sky.h"
33 #include "tree.h"
34 #include "water.h"
35 
36 #if QT_VERSION >= 0x040000
37 #include <QKeyEvent>
38 #endif
39 
40 using namespace std;
41 
42 // variables globales
43 SKY mySky;
44 QUADTREE myQuadtree;
45 WATER myWater;
46 TREE myTree;
47 int currentHeightmap = 0;
48 const int scaleFactor = 1;
49 const int mapSize = 128;
50 const float waterLevel = 0.15f;
51 const int numTrees = 100;
52 
draw()53 void Viewer::draw() {
54   myQuadtree.ComputeView();
55   myQuadtree.Init();
56   qglviewer::Vec v = camera()->position();
57   myQuadtree.Update(v.x, v.y, v.z);
58 
59   // render le terrain
60   myQuadtree.Render();
61 
62   if (myTree.wantTree())
63     myTree.Render();
64 
65   if (mySky.wantSky()) {
66     // le ciel
67     mySky.Set(-0.5, -0.5, -0.5, 2.0f);
68     // mySky.Set( v.x,v.y,v.z, 1.0f );
69     mySky.Render();
70   }
71 
72   if (myWater.wantWater()) {
73     // mise a jour des polygons et normales de l'eau
74     myWater.Update(0.001f);
75     myWater.CalcNormals();
76     // render le filet de l'eau a une hauteur de 15%
77     glTranslatef(0.0f, waterLevel, 0.0f);
78     myWater.Render();
79   }
80 }
81 
animate()82 void Viewer::animate() {
83   if (myWater.wantWater()) {
84     // mise a jour des polygons et normales de l'eau
85     myWater.Update(0.001f);
86     myWater.CalcNormals();
87   }
88 }
89 
init()90 void Viewer::init() {
91   // Restore previous viewer state.
92   restoreStateFromFile();
93 
94   // initialiser
95   DrawInit();
96   //  positioner la camera: a l'origine, regarder le centre de la scene (scene
97   //  entre 0..1,0..1)
98   //  camera()->setPosition(0,myQuadtree.GetScaledHeightAtPoint(
99   //  0,0)/myQuadtree.sizeHeightMap,0);
100   //  camera()->lookAt(0.5,myQuadtree.GetScaledHeightAtPoint(
101   //  (int)myQuadtree.sizeHeightMap/2,
102   //  (int)myQuadtree.sizeHeightMap/2)/myQuadtree.sizeHeightMap,0.5);
103 
104   // Large scene dimension so that the sky is not clipped
105   setSceneCenter(Vec(0.5f, 0.3f, 0.5f));
106   setSceneRadius(2.0);
107   showEntireScene();
108 
109   setKeyDescription(Qt::Key_C, "Create a new random terrain");
110   setKeyDescription(Qt::Key_H, "Load height field from file");
111   setKeyDescription(Qt::Key_M, "Toggle wireframe mesh display");
112   setKeyDescription(Qt::Key_O, "Toggles shadows");
113   setKeyDescription(Qt::Key_W, "Toggles water");
114   setKeyDescription(Qt::Key_S, "Toggles sky");
115   setKeyDescription(Qt::Key_T, "Toggles trees");
116   setKeyDescription(Qt::Key_L, "Change light direction");
117   setKeyDescription(Qt::Key_X, "Toggles textures");
118 
119   drawMesh = false;
120 
121   help();
122   startAnimation();
123 }
124 
DrawInit(void)125 bool Viewer::DrawInit(void) {
126   int numMultiTextures;
127   glShadeModel(GL_SMOOTH); // cacher les polygons individuels
128   glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
129   glClearDepth(1.0); // effacer z-tampon
130   glDepthFunc(
131       GL_LEQUAL); // tester distance "egale ou plus petite" (eviter "switching")
132   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // ameliorer l'affichage
133   glEnable(GL_DEPTH_TEST);                           // activer z-Buffer
134   glPolygonMode(GL_FRONT_AND_BACK,
135                 GL_FILL); // dessiner les polygones remplis sur les deux cotes
136 
137   glDisable(GL_TEXTURE_2D); // disable two dimensional texture mapping
138   glDisable(GL_LIGHTING);   // disable lighting
139   glDisable(GL_BLEND);
140 
141   // charger heightmap
142   // bool res = myQuadtree.LoadHeightMap( "height128.raw", 128 );
143 
144   // creer carte fractale
145   bool res = myQuadtree.MakeTerrainFault(mapSize, 32, 25, 150,
146                                          10); // terrain initial plus lisse
147   myQuadtree.SetHeightScale(scaleFactor / 4.0f);
148   myQuadtree.SetSizeScale(scaleFactor);
149 
150   // preparer les textures
151 
152   // lire les textures de base
153   if (!myQuadtree.LoadTile(LOWEST, "Data/lowest.jpg") ||
154       !myQuadtree.LoadTile(MEDIUM, "Data/medium.jpg") ||
155       !myQuadtree.LoadTile(HIGH, "Data/high.jpg") ||
156       !myQuadtree.LoadTile(HIGHEST, "Data/highest.jpg"))
157     printf("Base Texture load failed\n");
158 
159   // lire la carte de detail
160   if (!myQuadtree.LoadDetailMap("Data/detailMap.jpg"))
161     printf("Detail Texture load failed\n");
162 
163   // creer la texture complete, la sauvegarder
164   myQuadtree.GenerateTextureMap(
165       2 * mapSize); // double precision de la carte d'hauteur
166 
167   // creer la carte d'ombrages
168   myQuadtree.CalculateLighting();
169 
170   if (CheckExtension("GL_ARB_multitexture")) {
171     glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &numMultiTextures);
172     if (numMultiTextures > 1) {
173       myQuadtree.DoMultitexturing(true);
174       printf("Multitexturing available!\n");
175     } else {
176       myQuadtree.DoMultitexturing(false);
177       printf("No Multitexturing available on this card\n");
178     }
179   } else {
180     myQuadtree.DoMultitexturing(false);
181     printf("No Multitexturing available on this card\n");
182   }
183   myQuadtree.DoTexturing(true);
184   myQuadtree.DoLighting(true);
185   myQuadtree.SetDetailLevel(50.0f / (mapSize / 3));
186   myQuadtree.SetMinResolution(10.0f / (mapSize / 3));
187   myQuadtree.SetLightColor(1.0f, 1.0f, 1.0f);
188 
189   // initialiser l'eau
190   myWater.Init(1.0f * scaleFactor, scaleFactor / 4.0f);
191   myWater.LoadReflectionMap("Data/reflectionMap.jpg");
192   myWater.SetColor(QColor(qRgba(64, 74, 168, 230)));
193 
194   // initialiser le ciel
195   mySky.LoadTexture(SKY_FRONT, "Data/skyfront.jpg");
196   mySky.LoadTexture(SKY_BACK, "Data/skyback.jpg");
197   mySky.LoadTexture(SKY_RIGHT, "Data/skyright.jpg");
198   mySky.LoadTexture(SKY_LEFT, "Data/skyleft.jpg");
199   mySky.LoadTexture(SKY_TOP, "Data/skytop.jpg");
200   mySky.LoadTexture(SKY_BOTTOM, "Data/skybottom.jpg");
201 
202   myTree.LoadTexture("Data/palmier.png");
203   myTree.initTrees(myQuadtree, numTrees, waterLevel * mapSize);
204 
205   return res;
206 }
207 
DrawShutdown()208 bool Viewer::DrawShutdown() {
209   myQuadtree.UnloadAllTextures(); //..de base
210   myQuadtree.UnloadTexture();     //..texture complete
211   bool res = myQuadtree.UnloadHeightMap();
212   myQuadtree.Shutdown();
213   return res;
214 }
215 
216 // overload c,s,w,r,t
keyPressEvent(QKeyEvent * e)217 void Viewer::keyPressEvent(QKeyEvent *e) {
218 #if QT_VERSION < 0x040000
219   if (e->state() == Qt::NoButton)
220 #else
221   if (e->modifiers() == Qt::NoModifier)
222 #endif
223     switch (e->key()) {
224     case Qt::Key_C: // recreer le terrain
225       if (!myQuadtree.MakeTerrainFault(mapSize, 32, 0, 255, 3))
226         printf("prob creer terrain\n");
227       myQuadtree.SetHeightScale(scaleFactor / 4.0f);
228       // creer la texture complete, la sauvegarder
229       myQuadtree.GenerateTextureMap(
230           2 * mapSize); // double precision de la carte d'hauteur
231       myQuadtree.CalculateLighting();
232       myTree.initTrees(myQuadtree, numTrees, waterLevel * mapSize);
233       update();
234       break;
235     case Qt::Key_H: // charger la carte d'hauteur (dans le meme repertoire)
236       if (!myQuadtree.LoadHeightMap("height128.raw", mapSize))
237         printf("prob charger carte\n");
238       myQuadtree.SetHeightScale(scaleFactor / 4.0f);
239       // creer la texture complete, la sauvegarder
240       myQuadtree.GenerateTextureMap(
241           2 * mapSize); // double precision de la carte d'hauteur
242       myQuadtree.CalculateLighting();
243       myTree.initTrees(myQuadtree, numTrees, waterLevel * mapSize);
244       update();
245       break;
246     case Qt::Key_M: // ne pas dessiner les polygones, mais les lignes seulement
247       drawMesh = !drawMesh;
248       if (drawMesh)
249         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
250       else
251         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
252       update();
253       break;
254     case Qt::Key_O: // switch affichage ombres
255       if (myQuadtree.isLighted())
256         myQuadtree.DoLighting(false);
257       else
258         myQuadtree.DoLighting(true);
259       update();
260       break;
261     case Qt::Key_W: // switch water
262       myWater.switchWater();
263       update();
264       break;
265     case Qt::Key_S: // switch sky
266       mySky.switchSky();
267       update();
268       break;
269     case Qt::Key_T: // switch trees
270       myTree.switchTree();
271       update();
272       break;
273     case Qt::Key_L: // switch direction de lumiere (45 degrees steps)
274       myQuadtree.StepLightingDirection();
275       myQuadtree.CalculateLighting();
276       update();
277       break;
278     case Qt::Key_X: // switch affichage textures (detail+base)
279       if (myQuadtree.isTexture())
280         myQuadtree.DoTexturing(false);
281       else {
282         // creer la texture complete, la sauvegarder
283         myQuadtree.GenerateTextureMap(
284             2 * mapSize); // double precision de la carte d'hauteur
285         myQuadtree.DoTexturing(true);
286       }
287       update();
288       break;
289     default:
290       QGLViewer::keyPressEvent(e); // handler de la classe superieure
291     }
292   else
293     QGLViewer::keyPressEvent(e);
294 }
295 
296 //--------------------------------------------------------------
297 // CODE EXTERNE DE Evan Pipho (evan@codershq.com) ,
298 // .. permet de tester les capacites GL hardware de la carte graphique
299 //--------------------------------------------------------------
CheckExtension(const QString & szExtensionName)300 bool Viewer::CheckExtension(const QString &szExtensionName) {
301   unsigned int uiNextExtension;
302   char *szSupExt = (char *)glGetString(GL_EXTENSIONS);
303   ;
304   char *cEndExtensions;
305 
306   // find the end of the extension list
307   cEndExtensions = szSupExt + strlen(szSupExt);
308 
309   // search through the entire list
310   while (szSupExt < cEndExtensions) {
311     // find the next extension in the list
312     uiNextExtension = strcspn(szSupExt, " ");
313 
314     // check the extension to the one given in the argument list
315     if (szExtensionName == szSupExt) {
316       // the extension is supported
317       // printf( "Your video card supports extension: %s", szExtensionName );
318       return true;
319     }
320 
321     // move to the nexte extension in the list
322     szSupExt += (uiNextExtension + 1);
323   }
324 
325   // the extension is not supported
326   QMessageBox::warning(NULL, "Viewer",
327                        QString("Your video card does not support extension: %1")
328                            .arg(szExtensionName));
329   return false;
330 }
331 // fin code externe
332 // ---------------------------------------------------------------
333 
helpString() const334 QString Viewer::helpString() const {
335   QString text("<h2>T e r r a i n   V i e w e r</h2>");
336   text += "The resolution of the terrain is dynamically updated depending on "
337           "the camera position.<br>";
338   text += "You can toggle the display of water (<b>W</b>), trees (<b>T</b>) "
339           "and sky (<b>S</b>).<br><br>";
340   text += "Press <b>X</b> to switch texturing on and off.<br>";
341   text += "Press <b>O</b> to switch shading on and off.<br>";
342   text += "Press <b>L</b> to cycle through different light source positions "
343           "(+45°).<br>";
344   text += "Press <b>M</b> to toggle wireframe mesh display.<br><br>";
345   text += "Press <b>S</b> to toggle sky display.<br>";
346   text += "Press <b>T</b> to toggle tree display.<br>";
347   text += "Press <b>W</b> to toggle water display.<br><br>";
348   text += "Press <b>C</b> to create a new fractal terrain.<br>";
349   text += "Press <b>H</b> to load a terrain from a heightmap-file "
350           "height128.raw.<br>";
351   return text;
352 }
353