source: opengl-game/new-game.cpp@ 20e0020

feature/imgui-sdl points-test
Last change on this file since 20e0020 was 20e0020, checked in by Dmitry Portnoy <dmp1488@…>, 6 years ago

Finish building the player ship model and scale and rotate it correctly.

  • Property mode set to 100644
File size: 47.9 KB
Line 
1#include "logger.h"
2
3#include "stb_image.h"
4
5// I think this was for the OpenGL 4 book font file tutorial
6//#define STB_IMAGE_WRITE_IMPLEMENTATION
7//#include "stb_image_write.h"
8
9#define _USE_MATH_DEFINES
10#define GLM_SWIZZLE
11
12// This is to fix a non-alignment issue when passing vec4 params.
13// Check if it got fixed in a later version of GLM
14#define GLM_FORCE_PURE
15
16#include <glm/mat4x4.hpp>
17#include <glm/gtc/matrix_transform.hpp>
18#include <glm/gtc/type_ptr.hpp>
19
20#include "IMGUI/imgui.h"
21#include "imgui_impl_glfw_gl3.h"
22
23#include <GL/glew.h>
24#include <GLFW/glfw3.h>
25
26#include <cstdio>
27#include <iostream>
28#include <fstream>
29#include <cmath>
30#include <string>
31#include <array>
32#include <vector>
33#include <queue>
34#include <map>
35
36using namespace std;
37using namespace glm;
38
39struct SceneObject {
40 unsigned int id;
41 mat4 model_mat, model_base, model_transform;
42 GLuint shader_program;
43 unsigned int num_points;
44 GLint vertex_vbo_offset;
45 GLint ubo_offset;
46 vector<GLfloat> points;
47 vector<GLfloat> colors;
48 vector<GLfloat> texcoords;
49 vector<GLfloat> normals;
50 vector<GLfloat> selected_colors;
51};
52
53enum State {
54 STATE_MAIN_MENU,
55 STATE_GAME,
56};
57
58enum Event {
59 EVENT_GO_TO_MAIN_MENU,
60 EVENT_GO_TO_GAME,
61 EVENT_QUIT,
62};
63
64#define NUM_KEYS (512)
65#define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444 (maybe make this a const instead)
66
67const int KEY_STATE_UNCHANGED = -1;
68const bool FULLSCREEN = false;
69const bool SHOW_FPS = false;
70const bool DISABLE_VSYNC = false; // disable vsync to see real framerate
71unsigned int MAX_UNIFORMS = 0; // Requires OpenGL constants only available at runtime, so it can't be const
72
73int key_state[NUM_KEYS];
74bool key_pressed[NUM_KEYS];
75
76int width = 640;
77int height = 480;
78
79double fps;
80
81vec3 cam_pos;
82
83mat4 view_mat;
84mat4 proj_mat;
85
86vector<SceneObject> objects;
87queue<Event> events;
88
89SceneObject* clickedObject = NULL;
90SceneObject* selectedObject = NULL;
91
92float NEAR_CLIP = 0.1f;
93float FAR_CLIP = 100.0f;
94
95// Should really have some array or struct of UI-related variables
96bool isRunning = true;
97
98ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
99
100void glfw_error_callback(int error, const char* description);
101
102void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
103void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
104
105bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point);
106bool insideTriangle(vec3 p, array<vec3, 3> triangle_points);
107
108GLuint loadShader(GLenum type, string file);
109GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath);
110unsigned char* loadImage(string file_name, int* x, int* y);
111
112void printVector(string label, vec3 v);
113void print4DVector(string label, vec4 v);
114
115void addObjectToScene(SceneObject& obj);
116void populateBuffers(vector<SceneObject>& objects,
117 GLuint* points_vbo,
118 GLuint* colors_vbo,
119 GLuint* selected_colors_vbo,
120 GLuint* texcoords_vbo,
121 GLuint* normals_vbo,
122 GLuint* ubo,
123 GLuint* model_mat_idx_vbo,
124 map<GLuint, unsigned int>& shaderCounts,
125 map<GLuint, unsigned int>& curShaderBase);
126
127void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo);
128
129void renderMainMenu();
130void renderMainMenuGui();
131
132void renderScene(vector<SceneObject>& objects,
133 GLuint color_sp, GLuint texture_sp,
134 GLuint vao1, GLuint vao2,
135 GLuint points_vbo, GLuint normals_vbo,
136 GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
137 SceneObject* selectedObject,
138 map<GLuint, unsigned int>& shaderCounts,
139 map<GLuint, unsigned int>& curShaderBase);
140void renderSceneGui();
141
142int main(int argc, char* argv[]) {
143 cout << "New OpenGL Game" << endl;
144
145 if (!restart_gl_log()) {}
146 gl_log("starting GLFW\n%s\n", glfwGetVersionString());
147
148 glfwSetErrorCallback(glfw_error_callback);
149 if (!glfwInit()) {
150 fprintf(stderr, "ERROR: could not start GLFW3\n");
151 return 1;
152 }
153
154#ifdef __APPLE__
155 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
156 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
157 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
158 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
159#endif
160
161 glfwWindowHint(GLFW_SAMPLES, 4);
162
163 GLFWwindow* window = NULL;
164 GLFWmonitor* mon = NULL;
165
166 if (FULLSCREEN) {
167 mon = glfwGetPrimaryMonitor();
168 const GLFWvidmode* vmode = glfwGetVideoMode(mon);
169
170 width = vmode->width;
171 height = vmode->height;
172 cout << "Fullscreen resolution " << vmode->width << "x" << vmode->height << endl;
173 }
174 window = glfwCreateWindow(width, height, "New OpenGL Game", mon, NULL);
175
176 if (!window) {
177 fprintf(stderr, "ERROR: could not open window with GLFW3\n");
178 glfwTerminate();
179 return 1;
180 }
181
182 glfwMakeContextCurrent(window);
183 glewExperimental = GL_TRUE;
184 glewInit();
185
186 /*
187 * RENDERING ALGORITHM NOTES:
188 *
189 * Basically, I need to split my objects into groups, so that each group fits into
190 * GL_MAX_UNIFORM_BLOCK_SIZE. I need to have an offset and a size for each group.
191 * Getting the offset is straitforward. The size may as well be GL_MAX_UNIFORM_BLOCK_SIZE
192 * for each group, since it seems that smaller sizes just round up to the nearest GL_MAX_UNIFORM_BLOCK_SIZE
193 *
194 * I'll need to have a loop inside my render loop that calls glBindBufferRange(GL_UNIFORM_BUFFER, ...
195 * for every 1024 objects and then draws all those objects with one glDraw call.
196 *
197 * Since I currently have very few objects, I'll wait to implement this until I have
198 * a reasonable number of objects always using the same shader.
199 */
200
201 GLint UNIFORM_BUFFER_OFFSET_ALIGNMENT, MAX_UNIFORM_BLOCK_SIZE;
202 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &UNIFORM_BUFFER_OFFSET_ALIGNMENT);
203 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &MAX_UNIFORM_BLOCK_SIZE);
204
205 MAX_UNIFORMS = MAX_UNIFORM_BLOCK_SIZE / sizeof(mat4);
206
207 cout << "UNIFORM_BUFFER_OFFSET_ALIGNMENT: " << UNIFORM_BUFFER_OFFSET_ALIGNMENT << endl;
208 cout << "MAX_UNIFORMS: " << MAX_UNIFORMS << endl;
209
210 // Setup Dear ImGui binding
211 IMGUI_CHECKVERSION();
212 ImGui::CreateContext();
213 ImGuiIO& io = ImGui::GetIO(); (void)io;
214 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
215 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
216 ImGui_ImplGlfwGL3_Init(window, true);
217
218 // Setup style
219 ImGui::StyleColorsDark();
220 //ImGui::StyleColorsClassic();
221
222 glfwSetMouseButtonCallback(window, mouse_button_callback);
223 glfwSetKeyCallback(window, key_callback);
224
225 const GLubyte* renderer = glGetString(GL_RENDERER);
226 const GLubyte* version = glGetString(GL_VERSION);
227 printf("Renderer: %s\n", renderer);
228 printf("OpenGL version supported %s\n", version);
229
230 glEnable(GL_DEPTH_TEST);
231 glDepthFunc(GL_LESS);
232
233 glEnable(GL_CULL_FACE);
234 // glCullFace(GL_BACK);
235 // glFrontFace(GL_CW);
236
237 int x, y;
238 unsigned char* texImage = loadImage("test.png", &x, &y);
239 if (texImage) {
240 cout << "Yay, I loaded an image!" << endl;
241 cout << x << endl;
242 cout << y << endl;
243 printf("first 4 bytes are: %i %i %i %i\n", texImage[0], texImage[1], texImage[2], texImage[3]);
244 }
245
246 GLuint tex = 0;
247 glGenTextures(1, &tex);
248 glActiveTexture(GL_TEXTURE0);
249 glBindTexture(GL_TEXTURE_2D, tex);
250 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage);
251
252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
254 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
255 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
256
257 /* RENDERING ALGORITHM
258 *
259 * Create a separate vbo for each of the following things:
260 * - points
261 * - colors
262 * - texture coordinates
263 * - selected colors
264 * - normals
265 * - indices into a ubo that stores a model matrix for each object
266 *
267 * Also, make a model matrix ubo, the entirety of which will be passed to the vertex shader.
268 * The vbo containing the correct index into the ubo (mentioned above) will be used to select
269 * the right model matrix for each point. The index in the vbo will be the saem for all points
270 * of any given object.
271 *
272 * There will be two shader programs for now, one for draing colored objects, and another for
273 * drawing textured ones. The points, normals, and model mat ubo indices will be passed to both
274 * shaders, while the colors vbo will only be passed to the colors shader, and the texcoords vbo
275 * only to the texture shader.
276 *
277 * Right now, the currently selected object is drawn using one color (specified in the selected
278 * colors vbo) regardless of whether it is normally rendering using colors or a texture. The selected
279 * object is rendering by binding the selected colors vbo in place of the colors vbo and using the colors
280 * shader. Then, the selected object is redrawn along with all other objects, but the depth buffer test
281 * prevents the unselected version of the object from appearing on the screen. This lets me render all the
282 * objects that use a particular shader using one glDrawArrays() call.
283 */
284
285 GLuint color_sp = loadShaderProgram("./color.vert", "./color.frag");
286 GLuint texture_sp = loadShaderProgram("./texture.vert", "./texture.frag");
287
288 SceneObject obj;
289 mat4 T_model, R_model;
290
291 // triangle
292 obj = SceneObject();
293 obj.shader_program = color_sp;
294 obj.points = {
295 0.0f, 0.5f, 0.0f,
296 -0.5f, -0.5f, 0.0f,
297 0.5f, -0.5f, 0.0f,
298 0.5f, -0.5f, 0.0f,
299 -0.5f, -0.5f, 0.0f,
300 0.0f, 0.5f, 0.0f,
301 };
302 obj.colors = {
303 1.0f, 0.0f, 0.0f,
304 0.0f, 0.0f, 1.0f,
305 0.0f, 1.0f, 0.0f,
306 0.0f, 1.0f, 0.0f,
307 0.0f, 0.0f, 1.0f,
308 1.0f, 0.0f, 0.0f,
309 };
310 obj.texcoords = {
311 1.0f, 1.0f,
312 0.0f, 1.0f,
313 0.0f, 0.0f,
314 1.0f, 1.0f,
315 0.0f, 0.0f,
316 1.0f, 0.0f
317 };
318 obj.selected_colors = {
319 0.0f, 1.0f, 0.0f,
320 0.0f, 1.0f, 0.0f,
321 0.0f, 1.0f, 0.0f,
322 0.0f, 1.0f, 0.0f,
323 0.0f, 1.0f, 0.0f,
324 0.0f, 1.0f, 0.0f,
325 };
326
327 T_model = translate(mat4(), vec3(0.45f, 0.0f, 0.0f));
328 R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
329 obj.model_base = T_model*R_model;
330
331 addObjectToScene(obj);
332
333 // square
334 obj = SceneObject();
335 obj.shader_program = texture_sp;
336 obj.points = {
337 0.5f, 0.5f, 0.0f,
338 -0.5f, 0.5f, 0.0f,
339 -0.5f, -0.5f, 0.0f,
340 0.5f, 0.5f, 0.0f,
341 -0.5f, -0.5f, 0.0f,
342 0.5f, -0.5f, 0.0f,
343 };
344 obj.colors = {
345 1.0f, 0.0f, 0.0f,
346 0.0f, 0.0f, 1.0f,
347 0.0f, 1.0f, 0.0f,
348 0.0f, 1.0f, 0.0f,
349 0.0f, 0.0f, 1.0f,
350 1.0f, 0.0f, 0.0f,
351 };
352 obj.texcoords = {
353 1.0f, 1.0f,
354 0.0f, 1.0f,
355 0.0f, 0.0f,
356 1.0f, 1.0f,
357 0.0f, 0.0f,
358 1.0f, 0.0f
359 };
360 obj.selected_colors = {
361 0.0f, 0.6f, 0.9f,
362 0.0f, 0.6f, 0.9f,
363 0.0f, 0.6f, 0.9f,
364 0.0f, 0.6f, 0.9f,
365 0.0f, 0.6f, 0.9f,
366 0.0f, 0.6f, 0.9f,
367 };
368
369 T_model = translate(mat4(), vec3(-0.5f, 0.0f, -1.00f));
370 R_model = rotate(mat4(), 0.5f, vec3(0.0f, 1.0f, 0.0f));
371 obj.model_base = T_model*R_model;
372
373 addObjectToScene(obj);
374
375 // player ship
376 obj = SceneObject();
377 obj.shader_program = color_sp;
378 obj.points = {
379 //back
380 -0.5f, 0.3f, 0.0f,
381 -0.5f, 0.0f, 0.0f,
382 0.5f, 0.0f, 0.0f,
383 -0.5f, 0.3f, 0.0f,
384 0.5f, 0.0f, 0.0f,
385 0.5f, 0.3f, 0.0f,
386
387 // left back
388 -0.5f, 0.3f, -2.0f,
389 -0.5f, 0.0f, -2.0f,
390 -0.5f, 0.0f, 0.0f,
391 -0.5f, 0.3f, -2.0f,
392 -0.5f, 0.0f, 0.0f,
393 -0.5f, 0.3f, 0.0f,
394
395 // right back
396 0.5f, 0.3f, 0.0f,
397 0.5f, 0.0f, 0.0f,
398 0.5f, 0.0f, -2.0f,
399 0.5f, 0.3f, 0.0f,
400 0.5f, 0.0f, -2.0f,
401 0.5f, 0.3f, -2.0f,
402
403 // left mid
404 -0.25f, 0.3f, -3.0f,
405 -0.25f, 0.0f, -3.0f,
406 -0.5f, 0.0f, -2.0f,
407 -0.25f, 0.3f, -3.0f,
408 -0.5f, 0.0f, -2.0f,
409 -0.5f, 0.3f, -2.0f,
410
411 // right mid
412 0.5f, 0.3f, -2.0f,
413 0.5f, 0.0f, -2.0f,
414 0.25f, 0.0f, -3.0f,
415 0.5f, 0.3f, -2.0f,
416 0.25f, 0.0f, -3.0f,
417 0.25f, 0.3f, -3.0f,
418
419 // left front
420 0.0f, 0.0f, -3.5f,
421 -0.25f, 0.0f, -3.0f,
422 -0.25f, 0.3f, -3.0f,
423
424 // right front
425 0.25f, 0.3f, -3.0f,
426 0.25f, 0.0f, -3.0f,
427 0.0f, 0.0f, -3.5f,
428
429 // top back
430 -0.5f, 0.3f, -2.0f,
431 -0.5f, 0.3f, 0.0f,
432 0.5f, 0.3f, 0.0f,
433 -0.5f, 0.3f, -2.0f,
434 0.5f, 0.3f, 0.0f,
435 0.5f, 0.3f, -2.0f,
436
437 // bottom back
438 -0.5f, 0.0f, 0.0f,
439 -0.5f, 0.0f, -2.0f,
440 0.5f, 0.0f, 0.0f,
441 0.5f, 0.0f, 0.0f,
442 -0.5f, 0.0f, -2.0f,
443 0.5f, 0.0f, -2.0f,
444
445 // top mid
446 -0.25f, 0.3f, -3.0f,
447 -0.5f, 0.3f, -2.0f,
448 0.5f, 0.3f, -2.0f,
449 -0.25f, 0.3f, -3.0f,
450 0.5f, 0.3f, -2.0f,
451 0.25f, 0.3f, -3.0f,
452
453 // bottom mid
454 -0.5f, 0.0f, -2.0f,
455 -0.25f, 0.0f, -3.0f,
456 0.5f, 0.0f, -2.0f,
457 0.5f, 0.0f, -2.0f,
458 -0.25f, 0.0f, -3.0f,
459 0.25f, 0.0f, -3.0f,
460
461 // top front
462 -0.25f, 0.3f, -3.0f,
463 0.25f, 0.3f, -3.0f,
464 0.0f, 0.0f, -3.5f,
465
466 // bottom front
467 0.25f, 0.0f, -3.0f,
468 -0.25f, 0.0f, -3.0f,
469 0.0f, 0.0f, -3.5f,
470
471 // left wing start back
472 -1.5f, 0.3f, 0.0f,
473 -1.5f, 0.0f, 0.0f,
474 -0.5f, 0.0f, 0.0f,
475 -1.5f, 0.3f, 0.0f,
476 -0.5f, 0.0f, 0.0f,
477 -0.5f, 0.3f, 0.0f,
478
479 // left wing start top
480 -0.5f, 0.3f, -0.3f,
481 -1.3f, 0.3f, -0.3f,
482 -1.5f, 0.3f, 0.0f,
483 -0.5f, 0.3f, -0.3f,
484 -1.5f, 0.3f, 0.0f,
485 -0.5f, 0.3f, 0.0f,
486
487 // left wing start front
488 -0.5f, 0.3f, -0.3f,
489 -0.5f, 0.0f, -0.3f,
490 -1.3f, 0.0f, -0.3f,
491 -0.5f, 0.3f, -0.3f,
492 -1.3f, 0.0f, -0.3f,
493 -1.3f, 0.3f, -0.3f,
494
495 // left wing start bottom
496 -0.5f, 0.0f, 0.0f,
497 -1.5f, 0.0f, 0.0f,
498 -1.3f, 0.0f, -0.3f,
499 -0.5f, 0.0f, 0.0f,
500 -1.3f, 0.0f, -0.3f,
501 -0.5f, 0.0f, -0.3f,
502
503 // left wing end outside
504 -1.5f, 0.3f, 0.0f,
505 -2.2f, 0.15f, -0.8f,
506 -1.5f, 0.0f, 0.0f,
507
508 // left wing end top
509 -1.3f, 0.3f, -0.3f,
510 -2.2f, 0.15f, -0.8f,
511 -1.5f, 0.3f, 0.0f,
512
513 // left wing end front
514 -1.3f, 0.0f, -0.3f,
515 -2.2f, 0.15f, -0.8f,
516 -1.3f, 0.3f, -0.3f,
517
518 // left wing end bottom
519 -1.5f, 0.0f, 0.0f,
520 -2.2f, 0.15f, -0.8f,
521 -1.3f, 0.0f, -0.3f,
522
523 // right wing start back
524 1.5f, 0.0f, 0.0f,
525 1.5f, 0.3f, 0.0f,
526 0.5f, 0.0f, 0.0f,
527 0.5f, 0.0f, 0.0f,
528 1.5f, 0.3f, 0.0f,
529 0.5f, 0.3f, 0.0f,
530
531 // right wing start top
532 1.3f, 0.3f, -0.3f,
533 0.5f, 0.3f, -0.3f,
534 1.5f, 0.3f, 0.0f,
535 1.5f, 0.3f, 0.0f,
536 0.5f, 0.3f, -0.3f,
537 0.5f, 0.3f, 0.0f,
538
539 // right wing start front
540 0.5f, 0.0f, -0.3f,
541 0.5f, 0.3f, -0.3f,
542 1.3f, 0.0f, -0.3f,
543 1.3f, 0.0f, -0.3f,
544 0.5f, 0.3f, -0.3f,
545 1.3f, 0.3f, -0.3f,
546
547 // right wing start bottom
548 1.5f, 0.0f, 0.0f,
549 0.5f, 0.0f, 0.0f,
550 1.3f, 0.0f, -0.3f,
551 1.3f, 0.0f, -0.3f,
552 0.5f, 0.0f, 0.0f,
553 0.5f, 0.0f, -0.3f,
554
555 // right wing end outside
556 2.2f, 0.15f, -0.8f,
557 1.5f, 0.3f, 0.0f,
558 1.5f, 0.0f, 0.0f,
559
560 // right wing end top
561 2.2f, 0.15f, -0.8f,
562 1.3f, 0.3f, -0.3f,
563 1.5f, 0.3f, 0.0f,
564
565 // right wing end front
566 2.2f, 0.15f, -0.8f,
567 1.3f, 0.0f, -0.3f,
568 1.3f, 0.3f, -0.3f,
569
570 // right wing end bottom
571 2.2f, 0.15f, -0.8f,
572 1.5f, 0.0f, 0.0f,
573 1.3f, 0.0f, -0.3f,
574 };
575 obj.colors = {
576 0.0f, 0.0f, 0.3f,
577 0.0f, 0.0f, 0.3f,
578 0.0f, 0.0f, 0.3f,
579 0.0f, 0.0f, 0.3f,
580 0.0f, 0.0f, 0.3f,
581 0.0f, 0.0f, 0.3f,
582
583 0.0f, 0.0f, 0.3f,
584 0.0f, 0.0f, 0.3f,
585 0.0f, 0.0f, 0.3f,
586 0.0f, 0.0f, 0.3f,
587 0.0f, 0.0f, 0.3f,
588 0.0f, 0.0f, 0.3f,
589
590 0.0f, 0.0f, 0.3f,
591 0.0f, 0.0f, 0.3f,
592 0.0f, 0.0f, 0.3f,
593 0.0f, 0.0f, 0.3f,
594 0.0f, 0.0f, 0.3f,
595 0.0f, 0.0f, 0.3f,
596
597 0.0f, 0.0f, 0.3f,
598 0.0f, 0.0f, 0.3f,
599 0.0f, 0.0f, 0.3f,
600 0.0f, 0.0f, 0.3f,
601 0.0f, 0.0f, 0.3f,
602 0.0f, 0.0f, 0.3f,
603
604 0.0f, 0.0f, 0.3f,
605 0.0f, 0.0f, 0.3f,
606 0.0f, 0.0f, 0.3f,
607 0.0f, 0.0f, 0.3f,
608 0.0f, 0.0f, 0.3f,
609 0.0f, 0.0f, 0.3f,
610
611 0.0f, 0.0f, 0.3f,
612 0.0f, 0.0f, 0.3f,
613 0.0f, 0.0f, 0.3f,
614
615 0.0f, 0.0f, 0.3f,
616 0.0f, 0.0f, 0.3f,
617 0.0f, 0.0f, 0.3f,
618
619 0.0f, 0.0f, 0.3f,
620 0.0f, 0.0f, 0.3f,
621 0.0f, 0.0f, 0.3f,
622 0.0f, 0.0f, 0.3f,
623 0.0f, 0.0f, 0.3f,
624 0.0f, 0.0f, 0.3f,
625
626 0.0f, 0.0f, 0.3f,
627 0.0f, 0.0f, 0.3f,
628 0.0f, 0.0f, 0.3f,
629 0.0f, 0.0f, 0.3f,
630 0.0f, 0.0f, 0.3f,
631 0.0f, 0.0f, 0.3f,
632
633 0.0f, 0.0f, 0.3f,
634 0.0f, 0.0f, 0.3f,
635 0.0f, 0.0f, 0.3f,
636 0.0f, 0.0f, 0.3f,
637 0.0f, 0.0f, 0.3f,
638 0.0f, 0.0f, 0.3f,
639
640 0.0f, 0.0f, 0.3f,
641 0.0f, 0.0f, 0.3f,
642 0.0f, 0.0f, 0.3f,
643 0.0f, 0.0f, 0.3f,
644 0.0f, 0.0f, 0.3f,
645 0.0f, 0.0f, 0.3f,
646
647 0.0f, 0.0f, 0.3f,
648 0.0f, 0.0f, 0.3f,
649 0.0f, 0.0f, 0.3f,
650
651 0.0f, 0.0f, 0.3f,
652 0.0f, 0.0f, 0.3f,
653 0.0f, 0.0f, 0.3f,
654
655 0.0f, 0.0f, 0.3f,
656 0.0f, 0.0f, 0.3f,
657 0.0f, 0.0f, 0.3f,
658 0.0f, 0.0f, 0.3f,
659 0.0f, 0.0f, 0.3f,
660 0.0f, 0.0f, 0.3f,
661
662 0.0f, 0.0f, 0.3f,
663 0.0f, 0.0f, 0.3f,
664 0.0f, 0.0f, 0.3f,
665 0.0f, 0.0f, 0.3f,
666 0.0f, 0.0f, 0.3f,
667 0.0f, 0.0f, 0.3f,
668
669 0.0f, 0.0f, 0.3f,
670 0.0f, 0.0f, 0.3f,
671 0.0f, 0.0f, 0.3f,
672 0.0f, 0.0f, 0.3f,
673 0.0f, 0.0f, 0.3f,
674 0.0f, 0.0f, 0.3f,
675
676 0.0f, 0.0f, 0.3f,
677 0.0f, 0.0f, 0.3f,
678 0.0f, 0.0f, 0.3f,
679 0.0f, 0.0f, 0.3f,
680 0.0f, 0.0f, 0.3f,
681 0.0f, 0.0f, 0.3f,
682
683 0.0f, 0.0f, 0.3f,
684 0.0f, 0.0f, 0.3f,
685 0.0f, 0.0f, 0.3f,
686
687 0.0f, 0.0f, 0.3f,
688 0.0f, 0.0f, 0.3f,
689 0.0f, 0.0f, 0.3f,
690
691 0.0f, 0.0f, 0.3f,
692 0.0f, 0.0f, 0.3f,
693 0.0f, 0.0f, 0.3f,
694
695 0.0f, 0.0f, 0.3f,
696 0.0f, 0.0f, 0.3f,
697 0.0f, 0.0f, 0.3f,
698
699 0.0f, 0.0f, 0.3f,
700 0.0f, 0.0f, 0.3f,
701 0.0f, 0.0f, 0.3f,
702 0.0f, 0.0f, 0.3f,
703 0.0f, 0.0f, 0.3f,
704 0.0f, 0.0f, 0.3f,
705
706 0.0f, 0.0f, 0.3f,
707 0.0f, 0.0f, 0.3f,
708 0.0f, 0.0f, 0.3f,
709 0.0f, 0.0f, 0.3f,
710 0.0f, 0.0f, 0.3f,
711 0.0f, 0.0f, 0.3f,
712
713 0.0f, 0.0f, 0.3f,
714 0.0f, 0.0f, 0.3f,
715 0.0f, 0.0f, 0.3f,
716 0.0f, 0.0f, 0.3f,
717 0.0f, 0.0f, 0.3f,
718 0.0f, 0.0f, 0.3f,
719
720 0.0f, 0.0f, 0.3f,
721 0.0f, 0.0f, 0.3f,
722 0.0f, 0.0f, 0.3f,
723 0.0f, 0.0f, 0.3f,
724 0.0f, 0.0f, 0.3f,
725 0.0f, 0.0f, 0.3f,
726
727 0.0f, 0.0f, 0.3f,
728 0.0f, 0.0f, 0.3f,
729 0.0f, 0.0f, 0.3f,
730
731 0.0f, 0.0f, 0.3f,
732 0.0f, 0.0f, 0.3f,
733 0.0f, 0.0f, 0.3f,
734
735 0.0f, 0.0f, 0.3f,
736 0.0f, 0.0f, 0.3f,
737 0.0f, 0.0f, 0.3f,
738
739 0.0f, 0.0f, 0.3f,
740 0.0f, 0.0f, 0.3f,
741 0.0f, 0.0f, 0.3f,
742 };
743 obj.texcoords = {
744 1.0f, 1.0f,
745 0.0f, 1.0f,
746 0.0f, 0.0f,
747 1.0f, 1.0f,
748 0.0f, 0.0f,
749 1.0f, 0.0f,
750
751 1.0f, 1.0f,
752 0.0f, 1.0f,
753 0.0f, 0.0f,
754 1.0f, 1.0f,
755 0.0f, 0.0f,
756 1.0f, 0.0f,
757
758 1.0f, 1.0f,
759 0.0f, 1.0f,
760 0.0f, 0.0f,
761 1.0f, 1.0f,
762 0.0f, 0.0f,
763 1.0f, 0.0f,
764
765 1.0f, 1.0f,
766 0.0f, 1.0f,
767 0.0f, 0.0f,
768 1.0f, 1.0f,
769 0.0f, 0.0f,
770 1.0f, 0.0f,
771
772 1.0f, 1.0f,
773 0.0f, 1.0f,
774 0.0f, 0.0f,
775 1.0f, 1.0f,
776 0.0f, 0.0f,
777 1.0f, 0.0f,
778
779 1.0f, 1.0f,
780 0.0f, 1.0f,
781 0.0f, 0.0f,
782
783 1.0f, 1.0f,
784 0.0f, 1.0f,
785 0.0f, 0.0f,
786
787 1.0f, 1.0f,
788 0.0f, 1.0f,
789 0.0f, 0.0f,
790 1.0f, 1.0f,
791 0.0f, 0.0f,
792 1.0f, 0.0f,
793
794 1.0f, 1.0f,
795 0.0f, 1.0f,
796 0.0f, 0.0f,
797 1.0f, 1.0f,
798 0.0f, 0.0f,
799 1.0f, 0.0f,
800
801 1.0f, 1.0f,
802 0.0f, 1.0f,
803 0.0f, 0.0f,
804 1.0f, 1.0f,
805 0.0f, 0.0f,
806 1.0f, 0.0f,
807
808 1.0f, 1.0f,
809 0.0f, 1.0f,
810 0.0f, 0.0f,
811 1.0f, 1.0f,
812 0.0f, 0.0f,
813 1.0f, 0.0f,
814
815 1.0f, 1.0f,
816 0.0f, 1.0f,
817 0.0f, 0.0f,
818
819 1.0f, 1.0f,
820 0.0f, 1.0f,
821 0.0f, 0.0f,
822
823 1.0f, 1.0f,
824 0.0f, 1.0f,
825 0.0f, 0.0f,
826 1.0f, 1.0f,
827 0.0f, 0.0f,
828 1.0f, 0.0f,
829
830 1.0f, 1.0f,
831 0.0f, 1.0f,
832 0.0f, 0.0f,
833 1.0f, 1.0f,
834 0.0f, 0.0f,
835 1.0f, 0.0f,
836
837 1.0f, 1.0f,
838 0.0f, 1.0f,
839 0.0f, 0.0f,
840 1.0f, 1.0f,
841 0.0f, 0.0f,
842 1.0f, 0.0f,
843
844 1.0f, 1.0f,
845 0.0f, 1.0f,
846 0.0f, 0.0f,
847 1.0f, 1.0f,
848 0.0f, 0.0f,
849 1.0f, 0.0f,
850
851 1.0f, 1.0f,
852 0.0f, 1.0f,
853 0.0f, 0.0f,
854
855 1.0f, 1.0f,
856 0.0f, 1.0f,
857 0.0f, 0.0f,
858
859 1.0f, 1.0f,
860 0.0f, 1.0f,
861 0.0f, 0.0f,
862
863 1.0f, 1.0f,
864 0.0f, 1.0f,
865 0.0f, 0.0f,
866
867 1.0f, 1.0f,
868 0.0f, 1.0f,
869 0.0f, 0.0f,
870 1.0f, 1.0f,
871 0.0f, 0.0f,
872 1.0f, 0.0f,
873
874 1.0f, 1.0f,
875 0.0f, 1.0f,
876 0.0f, 0.0f,
877 1.0f, 1.0f,
878 0.0f, 0.0f,
879 1.0f, 0.0f,
880
881 1.0f, 1.0f,
882 0.0f, 1.0f,
883 0.0f, 0.0f,
884 1.0f, 1.0f,
885 0.0f, 0.0f,
886 1.0f, 0.0f,
887
888 1.0f, 1.0f,
889 0.0f, 1.0f,
890 0.0f, 0.0f,
891 1.0f, 1.0f,
892 0.0f, 0.0f,
893 1.0f, 0.0f,
894
895 1.0f, 1.0f,
896 0.0f, 1.0f,
897 0.0f, 0.0f,
898
899 1.0f, 1.0f,
900 0.0f, 1.0f,
901 0.0f, 0.0f,
902
903 1.0f, 1.0f,
904 0.0f, 1.0f,
905 0.0f, 0.0f,
906
907 1.0f, 1.0f,
908 0.0f, 1.0f,
909 0.0f, 0.0f,
910 };
911 obj.selected_colors = {
912 0.0f, 1.0f, 0.0f,
913 0.0f, 1.0f, 0.0f,
914 0.0f, 1.0f, 0.0f,
915 0.0f, 1.0f, 0.0f,
916 0.0f, 1.0f, 0.0f,
917 0.0f, 1.0f, 0.0f,
918 };
919
920 T_model = translate(mat4(), vec3(0.0f, -0.9f, 0.0f));
921 R_model = rotate(mat4(), 0.6f, vec3(1.0f, 0.0f, 0.0f));
922 obj.model_base = T_model * R_model * scale(mat4(), vec3(0.3f, 0.3f, 0.3f));;
923
924 addObjectToScene(obj);
925
926 vector<SceneObject>::iterator obj_it;
927 GLsizeiptr offset;
928
929 GLuint points_vbo, colors_vbo, selected_colors_vbo, texcoords_vbo,
930 normals_vbo, ubo, model_mat_idx_vbo;
931
932 map<GLuint, unsigned int> shaderCounts, curShaderBase;
933
934 populateBuffers(objects,
935 &points_vbo,
936 &colors_vbo,
937 &selected_colors_vbo,
938 &texcoords_vbo,
939 &normals_vbo,
940 &ubo,
941 &model_mat_idx_vbo,
942 shaderCounts,
943 curShaderBase);
944
945 GLuint vao = 0;
946 glGenVertexArrays(1, &vao);
947 glBindVertexArray(vao);
948
949 glEnableVertexAttribArray(0);
950 glEnableVertexAttribArray(1);
951 glEnableVertexAttribArray(2);
952 glEnableVertexAttribArray(3);
953
954 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
955 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
956
957 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
958 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
959
960 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
961 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
962
963 GLuint vao2 = 0;
964 glGenVertexArrays(1, &vao2);
965 glBindVertexArray(vao2);
966
967 glEnableVertexAttribArray(0);
968 glEnableVertexAttribArray(1);
969 glEnableVertexAttribArray(2);
970 glEnableVertexAttribArray(3);
971
972 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
973 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
974
975 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
976 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
977
978 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
979 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
980
981 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
982 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
983
984 float cam_speed = 1.0f;
985 float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
986 float cam_pitch_speed = 60.0f*ONE_DEG_IN_RAD;
987
988 // glm::lookAt can create the view matrix
989 // glm::perspective can create the projection matrix
990
991 cam_pos = vec3(0.0f, 0.0f, 2.0f);
992 //cam_pos = vec3(-2.1f, -1.5f, -1.5f); // Good position for checking ship faces
993 float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
994 float cam_pitch = 0.0f * 2.0f * 3.14159f / 360.0f;
995
996 mat4 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
997 mat4 R = mat4();
998 view_mat = R*T;
999
1000 float fov = 67.0f * ONE_DEG_IN_RAD;
1001 float aspect = (float)width / (float)height;
1002
1003 float range = tan(fov * 0.5f) * NEAR_CLIP;
1004 float Sx = NEAR_CLIP / (range * aspect);
1005 float Sy = NEAR_CLIP / range;
1006 float Sz = -(FAR_CLIP + NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
1007 float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
1008
1009 float proj_arr[] = {
1010 Sx, 0.0f, 0.0f, 0.0f,
1011 0.0f, Sy, 0.0f, 0.0f,
1012 0.0f, 0.0f, Sz, -1.0f,
1013 0.0f, 0.0f, Pz, 0.0f,
1014 };
1015 proj_mat = make_mat4(proj_arr);
1016
1017 GLuint ub_binding_point = 0;
1018
1019 GLuint view_test_loc = glGetUniformLocation(color_sp, "view");
1020 GLuint proj_test_loc = glGetUniformLocation(color_sp, "proj");
1021 GLuint color_sp_ub_index = glGetUniformBlockIndex(color_sp, "models");
1022
1023 GLuint view_mat_loc = glGetUniformLocation(texture_sp, "view");
1024 GLuint proj_mat_loc = glGetUniformLocation(texture_sp, "proj");
1025 GLuint texture_sp_ub_index = glGetUniformBlockIndex(texture_sp, "models");
1026
1027 glUseProgram(color_sp);
1028 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
1029 glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
1030
1031 glUniformBlockBinding(color_sp, color_sp_ub_index, ub_binding_point);
1032 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
1033
1034 glUseProgram(texture_sp);
1035 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
1036 glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
1037
1038 glUniformBlockBinding(texture_sp, texture_sp_ub_index, ub_binding_point);
1039 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
1040
1041 bool cam_moved = false;
1042
1043 int frame_count = 0;
1044 double elapsed_seconds_fps = 0.0f;
1045 double previous_seconds = glfwGetTime();
1046
1047 // This draws wireframes. Useful for seeing separate faces and occluded objects.
1048 //glPolygonMode(GL_FRONT, GL_LINE);
1049
1050 if (DISABLE_VSYNC && SHOW_FPS) {
1051 glfwSwapInterval(0);
1052 }
1053
1054 State curState = STATE_MAIN_MENU;
1055
1056 while (!glfwWindowShouldClose(window) && isRunning) {
1057 double current_seconds = glfwGetTime();
1058 double elapsed_seconds = current_seconds - previous_seconds;
1059 previous_seconds = current_seconds;
1060
1061 if (SHOW_FPS) {
1062 elapsed_seconds_fps += elapsed_seconds;
1063 if (elapsed_seconds_fps > 0.25f) {
1064 fps = (double)frame_count / elapsed_seconds_fps;
1065 cout << "FPS: " << fps << endl;
1066
1067 frame_count = 0;
1068 elapsed_seconds_fps = 0.0f;
1069 }
1070
1071 frame_count++;
1072 }
1073
1074 // Handle events
1075
1076 clickedObject = NULL;
1077
1078 // reset the all key states to KEY_STATE_UNCHANGED (something the GLFW key callback can never return)
1079 // so that GLFW_PRESS and GLFW_RELEASE are only detected once
1080 // TODO: Change this if we ever need to act on GLFW_REPEAT (which is when a key is held down continuously)
1081 fill(key_state, key_state + NUM_KEYS, KEY_STATE_UNCHANGED);
1082
1083 glfwPollEvents();
1084
1085 while (!events.empty()) {
1086 switch (events.front()) {
1087 case EVENT_GO_TO_MAIN_MENU:
1088 curState = STATE_MAIN_MENU;
1089 break;
1090 case EVENT_GO_TO_GAME:
1091 curState = STATE_GAME;
1092 break;
1093 case EVENT_QUIT:
1094 isRunning = false;
1095 break;
1096 }
1097 events.pop();
1098 }
1099
1100 if (curState == STATE_GAME) {
1101 if (clickedObject == &objects[0]) {
1102 selectedObject = &objects[0];
1103 }
1104 if (clickedObject == &objects[1]) {
1105 selectedObject = &objects[1];
1106 }
1107
1108 /*
1109 if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
1110 transformObject(objects[1], translate(mat4(), vec3(0.3f, 0.0f, 0.0f)), ubo);
1111 }
1112 if (key_pressed[GLFW_KEY_RIGHT]) {
1113 transformObject(objects[2], translate(mat4(), vec3(0.01f, 0.0f, 0.0f)), ubo);
1114 }
1115 if (key_pressed[GLFW_KEY_LEFT]) {
1116 transformObject(objects[2], translate(mat4(), vec3(-0.01f, 0.0f, 0.0f)), ubo);
1117 }
1118 */
1119 }
1120
1121 // Render scene
1122
1123 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1124
1125 switch (curState) {
1126 case STATE_MAIN_MENU:
1127 renderMainMenu();
1128 renderMainMenuGui();
1129 break;
1130 case STATE_GAME:
1131 renderScene(objects,
1132 color_sp, texture_sp,
1133 vao, vao2,
1134 points_vbo, normals_vbo,
1135 colors_vbo, texcoords_vbo, selected_colors_vbo,
1136 selectedObject,
1137 shaderCounts, curShaderBase);
1138 renderSceneGui();
1139 break;
1140 }
1141
1142 glfwSwapBuffers(window);
1143
1144 if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
1145 glfwSetWindowShouldClose(window, 1);
1146 }
1147
1148 float dist = cam_speed * elapsed_seconds;
1149 if (glfwGetKey(window, GLFW_KEY_A)) {
1150 vec3 dir = (inverse(R) * vec4(-1.0f, 0.0f, 0.0f, 1.0f)).xyz();
1151 cam_pos += dir * dist;
1152
1153 cam_moved = true;
1154 }
1155 if (glfwGetKey(window, GLFW_KEY_D)) {
1156 vec3 dir = (inverse(R) * vec4(1.0f, 0.0f, 0.0f, 1.0f)).xyz();
1157 cam_pos += dir * dist;
1158
1159 cam_moved = true;
1160 }
1161 if (glfwGetKey(window, GLFW_KEY_W)) {
1162 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, -1.0f, 1.0f)).xyz();
1163 cam_pos += dir * dist;
1164
1165 cam_moved = true;
1166 }
1167 if (glfwGetKey(window, GLFW_KEY_S)) {
1168 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
1169 cam_pos += dir * dist;
1170
1171 cam_moved = true;
1172 }
1173 if (glfwGetKey(window, GLFW_KEY_LEFT)) {
1174 cam_yaw += cam_yaw_speed * elapsed_seconds;
1175 cam_moved = true;
1176 }
1177 if (glfwGetKey(window, GLFW_KEY_RIGHT)) {
1178 cam_yaw -= cam_yaw_speed * elapsed_seconds;
1179 cam_moved = true;
1180 }
1181 if (glfwGetKey(window, GLFW_KEY_UP)) {
1182 cam_pitch += cam_pitch_speed * elapsed_seconds;
1183 cam_moved = true;
1184 }
1185 if (glfwGetKey(window, GLFW_KEY_DOWN)) {
1186 cam_pitch -= cam_pitch_speed * elapsed_seconds;
1187 cam_moved = true;
1188 }
1189 if (cam_moved) {
1190 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
1191
1192 mat4 yaw_mat = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
1193 mat4 pitch_mat = rotate(mat4(), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
1194 R = pitch_mat * yaw_mat;
1195
1196 view_mat = R*T;
1197
1198 //printVector("cam pos", cam_pos);
1199
1200 glUseProgram(color_sp);
1201 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
1202
1203 glUseProgram(texture_sp);
1204 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
1205
1206 cam_moved = false;
1207 }
1208 }
1209
1210 ImGui_ImplGlfwGL3_Shutdown();
1211 ImGui::DestroyContext();
1212
1213 glfwDestroyWindow(window);
1214 glfwTerminate();
1215
1216 return 0;
1217}
1218
1219void glfw_error_callback(int error, const char* description) {
1220 gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
1221}
1222
1223void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
1224 double mouse_x, mouse_y;
1225 glfwGetCursorPos(window, &mouse_x, &mouse_y);
1226
1227 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
1228 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
1229 selectedObject = NULL;
1230
1231 float x = (2.0f*mouse_x) / width - 1.0f;
1232 float y = 1.0f - (2.0f*mouse_y) / height;
1233
1234 cout << "x: " << x << ", y: " << y << endl;
1235
1236 vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
1237 vec4 ray_eye = inverse(proj_mat) * ray_clip;
1238 ray_eye = vec4(ray_eye.xy(), -1.0f, 1.0f);
1239 vec4 ray_world = inverse(view_mat) * ray_eye;
1240
1241 vec4 cam_pos_temp = vec4(cam_pos, 1.0f);
1242
1243 vec4 click_point;
1244 vec3 closest_point = vec3(0.0f, 0.0f, -FAR_CLIP); // Any valid point will be closer than the far clipping plane, so initial value to that
1245 SceneObject* closest_object = NULL;
1246
1247 for (vector<SceneObject>::iterator it = objects.begin(); it != objects.end(); it++) {
1248 for (unsigned int p_idx = 0; p_idx < it->points.size(); p_idx += 9) {
1249 if (faceClicked(
1250 {
1251 vec3(it->points[p_idx], it->points[p_idx + 1], it->points[p_idx + 2]),
1252 vec3(it->points[p_idx + 3], it->points[p_idx + 4], it->points[p_idx + 5]),
1253 vec3(it->points[p_idx + 6], it->points[p_idx + 7], it->points[p_idx + 8]),
1254 },
1255 &*it, ray_world, cam_pos_temp, click_point
1256 )) {
1257 click_point = view_mat * click_point;
1258
1259 if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
1260 closest_point = click_point.xyz();
1261 closest_object = &*it;
1262 }
1263 }
1264 }
1265 }
1266
1267 if (closest_object == NULL) {
1268 cout << "No object was clicked" << endl;
1269 } else {
1270 clickedObject = closest_object;
1271 cout << "Clicked object: " << clickedObject->id << endl;
1272 }
1273 }
1274}
1275
1276void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
1277 key_state[key] = action;
1278
1279 // should be true for GLFW_PRESS and GLFW_REPEAT
1280 key_pressed[key] = (action != GLFW_RELEASE);
1281}
1282
1283
1284GLuint loadShader(GLenum type, string file) {
1285 cout << "Loading shader from file " << file << endl;
1286
1287 ifstream shaderFile(file);
1288 GLuint shaderId = 0;
1289
1290 if (shaderFile.is_open()) {
1291 string line, shaderString;
1292
1293 while(getline(shaderFile, line)) {
1294 shaderString += line + "\n";
1295 }
1296 shaderFile.close();
1297 const char* shaderCString = shaderString.c_str();
1298
1299 shaderId = glCreateShader(type);
1300 glShaderSource(shaderId, 1, &shaderCString, NULL);
1301 glCompileShader(shaderId);
1302
1303 cout << "Loaded successfully" << endl;
1304 } else {
1305 cout << "Failed to load the file" << endl;
1306 }
1307
1308 return shaderId;
1309}
1310
1311GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
1312 GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
1313 GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
1314
1315 GLuint shader_program = glCreateProgram();
1316 glAttachShader(shader_program, vs);
1317 glAttachShader(shader_program, fs);
1318
1319 glLinkProgram(shader_program);
1320
1321 return shader_program;
1322}
1323
1324unsigned char* loadImage(string file_name, int* x, int* y) {
1325 int n;
1326 int force_channels = 4; // This forces RGBA (4 bytes per pixel)
1327 unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
1328
1329 int width_in_bytes = *x * 4;
1330 unsigned char *top = NULL;
1331 unsigned char *bottom = NULL;
1332 unsigned char temp = 0;
1333 int half_height = *y / 2;
1334
1335 // flip image upside-down to account for OpenGL treating lower-left as (0, 0)
1336 for (int row = 0; row < half_height; row++) {
1337 top = image_data + row * width_in_bytes;
1338 bottom = image_data + (*y - row - 1) * width_in_bytes;
1339 for (int col = 0; col < width_in_bytes; col++) {
1340 temp = *top;
1341 *top = *bottom;
1342 *bottom = temp;
1343 top++;
1344 bottom++;
1345 }
1346 }
1347
1348 if (!image_data) {
1349 fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
1350 }
1351
1352 // Not Power-of-2 check
1353 if ((*x & (*x - 1)) != 0 || (*y & (*y - 1)) != 0) {
1354 fprintf(stderr, "WARNING: texture %s is not power-of-2 dimensions\n", file_name.c_str());
1355 }
1356
1357 return image_data;
1358}
1359
1360bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point) {
1361 // LINE EQUATION: P = O + Dt
1362 // O = cam
1363 // D = ray_world
1364
1365 // PLANE EQUATION: P dot n + d = 0
1366 // n is the normal vector
1367 // d is the offset from the origin
1368
1369 // Take the cross-product of two vectors on the plane to get the normal
1370 vec3 v1 = points[1] - points[0];
1371 vec3 v2 = points[2] - points[0];
1372
1373 vec3 normal = vec3(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
1374
1375 vec3 local_ray = (inverse(obj->model_mat) * world_ray).xyz();
1376 vec3 local_cam = (inverse(obj->model_mat) * cam).xyz();
1377
1378 local_ray = local_ray - local_cam;
1379
1380 float d = -glm::dot(points[0], normal);
1381 float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
1382
1383 vec3 intersection = local_cam + t*local_ray;
1384
1385 if (insideTriangle(intersection, points)) {
1386 click_point = obj->model_mat * vec4(intersection, 1.0f);
1387 return true;
1388 } else {
1389 return false;
1390 }
1391}
1392
1393bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
1394 vec3 v21 = triangle_points[1] - triangle_points[0];
1395 vec3 v31 = triangle_points[2] - triangle_points[0];
1396 vec3 pv1 = p - triangle_points[0];
1397
1398 float y = (pv1.y*v21.x - pv1.x*v21.y) / (v31.y*v21.x - v31.x*v21.y);
1399 float x = (pv1.x-y*v31.x) / v21.x;
1400
1401 return x > 0.0f && y > 0.0f && x+y < 1.0f;
1402}
1403
1404void printVector(string label, vec3 v) {
1405 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
1406}
1407
1408void print4DVector(string label, vec4 v) {
1409 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
1410}
1411
1412void addObjectToScene(SceneObject& obj) {
1413 obj.id = objects.size(); // currently unused
1414 obj.num_points = obj.points.size() / 3;
1415 obj.model_transform = mat4();
1416
1417 obj.normals.reserve(obj.points.size());
1418 for (int i = 0; i < obj.points.size(); i += 9) {
1419 vec3 point1 = vec3(obj.points[i], obj.points[i + 1], obj.points[i + 2]);
1420 vec3 point2 = vec3(obj.points[i + 3], obj.points[i + 4], obj.points[i + 5]);
1421 vec3 point3 = vec3(obj.points[i + 6], obj.points[i + 7], obj.points[i + 8]);
1422
1423 vec3 normal = normalize(cross(point2 - point1, point3 - point1));
1424
1425 // Add the same normal for all 3 points
1426 for (int j = 0; j < 3; j++) {
1427 obj.normals.push_back(normal.x);
1428 obj.normals.push_back(normal.y);
1429 obj.normals.push_back(normal.z);
1430 }
1431 }
1432
1433 objects.push_back(obj);
1434}
1435
1436void populateBuffers(vector<SceneObject>& objects,
1437 GLuint* points_vbo,
1438 GLuint* colors_vbo,
1439 GLuint* selected_colors_vbo,
1440 GLuint* texcoords_vbo,
1441 GLuint* normals_vbo,
1442 GLuint* ubo,
1443 GLuint* model_mat_idx_vbo,
1444 map<GLuint, unsigned int>& shaderCounts,
1445 map<GLuint, unsigned int>& curShaderBase) {
1446 GLsizeiptr points_buffer_size = 0;
1447 GLsizeiptr textures_buffer_size = 0;
1448 GLsizeiptr ubo_buffer_size = 0;
1449 GLsizeiptr model_mat_idx_buffer_size = 0;
1450
1451 map<GLuint, unsigned int> curShaderOffset;
1452
1453 map<GLuint, unsigned int> shaderUboCounts;
1454 map<GLuint, unsigned int> curShaderUboBase;
1455 map<GLuint, unsigned int> curShaderUboOffset;
1456
1457 vector<SceneObject>::iterator it;
1458
1459 /* Find all shaders that need to be used and the number of objects and
1460 * number of points for each shader. Construct a map from shader id to count
1461 * of points being drawn using that shader (for thw model matrix ubo, we
1462 * need object counts instead). These will be used to get offsets into the
1463 * vertex buffer for each shader.
1464 */
1465 for (it = objects.begin(); it != objects.end(); it++) {
1466 points_buffer_size += it->points.size() * sizeof(GLfloat);
1467 textures_buffer_size += it->texcoords.size() * sizeof(GLfloat);
1468 ubo_buffer_size += 16 * sizeof(GLfloat);
1469 model_mat_idx_buffer_size += it->num_points * sizeof(GLuint);
1470
1471 if (shaderCounts.count(it->shader_program) == 0) {
1472 shaderCounts[it->shader_program] = it->num_points;
1473 shaderUboCounts[it->shader_program] = 1;
1474 } else {
1475 shaderCounts[it->shader_program] += it->num_points;
1476 shaderUboCounts[it->shader_program]++;
1477 }
1478 }
1479
1480 map<GLuint, unsigned int>::iterator shaderIt;
1481 unsigned int lastShaderCount = 0;
1482 unsigned int lastShaderUboCount = 0;
1483
1484 /*
1485 * The counts calculated above can be used to get the starting offset of
1486 * each shader in the vertex buffer. Create a map of base offsets to mark
1487 * where the data for the first object using a given shader begins. Also,
1488 * create a map of current offsets to mark where to copy data for the next
1489 * object being added.
1490 */
1491 cout << "Shader counts:" << endl;
1492 for (shaderIt = shaderCounts.begin(); shaderIt != shaderCounts.end(); shaderIt++) {
1493 curShaderOffset[shaderIt->first] = 0;
1494 curShaderUboOffset[shaderIt->first] = 0;
1495
1496 curShaderBase[shaderIt->first] = lastShaderCount;
1497 lastShaderCount += shaderCounts[shaderIt->first];
1498
1499 curShaderUboBase[shaderIt->first] = lastShaderUboCount;
1500 lastShaderUboCount += shaderUboCounts[shaderIt->first];
1501 }
1502
1503 // Initialize all the buffers using the counts calculated above
1504
1505 *points_vbo = 0;
1506 glGenBuffers(1, points_vbo);
1507 glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
1508 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1509
1510 *colors_vbo = 0;
1511 glGenBuffers(1, colors_vbo);
1512 glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
1513 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1514
1515 *selected_colors_vbo = 0;
1516 glGenBuffers(1, selected_colors_vbo);
1517 glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
1518 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1519
1520 *texcoords_vbo = 0;
1521 glGenBuffers(1, texcoords_vbo);
1522 glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
1523 glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
1524
1525 *normals_vbo = 0;
1526 glGenBuffers(1, normals_vbo);
1527 glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
1528 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1529
1530 *ubo = 0;
1531 glGenBuffers(1, ubo);
1532 glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
1533 glBufferData(GL_UNIFORM_BUFFER, ubo_buffer_size, NULL, GL_DYNAMIC_DRAW);
1534
1535 *model_mat_idx_vbo = 0;
1536 glGenBuffers(1, model_mat_idx_vbo);
1537 glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
1538 glBufferData(GL_ARRAY_BUFFER, model_mat_idx_buffer_size, NULL, GL_DYNAMIC_DRAW);
1539
1540 for (it = objects.begin(); it != objects.end(); it++) {
1541 it->vertex_vbo_offset = curShaderBase[it->shader_program] + curShaderOffset[it->shader_program];
1542 it->ubo_offset = curShaderUboBase[it->shader_program] + curShaderUboOffset[it->shader_program];
1543
1544 glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
1545 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->points.size() * sizeof(GLfloat), &it->points[0]);
1546
1547 glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
1548 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->colors.size() * sizeof(GLfloat), &it->colors[0]);
1549
1550 glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
1551 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->selected_colors.size() * sizeof(GLfloat), &it->selected_colors[0]);
1552
1553 glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
1554 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 2, it->texcoords.size() * sizeof(GLfloat), &it->texcoords[0]);
1555
1556 glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
1557 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->normals.size() * sizeof(GLfloat), &it->normals[0]);
1558
1559 glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
1560 for (int i = 0; i < it->num_points; i++) {
1561 glBufferSubData(GL_ARRAY_BUFFER, (it->vertex_vbo_offset + i) * sizeof(GLuint), sizeof(GLuint), &it->ubo_offset);
1562 }
1563
1564 curShaderOffset[it->shader_program] += it->num_points;
1565
1566 it->model_mat = it->model_base * it->model_transform;
1567 glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
1568 glBufferSubData(GL_UNIFORM_BUFFER, it->ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(it->model_mat));
1569
1570 curShaderUboOffset[it->shader_program]++;
1571 }
1572}
1573
1574void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo) {
1575 obj.model_transform = obj.model_transform * transform;
1576 obj.model_mat = obj.model_transform * obj.model_base;
1577
1578 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1579 glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
1580}
1581
1582void renderScene(vector<SceneObject>& objects,
1583 GLuint color_sp, GLuint texture_sp,
1584 GLuint vao1, GLuint vao2,
1585 GLuint points_vbo, GLuint normals_vbo,
1586 GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
1587 SceneObject* selectedObject,
1588 map<GLuint, unsigned int>& shaderCounts,
1589 map<GLuint, unsigned int>& curShaderBase) {
1590
1591 glUseProgram(color_sp);
1592 glBindVertexArray(vao1);
1593
1594 if (selectedObject != NULL) {
1595 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1596 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1597
1598 glDrawArrays(GL_TRIANGLES, selectedObject->vertex_vbo_offset, selectedObject->num_points);
1599 }
1600
1601 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
1602 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1603
1604 glDrawArrays(GL_TRIANGLES, curShaderBase[color_sp], shaderCounts[color_sp]);
1605
1606 glUseProgram(texture_sp);
1607 glBindVertexArray(vao2);
1608
1609 glDrawArrays(GL_TRIANGLES, curShaderBase[texture_sp], shaderCounts[texture_sp]);
1610}
1611
1612void renderSceneGui() {
1613 ImGui_ImplGlfwGL3_NewFrame();
1614
1615 // 1. Show a simple window.
1616 // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
1617 /*
1618 {
1619 static float f = 0.0f;
1620 static int counter = 0;
1621 ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
1622 ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
1623 ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
1624
1625 ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
1626 ImGui::Checkbox("Another Window", &show_another_window);
1627
1628 if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
1629 counter++;
1630 ImGui::SameLine();
1631 ImGui::Text("counter = %d", counter);
1632
1633 ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
1634 }
1635 */
1636
1637 {
1638 ImGui::SetNextWindowSize(ImVec2(85, 22), ImGuiCond_Once);
1639 ImGui::SetNextWindowPos(ImVec2(10, 50), ImGuiCond_Once);
1640 ImGui::Begin("WndStats", NULL,
1641 ImGuiWindowFlags_NoTitleBar |
1642 ImGuiWindowFlags_NoResize |
1643 ImGuiWindowFlags_NoMove);
1644 ImGui::Text("Score: ???");
1645 ImGui::End();
1646 }
1647
1648 {
1649 ImGui::SetNextWindowPos(ImVec2(380, 10), ImGuiCond_Once);
1650 ImGui::SetNextWindowSize(ImVec2(250, 35), ImGuiCond_Once);
1651 ImGui::Begin("WndMenubar", NULL,
1652 ImGuiWindowFlags_NoTitleBar |
1653 ImGuiWindowFlags_NoResize |
1654 ImGuiWindowFlags_NoMove);
1655 ImGui::InvisibleButton("", ImVec2(155, 18));
1656 ImGui::SameLine();
1657 if (ImGui::Button("Main Menu")) {
1658 events.push(EVENT_GO_TO_MAIN_MENU);
1659 }
1660 ImGui::End();
1661 }
1662
1663 ImGui::Render();
1664 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1665}
1666
1667void renderMainMenu() {
1668}
1669
1670void renderMainMenuGui() {
1671 ImGui_ImplGlfwGL3_NewFrame();
1672
1673 {
1674 int padding = 4;
1675 ImGui::SetNextWindowPos(ImVec2(-padding, -padding), ImGuiCond_Once);
1676 ImGui::SetNextWindowSize(ImVec2(width + 2 * padding, height + 2 * padding), ImGuiCond_Once);
1677 ImGui::Begin("WndMain", NULL,
1678 ImGuiWindowFlags_NoTitleBar |
1679 ImGuiWindowFlags_NoResize |
1680 ImGuiWindowFlags_NoMove);
1681
1682 ImGui::InvisibleButton("", ImVec2(10, 80));
1683 ImGui::InvisibleButton("", ImVec2(285, 18));
1684 ImGui::SameLine();
1685 if (ImGui::Button("New Game")) {
1686 events.push(EVENT_GO_TO_GAME);
1687 }
1688
1689 ImGui::InvisibleButton("", ImVec2(10, 15));
1690 ImGui::InvisibleButton("", ImVec2(300, 18));
1691 ImGui::SameLine();
1692 if (ImGui::Button("Quit")) {
1693 events.push(EVENT_QUIT);
1694 }
1695
1696 ImGui::End();
1697 }
1698
1699 ImGui::Render();
1700 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1701}
Note: See TracBrowser for help on using the repository browser.