source: opengl-game/new-game.cpp@ 81f28c0

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

Begin creating a simple model for the player's ship.

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