source: opengl-game/new-game.cpp@ 95595de

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

Update each object's bounding center as the object moves, and remove asteroids from the scene once they leave the visible area.

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