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

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

Fix rendering of textured objects

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