source: opengl-game/new-game.cpp@ 5527206

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

Add a random number generating function and continuously spawn asteroids at random positions.

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