Stuff
[opengl.git] / main.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <iostream>
4 #include <fstream>
5 #include <sstream>
6 #include <array>
7 #include <vector>
8 #ifdef __APPLE__
9 #include <GL/glew.h>
10 #else
11 #include <OpenGL/glew.h>
12 #endif
13 #include <GLUT/glut.h>
14 #include <glm/glm.hpp>
15 #include <glm/ext.hpp>
16 #include <glm/gtc/type_ptr.hpp>
17 #include "model.hpp"
18 #include "teapot.h"
19
20 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
21
22 using namespace std;
23
24 GLuint pyramidVao, lightVao, teapotVao;
25 GLuint gradientProgId, plainProgId, normalProgId, solidProgId, textureProgId;
26 glm::vec3 camPos   = glm::vec3(0.0f, 0.0f,  0.0f);
27 glm::vec3 camFront = glm::vec3(0.0f, 0.0f, 1.0f);
28 glm::vec3 camUp    = glm::vec3(0.0f, 1.0f,  0.0f);
29 float yaw = 1.57, pitch = 0;
30 bool doScale, doRotate, doTranslate;
31 Model *monkeyHead, *chest;
32 glm::vec3 lightPos(0);
33
34 const int WIDTH = 800, HEIGHT = 600;
35 const float ASPECT = (float)WIDTH / (float)HEIGHT;
36
37 void setProjectionAndViewUniforms(GLuint progId) {
38         GLuint projLoc = glGetUniformLocation(progId, "projection");
39         glm::mat4 proj = glm::perspective(glm::radians(45.f), ASPECT, 0.01f, 10000.f);
40         glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
41
42         GLuint viewLoc = glGetUniformLocation(progId, "view");
43         glm::mat4 view = glm::lookAt(camPos, camPos + camFront, camUp);
44         glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
45 }
46
47 void setLightColorAndPos(GLuint progId, glm::vec3 lightPos, glm::vec4 lightColor) {
48         GLuint lightColorLoc = glGetUniformLocation(progId, "lightColor");
49         glUniform4fv(lightColorLoc, 1, glm::value_ptr(lightColor));
50
51         GLuint lightPosLoc = glGetUniformLocation(progId, "vLightPos");
52         glUniform3fv(lightPosLoc, 1, glm::value_ptr(lightPos));
53
54         GLuint viewPosLoc = glGetUniformLocation(progId, "vViewPos");
55         glUniform3fv(viewPosLoc, 1, glm::value_ptr(camPos));
56 }
57
58 void drawLight(float d, glm::vec3 lightPos, glm::vec4 lightColor) {
59         glUseProgram(plainProgId);
60         glBindVertexArray(lightVao);
61         setProjectionAndViewUniforms(plainProgId);
62         glm::mat4 model = glm::translate(glm::mat4(1.f), lightPos);
63         model = glm::scale(model, glm::vec3(0.2));
64         GLuint modelLoc = glGetUniformLocation(plainProgId, "model");
65         glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
66
67         GLuint colorLoc = glGetUniformLocation(plainProgId, "color");
68         glm::vec4 color(lightColor);
69         glUniform4fv(colorLoc, 1, glm::value_ptr(color));
70                 
71         glDrawArrays(GL_TRIANGLES, 0, 36);
72 };
73
74 void drawPyramids(float d, glm::vec3 lightPos, glm::vec4 lightColor) {
75         glUseProgram(gradientProgId);
76         glBindVertexArray(pyramidVao);
77         setProjectionAndViewUniforms(gradientProgId);
78
79         setLightColorAndPos(gradientProgId, lightPos, lightColor);
80
81         GLuint modelId = glGetUniformLocation(gradientProgId, "model");
82
83         for (int i = 0; i < 10; i++) {
84
85                 glm::mat4 model = glm::mat4(1.f);
86
87                 model = glm::translate(model, glm::vec3(sin(i * 30) * 10, 0, i * 2 - 10));
88                 
89                 if (doRotate) {
90                         model = glm::rotate(model, d * glm::radians(30.f), glm::vec3(0.f, 1.f, 0.f));
91                         model = glm::rotate(model, d * glm::radians(20.f), glm::vec3(1.f, 0.f, 0.f));
92                 }
93                 
94                 if (doScale)
95                         model = glm::scale(model, glm::vec3(1.f, 0.7f + 0.7f * (1 + sin(d + (i + 3))), 1.f));
96
97                 if (doTranslate)
98                         model = glm::translate(model, glm::vec3(sin(d + (i + 1)), cos(d + (i + -3)), sin(d + (i + 4))));
99         
100
101                 glUniformMatrix4fv(modelId, 1, GL_FALSE, glm::value_ptr(model));
102                 
103                 glDrawArrays(GL_TRIANGLES, 0, 18);
104         }
105
106 };
107
108 enum TeapotProjection { teapotOrtho, teapotCamera, teapotPerspStatic, teapotPerspAnimated };
109
110 void drawTeapot(TeapotProjection proj, bool rotate, float d, glm::vec3 lightPos, glm::vec4 lightColor) {
111         glUseProgram(normalProgId);
112         
113         GLuint projLoc = glGetUniformLocation(normalProgId, "projection");
114         GLuint viewLoc = glGetUniformLocation(normalProgId, "view");
115         switch (proj) {
116         case teapotCamera:
117                 setProjectionAndViewUniforms(normalProgId);
118                 break;
119         case teapotOrtho:
120                 {
121                         glm::mat4 proj = glm::ortho(-5.f * ASPECT, 5.f * ASPECT, -5.f, 5.f, 0.01f, 1000.f);
122                         glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
123
124                         glm::vec3 camPos(-5, 5, -5), camFront = glm::vec3(0) - camPos;
125                         glm::mat4 view = glm::lookAt(camPos, camPos + camFront, camUp);
126                         glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
127                 }
128                 break;
129         case teapotPerspStatic:
130         case teapotPerspAnimated:
131                 {
132                         float fov = glm::radians(45.f);
133                         if (proj == teapotPerspAnimated)
134                                 fov += glm::radians(sin(d) * 30.f);
135                         glm::mat4 proj = glm::perspective(fov, ASPECT, 0.01f, 10000.f);
136                         glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
137
138                         glm::mat4 view = glm::lookAt(glm::vec3(0, 0, -10), glm::vec3(0), camUp);
139                         glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
140                 }
141                 break;
142         }
143         setLightColorAndPos(normalProgId, lightPos, lightColor);
144         glBindVertexArray(teapotVao);
145         GLuint modelId = glGetUniformLocation(normalProgId, "model");
146         glm::mat4 model(1);
147         model = glm::scale(model, glm::vec3(0.3));
148         if (rotate) model = glm::rotate(model, d, glm::vec3(0, 1, 0));
149         glUniformMatrix4fv(modelId, 1, GL_FALSE, glm::value_ptr(model));
150
151         glDrawArrays(GL_TRIANGLES, 0, teapot_vertex_count);
152 }
153
154 void display() {
155         glClearColor(0.5, 0.5, 0.5, 1);
156         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
157         float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
158
159         /* glm::vec3 lightPos = glm::vec3(sin(d / 10.f) * 10, 0, cos(d / 10.f) * 10); */
160         glm::vec4 lightColor(1, 1, 1, 1);
161
162         drawLight(d, lightPos, lightColor);
163
164         glUseProgram(textureProgId);
165         setProjectionAndViewUniforms(textureProgId);
166         setLightColorAndPos(textureProgId, lightPos, lightColor);
167
168         Model::Node *top = chest->find("top");
169         top->model = glm::translate(glm::mat4(1), glm::vec3(0, 1, -1));
170         top->model = glm::rotate(top->model, sin(d / 2.5f) * 0.5f, glm::vec3(1, 0, 0));
171         top->model = glm::translate(top->model, glm::vec3(0, -1, 1));
172         
173         /* Model::Node *jewels = chest->find("jewels"); */
174         /* jewels->model = glm::scale(glm::mat4(1), glm::vec3((sin(d) + 1.2f) / 2.f)); */
175
176         /* Model::Node *lock = chest->find("lock"); */
177         /* lock->model = glm::translate(glm::mat4(1), glm::vec3(0.22610, 3.36478, -0.75649)); */
178         /* lock->model = glm::rotate(lock->model, (d / 2.5f), glm::vec3(0, 1, 0.4)); */
179         /* lock->model = glm::translate(lock->model, -glm::vec3(0.22610, 3.36478, -0.75649)); */
180
181         /* Model::Node *key = chest->find("key"); */
182         /* key->model = glm::translate(glm::mat4(1), glm::vec3(0, 0, sin(d))); */
183         
184         /* chest->getRoot()->model = glm::translate(glm::mat4(1), lightPos); */
185         chest->draw();
186
187         glutSwapBuffers();
188 }
189
190 void attachShader(GLuint progId, const char* filePath, GLenum type) {
191         GLuint shader = glCreateShader(type);
192
193         if (!shader) {
194                 fprintf(stderr, "error creating shader\n");
195                 exit(1);
196         }
197
198         ifstream file(filePath);
199         stringstream buffer;
200         buffer << file.rdbuf();
201         string str = buffer.str();
202         const char* contents = str.c_str();
203
204         glShaderSource(shader, 1, (const GLchar**)&contents, NULL);
205         glCompileShader(shader);
206         GLint success;
207         glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
208         if (!success) {
209                 GLchar log[1024];
210                 glGetShaderInfoLog(shader, 1024, NULL, log);
211                 fprintf(stderr, "error: %s\n", log);
212                 exit(1);
213         }
214         glAttachShader(progId, shader);
215 }
216
217 GLuint compileShaders(char* vertexShader, char* fragmentShader) {
218         GLuint progId = glCreateProgram();
219
220         attachShader(progId, vertexShader, GL_VERTEX_SHADER);
221         attachShader(progId, fragmentShader, GL_FRAGMENT_SHADER);
222
223         glLinkProgram(progId);
224         GLint success = 0;
225         glGetProgramiv(progId, GL_LINK_STATUS, &success);
226         if (!success) {
227                 GLchar log[1024];
228                 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
229                 fprintf(stderr, "error linking: %s\n", log);
230                 exit(1);
231         }
232
233         return progId;
234 }
235
236 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
237
238 GLuint setupBuffers(glm::vec3* vertices, glm::vec3* normals, GLuint progId) {
239
240         GLfloat colors[] = {
241                 0, 1, 0, 1,
242                 1, 0, 0, 1,
243                 0, 0, 1, 1,
244
245                 0, 1, 0, 1,
246                 1, 0, 0, 1,
247                 0, 0, 1, 1,
248
249                 0, 1, 0, 1,
250                 1, 0, 0, 1,
251                 0, 0, 1, 1,
252
253                 0, 1, 0, 1,
254                 1, 0, 0, 1,
255                 0, 0, 1, 1,
256
257                 0, 1, 0, 1,
258                 1, 0, 0, 1,
259                 0, 0, 1, 1,
260                 
261                 0, 1, 0, 1,
262                 1, 0, 0, 1,
263                 0, 0, 1, 1
264         };
265
266         GLuint numVerts = 18;
267
268         GLuint vbo;
269         glGenBuffers(1, &vbo);
270
271         GLuint vao;
272         glGenVertexArrays(1, &vao);
273
274         GLuint posId = glGetAttribLocation(progId, "vPosition");
275         GLuint colorId = glGetAttribLocation(progId, "vColor");
276         GLuint normalLoc = glGetAttribLocation(progId, "vNormal");
277
278         GLuint vertsLen = numVerts * 3 * sizeof(GLfloat);
279         GLuint colorsLen = numVerts * 4 * sizeof(GLfloat);
280         GLuint normalLen = numVerts * 3 * sizeof(GLfloat);
281
282         glBindBuffer(GL_ARRAY_BUFFER, vbo);
283         glBufferData(GL_ARRAY_BUFFER, vertsLen + colorsLen + normalLen, NULL, GL_STATIC_DRAW);
284
285         glBufferSubData(GL_ARRAY_BUFFER, 0, vertsLen, glm::value_ptr(vertices[0]));
286         glBufferSubData(GL_ARRAY_BUFFER, vertsLen, colorsLen, colors);
287         glBufferSubData(GL_ARRAY_BUFFER, vertsLen + colorsLen, normalLen, glm::value_ptr(normals[0]));
288         
289         glBindVertexArray(vao);
290
291         glEnableVertexAttribArray(posId);
292         glVertexAttribPointer(posId, 3, GL_FLOAT, GL_FALSE, 0, 0);
293
294         glEnableVertexAttribArray(colorId);
295         glVertexAttribPointer(colorId, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(vertsLen));
296
297         glEnableVertexAttribArray(normalLoc);
298         glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(vertsLen + colorsLen));
299
300         return vao;
301 }
302
303 vector<glm::vec3> quadToTriangles(glm::vec3 *quads) {
304         vector<glm::vec3> triangles(6);
305         triangles[0] = quads[0];
306         triangles[1] = quads[1];
307         triangles[2] = quads[2];
308         triangles[3] = quads[2];
309         triangles[4] = quads[3];
310         triangles[5] = quads[0];
311         return triangles;
312 }
313
314 template <typename T>
315 void append(vector<T> &a, vector<T> &b) {
316         a.insert(a.end(), b.begin(), b.end());
317 };
318
319 void setupLightBuffers(GLuint progId) {
320         vector<glm::vec3> vertices;
321         glm::vec3 front[] = {
322                 glm::vec3(1, -1, -1),
323                 glm::vec3(-1, -1, -1),
324                 glm::vec3(-1, 1, -1),
325                 glm::vec3(1, 1, -1)
326         };
327         vector<glm::vec3> frontTriangles = quadToTriangles(front);
328         append(vertices, frontTriangles);
329
330         glm::vec3 back[] = {
331                 glm::vec3(1, 1, 1),
332                 glm::vec3(-1, 1, 1),
333                 glm::vec3(-1, -1, 1),
334                 glm::vec3(1, -1, 1)
335         };
336         vector<glm::vec3> backQuads = quadToTriangles(back);
337         append(vertices, backQuads);
338
339         glm::vec3 top[] = {
340                 glm::vec3(1, 1, -1),
341                 glm::vec3(-1, 1, -1),
342                 glm::vec3(-1, 1, 1),
343                 glm::vec3(1, 1, 1)
344         };
345         vector<glm::vec3> topTriangles = quadToTriangles(top);
346         append(vertices, topTriangles);
347
348         glm::vec3 bottom[] = {
349                 glm::vec3(1, -1, 1),
350                 glm::vec3(-1, -1, 1),
351                 glm::vec3(-1, -1, -1),
352                 glm::vec3(1, -1, -1)
353         };
354         vector<glm::vec3> bottomTriangles = quadToTriangles(bottom);
355         append(vertices, bottomTriangles);
356
357         glm::vec3 left[] = {
358                 glm::vec3(-1, 1, 1),
359                 glm::vec3(-1, 1, -1),
360                 glm::vec3(-1, -1, -1),
361                 glm::vec3(-1, -1, 1)
362         };
363         vector<glm::vec3> leftTriangles = quadToTriangles(left);
364         append(vertices, leftTriangles);
365
366         glm::vec3 right[] = {
367                 glm::vec3(1, 1, -1),
368                 glm::vec3(1, 1, 1),
369                 glm::vec3(1, -1, 1),
370                 glm::vec3(1, -1, -1)
371         };
372         vector<glm::vec3> rightTriangles = quadToTriangles(right);
373         append(vertices, rightTriangles);
374         GLuint verticesSize = 36 * 3 * sizeof(GLfloat);
375
376         glGenVertexArrays(1, &lightVao);
377         GLuint vbo;
378         glBindVertexArray(lightVao);
379         glGenBuffers(1, &vbo);
380         glBindBuffer(GL_ARRAY_BUFFER, vbo);
381         glBufferData(GL_ARRAY_BUFFER, verticesSize, NULL, GL_STATIC_DRAW);
382         glBufferSubData(GL_ARRAY_BUFFER, 0, verticesSize, glm::value_ptr(vertices[0]));
383         GLuint posLoc = glGetAttribLocation(progId, "vPosition");
384         glEnableVertexAttribArray(posLoc);
385         glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
386 }
387
388 void setupTeapotBuffers(GLuint progId) {
389         GLuint vbos[2];
390         glGenBuffers(2, vbos);
391         glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
392         glBufferData(GL_ARRAY_BUFFER, 3 * teapot_vertex_count * sizeof(float), teapot_vertex_points, GL_STATIC_DRAW);
393         glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
394         glBufferData(GL_ARRAY_BUFFER, 3 * teapot_vertex_count * sizeof(float), teapot_normals, GL_STATIC_DRAW);
395
396         glGenVertexArrays(1, &teapotVao);
397         glBindVertexArray(teapotVao);
398
399         GLuint posLoc = glGetAttribLocation(progId, "vPosition");
400         GLuint normalLoc = glGetAttribLocation(progId, "vNormal");
401
402         glEnableVertexAttribArray(posLoc);
403         glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
404         glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
405         
406         glEnableVertexAttribArray(normalLoc);
407         glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
408         glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
409 }
410
411 void validateProgram(GLuint progId) {
412         glValidateProgram(progId);
413         
414         GLint success;
415         glGetProgramiv(progId, GL_VALIDATE_STATUS, &success);
416         if (!success) {
417                 GLchar log[1024];
418                 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
419                 fprintf(stderr, "error: %s\n", log);
420                 exit(1);
421         }
422 }
423
424 void init() {
425         glm::vec3 vertices[18] = {
426                 glm::vec3(0.0f, 1.0f, 0.0f),
427                 glm::vec3(1.0f, -1.0f, -1.0f),
428                 glm::vec3(-1.0f, -1.0f, -1.0f),
429
430                 glm::vec3(0.0f, 1.0f, 0.0f),
431                 glm::vec3(-1.0f, -1.0f, 1.0f),
432                 glm::vec3(1.0f, -1.0f, 1.0f),
433
434                 glm::vec3(0.0f, 1.0f, 0.0f),
435                 glm::vec3(-1.0f, -1.0f, -1.0f),
436                 glm::vec3(-1.0f, -1.0f, 1.0f),
437
438                 glm::vec3(0.0f, 1.0f, 0.0f),
439                 glm::vec3(1.0f, -1.0f, 1.0f),
440                 glm::vec3(1.0f, -1.0f, -1.0f),
441
442                 glm::vec3(1, -1, 1),
443                 glm::vec3(-1, -1, 1),
444                 glm::vec3(-1, -1, -1),
445                 glm::vec3(-1, -1, -1),
446                 glm::vec3(1, -1, -1),
447                 glm::vec3(1, -1, 1)
448         };
449
450         // work out the normals
451         glm::vec3 normals[18];
452         for (int i = 0; i < 6; i++) {
453                 glm::vec3 a = vertices[i * 3];
454                 glm::vec3 b = vertices[i * 3 + 1];
455                 glm::vec3 c = vertices[i * 3 + 2];
456                 glm::vec3 u = glm::normalize(a - c);
457                 glm::vec3 v = glm::normalize(b - c);
458                 glm::vec3 norm = glm::normalize(glm::cross(v, u));
459                 for(int j = 0; j < 3; j++) {
460                         normals[i * 3 + j] = -glm::vec3(norm);
461                 }
462         }
463
464         gradientProgId = compileShaders((char*)"vertex.glsl", (char*)"gradientfrag.glsl");
465         glUseProgram(gradientProgId);
466         pyramidVao = setupBuffers(vertices, normals, gradientProgId);
467         validateProgram(gradientProgId);
468
469         plainProgId = compileShaders((char*)"plainvertex.glsl", (char*)"plainfrag.glsl");
470         glUseProgram(plainProgId);
471         setupLightBuffers(plainProgId);
472         validateProgram(plainProgId);
473
474         normalProgId = compileShaders((char*)"vertex.glsl", (char*)"normalfrag.glsl");
475         glUseProgram(normalProgId);
476         setupTeapotBuffers(normalProgId);
477         validateProgram(normalProgId);
478
479         solidProgId = compileShaders((char*)"vertex.glsl", (char*)"solidfrag.glsl");
480         glUseProgram(solidProgId);
481         validateProgram(solidProgId);
482
483         textureProgId = compileShaders((char*)"texturevertex.glsl", (char*)"texturefrag.glsl");
484         glUseProgram(textureProgId);
485         validateProgram(textureProgId);
486
487         monkeyHead = new Model("monkeyhead_smooth.dae", solidProgId);
488         chest = new Model("models/chest.dae", textureProgId);
489
490         glEnable(GL_DEPTH_TEST); 
491         glEnable(GL_CULL_FACE); 
492 }
493
494 bool* keyStates = new bool[256];
495
496 void keyboard(unsigned char key, int x, int y) {
497         keyStates[key] = true;
498         if (key == 'z')
499                 doScale = !doScale;
500         if (key == 'x')
501                 doRotate = !doRotate;
502         if (key == 'c')
503                 doTranslate = !doTranslate;
504 }
505
506 void keyboardUp(unsigned char key, int x, int y) {
507         keyStates[key] = false;
508 }
509
510 void timer(int _) {
511         float xSpeed = 0.f, ySpeed = 0.f, zSpeed = 0.f;
512         if (keyStates['w'])
513                 zSpeed = 0.1f;
514         if (keyStates['s'])
515                 zSpeed = -0.1f;
516         if (keyStates['a'])
517                 xSpeed = 0.1f;
518         if (keyStates['d'])
519                 xSpeed = -0.1f;
520         if (keyStates['q'])
521                 ySpeed = 0.1f;
522         if (keyStates['e'])
523                 ySpeed = -0.1f;
524
525         if (keyStates['j']) lightPos.z += 0.1f;
526         if (keyStates['k']) lightPos.z -= 0.1f;
527         if (keyStates['h']) lightPos.x -= 0.1f;
528         if (keyStates['l']) lightPos.x += 0.1f;
529         if (keyStates['m']) lightPos.y -= 0.1f;
530         if (keyStates['n']) lightPos.y += 0.1f;
531
532         camPos.x += xSpeed * sin(yaw) + zSpeed * cos(yaw);
533         camPos.y += ySpeed;
534         camPos.z += zSpeed * sin(yaw) - xSpeed * cos(yaw);
535         glutPostRedisplay();
536         glutTimerFunc(16, timer, 0);
537 }
538
539 int prevMouseX, prevMouseY;
540 bool firstMouse = true;
541
542 void motion(int x, int y) {
543         if (firstMouse) {
544                 prevMouseX = x;
545                 prevMouseY = y;
546                 firstMouse = false;
547         }
548         int dx = x - prevMouseX, dy = y - prevMouseY;
549
550         prevMouseX = x;
551         prevMouseY = y;
552
553         const float sensitivity = 0.005f;
554         yaw += dx * sensitivity;
555         pitch -= dy * sensitivity;
556
557         glm::vec3 front;
558         front.x = cos(pitch) * cos(yaw);
559         front.y = sin(pitch);
560         front.z = cos(pitch) * sin(yaw);
561         camFront = glm::normalize(front);
562
563         if (pitch < -1.57079632679 || pitch >= 1.57079632679) {
564                 camUp = glm::vec3(0, -1, 0);
565         } else {
566                 camUp = glm::vec3(0, 1, 0);
567         }
568 }
569
570 void mouse(int button, int state, int x, int y) {
571         if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
572                 firstMouse = true;
573 }
574
575 int main(int argc, char** argv) {
576         glutInit(&argc, argv);
577         glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGB|GLUT_3_2_CORE_PROFILE);
578         glutInitWindowSize(WIDTH, HEIGHT);
579         int win = glutCreateWindow("Hello Triangle");
580         glutDisplayFunc(display);
581
582         glewInit();
583         
584         init();
585
586         glutKeyboardFunc(keyboard);
587         glutKeyboardUpFunc(keyboardUp);
588         glutTimerFunc(16, timer, 0);
589         glutMotionFunc(motion);
590         glutMouseFunc(mouse);
591
592         glutMainLoop();
593
594         return 0;
595 }
596