source: opengl-game/new-game.cpp@ 8d5e67b

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

Modify the scene to have the asteroids come out of the top edge of the screen toward the player's ship.

  • Property mode set to 100644
File size: 48.8 KB
Line 
1#include "logger.h"
2
3#include "stb_image.h"
4
5// I think this was for the OpenGL 4 book font file tutorial
6//#define STB_IMAGE_WRITE_IMPLEMENTATION
7//#include "stb_image_write.h"
8
9#define _USE_MATH_DEFINES
10#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, 1.8f));
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.1f, 0.1f, 0.1f));
754
755 addObjectToScene(obj);
756
757 spawnAsteroid(vec3(0.0f, -1.2f, -21.5f), color_sp);
758 spawnAsteroid(vec3(1.0f, -1.2f, -21.5f), color_sp);
759 spawnAsteroid(vec3(-0.5f, -1.2f, -20.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 = -50.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 yaw_mat = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
833 mat4 pitch_mat = rotate(mat4(), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
834 mat4 R = pitch_mat * yaw_mat;
835 view_mat = R*T;
836
837 float fov = 67.0f * ONE_DEG_IN_RAD;
838 float aspect = (float)width / (float)height;
839
840 float range = tan(fov * 0.5f) * NEAR_CLIP;
841 float Sx = NEAR_CLIP / (range * aspect);
842 float Sy = NEAR_CLIP / range;
843 float Sz = -(FAR_CLIP + NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
844 float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
845
846 float proj_arr[] = {
847 Sx, 0.0f, 0.0f, 0.0f,
848 0.0f, Sy, 0.0f, 0.0f,
849 0.0f, 0.0f, Sz, -1.0f,
850 0.0f, 0.0f, Pz, 0.0f,
851 };
852 proj_mat = make_mat4(proj_arr);
853
854 GLuint ub_binding_point = 0;
855
856 GLuint view_test_loc = glGetUniformLocation(color_sp, "view");
857 GLuint proj_test_loc = glGetUniformLocation(color_sp, "proj");
858 GLuint color_sp_ub_index = glGetUniformBlockIndex(color_sp, "models");
859
860 GLuint view_mat_loc = glGetUniformLocation(texture_sp, "view");
861 GLuint proj_mat_loc = glGetUniformLocation(texture_sp, "proj");
862 GLuint texture_sp_ub_index = glGetUniformBlockIndex(texture_sp, "models");
863
864 glUseProgram(color_sp);
865 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
866 glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
867
868 glUniformBlockBinding(color_sp, color_sp_ub_index, ub_binding_point);
869 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
870
871 glUseProgram(texture_sp);
872 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
873 glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
874
875 glUniformBlockBinding(texture_sp, texture_sp_ub_index, ub_binding_point);
876 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
877
878 bool cam_moved = false;
879
880 int frame_count = 0;
881 double elapsed_seconds_fps = 0.0f;
882 double previous_seconds = glfwGetTime();
883
884 // This draws wireframes. Useful for seeing separate faces and occluded objects.
885 //glPolygonMode(GL_FRONT, GL_LINE);
886
887 if (DISABLE_VSYNC && SHOW_FPS) {
888 glfwSwapInterval(0);
889 }
890
891 State curState = STATE_MAIN_MENU;
892
893 while (!glfwWindowShouldClose(window) && isRunning) {
894 double current_seconds = glfwGetTime();
895 double elapsed_seconds = current_seconds - previous_seconds;
896 previous_seconds = current_seconds;
897
898 if (SHOW_FPS) {
899 elapsed_seconds_fps += elapsed_seconds;
900 if (elapsed_seconds_fps > 0.25f) {
901 fps = (double)frame_count / elapsed_seconds_fps;
902 cout << "FPS: " << fps << endl;
903
904 frame_count = 0;
905 elapsed_seconds_fps = 0.0f;
906 }
907
908 frame_count++;
909 }
910
911 // Handle events
912
913 clickedObject = NULL;
914
915 // reset the all key states to KEY_STATE_UNCHANGED (something the GLFW key callback can never return)
916 // so that GLFW_PRESS and GLFW_RELEASE are only detected once
917 // TODO: Change this if we ever need to act on GLFW_REPEAT (which is when a key is held down
918 // continuously for a period of time)
919 fill(key_state, key_state + NUM_KEYS, KEY_STATE_UNCHANGED);
920
921 glfwPollEvents();
922
923 while (!events.empty()) {
924 switch (events.front()) {
925 case EVENT_GO_TO_MAIN_MENU:
926 curState = STATE_MAIN_MENU;
927 break;
928 case EVENT_GO_TO_GAME:
929 curState = STATE_GAME;
930 break;
931 case EVENT_QUIT:
932 isRunning = false;
933 break;
934 }
935 events.pop();
936 }
937
938 if (curState == STATE_GAME) {
939 /*
940 if (clickedObject == &objects[0]) {
941 selectedObject = &objects[0];
942 }
943 if (clickedObject == &objects[1]) {
944 selectedObject = &objects[1];
945 }
946 */
947
948 /*
949 if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
950 transformObject(objects[1], translate(mat4(), vec3(0.3f, 0.0f, 0.0f)), ubo);
951 }
952 if (key_pressed[GLFW_KEY_RIGHT]) {
953 transformObject(objects[2], translate(mat4(), vec3(0.01f, 0.0f, 0.0f)), ubo);
954 }
955 if (key_pressed[GLFW_KEY_LEFT]) {
956 transformObject(objects[2], translate(mat4(), vec3(-0.01f, 0.0f, 0.0f)), ubo);
957 }
958 */
959
960 if (key_pressed[GLFW_KEY_RIGHT]) {
961 transformObject(objects[0], translate(mat4(), vec3(0.01f, 0.0f, 0.0f)), ubo);
962 }
963 if (key_pressed[GLFW_KEY_LEFT]) {
964 transformObject(objects[0], translate(mat4(), vec3(-0.01f, 0.0f, 0.0f)), ubo);
965 }
966
967 if (key_pressed[GLFW_KEY_DOWN]) {
968 transformObject(objects[1], translate(mat4(), vec3(0.0f, 0.0f, 0.03f)), ubo);
969 transformObject(objects[2], translate(mat4(), vec3(0.0f, 0.0f, 0.06f)), ubo);
970 transformObject(objects[3], translate(mat4(), vec3(0.0f, 0.0f, 0.04f)), ubo);
971 }
972 }
973
974 // Render scene
975
976 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
977
978 switch (curState) {
979 case STATE_MAIN_MENU:
980 renderMainMenu();
981 renderMainMenuGui();
982 break;
983 case STATE_GAME:
984 renderScene(objects,
985 color_sp, texture_sp,
986 vao, vao2,
987 points_vbo, normals_vbo,
988 colors_vbo, texcoords_vbo, selected_colors_vbo,
989 selectedObject,
990 shaderCounts, curShaderBase);
991 renderSceneGui();
992 break;
993 }
994
995 glfwSwapBuffers(window);
996
997 if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
998 glfwSetWindowShouldClose(window, 1);
999 }
1000
1001 float dist = cam_speed * elapsed_seconds;
1002 if (glfwGetKey(window, GLFW_KEY_A)) {
1003 vec3 dir = (inverse(R) * vec4(-1.0f, 0.0f, 0.0f, 1.0f)).xyz();
1004 cam_pos += dir * dist;
1005
1006 cam_moved = true;
1007 }
1008 if (glfwGetKey(window, GLFW_KEY_D)) {
1009 vec3 dir = (inverse(R) * vec4(1.0f, 0.0f, 0.0f, 1.0f)).xyz();
1010 cam_pos += dir * dist;
1011
1012 cam_moved = true;
1013 }
1014 if (glfwGetKey(window, GLFW_KEY_W)) {
1015 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, -1.0f, 1.0f)).xyz();
1016 cam_pos += dir * dist;
1017
1018 cam_moved = true;
1019 }
1020 if (glfwGetKey(window, GLFW_KEY_S)) {
1021 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
1022 cam_pos += dir * dist;
1023
1024 cam_moved = true;
1025 }
1026 /*
1027 if (glfwGetKey(window, GLFW_KEY_LEFT)) {
1028 cam_yaw += cam_yaw_speed * elapsed_seconds;
1029 cam_moved = true;
1030 }
1031 if (glfwGetKey(window, GLFW_KEY_RIGHT)) {
1032 cam_yaw -= cam_yaw_speed * elapsed_seconds;
1033 cam_moved = true;
1034 }
1035 if (glfwGetKey(window, GLFW_KEY_UP)) {
1036 cam_pitch += cam_pitch_speed * elapsed_seconds;
1037 cam_moved = true;
1038 }
1039 if (glfwGetKey(window, GLFW_KEY_DOWN)) {
1040 cam_pitch -= cam_pitch_speed * elapsed_seconds;
1041 cam_moved = true;
1042 }
1043 */
1044 if (cam_moved) {
1045 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
1046
1047 mat4 yaw_mat = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
1048 mat4 pitch_mat = rotate(mat4(), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
1049 R = pitch_mat * yaw_mat;
1050
1051 view_mat = R*T;
1052
1053 //printVector("cam pos", cam_pos);
1054
1055 glUseProgram(color_sp);
1056 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
1057
1058 glUseProgram(texture_sp);
1059 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
1060
1061 cam_moved = false;
1062 }
1063 }
1064
1065 ImGui_ImplGlfwGL3_Shutdown();
1066 ImGui::DestroyContext();
1067
1068 glfwDestroyWindow(window);
1069 glfwTerminate();
1070
1071 return 0;
1072}
1073
1074void glfw_error_callback(int error, const char* description) {
1075 gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
1076}
1077
1078void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
1079 double mouse_x, mouse_y;
1080 glfwGetCursorPos(window, &mouse_x, &mouse_y);
1081
1082 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
1083 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
1084 selectedObject = NULL;
1085
1086 float x = (2.0f*mouse_x) / width - 1.0f;
1087 float y = 1.0f - (2.0f*mouse_y) / height;
1088
1089 cout << "x: " << x << ", y: " << y << endl;
1090
1091 vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
1092 vec4 ray_eye = inverse(proj_mat) * ray_clip;
1093 ray_eye = vec4(ray_eye.xy(), -1.0f, 1.0f);
1094 vec4 ray_world = inverse(view_mat) * ray_eye;
1095
1096 vec4 cam_pos_temp = vec4(cam_pos, 1.0f);
1097
1098 vec4 click_point;
1099 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
1100 SceneObject* closest_object = NULL;
1101
1102 for (vector<SceneObject>::iterator it = objects.begin(); it != objects.end(); it++) {
1103 for (unsigned int p_idx = 0; p_idx < it->points.size(); p_idx += 9) {
1104 if (faceClicked(
1105 {
1106 vec3(it->points[p_idx], it->points[p_idx + 1], it->points[p_idx + 2]),
1107 vec3(it->points[p_idx + 3], it->points[p_idx + 4], it->points[p_idx + 5]),
1108 vec3(it->points[p_idx + 6], it->points[p_idx + 7], it->points[p_idx + 8]),
1109 },
1110 &*it, ray_world, cam_pos_temp, click_point
1111 )) {
1112 click_point = view_mat * click_point;
1113
1114 if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
1115 closest_point = click_point.xyz();
1116 closest_object = &*it;
1117 }
1118 }
1119 }
1120 }
1121
1122 if (closest_object == NULL) {
1123 cout << "No object was clicked" << endl;
1124 } else {
1125 clickedObject = closest_object;
1126 cout << "Clicked object: " << clickedObject->id << endl;
1127 }
1128 }
1129}
1130
1131void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
1132 key_state[key] = action;
1133
1134 // should be true for GLFW_PRESS and GLFW_REPEAT
1135 key_pressed[key] = (action != GLFW_RELEASE);
1136}
1137
1138
1139GLuint loadShader(GLenum type, string file) {
1140 cout << "Loading shader from file " << file << endl;
1141
1142 ifstream shaderFile(file);
1143 GLuint shaderId = 0;
1144
1145 if (shaderFile.is_open()) {
1146 string line, shaderString;
1147
1148 while(getline(shaderFile, line)) {
1149 shaderString += line + "\n";
1150 }
1151 shaderFile.close();
1152 const char* shaderCString = shaderString.c_str();
1153
1154 shaderId = glCreateShader(type);
1155 glShaderSource(shaderId, 1, &shaderCString, NULL);
1156 glCompileShader(shaderId);
1157
1158 cout << "Loaded successfully" << endl;
1159 } else {
1160 cout << "Failed to load the file" << endl;
1161 }
1162
1163 return shaderId;
1164}
1165
1166GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
1167 GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
1168 GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
1169
1170 GLuint shader_program = glCreateProgram();
1171 glAttachShader(shader_program, vs);
1172 glAttachShader(shader_program, fs);
1173
1174 glLinkProgram(shader_program);
1175
1176 return shader_program;
1177}
1178
1179unsigned char* loadImage(string file_name, int* x, int* y) {
1180 int n;
1181 int force_channels = 4; // This forces RGBA (4 bytes per pixel)
1182 unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
1183
1184 int width_in_bytes = *x * 4;
1185 unsigned char *top = NULL;
1186 unsigned char *bottom = NULL;
1187 unsigned char temp = 0;
1188 int half_height = *y / 2;
1189
1190 // flip image upside-down to account for OpenGL treating lower-left as (0, 0)
1191 for (int row = 0; row < half_height; row++) {
1192 top = image_data + row * width_in_bytes;
1193 bottom = image_data + (*y - row - 1) * width_in_bytes;
1194 for (int col = 0; col < width_in_bytes; col++) {
1195 temp = *top;
1196 *top = *bottom;
1197 *bottom = temp;
1198 top++;
1199 bottom++;
1200 }
1201 }
1202
1203 if (!image_data) {
1204 fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
1205 }
1206
1207 // Not Power-of-2 check
1208 if ((*x & (*x - 1)) != 0 || (*y & (*y - 1)) != 0) {
1209 fprintf(stderr, "WARNING: texture %s is not power-of-2 dimensions\n", file_name.c_str());
1210 }
1211
1212 return image_data;
1213}
1214
1215bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point) {
1216 // LINE EQUATION: P = O + Dt
1217 // O = cam
1218 // D = ray_world
1219
1220 // PLANE EQUATION: P dot n + d = 0
1221 // n is the normal vector
1222 // d is the offset from the origin
1223
1224 // Take the cross-product of two vectors on the plane to get the normal
1225 vec3 v1 = points[1] - points[0];
1226 vec3 v2 = points[2] - points[0];
1227
1228 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);
1229
1230 vec3 local_ray = (inverse(obj->model_mat) * world_ray).xyz();
1231 vec3 local_cam = (inverse(obj->model_mat) * cam).xyz();
1232
1233 local_ray = local_ray - local_cam;
1234
1235 float d = -glm::dot(points[0], normal);
1236 float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
1237
1238 vec3 intersection = local_cam + t*local_ray;
1239
1240 if (insideTriangle(intersection, points)) {
1241 click_point = obj->model_mat * vec4(intersection, 1.0f);
1242 return true;
1243 } else {
1244 return false;
1245 }
1246}
1247
1248bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
1249 vec3 v21 = triangle_points[1] - triangle_points[0];
1250 vec3 v31 = triangle_points[2] - triangle_points[0];
1251 vec3 pv1 = p - triangle_points[0];
1252
1253 float y = (pv1.y*v21.x - pv1.x*v21.y) / (v31.y*v21.x - v31.x*v21.y);
1254 float x = (pv1.x-y*v31.x) / v21.x;
1255
1256 return x > 0.0f && y > 0.0f && x+y < 1.0f;
1257}
1258
1259void printVector(string label, vec3 v) {
1260 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
1261}
1262
1263void print4DVector(string label, vec4 v) {
1264 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
1265}
1266
1267void addObjectToScene(SceneObject& obj) {
1268 obj.id = objects.size(); // currently unused
1269 obj.num_points = obj.points.size() / 3;
1270 obj.model_transform = mat4();
1271
1272 obj.normals.reserve(obj.points.size());
1273 for (int i = 0; i < obj.points.size(); i += 9) {
1274 vec3 point1 = vec3(obj.points[i], obj.points[i + 1], obj.points[i + 2]);
1275 vec3 point2 = vec3(obj.points[i + 3], obj.points[i + 4], obj.points[i + 5]);
1276 vec3 point3 = vec3(obj.points[i + 6], obj.points[i + 7], obj.points[i + 8]);
1277
1278 vec3 normal = normalize(cross(point2 - point1, point3 - point1));
1279
1280 // Add the same normal for all 3 points
1281 for (int j = 0; j < 3; j++) {
1282 obj.normals.push_back(normal.x);
1283 obj.normals.push_back(normal.y);
1284 obj.normals.push_back(normal.z);
1285 }
1286 }
1287
1288 objects.push_back(obj);
1289}
1290
1291void populateBuffers(vector<SceneObject>& objects,
1292 GLuint* points_vbo,
1293 GLuint* colors_vbo,
1294 GLuint* selected_colors_vbo,
1295 GLuint* texcoords_vbo,
1296 GLuint* normals_vbo,
1297 GLuint* ubo,
1298 GLuint* model_mat_idx_vbo,
1299 map<GLuint, unsigned int>& shaderCounts,
1300 map<GLuint, unsigned int>& curShaderBase) {
1301 GLsizeiptr points_buffer_size = 0;
1302 GLsizeiptr textures_buffer_size = 0;
1303 GLsizeiptr ubo_buffer_size = 0;
1304 GLsizeiptr model_mat_idx_buffer_size = 0;
1305
1306 map<GLuint, unsigned int> curShaderOffset;
1307
1308 map<GLuint, unsigned int> shaderUboCounts;
1309 map<GLuint, unsigned int> curShaderUboBase;
1310 map<GLuint, unsigned int> curShaderUboOffset;
1311
1312 vector<SceneObject>::iterator it;
1313
1314 /* Find all shaders that need to be used and the number of objects and
1315 * number of points for each shader. Construct a map from shader id to count
1316 * of points being drawn using that shader (for thw model matrix ubo, we
1317 * need object counts instead). These will be used to get offsets into the
1318 * vertex buffer for each shader.
1319 */
1320 for (it = objects.begin(); it != objects.end(); it++) {
1321 points_buffer_size += it->points.size() * sizeof(GLfloat);
1322 textures_buffer_size += it->texcoords.size() * sizeof(GLfloat);
1323 ubo_buffer_size += 16 * sizeof(GLfloat);
1324 model_mat_idx_buffer_size += it->num_points * sizeof(GLuint);
1325
1326 if (shaderCounts.count(it->shader_program) == 0) {
1327 shaderCounts[it->shader_program] = it->num_points;
1328 shaderUboCounts[it->shader_program] = 1;
1329 } else {
1330 shaderCounts[it->shader_program] += it->num_points;
1331 shaderUboCounts[it->shader_program]++;
1332 }
1333 }
1334
1335 map<GLuint, unsigned int>::iterator shaderIt;
1336 unsigned int lastShaderCount = 0;
1337 unsigned int lastShaderUboCount = 0;
1338
1339 /*
1340 * The counts calculated above can be used to get the starting offset of
1341 * each shader in the vertex buffer. Create a map of base offsets to mark
1342 * where the data for the first object using a given shader begins. Also,
1343 * create a map of current offsets to mark where to copy data for the next
1344 * object being added.
1345 */
1346 cout << "Shader counts:" << endl;
1347 for (shaderIt = shaderCounts.begin(); shaderIt != shaderCounts.end(); shaderIt++) {
1348 curShaderOffset[shaderIt->first] = 0;
1349 curShaderUboOffset[shaderIt->first] = 0;
1350
1351 curShaderBase[shaderIt->first] = lastShaderCount;
1352 lastShaderCount += shaderCounts[shaderIt->first];
1353
1354 curShaderUboBase[shaderIt->first] = lastShaderUboCount;
1355 lastShaderUboCount += shaderUboCounts[shaderIt->first];
1356 }
1357
1358 // Initialize all the buffers using the counts calculated above
1359
1360 *points_vbo = 0;
1361 glGenBuffers(1, points_vbo);
1362 glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
1363 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1364
1365 *colors_vbo = 0;
1366 glGenBuffers(1, colors_vbo);
1367 glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
1368 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1369
1370 *selected_colors_vbo = 0;
1371 glGenBuffers(1, selected_colors_vbo);
1372 glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
1373 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1374
1375 *texcoords_vbo = 0;
1376 glGenBuffers(1, texcoords_vbo);
1377 glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
1378 glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
1379
1380 *normals_vbo = 0;
1381 glGenBuffers(1, normals_vbo);
1382 glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
1383 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1384
1385 *ubo = 0;
1386 glGenBuffers(1, ubo);
1387 glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
1388 glBufferData(GL_UNIFORM_BUFFER, ubo_buffer_size, NULL, GL_DYNAMIC_DRAW);
1389
1390 *model_mat_idx_vbo = 0;
1391 glGenBuffers(1, model_mat_idx_vbo);
1392 glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
1393 glBufferData(GL_ARRAY_BUFFER, model_mat_idx_buffer_size, NULL, GL_DYNAMIC_DRAW);
1394
1395 for (it = objects.begin(); it != objects.end(); it++) {
1396 it->vertex_vbo_offset = curShaderBase[it->shader_program] + curShaderOffset[it->shader_program];
1397 it->ubo_offset = curShaderUboBase[it->shader_program] + curShaderUboOffset[it->shader_program];
1398
1399 glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
1400 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->points.size() * sizeof(GLfloat), &it->points[0]);
1401
1402 glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
1403 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->colors.size() * sizeof(GLfloat), &it->colors[0]);
1404
1405 glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
1406 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->selected_colors.size() * sizeof(GLfloat), &it->selected_colors[0]);
1407
1408 glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
1409 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 2, it->texcoords.size() * sizeof(GLfloat), &it->texcoords[0]);
1410
1411 glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
1412 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->normals.size() * sizeof(GLfloat), &it->normals[0]);
1413
1414 glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
1415 for (int i = 0; i < it->num_points; i++) {
1416 glBufferSubData(GL_ARRAY_BUFFER, (it->vertex_vbo_offset + i) * sizeof(GLuint), sizeof(GLuint), &it->ubo_offset);
1417 }
1418
1419 curShaderOffset[it->shader_program] += it->num_points;
1420
1421 it->model_mat = it->model_base * it->model_transform;
1422 glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
1423 glBufferSubData(GL_UNIFORM_BUFFER, it->ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(it->model_mat));
1424
1425 curShaderUboOffset[it->shader_program]++;
1426 }
1427}
1428
1429void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo) {
1430 obj.model_transform = obj.model_transform * transform;
1431 obj.model_mat = obj.model_transform * obj.model_base;
1432
1433 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1434 glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
1435}
1436
1437void renderScene(vector<SceneObject>& objects,
1438 GLuint color_sp, GLuint texture_sp,
1439 GLuint vao1, GLuint vao2,
1440 GLuint points_vbo, GLuint normals_vbo,
1441 GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
1442 SceneObject* selectedObject,
1443 map<GLuint, unsigned int>& shaderCounts,
1444 map<GLuint, unsigned int>& curShaderBase) {
1445
1446 glUseProgram(color_sp);
1447 glBindVertexArray(vao1);
1448
1449 if (selectedObject != NULL) {
1450 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1451 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1452
1453 glDrawArrays(GL_TRIANGLES, selectedObject->vertex_vbo_offset, selectedObject->num_points);
1454 }
1455
1456 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
1457 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1458
1459 glDrawArrays(GL_TRIANGLES, curShaderBase[color_sp], shaderCounts[color_sp]);
1460
1461 glUseProgram(texture_sp);
1462 glBindVertexArray(vao2);
1463
1464 glDrawArrays(GL_TRIANGLES, curShaderBase[texture_sp], shaderCounts[texture_sp]);
1465}
1466
1467void renderSceneGui() {
1468 ImGui_ImplGlfwGL3_NewFrame();
1469
1470 // 1. Show a simple window.
1471 // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
1472 /*
1473 {
1474 static float f = 0.0f;
1475 static int counter = 0;
1476 ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
1477 ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
1478 ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
1479
1480 ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
1481 ImGui::Checkbox("Another Window", &show_another_window);
1482
1483 if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
1484 counter++;
1485 ImGui::SameLine();
1486 ImGui::Text("counter = %d", counter);
1487
1488 ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
1489 }
1490 */
1491
1492 {
1493 ImGui::SetNextWindowSize(ImVec2(85, 22), ImGuiCond_Once);
1494 ImGui::SetNextWindowPos(ImVec2(10, 50), ImGuiCond_Once);
1495 ImGui::Begin("WndStats", NULL,
1496 ImGuiWindowFlags_NoTitleBar |
1497 ImGuiWindowFlags_NoResize |
1498 ImGuiWindowFlags_NoMove);
1499 ImGui::Text("Score: ???");
1500 ImGui::End();
1501 }
1502
1503 {
1504 ImGui::SetNextWindowPos(ImVec2(380, 10), ImGuiCond_Once);
1505 ImGui::SetNextWindowSize(ImVec2(250, 35), ImGuiCond_Once);
1506 ImGui::Begin("WndMenubar", NULL,
1507 ImGuiWindowFlags_NoTitleBar |
1508 ImGuiWindowFlags_NoResize |
1509 ImGuiWindowFlags_NoMove);
1510 ImGui::InvisibleButton("", ImVec2(155, 18));
1511 ImGui::SameLine();
1512 if (ImGui::Button("Main Menu")) {
1513 events.push(EVENT_GO_TO_MAIN_MENU);
1514 }
1515 ImGui::End();
1516 }
1517
1518 ImGui::Render();
1519 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1520}
1521
1522void renderMainMenu() {
1523}
1524
1525void renderMainMenuGui() {
1526 ImGui_ImplGlfwGL3_NewFrame();
1527
1528 {
1529 int padding = 4;
1530 ImGui::SetNextWindowPos(ImVec2(-padding, -padding), ImGuiCond_Once);
1531 ImGui::SetNextWindowSize(ImVec2(width + 2 * padding, height + 2 * padding), ImGuiCond_Once);
1532 ImGui::Begin("WndMain", NULL,
1533 ImGuiWindowFlags_NoTitleBar |
1534 ImGuiWindowFlags_NoResize |
1535 ImGuiWindowFlags_NoMove);
1536
1537 ImGui::InvisibleButton("", ImVec2(10, 80));
1538 ImGui::InvisibleButton("", ImVec2(285, 18));
1539 ImGui::SameLine();
1540 if (ImGui::Button("New Game")) {
1541 events.push(EVENT_GO_TO_GAME);
1542 }
1543
1544 ImGui::InvisibleButton("", ImVec2(10, 15));
1545 ImGui::InvisibleButton("", ImVec2(300, 18));
1546 ImGui::SameLine();
1547 if (ImGui::Button("Quit")) {
1548 events.push(EVENT_QUIT);
1549 }
1550
1551 ImGui::End();
1552 }
1553
1554 ImGui::Render();
1555 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1556}
1557
1558void spawnAsteroid(vec3 pos, GLuint shader) {
1559 SceneObject obj = SceneObject();
1560 obj.shader_program = shader;
1561
1562 obj.points = {
1563 // front
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 -1.0f, -1.0f, 1.0f,
1569 1.0f, -1.0f, 1.0f,
1570
1571 // top
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 -1.0f, 1.0f, 1.0f,
1577 1.0f, 1.0f, 1.0f,
1578
1579 // bottom
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 -1.0f, -1.0f, -1.0f,
1585 1.0f, -1.0f, -1.0f,
1586
1587 // back
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 1.0f, -1.0f, -1.0f,
1593 -1.0f, -1.0f, -1.0f,
1594
1595 // right
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 1.0f, -1.0f, 1.0f,
1601 1.0f, -1.0f, -1.0f,
1602
1603 // left
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 -1.0f, -1.0f, -1.0f,
1609 -1.0f, -1.0f, 1.0f,
1610 };
1611 obj.colors = {
1612 // front
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 0.8f, 0.0f, 0.0f,
1618 0.8f, 0.0f, 0.0f,
1619
1620 // top
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 0.8f, 0.0f, 0.0f,
1626 0.8f, 0.0f, 0.0f,
1627
1628 // bottom
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 0.8f, 0.0f, 0.0f,
1634 0.8f, 0.0f, 0.0f,
1635
1636 // back
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 0.8f, 0.0f, 0.0f,
1642 0.8f, 0.0f, 0.0f,
1643
1644 // right
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 0.8f, 0.0f, 0.0f,
1650 0.8f, 0.0f, 0.0f,
1651
1652 // left
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 0.8f, 0.0f, 0.0f,
1658 0.8f, 0.0f, 0.0f,
1659 };
1660 obj.texcoords = { 0.0f };
1661 obj.selected_colors = { 0.0f };
1662
1663 mat4 T = translate(mat4(), pos);
1664 mat4 R = rotate(mat4(), 60.0f * (float)ONE_DEG_IN_RAD, vec3(1.0f, 1.0f, -1.0f));
1665 obj.model_base = T * R * scale(mat4(), vec3(0.1f, 0.1f, 0.1f));
1666
1667 addObjectToScene(obj);
1668}
Note: See TracBrowser for help on using the repository browser.