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