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

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

WIP: Start writing code for rendering lasers

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