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

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

Allow objects to be added to the scene after the graphics buffers are initially populated, resize the buffers as needed to fit newly added objects, support deletion of objects, and spawn several asteroids that move toward the player when the down arrow is pressed.

  • Property mode set to 100644
File size: 55.3 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 = {
365 1.0f, 1.0f,
366 0.0f, 1.0f,
367 0.0f, 0.0f,
368 1.0f, 1.0f,
369 0.0f, 0.0f,
370 1.0f, 0.0f
371 };
372 obj.selected_colors = {
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 0.0f, 1.0f, 0.0f,
379 };
380
381 T_model = translate(mat4(), vec3(0.45f, -1.5f, 0.0f));
382 R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
383 obj.model_base = T_model*R_model;
384
385 addObjectToSceneDuringInit(obj);
386
387 // square
388 obj = SceneObject();
389 obj.shader_program = texture_sp;
390 obj.points = {
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 0.5f, -0.5f, 0.0f,
397 };
398 obj.colors = {
399 1.0f, 0.0f, 0.0f,
400 0.0f, 0.0f, 1.0f,
401 0.0f, 1.0f, 0.0f,
402 0.0f, 1.0f, 0.0f,
403 0.0f, 0.0f, 1.0f,
404 1.0f, 0.0f, 0.0f,
405 };
406 obj.texcoords = {
407 1.0f, 1.0f,
408 0.0f, 1.0f,
409 0.0f, 0.0f,
410 1.0f, 1.0f,
411 0.0f, 0.0f,
412 1.0f, 0.0f
413 };
414 obj.selected_colors = {
415 0.0f, 0.6f, 0.9f,
416 0.0f, 0.6f, 0.9f,
417 0.0f, 0.6f, 0.9f,
418 0.0f, 0.6f, 0.9f,
419 0.0f, 0.6f, 0.9f,
420 0.0f, 0.6f, 0.9f,
421 };
422
423 T_model = translate(mat4(), vec3(-0.5f, -1.5f, -1.00f));
424 R_model = rotate(mat4(), 0.5f, vec3(0.0f, 1.0f, 0.0f));
425 obj.model_base = T_model*R_model;
426
427 addObjectToSceneDuringInit(obj);
428 */
429
430 // player ship
431 obj = SceneObject();
432 obj.shader_program = color_sp;
433 obj.points = {
434 //back
435 -0.5f, 0.3f, 0.0f,
436 -0.5f, 0.0f, 0.0f,
437 0.5f, 0.0f, 0.0f,
438 -0.5f, 0.3f, 0.0f,
439 0.5f, 0.0f, 0.0f,
440 0.5f, 0.3f, 0.0f,
441
442 // left back
443 -0.5f, 0.3f, -2.0f,
444 -0.5f, 0.0f, -2.0f,
445 -0.5f, 0.0f, 0.0f,
446 -0.5f, 0.3f, -2.0f,
447 -0.5f, 0.0f, 0.0f,
448 -0.5f, 0.3f, 0.0f,
449
450 // right back
451 0.5f, 0.3f, 0.0f,
452 0.5f, 0.0f, 0.0f,
453 0.5f, 0.0f, -2.0f,
454 0.5f, 0.3f, 0.0f,
455 0.5f, 0.0f, -2.0f,
456 0.5f, 0.3f, -2.0f,
457
458 // left mid
459 -0.25f, 0.3f, -3.0f,
460 -0.25f, 0.0f, -3.0f,
461 -0.5f, 0.0f, -2.0f,
462 -0.25f, 0.3f, -3.0f,
463 -0.5f, 0.0f, -2.0f,
464 -0.5f, 0.3f, -2.0f,
465
466 // right mid
467 0.5f, 0.3f, -2.0f,
468 0.5f, 0.0f, -2.0f,
469 0.25f, 0.0f, -3.0f,
470 0.5f, 0.3f, -2.0f,
471 0.25f, 0.0f, -3.0f,
472 0.25f, 0.3f, -3.0f,
473
474 // left front
475 0.0f, 0.0f, -3.5f,
476 -0.25f, 0.0f, -3.0f,
477 -0.25f, 0.3f, -3.0f,
478
479 // right front
480 0.25f, 0.3f, -3.0f,
481 0.25f, 0.0f, -3.0f,
482 0.0f, 0.0f, -3.5f,
483
484 // top back
485 -0.5f, 0.3f, -2.0f,
486 -0.5f, 0.3f, 0.0f,
487 0.5f, 0.3f, 0.0f,
488 -0.5f, 0.3f, -2.0f,
489 0.5f, 0.3f, 0.0f,
490 0.5f, 0.3f, -2.0f,
491
492 // bottom back
493 -0.5f, 0.0f, 0.0f,
494 -0.5f, 0.0f, -2.0f,
495 0.5f, 0.0f, 0.0f,
496 0.5f, 0.0f, 0.0f,
497 -0.5f, 0.0f, -2.0f,
498 0.5f, 0.0f, -2.0f,
499
500 // top mid
501 -0.25f, 0.3f, -3.0f,
502 -0.5f, 0.3f, -2.0f,
503 0.5f, 0.3f, -2.0f,
504 -0.25f, 0.3f, -3.0f,
505 0.5f, 0.3f, -2.0f,
506 0.25f, 0.3f, -3.0f,
507
508 // bottom mid
509 -0.5f, 0.0f, -2.0f,
510 -0.25f, 0.0f, -3.0f,
511 0.5f, 0.0f, -2.0f,
512 0.5f, 0.0f, -2.0f,
513 -0.25f, 0.0f, -3.0f,
514 0.25f, 0.0f, -3.0f,
515
516 // top front
517 -0.25f, 0.3f, -3.0f,
518 0.25f, 0.3f, -3.0f,
519 0.0f, 0.0f, -3.5f,
520
521 // bottom front
522 0.25f, 0.0f, -3.0f,
523 -0.25f, 0.0f, -3.0f,
524 0.0f, 0.0f, -3.5f,
525
526 // left wing start back
527 -1.5f, 0.3f, 0.0f,
528 -1.5f, 0.0f, 0.0f,
529 -0.5f, 0.0f, 0.0f,
530 -1.5f, 0.3f, 0.0f,
531 -0.5f, 0.0f, 0.0f,
532 -0.5f, 0.3f, 0.0f,
533
534 // left wing start top
535 -0.5f, 0.3f, -0.3f,
536 -1.3f, 0.3f, -0.3f,
537 -1.5f, 0.3f, 0.0f,
538 -0.5f, 0.3f, -0.3f,
539 -1.5f, 0.3f, 0.0f,
540 -0.5f, 0.3f, 0.0f,
541
542 // left wing start front
543 -0.5f, 0.3f, -0.3f,
544 -0.5f, 0.0f, -0.3f,
545 -1.3f, 0.0f, -0.3f,
546 -0.5f, 0.3f, -0.3f,
547 -1.3f, 0.0f, -0.3f,
548 -1.3f, 0.3f, -0.3f,
549
550 // left wing start bottom
551 -0.5f, 0.0f, 0.0f,
552 -1.5f, 0.0f, 0.0f,
553 -1.3f, 0.0f, -0.3f,
554 -0.5f, 0.0f, 0.0f,
555 -1.3f, 0.0f, -0.3f,
556 -0.5f, 0.0f, -0.3f,
557
558 // left wing end outside
559 -1.5f, 0.3f, 0.0f,
560 -2.2f, 0.15f, -0.8f,
561 -1.5f, 0.0f, 0.0f,
562
563 // left wing end top
564 -1.3f, 0.3f, -0.3f,
565 -2.2f, 0.15f, -0.8f,
566 -1.5f, 0.3f, 0.0f,
567
568 // left wing end front
569 -1.3f, 0.0f, -0.3f,
570 -2.2f, 0.15f, -0.8f,
571 -1.3f, 0.3f, -0.3f,
572
573 // left wing end bottom
574 -1.5f, 0.0f, 0.0f,
575 -2.2f, 0.15f, -0.8f,
576 -1.3f, 0.0f, -0.3f,
577
578 // right wing start back
579 1.5f, 0.0f, 0.0f,
580 1.5f, 0.3f, 0.0f,
581 0.5f, 0.0f, 0.0f,
582 0.5f, 0.0f, 0.0f,
583 1.5f, 0.3f, 0.0f,
584 0.5f, 0.3f, 0.0f,
585
586 // right wing start top
587 1.3f, 0.3f, -0.3f,
588 0.5f, 0.3f, -0.3f,
589 1.5f, 0.3f, 0.0f,
590 1.5f, 0.3f, 0.0f,
591 0.5f, 0.3f, -0.3f,
592 0.5f, 0.3f, 0.0f,
593
594 // right wing start front
595 0.5f, 0.0f, -0.3f,
596 0.5f, 0.3f, -0.3f,
597 1.3f, 0.0f, -0.3f,
598 1.3f, 0.0f, -0.3f,
599 0.5f, 0.3f, -0.3f,
600 1.3f, 0.3f, -0.3f,
601
602 // right wing start bottom
603 1.5f, 0.0f, 0.0f,
604 0.5f, 0.0f, 0.0f,
605 1.3f, 0.0f, -0.3f,
606 1.3f, 0.0f, -0.3f,
607 0.5f, 0.0f, 0.0f,
608 0.5f, 0.0f, -0.3f,
609
610 // right wing end outside
611 2.2f, 0.15f, -0.8f,
612 1.5f, 0.3f, 0.0f,
613 1.5f, 0.0f, 0.0f,
614
615 // right wing end top
616 2.2f, 0.15f, -0.8f,
617 1.3f, 0.3f, -0.3f,
618 1.5f, 0.3f, 0.0f,
619
620 // right wing end front
621 2.2f, 0.15f, -0.8f,
622 1.3f, 0.0f, -0.3f,
623 1.3f, 0.3f, -0.3f,
624
625 // right wing end bottom
626 2.2f, 0.15f, -0.8f,
627 1.5f, 0.0f, 0.0f,
628 1.3f, 0.0f, -0.3f,
629 };
630 obj.colors = {
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, 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 0.0f, 0.0f, 0.3f,
658
659 0.0f, 0.0f, 0.3f,
660 0.0f, 0.0f, 0.3f,
661 0.0f, 0.0f, 0.3f,
662 0.0f, 0.0f, 0.3f,
663 0.0f, 0.0f, 0.3f,
664 0.0f, 0.0f, 0.3f,
665
666 0.0f, 0.0f, 1.0f,
667 0.0f, 0.0f, 1.0f,
668 0.0f, 0.0f, 1.0f,
669
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, 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 0.0f, 0.0f, 1.0f,
694
695 0.0f, 0.0f, 1.0f,
696 0.0f, 0.0f, 1.0f,
697 0.0f, 0.0f, 1.0f,
698 0.0f, 0.0f, 1.0f,
699 0.0f, 0.0f, 1.0f,
700 0.0f, 0.0f, 1.0f,
701
702 0.0f, 0.0f, 0.3f,
703 0.0f, 0.0f, 0.3f,
704 0.0f, 0.0f, 0.3f,
705
706 0.0f, 0.0f, 0.3f,
707 0.0f, 0.0f, 0.3f,
708 0.0f, 0.0f, 0.3f,
709
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 0.0f, 0.0f, 0.3f,
728 0.0f, 0.0f, 0.3f,
729 0.0f, 0.0f, 0.3f,
730
731 0.0f, 0.0f, 0.3f,
732 0.0f, 0.0f, 0.3f,
733 0.0f, 0.0f, 0.3f,
734 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
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 0.0f, 0.0f, 0.3f,
772 0.0f, 0.0f, 0.3f,
773 0.0f, 0.0f, 0.3f,
774
775 0.0f, 0.0f, 0.3f,
776 0.0f, 0.0f, 0.3f,
777 0.0f, 0.0f, 0.3f,
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 0.0f, 0.0f, 0.3f,
791 0.0f, 0.0f, 0.3f,
792 0.0f, 0.0f, 0.3f,
793
794 0.0f, 0.0f, 0.3f,
795 0.0f, 0.0f, 0.3f,
796 0.0f, 0.0f, 0.3f,
797 };
798 obj.texcoords = { 0.0f };
799 obj.selected_colors = { 0.0f };
800
801 T_model = translate(mat4(), vec3(0.0f, -1.2f, 1.8f));
802 R_model = rotate(mat4(), 20.0f * (float)ONE_DEG_IN_RAD, vec3(1.0f, 0.0f, 0.0f));
803 R_model = mat4();
804 obj.model_base = T_model * R_model * scale(mat4(), vec3(0.1f, 0.1f, 0.1f));
805
806 addObjectToSceneDuringInit(obj);
807
808 vector<SceneObject>::iterator obj_it;
809
810 GLuint points_vbo, colors_vbo, selected_colors_vbo, texcoords_vbo,
811 normals_vbo, ubo, model_mat_idx_vbo;
812
813 initializeBuffers(
814 &points_vbo,
815 &colors_vbo,
816 &selected_colors_vbo,
817 &texcoords_vbo,
818 &normals_vbo,
819 &ubo,
820 &model_mat_idx_vbo);
821
822 populateBuffers(objects,
823 shaderBufferInfo,
824 points_vbo,
825 colors_vbo,
826 selected_colors_vbo,
827 texcoords_vbo,
828 normals_vbo,
829 ubo,
830 model_mat_idx_vbo);
831
832 spawnAsteroid(vec3(0.0f, -1.2f, -21.5f), color_sp,
833 shaderBufferInfo,
834 points_vbo,
835 colors_vbo,
836 selected_colors_vbo,
837 texcoords_vbo,
838 normals_vbo,
839 ubo,
840 model_mat_idx_vbo);
841 spawnAsteroid(vec3(1.0f, -1.2f, -21.5f), color_sp,
842 shaderBufferInfo,
843 points_vbo,
844 colors_vbo,
845 selected_colors_vbo,
846 texcoords_vbo,
847 normals_vbo,
848 ubo,
849 model_mat_idx_vbo);
850 spawnAsteroid(vec3(-0.5f, -1.2f, -20.8f), color_sp,
851 shaderBufferInfo,
852 points_vbo,
853 colors_vbo,
854 selected_colors_vbo,
855 texcoords_vbo,
856 normals_vbo,
857 ubo,
858 model_mat_idx_vbo);
859 spawnAsteroid(vec3(-0.3f, -1.2f, -20.8f), color_sp,
860 shaderBufferInfo,
861 points_vbo,
862 colors_vbo,
863 selected_colors_vbo,
864 texcoords_vbo,
865 normals_vbo,
866 ubo,
867 model_mat_idx_vbo);
868 spawnAsteroid(vec3(-0.1f, -1.2f, -20.8f), color_sp,
869 shaderBufferInfo,
870 points_vbo,
871 colors_vbo,
872 selected_colors_vbo,
873 texcoords_vbo,
874 normals_vbo,
875 ubo,
876 model_mat_idx_vbo);
877
878 GLuint vao = 0;
879 glGenVertexArrays(1, &vao);
880 glBindVertexArray(vao);
881
882 glEnableVertexAttribArray(0);
883 glEnableVertexAttribArray(1);
884 glEnableVertexAttribArray(2);
885 glEnableVertexAttribArray(3);
886
887 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
888 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
889
890 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
891 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
892
893 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
894 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
895
896 GLuint vao2 = 0;
897 glGenVertexArrays(1, &vao2);
898 glBindVertexArray(vao2);
899
900 glEnableVertexAttribArray(0);
901 glEnableVertexAttribArray(1);
902 glEnableVertexAttribArray(2);
903 glEnableVertexAttribArray(3);
904
905 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
906 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
907
908 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
909 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
910
911 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
912 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
913
914 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
915 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
916
917 float cam_speed = 1.0f;
918 float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
919 float cam_pitch_speed = 60.0f*ONE_DEG_IN_RAD;
920
921 // glm::lookAt can create the view matrix
922 // glm::perspective can create the projection matrix
923
924 cam_pos = vec3(0.0f, 0.0f, 2.0f);
925 //cam_pos = vec3(-2.1f, -1.5f, -1.5f); // Good position for checking ship faces
926 float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
927 float cam_pitch = -50.0f * 2.0f * 3.14159f / 360.0f;
928
929 mat4 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
930 mat4 yaw_mat = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
931 mat4 pitch_mat = rotate(mat4(), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
932 mat4 R = pitch_mat * yaw_mat;
933 view_mat = R*T;
934
935 float fov = 67.0f * ONE_DEG_IN_RAD;
936 float aspect = (float)width / (float)height;
937
938 float range = tan(fov * 0.5f) * NEAR_CLIP;
939 float Sx = NEAR_CLIP / (range * aspect);
940 float Sy = NEAR_CLIP / range;
941 float Sz = -(FAR_CLIP + NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
942 float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
943
944 float proj_arr[] = {
945 Sx, 0.0f, 0.0f, 0.0f,
946 0.0f, Sy, 0.0f, 0.0f,
947 0.0f, 0.0f, Sz, -1.0f,
948 0.0f, 0.0f, Pz, 0.0f,
949 };
950 proj_mat = make_mat4(proj_arr);
951
952 GLuint ub_binding_point = 0;
953
954 GLuint view_test_loc = glGetUniformLocation(color_sp, "view");
955 GLuint proj_test_loc = glGetUniformLocation(color_sp, "proj");
956 GLuint color_sp_ub_index = glGetUniformBlockIndex(color_sp, "models");
957
958 GLuint view_mat_loc = glGetUniformLocation(texture_sp, "view");
959 GLuint proj_mat_loc = glGetUniformLocation(texture_sp, "proj");
960 GLuint texture_sp_ub_index = glGetUniformBlockIndex(texture_sp, "models");
961
962 glUseProgram(color_sp);
963 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
964 glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
965
966 glUniformBlockBinding(color_sp, color_sp_ub_index, ub_binding_point);
967 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
968
969 glUseProgram(texture_sp);
970 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
971 glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
972
973 glUniformBlockBinding(texture_sp, texture_sp_ub_index, ub_binding_point);
974 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
975
976 bool cam_moved = false;
977
978 int frame_count = 0;
979 double elapsed_seconds_fps = 0.0f;
980 double previous_seconds = glfwGetTime();
981
982 // This draws wireframes. Useful for seeing separate faces and occluded objects.
983 //glPolygonMode(GL_FRONT, GL_LINE);
984
985 if (DISABLE_VSYNC && SHOW_FPS) {
986 glfwSwapInterval(0);
987 }
988
989 State curState = STATE_MAIN_MENU;
990
991 while (!glfwWindowShouldClose(window) && isRunning) {
992 double current_seconds = glfwGetTime();
993 double elapsed_seconds = current_seconds - previous_seconds;
994 previous_seconds = current_seconds;
995
996 if (SHOW_FPS) {
997 elapsed_seconds_fps += elapsed_seconds;
998 if (elapsed_seconds_fps > 0.25f) {
999 fps = (double)frame_count / elapsed_seconds_fps;
1000 cout << "FPS: " << fps << endl;
1001
1002 frame_count = 0;
1003 elapsed_seconds_fps = 0.0f;
1004 }
1005
1006 frame_count++;
1007 }
1008
1009 // Handle events
1010
1011 clickedObject = NULL;
1012
1013 // reset the all key states to KEY_STATE_UNCHANGED (something the GLFW key callback can never return)
1014 // so that GLFW_PRESS and GLFW_RELEASE are only detected once
1015 // TODO: Change this if we ever need to act on GLFW_REPEAT (which is when a key is held down
1016 // continuously for a period of time)
1017 fill(key_state, key_state + NUM_KEYS, KEY_STATE_UNCHANGED);
1018
1019 glfwPollEvents();
1020
1021 while (!events.empty()) {
1022 switch (events.front()) {
1023 case EVENT_GO_TO_MAIN_MENU:
1024 curState = STATE_MAIN_MENU;
1025 break;
1026 case EVENT_GO_TO_GAME:
1027 curState = STATE_GAME;
1028 break;
1029 case EVENT_QUIT:
1030 isRunning = false;
1031 break;
1032 }
1033 events.pop();
1034 }
1035
1036 if (curState == STATE_GAME) {
1037 /*
1038 if (clickedObject == &objects[0]) {
1039 selectedObject = &objects[0];
1040 }
1041 if (clickedObject == &objects[1]) {
1042 selectedObject = &objects[1];
1043 }
1044 */
1045
1046 /*
1047 if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
1048 transformObject(objects[1], translate(mat4(), vec3(0.3f, 0.0f, 0.0f)), ubo);
1049 }
1050 if (key_pressed[GLFW_KEY_RIGHT]) {
1051 transformObject(objects[2], translate(mat4(), vec3(0.01f, 0.0f, 0.0f)), ubo);
1052 }
1053 if (key_pressed[GLFW_KEY_LEFT]) {
1054 transformObject(objects[2], translate(mat4(), vec3(-0.01f, 0.0f, 0.0f)), ubo);
1055 }
1056 */
1057
1058 if (key_pressed[GLFW_KEY_RIGHT]) {
1059 transformObject(objects[0], translate(mat4(), vec3(0.01f, 0.0f, 0.0f)), ubo);
1060 }
1061 if (key_pressed[GLFW_KEY_LEFT]) {
1062 transformObject(objects[0], translate(mat4(), vec3(-0.01f, 0.0f, 0.0f)), ubo);
1063 }
1064
1065 if (key_pressed[GLFW_KEY_DOWN]) {
1066 transformObject(objects[1], translate(mat4(), vec3(0.0f, 0.0f, 0.03f)), ubo);
1067 transformObject(objects[2], translate(mat4(), vec3(0.0f, 0.0f, 0.06f)), ubo);
1068 transformObject(objects[3], translate(mat4(), vec3(0.0f, 0.0f, 0.04f)), ubo);
1069 transformObject(objects[4], translate(mat4(), vec3(0.0f, 0.0f, 0.06f)), ubo);
1070 transformObject(objects[5], translate(mat4(), vec3(0.0f, 0.0f, 0.04f)), ubo);
1071 }
1072
1073 if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
1074 removeObjectFromScene(0, ubo);
1075 }
1076 }
1077
1078 if (key_state[GLFW_KEY_ESCAPE] == GLFW_PRESS) {
1079 glfwSetWindowShouldClose(window, 1);
1080 }
1081
1082 float dist = cam_speed * elapsed_seconds;
1083 if (key_pressed[GLFW_KEY_A]) {
1084 vec3 dir = (inverse(R) * vec4(-1.0f, 0.0f, 0.0f, 1.0f)).xyz();
1085 cam_pos += dir * dist;
1086
1087 cam_moved = true;
1088 }
1089 if (key_pressed[GLFW_KEY_D]) {
1090 vec3 dir = (inverse(R) * vec4(1.0f, 0.0f, 0.0f, 1.0f)).xyz();
1091 cam_pos += dir * dist;
1092
1093 cam_moved = true;
1094 }
1095 if (key_pressed[GLFW_KEY_W]) {
1096 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, -1.0f, 1.0f)).xyz();
1097 cam_pos += dir * dist;
1098
1099 cam_moved = true;
1100 }
1101 if (key_pressed[GLFW_KEY_S]) {
1102 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
1103 cam_pos += dir * dist;
1104
1105 cam_moved = true;
1106 }
1107 /*
1108 if (key_pressed[GLFW_KEY_LEFT]) {
1109 cam_yaw += cam_yaw_speed * elapsed_seconds;
1110 cam_moved = true;
1111 }
1112 if (key_pressed[GLFW_KEY_RIGHT]) {
1113 cam_yaw -= cam_yaw_speed * elapsed_seconds;
1114 cam_moved = true;
1115 }
1116 if (key_pressed[GLFW_KEY_UP]) {
1117 cam_pitch += cam_pitch_speed * elapsed_seconds;
1118 cam_moved = true;
1119 }
1120 if (key_pressed[GLFW_KEY_DOWN]) {
1121 cam_pitch -= cam_pitch_speed * elapsed_seconds;
1122 cam_moved = true;
1123 }
1124 */
1125 if (cam_moved) {
1126 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
1127
1128 mat4 yaw_mat = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
1129 mat4 pitch_mat = rotate(mat4(), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
1130 R = pitch_mat * yaw_mat;
1131
1132 view_mat = R * T;
1133
1134 //printVector("cam pos", cam_pos);
1135
1136 glUseProgram(color_sp);
1137 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
1138
1139 glUseProgram(texture_sp);
1140 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
1141
1142 cam_moved = false;
1143 }
1144
1145 // Render scene
1146
1147 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1148
1149 switch (curState) {
1150 case STATE_MAIN_MENU:
1151 renderMainMenu();
1152 renderMainMenuGui();
1153 break;
1154 case STATE_GAME:
1155 renderScene(objects,
1156 color_sp, texture_sp,
1157 vao, vao2,
1158 points_vbo, normals_vbo,
1159 colors_vbo, texcoords_vbo, selected_colors_vbo,
1160 selectedObject,
1161 shaderBufferInfo);
1162 renderSceneGui();
1163 break;
1164 }
1165
1166 glfwSwapBuffers(window);
1167 }
1168
1169 ImGui_ImplGlfwGL3_Shutdown();
1170 ImGui::DestroyContext();
1171
1172 glfwDestroyWindow(window);
1173 glfwTerminate();
1174
1175 return 0;
1176}
1177
1178void glfw_error_callback(int error, const char* description) {
1179 gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
1180}
1181
1182void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
1183 double mouse_x, mouse_y;
1184 glfwGetCursorPos(window, &mouse_x, &mouse_y);
1185
1186 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
1187 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
1188 selectedObject = NULL;
1189
1190 float x = (2.0f*mouse_x) / width - 1.0f;
1191 float y = 1.0f - (2.0f*mouse_y) / height;
1192
1193 cout << "x: " << x << ", y: " << y << endl;
1194
1195 vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
1196 vec4 ray_eye = inverse(proj_mat) * ray_clip;
1197 ray_eye = vec4(ray_eye.xy(), -1.0f, 1.0f);
1198 vec4 ray_world = inverse(view_mat) * ray_eye;
1199
1200 vec4 cam_pos_temp = vec4(cam_pos, 1.0f);
1201
1202 vec4 click_point;
1203 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
1204 SceneObject* closest_object = NULL;
1205
1206 for (vector<SceneObject>::iterator it = objects.begin(); it != objects.end(); it++) {
1207 for (unsigned int p_idx = 0; p_idx < it->points.size(); p_idx += 9) {
1208 if (faceClicked(
1209 {
1210 vec3(it->points[p_idx], it->points[p_idx + 1], it->points[p_idx + 2]),
1211 vec3(it->points[p_idx + 3], it->points[p_idx + 4], it->points[p_idx + 5]),
1212 vec3(it->points[p_idx + 6], it->points[p_idx + 7], it->points[p_idx + 8]),
1213 },
1214 &*it, ray_world, cam_pos_temp, click_point
1215 )) {
1216 click_point = view_mat * click_point;
1217
1218 if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
1219 closest_point = click_point.xyz();
1220 closest_object = &*it;
1221 }
1222 }
1223 }
1224 }
1225
1226 if (closest_object == NULL) {
1227 cout << "No object was clicked" << endl;
1228 } else {
1229 clickedObject = closest_object;
1230 cout << "Clicked object: " << clickedObject->id << endl;
1231 }
1232 }
1233}
1234
1235void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
1236 key_state[key] = action;
1237
1238 // should be true for GLFW_PRESS and GLFW_REPEAT
1239 key_pressed[key] = (action != GLFW_RELEASE);
1240}
1241
1242
1243GLuint loadShader(GLenum type, string file) {
1244 cout << "Loading shader from file " << file << endl;
1245
1246 ifstream shaderFile(file);
1247 GLuint shaderId = 0;
1248
1249 if (shaderFile.is_open()) {
1250 string line, shaderString;
1251
1252 while(getline(shaderFile, line)) {
1253 shaderString += line + "\n";
1254 }
1255 shaderFile.close();
1256 const char* shaderCString = shaderString.c_str();
1257
1258 shaderId = glCreateShader(type);
1259 glShaderSource(shaderId, 1, &shaderCString, NULL);
1260 glCompileShader(shaderId);
1261
1262 cout << "Loaded successfully" << endl;
1263 } else {
1264 cout << "Failed to load the file" << endl;
1265 }
1266
1267 return shaderId;
1268}
1269
1270GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
1271 GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
1272 GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
1273
1274 GLuint shader_program = glCreateProgram();
1275 glAttachShader(shader_program, vs);
1276 glAttachShader(shader_program, fs);
1277
1278 glLinkProgram(shader_program);
1279
1280 return shader_program;
1281}
1282
1283unsigned char* loadImage(string file_name, int* x, int* y) {
1284 int n;
1285 int force_channels = 4; // This forces RGBA (4 bytes per pixel)
1286 unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
1287
1288 int width_in_bytes = *x * 4;
1289 unsigned char *top = NULL;
1290 unsigned char *bottom = NULL;
1291 unsigned char temp = 0;
1292 int half_height = *y / 2;
1293
1294 // flip image upside-down to account for OpenGL treating lower-left as (0, 0)
1295 for (int row = 0; row < half_height; row++) {
1296 top = image_data + row * width_in_bytes;
1297 bottom = image_data + (*y - row - 1) * width_in_bytes;
1298 for (int col = 0; col < width_in_bytes; col++) {
1299 temp = *top;
1300 *top = *bottom;
1301 *bottom = temp;
1302 top++;
1303 bottom++;
1304 }
1305 }
1306
1307 if (!image_data) {
1308 fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
1309 }
1310
1311 // Not Power-of-2 check
1312 if ((*x & (*x - 1)) != 0 || (*y & (*y - 1)) != 0) {
1313 fprintf(stderr, "WARNING: texture %s is not power-of-2 dimensions\n", file_name.c_str());
1314 }
1315
1316 return image_data;
1317}
1318
1319bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point) {
1320 // LINE EQUATION: P = O + Dt
1321 // O = cam
1322 // D = ray_world
1323
1324 // PLANE EQUATION: P dot n + d = 0
1325 // n is the normal vector
1326 // d is the offset from the origin
1327
1328 // Take the cross-product of two vectors on the plane to get the normal
1329 vec3 v1 = points[1] - points[0];
1330 vec3 v2 = points[2] - points[0];
1331
1332 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);
1333
1334 vec3 local_ray = (inverse(obj->model_mat) * world_ray).xyz();
1335 vec3 local_cam = (inverse(obj->model_mat) * cam).xyz();
1336
1337 local_ray = local_ray - local_cam;
1338
1339 float d = -glm::dot(points[0], normal);
1340 float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
1341
1342 vec3 intersection = local_cam + t*local_ray;
1343
1344 if (insideTriangle(intersection, points)) {
1345 click_point = obj->model_mat * vec4(intersection, 1.0f);
1346 return true;
1347 } else {
1348 return false;
1349 }
1350}
1351
1352bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
1353 vec3 v21 = triangle_points[1] - triangle_points[0];
1354 vec3 v31 = triangle_points[2] - triangle_points[0];
1355 vec3 pv1 = p - triangle_points[0];
1356
1357 float y = (pv1.y*v21.x - pv1.x*v21.y) / (v31.y*v21.x - v31.x*v21.y);
1358 float x = (pv1.x-y*v31.x) / v21.x;
1359
1360 return x > 0.0f && y > 0.0f && x+y < 1.0f;
1361}
1362
1363void printVector(string label, vec3 v) {
1364 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
1365}
1366
1367void print4DVector(string label, vec4 v) {
1368 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
1369}
1370
1371void addObjectToSceneDuringInit(SceneObject& obj) {
1372 obj.id = objects.size(); // currently unused
1373 obj.num_points = obj.points.size() / 3;
1374 obj.model_transform = mat4();
1375 obj.deleted = false;
1376
1377 obj.normals.reserve(obj.points.size());
1378 for (int i = 0; i < obj.points.size(); i += 9) {
1379 vec3 point1 = vec3(obj.points[i], obj.points[i + 1], obj.points[i + 2]);
1380 vec3 point2 = vec3(obj.points[i + 3], obj.points[i + 4], obj.points[i + 5]);
1381 vec3 point3 = vec3(obj.points[i + 6], obj.points[i + 7], obj.points[i + 8]);
1382
1383 vec3 normal = normalize(cross(point2 - point1, point3 - point1));
1384
1385 // Add the same normal for all 3 points
1386 for (int j = 0; j < 3; j++) {
1387 obj.normals.push_back(normal.x);
1388 obj.normals.push_back(normal.y);
1389 obj.normals.push_back(normal.z);
1390 }
1391 }
1392
1393 objects.push_back(obj);
1394}
1395
1396void addObjectToScene(SceneObject& obj,
1397 map<GLuint, BufferInfo>& shaderBufferInfo,
1398 GLuint points_vbo,
1399 GLuint colors_vbo,
1400 GLuint selected_colors_vbo,
1401 GLuint texcoords_vbo,
1402 GLuint normals_vbo,
1403 GLuint ubo,
1404 GLuint model_mat_idx_vbo) {
1405 addObjectToSceneDuringInit(obj);
1406
1407 BufferInfo* bufferInfo = &shaderBufferInfo[obj.shader_program];
1408
1409 // Check if the buffers aren't large enough to fit the new object and, if so, print an error and quit.
1410 // This is a temporary sanity check to make sure things are working as expected
1411 if (bufferInfo->vbo_capacity < (bufferInfo->ubo_offset + obj.num_points) ||
1412 bufferInfo->ubo_capacity < (bufferInfo->ubo_offset + 1)) {
1413 populateBuffers(objects, shaderBufferInfo,
1414 points_vbo,
1415 colors_vbo,
1416 selected_colors_vbo,
1417 texcoords_vbo,
1418 normals_vbo,
1419 ubo,
1420 model_mat_idx_vbo);
1421 } else {
1422 copyObjectDataToBuffers(objects.back(), shaderBufferInfo,
1423 points_vbo,
1424 colors_vbo,
1425 selected_colors_vbo,
1426 texcoords_vbo,
1427 normals_vbo,
1428 ubo,
1429 model_mat_idx_vbo);
1430 }
1431}
1432
1433void removeObjectFromScene(int objectId, GLuint ubo) {
1434 SceneObject& obj = objects[objectId];
1435
1436 if (!obj.deleted) {
1437 // Move the object outside the render bounds of the scene so it doesn't get rendered
1438 // TODO: Find a better way of hiding the object until the next time buffers are repopulated
1439 transformObject(obj, translate(mat4(), vec3(0.0f, 0.0f, FAR_CLIP * 1000.0f)), ubo);
1440 obj.deleted = true;
1441 }
1442}
1443
1444void initializeBuffers(
1445 GLuint* points_vbo,
1446 GLuint* colors_vbo,
1447 GLuint* selected_colors_vbo,
1448 GLuint* texcoords_vbo,
1449 GLuint* normals_vbo,
1450 GLuint* ubo,
1451 GLuint* model_mat_idx_vbo) {
1452 *points_vbo = 0;
1453 glGenBuffers(1, points_vbo);
1454
1455 *colors_vbo = 0;
1456 glGenBuffers(1, colors_vbo);
1457
1458 *selected_colors_vbo = 0;
1459 glGenBuffers(1, selected_colors_vbo);
1460
1461 *texcoords_vbo = 0;
1462 glGenBuffers(1, texcoords_vbo);
1463
1464 *normals_vbo = 0;
1465 glGenBuffers(1, normals_vbo);
1466
1467 *ubo = 0;
1468 glGenBuffers(1, ubo);
1469
1470 *model_mat_idx_vbo = 0;
1471 glGenBuffers(1, model_mat_idx_vbo);
1472}
1473
1474void populateBuffers(vector<SceneObject>& objects,
1475 map<GLuint, BufferInfo>& shaderBufferInfo,
1476 GLuint points_vbo,
1477 GLuint colors_vbo,
1478 GLuint selected_colors_vbo,
1479 GLuint texcoords_vbo,
1480 GLuint normals_vbo,
1481 GLuint ubo,
1482 GLuint model_mat_idx_vbo) {
1483 GLsizeiptr points_buffer_size = 0;
1484 GLsizeiptr textures_buffer_size = 0;
1485 GLsizeiptr ubo_buffer_size = 0;
1486 GLsizeiptr model_mat_idx_buffer_size = 0;
1487
1488 map<GLuint, unsigned int> shaderCounts;
1489 map<GLuint, unsigned int> shaderUboCounts;
1490
1491 vector<SceneObject>::iterator it;
1492
1493 /* Find all shaders that need to be used and the number of objects and
1494 * number of points for each shader. Construct a map from shader id to count
1495 * of points being drawn using that shader (for thw model matrix ubo, we
1496 * need object counts instead). These will be used to get offsets into the
1497 * vertex buffer for each shader.
1498 */
1499 for (it = objects.begin(); it != objects.end();) {
1500 if (it->deleted) {
1501 it = objects.erase(it);
1502 } else {
1503 points_buffer_size += it->points.size() * sizeof(GLfloat);
1504 textures_buffer_size += it->texcoords.size() * sizeof(GLfloat);
1505 ubo_buffer_size += 16 * sizeof(GLfloat);
1506 model_mat_idx_buffer_size += it->num_points * sizeof(GLuint);
1507
1508 if (shaderCounts.count(it->shader_program) == 0) {
1509 shaderCounts[it->shader_program] = it->num_points;
1510 shaderUboCounts[it->shader_program] = 1;
1511 } else {
1512 shaderCounts[it->shader_program] += it->num_points;
1513 shaderUboCounts[it->shader_program]++;
1514 }
1515
1516 it++;
1517 }
1518 }
1519
1520 // double the buffer sizes to leave room for new objects
1521 points_buffer_size *= 2;
1522 textures_buffer_size *= 2;
1523 ubo_buffer_size *= 2;
1524 model_mat_idx_buffer_size *= 2;
1525
1526 map<GLuint, unsigned int>::iterator shaderIt;
1527 unsigned int lastShaderCount = 0;
1528 unsigned int lastShaderUboCount = 0;
1529
1530 /*
1531 * The counts calculated above can be used to get the starting offset of
1532 * each shader in the vertex buffer. Create a map of base offsets to mark
1533 * where the data for the first object using a given shader begins. Also,
1534 * create a map of current offsets to mark where to copy data for the next
1535 * object being added.
1536 */
1537 for (shaderIt = shaderCounts.begin(); shaderIt != shaderCounts.end(); shaderIt++) {
1538 shaderBufferInfo[shaderIt->first].vbo_base = lastShaderCount * 2;
1539 shaderBufferInfo[shaderIt->first].ubo_base = lastShaderUboCount * 2;
1540 cout << "shader: " << shaderIt->first << endl;
1541 cout << "point counts: " << shaderCounts[shaderIt->first] << endl;
1542 cout << "object counts: " << shaderUboCounts[shaderIt->first] << endl;
1543 cout << "vbo_base: " << shaderBufferInfo[shaderIt->first].vbo_base << endl;
1544 cout << "ubo_base: " << shaderBufferInfo[shaderIt->first].ubo_base << endl;
1545
1546 shaderBufferInfo[shaderIt->first].vbo_offset = 0;
1547 shaderBufferInfo[shaderIt->first].ubo_offset = 0;
1548
1549 shaderBufferInfo[shaderIt->first].vbo_capacity = shaderCounts[shaderIt->first] * 2;
1550 shaderBufferInfo[shaderIt->first].ubo_capacity = shaderUboCounts[shaderIt->first] * 2;
1551
1552 lastShaderCount += shaderCounts[shaderIt->first];
1553 lastShaderUboCount += shaderUboCounts[shaderIt->first];
1554 }
1555
1556 // Allocate all the buffers using the counts calculated above
1557
1558 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
1559 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1560
1561 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
1562 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1563
1564 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1565 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1566
1567 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
1568 glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
1569
1570 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
1571 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1572
1573 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1574 glBufferData(GL_UNIFORM_BUFFER, ubo_buffer_size, NULL, GL_DYNAMIC_DRAW);
1575
1576 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
1577 glBufferData(GL_ARRAY_BUFFER, model_mat_idx_buffer_size, NULL, GL_DYNAMIC_DRAW);
1578
1579 for (it = objects.begin(); it != objects.end(); it++) {
1580 copyObjectDataToBuffers(*it, shaderBufferInfo,
1581 points_vbo,
1582 colors_vbo,
1583 selected_colors_vbo,
1584 texcoords_vbo,
1585 normals_vbo,
1586 ubo,
1587 model_mat_idx_vbo);
1588 }
1589}
1590
1591void copyObjectDataToBuffers(SceneObject& obj,
1592 map<GLuint, BufferInfo>& shaderBufferInfo,
1593 GLuint points_vbo,
1594 GLuint colors_vbo,
1595 GLuint selected_colors_vbo,
1596 GLuint texcoords_vbo,
1597 GLuint normals_vbo,
1598 GLuint ubo,
1599 GLuint model_mat_idx_vbo) {
1600 BufferInfo* bufferInfo = &shaderBufferInfo[obj.shader_program];
1601
1602 obj.vertex_vbo_offset = bufferInfo->vbo_base + bufferInfo->vbo_offset;
1603 obj.ubo_offset = bufferInfo->ubo_base + bufferInfo->ubo_offset;
1604
1605 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
1606 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.points.size() * sizeof(GLfloat), &obj.points[0]);
1607
1608 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
1609 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.colors.size() * sizeof(GLfloat), &obj.colors[0]);
1610
1611 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1612 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.selected_colors.size() * sizeof(GLfloat), &obj.selected_colors[0]);
1613
1614 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
1615 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 2, obj.texcoords.size() * sizeof(GLfloat), &obj.texcoords[0]);
1616
1617 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
1618 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.normals.size() * sizeof(GLfloat), &obj.normals[0]);
1619
1620 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
1621 for (int i = 0; i < obj.num_points; i++) {
1622 glBufferSubData(GL_ARRAY_BUFFER, (obj.vertex_vbo_offset + i) * sizeof(GLuint), sizeof(GLuint), &obj.ubo_offset);
1623 }
1624
1625 obj.model_mat = obj.model_base * obj.model_transform;
1626 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1627 glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
1628
1629 bufferInfo->vbo_offset += obj.num_points;
1630 bufferInfo->ubo_offset++;
1631}
1632
1633void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo) {
1634 obj.model_transform = obj.model_transform * transform;
1635 obj.model_mat = obj.model_transform * obj.model_base;
1636
1637 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1638 glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
1639}
1640
1641void renderScene(vector<SceneObject>& objects,
1642 GLuint color_sp, GLuint texture_sp,
1643 GLuint vao1, GLuint vao2,
1644 GLuint points_vbo, GLuint normals_vbo,
1645 GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
1646 SceneObject* selectedObject,
1647 map<GLuint, BufferInfo>& shaderBufferInfo) {
1648
1649 glUseProgram(color_sp);
1650 glBindVertexArray(vao1);
1651
1652 if (selectedObject != NULL) {
1653 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1654 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1655
1656 glDrawArrays(GL_TRIANGLES, selectedObject->vertex_vbo_offset, selectedObject->num_points);
1657 }
1658
1659 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
1660 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1661
1662 glDrawArrays(GL_TRIANGLES, shaderBufferInfo[color_sp].vbo_base, shaderBufferInfo[color_sp].vbo_offset);
1663
1664 glUseProgram(texture_sp);
1665 glBindVertexArray(vao2);
1666
1667 glDrawArrays(GL_TRIANGLES, shaderBufferInfo[texture_sp].vbo_base, shaderBufferInfo[texture_sp].vbo_offset);
1668}
1669
1670void renderSceneGui() {
1671 ImGui_ImplGlfwGL3_NewFrame();
1672
1673 // 1. Show a simple window.
1674 // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
1675 /*
1676 {
1677 static float f = 0.0f;
1678 static int counter = 0;
1679 ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
1680 ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
1681 ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
1682
1683 ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
1684 ImGui::Checkbox("Another Window", &show_another_window);
1685
1686 if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
1687 counter++;
1688 ImGui::SameLine();
1689 ImGui::Text("counter = %d", counter);
1690
1691 ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
1692 }
1693 */
1694
1695 {
1696 ImGui::SetNextWindowSize(ImVec2(85, 22), ImGuiCond_Once);
1697 ImGui::SetNextWindowPos(ImVec2(10, 50), ImGuiCond_Once);
1698 ImGui::Begin("WndStats", NULL,
1699 ImGuiWindowFlags_NoTitleBar |
1700 ImGuiWindowFlags_NoResize |
1701 ImGuiWindowFlags_NoMove);
1702 ImGui::Text("Score: ???");
1703 ImGui::End();
1704 }
1705
1706 {
1707 ImGui::SetNextWindowPos(ImVec2(380, 10), ImGuiCond_Once);
1708 ImGui::SetNextWindowSize(ImVec2(250, 35), ImGuiCond_Once);
1709 ImGui::Begin("WndMenubar", NULL,
1710 ImGuiWindowFlags_NoTitleBar |
1711 ImGuiWindowFlags_NoResize |
1712 ImGuiWindowFlags_NoMove);
1713 ImGui::InvisibleButton("", ImVec2(155, 18));
1714 ImGui::SameLine();
1715 if (ImGui::Button("Main Menu")) {
1716 events.push(EVENT_GO_TO_MAIN_MENU);
1717 }
1718 ImGui::End();
1719 }
1720
1721 ImGui::Render();
1722 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1723}
1724
1725void renderMainMenu() {
1726}
1727
1728void renderMainMenuGui() {
1729 ImGui_ImplGlfwGL3_NewFrame();
1730
1731 {
1732 int padding = 4;
1733 ImGui::SetNextWindowPos(ImVec2(-padding, -padding), ImGuiCond_Once);
1734 ImGui::SetNextWindowSize(ImVec2(width + 2 * padding, height + 2 * padding), ImGuiCond_Once);
1735 ImGui::Begin("WndMain", NULL,
1736 ImGuiWindowFlags_NoTitleBar |
1737 ImGuiWindowFlags_NoResize |
1738 ImGuiWindowFlags_NoMove);
1739
1740 ImGui::InvisibleButton("", ImVec2(10, 80));
1741 ImGui::InvisibleButton("", ImVec2(285, 18));
1742 ImGui::SameLine();
1743 if (ImGui::Button("New Game")) {
1744 events.push(EVENT_GO_TO_GAME);
1745 }
1746
1747 ImGui::InvisibleButton("", ImVec2(10, 15));
1748 ImGui::InvisibleButton("", ImVec2(300, 18));
1749 ImGui::SameLine();
1750 if (ImGui::Button("Quit")) {
1751 events.push(EVENT_QUIT);
1752 }
1753
1754 ImGui::End();
1755 }
1756
1757 ImGui::Render();
1758 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1759}
1760
1761void spawnAsteroid(vec3 pos, GLuint shader,
1762 map<GLuint, BufferInfo>& shaderBufferInfo,
1763 GLuint points_vbo,
1764 GLuint colors_vbo,
1765 GLuint selected_colors_vbo,
1766 GLuint texcoords_vbo,
1767 GLuint normals_vbo,
1768 GLuint ubo,
1769 GLuint model_mat_idx_vbo) {
1770 SceneObject obj = SceneObject();
1771 obj.shader_program = shader;
1772
1773 obj.points = {
1774 // front
1775 1.0f, 1.0f, 1.0f,
1776 -1.0f, 1.0f, 1.0f,
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
1782 // top
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 // bottom
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 // back
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 // right
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 // left
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 obj.colors = {
1823 // front
1824 0.8f, 0.0f, 0.0f,
1825 0.8f, 0.0f, 0.0f,
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
1831 // top
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 // bottom
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 // back
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 // right
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 // left
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 obj.texcoords = { 0.0f };
1872 obj.selected_colors = { 0.0f };
1873
1874 mat4 T = translate(mat4(), pos);
1875 mat4 R = rotate(mat4(), 60.0f * (float)ONE_DEG_IN_RAD, vec3(1.0f, 1.0f, -1.0f));
1876 obj.model_base = T * R * scale(mat4(), vec3(0.1f, 0.1f, 0.1f));
1877
1878 addObjectToScene(obj, shaderBufferInfo,
1879 points_vbo,
1880 colors_vbo,
1881 selected_colors_vbo,
1882 texcoords_vbo,
1883 normals_vbo,
1884 ubo,
1885 model_mat_idx_vbo);
1886}
Note: See TracBrowser for help on using the repository browser.