-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
371 lines (314 loc) · 10.9 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/*
* Name: Susan Yuen
* MacID: yuens2
* Student ID: 001416198
*/
#include <stdio.h>
#include <stdlib.h>
#ifdef __APPLE__
# include <OpenGL/gl.h>
# include <OpenGL/glu.h>
# include <GLUT/glut.h>
#else
# include <GL/gl.h>
# include <GL/glu.h>
# include <GL/freeglut.h>
#endif
#include "Terrain.h"
// windows
int window1;
int window2;
// camera setup
float xAxisRotation = 0; // rotation around x axis
float yAxisRotation = 0; // rotation around y axis
// set up lighting
float lightPos1[] = {-400, 100, -250, 1};
float lightPos2[] = {400, 100, -150, 1};
float diffuseLight1[] = {0, 0.2, 1, 1}; // blue light (light source 1)
float diffuseLight2[] = {1, 0.6, 0, 1}; // amber light (light source 2)
float ambientLight[] = {0, 0, 0, 1};
// used to determine visual modes
int wireFrameMode = 1; // 1 = solid, 2 = both, 3 = wireframe
bool lightingMode = true; // true = show lighting, false = no lighting
bool flatShadingMode = false; // true = turn on flat shading, false = turn off flat shading
bool quadStripMode = true; // true = draws with quads, false = draws with triangles
int heightAlgorithm = 1; // 1 = circle algorithm, 2 = fault algorithm, 3 = particle deposition
Terrain terrain; // The terrain
float scaleFactor = 0.5/(terrain.getSize()/50); // scales terrain to fit screen
int oldSize; // used for changes in terrain size
/* handles user keyboard input */
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'q':
case 27: // 'esc' key
exit (0); // quits program
break;
// toggles wireframe mode
case 'w':
// toggles between the three modes
if (wireFrameMode < 3)
{
wireFrameMode++;
}
else
{
wireFrameMode = 1;
}
// sets the wireframe mode
if (wireFrameMode == 1 || wireFrameMode == 2)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // solid
}
else if (wireFrameMode == 3)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe
}
break;
// toggles lighting mode
case 'l':
lightingMode = !lightingMode; // toggles mode
if (lightingMode)
{
glEnable(GL_LIGHTING); // enables lighting mode
}
else
{
glDisable(GL_LIGHTING); // disables lighting mode
}
break;
// toggles flat shading mode
case 'f':
flatShadingMode = !flatShadingMode; // toggles mode
if (flatShadingMode)
{
glShadeModel(GL_FLAT); // enables flat shading
}
else
{
glShadeModel(GL_SMOOTH); // enables smooth shading
}
break;
// resets the terrain
case 'r':
terrain.reconstructTerrain(heightAlgorithm); // redraws random terrain
glutPostRedisplay(); // shows to main window
glutSetWindow(window2); // shows to second window
break;
// moves light source 1 in +z direction
case 'u':
lightPos1[2]+=2;
break;
// moves light source 1 in -z direction
case 'j':
lightPos1[2]-=2;
break;
// moves light source 1 in +x direction
case 'k':
lightPos1[0]+=2;
break;
// moves light source 1 in -x direction
case 'h':
lightPos1[0]-=2;
break;
// moves light source 2 in +z direction
case 'g':
lightPos2[2]+=2;
break;
// moves light source 2 in -z direction
case 'b':
lightPos2[2]-=2;
break;
// moves light source 2 in +x direction
case 'n':
lightPos2[0]+=2;
break;
// moves light source 2 in -x direction
case 'v':
lightPos2[0]-=2;
break;
// turns on triangle mode
case 't':
quadStripMode = false;
break;
// turns on quad mode
case 'y':
quadStripMode = true;
break;
// decreases size of terrain
case 'o':
oldSize = terrain.getSize();
terrain.decreaseSize(); // decreases terrain size
// only reconstruct terrain if size changed
if (oldSize != terrain.getSize())
{
terrain.reconstructTerrain(heightAlgorithm);
scaleFactor = 0.5/(terrain.getSize()/50); // update scaleFactor for camera
glutPostRedisplay(); // show to main window
glutSetWindow(window2); // show to second window
}
break;
// increases size of terrain
case 'p':
oldSize = terrain.getSize();
terrain.increaseSize(); // increases terrain size
// only reconstruct terrain if size changed
if (oldSize != terrain.getSize())
{
terrain.reconstructTerrain(heightAlgorithm);
scaleFactor = 0.5/(terrain.getSize()/50); // update scaleFactor for camera
glutPostRedisplay(); // show to main window
glutSetWindow(window2); // show to second window
}
break;
// toggle between height algorithms
case 'x':
if (heightAlgorithm < 3)
{
heightAlgorithm++;
}
else
{
heightAlgorithm = 1;
}
// draw terrain with new height algorithm
terrain.reconstructTerrain(heightAlgorithm); // redraws terrain
glutPostRedisplay(); // show to main window
glutSetWindow(window2); // show to second window
break;
}
glutPostRedisplay(); // re-displays
}
/* handles special key input */
void special(int key, int x, int y)
{
/* arrow key presses move the camera */
switch(key)
{
case GLUT_KEY_LEFT:
yAxisRotation--; // rotate y-axis in negative direction
break;
case GLUT_KEY_RIGHT:
yAxisRotation++; // rotate y-axis in positive direction
break;
case GLUT_KEY_UP:
if (xAxisRotation < 45) // prevents terrain from flipping
{
xAxisRotation++; // rotate x-axis in positive direction
}
break;
case GLUT_KEY_DOWN:
if (xAxisRotation > -45) // prevents terrain from flipping
{
xAxisRotation--; // rotate x-axis in negative direction
}
break;
}
glutPostRedisplay();
}
/* sets up OpenGL */
void init(void)
{
// intially clears colour
glClearColor(0, 0, 0, 0);
glColor3f(1, 1, 1);
// enables lighting and colour material
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
// sets matrices
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50, 1, 1, 100);
// enable backface culling
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
}
/* display function - GLUT display callback function */
void display(void)
{
// clears the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// sets light colour and positions
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight2);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT1, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
// set camera position
gluLookAt(scaleFactor*terrain.getSize()/2, 25, -scaleFactor*terrain.getSize()/2,
scaleFactor*terrain.getSize()/2, 0, scaleFactor*terrain.getSize()/2,
0, 1, 0);
// handle camera movement
glPushMatrix();
glScalef(scaleFactor, scaleFactor, scaleFactor);
glTranslatef(terrain.getSize()/2, 0, terrain.getSize()/2);
glRotatef(xAxisRotation, 1, 0, 0);
glRotatef(yAxisRotation, 0, 1, 0);
glTranslatef(-terrain.getSize()/2, 0, -terrain.getSize()/2);
terrain.drawTerrain(wireFrameMode == 2, quadStripMode); // draw terrain
glPopMatrix();
glutSwapBuffers(); // used for double buffering
}
/* display function for second window (2D Representation) */
void display2(void)
{
// clears screen
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0, 0, 0, 0);
terrain.draw2DTerrain(); // draws 2D representation of terrain
glutSwapBuffers(); // used for double buffering
}
/* prints control instructions to console */
void printInstructions()
{
cout << "TERRAIN GENERATOR" << endl;
cout << "~ Created by Susan Yuen ~" << endl << endl;
cout << "* q or ESC = quit the program" << endl;
cout << "* LEFT/RIGHT ARROW = rotates scene about the y axis" << endl;
cout << "* UP/DOWN ARROW = rotates scene about the x axis" << endl;
cout << "* w = toggles between solid view, wireframe, or both" << endl;
cout << "* l = enables/disables lighting" << endl;
cout << "* f = enables/disables flat/gouraud shading" << endl;
cout << "* t = enables triangle mesh" << endl;
cout << "* y = enables quad mesh" << endl;
cout << "* o = decreases terrain size by 50 tiles (minimum 50x50)" << endl;
cout << "* p = increases terrain size by 50 tiles (max 300x300)" << endl;
cout << "* u, j, h, k = moves light source 1 (blue light) along the x-z plane" << endl;
cout << "* g, b, v, n = moves light source 2 (amber light) along the x-z plane" << endl;
cout << "* x = toggle height algorithm (circle algorithm, fault algorithm, particle deposition)" << endl;
cout << "* r = randomizes the terrain" << endl << endl;
cout << "* BONUS FEATURE: 2D Representation of Array (Displayed in second window)" << endl;
cout << "* BONUS FEATURE: Fault Algorithm (toggle to it using x)" << endl;
cout << "* BONUS FEATURE: Particle Deposition (toggle to it using x)" << endl << endl;
}
/* main function - program entry point */
int main(int argc, char** argv)
{
glutInit(&argc, argv); //starts GLUT
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // set display mode
printInstructions();
// set up second window (2D representation of terrain)
glutInitWindowSize(400, 400);
glutInitWindowPosition(1000, 50);
window2 = glutCreateWindow("2D Representation of Terrain"); // second window
glutDisplayFunc(display2);
// set up main window
glutInitWindowSize(800, 800);
glutInitWindowPosition(100, 100);
window1 = glutCreateWindow("yuens2 | 001416198 | Assignment 2"); //creates the window
// register callback functions
glutDisplayFunc(display); // registers "display" as the display callback function
glutKeyboardFunc(keyboard); // registers "keyboard" as the keyboard callback function
glutSpecialFunc(special); // registers "special" as the keyboard callback function
glEnable(GL_DEPTH_TEST); // enable depth test
init(); // calls init to set up OpenGL
glutMainLoop(); // starts the event loop
return(0); // return may not be necessary on all compilers
}