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

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

-Stop rendering the triangle and square
-Place the player ship at the bottom center of screen, heading up and

into the screen

-Create a method for spawning asteroids and place several in the scene
-Allow the player to move the ship left and right and move the asteroids

towards the ship

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