source: opengl-game/new-game.cpp@ 92b1e90

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

Add a type field to SceneObject and mostly integrate lasers into the pipeline for creating and rendering objects to the scene (Lasers currently still use their own VBOs).

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