source: opengl-game/new-game.cpp@ 6877ef3

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

Finish integrating lasers into the object rendering pipeline and remove a bunch of code for creating and using laser-specific vbos.

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