source: opengl-game/new-game.cpp@ 3effd81

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

Change addLaserToScene() to position the laser between the correct endpoints and rotate it towards the camera so perceived width is constant.

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