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

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

Change the laser rendering algorithm to draw lasers starting from the origin and then translate them into the correct position using the model matrix.

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