source: opengl-game/new-game.cpp@ 809ce16

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

Add the ability to tilt the camera up or down with arrow keys. Moving the camera still moves it forward, backward, left, or right based on the cmera's current orientation. Using the right or left arrow keys will pan the cemra around the world y axis, regardless of its vertical tilt.

  • Property mode set to 100644
File size: 38.1 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 0.0f, 0.5f, 0.0f,
380 -0.5f, -0.5f, 0.0f,
381 0.5f, -0.5f, 0.0f,
382 0.5f, -0.5f, 0.0f,
383 -0.5f, -0.5f, 0.0f,
384 0.0f, 0.5f, 0.0f,
385 };
386 obj.colors = {
387 0.0f, 0.0f, 0.3f,
388 0.0f, 0.0f, 0.3f,
389 0.0f, 0.0f, 0.3f,
390 0.0f, 0.0f, 0.3f,
391 0.0f, 0.0f, 0.3f,
392 0.0f, 0.0f, 0.3f,
393 };
394 obj.texcoords = {
395 1.0f, 1.0f,
396 0.0f, 1.0f,
397 0.0f, 0.0f,
398 1.0f, 1.0f,
399 0.0f, 0.0f,
400 1.0f, 0.0f,
401 };
402 obj.selected_colors = {
403 0.0f, 1.0f, 0.0f,
404 0.0f, 1.0f, 0.0f,
405 0.0f, 1.0f, 0.0f,
406 0.0f, 1.0f, 0.0f,
407 0.0f, 1.0f, 0.0f,
408 0.0f, 1.0f, 0.0f,
409 };
410
411 T_model = translate(mat4(), vec3(0.0f, -0.9f, 0.0f));
412 R_model = rotate(mat4(), -1.0f, vec3(1.0f, 0.0f, 0.0f));
413 obj.model_base = T_model; //T_model * R_model;
414
415 addObjectToScene(obj);
416
417 vector<SceneObject>::iterator obj_it;
418 GLsizeiptr offset;
419
420 GLuint points_vbo, colors_vbo, selected_colors_vbo, texcoords_vbo,
421 normals_vbo, ubo, model_mat_idx_vbo;
422
423 map<GLuint, unsigned int> shaderCounts, curShaderBase;
424
425 populateBuffers(objects,
426 &points_vbo,
427 &colors_vbo,
428 &selected_colors_vbo,
429 &texcoords_vbo,
430 &normals_vbo,
431 &ubo,
432 &model_mat_idx_vbo,
433 shaderCounts,
434 curShaderBase);
435
436 GLuint vao = 0;
437 glGenVertexArrays(1, &vao);
438 glBindVertexArray(vao);
439
440 glEnableVertexAttribArray(0);
441 glEnableVertexAttribArray(1);
442 glEnableVertexAttribArray(2);
443 glEnableVertexAttribArray(3);
444
445 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
446 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
447
448 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
449 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
450
451 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
452 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
453
454 GLuint vao2 = 0;
455 glGenVertexArrays(1, &vao2);
456 glBindVertexArray(vao2);
457
458 glEnableVertexAttribArray(0);
459 glEnableVertexAttribArray(1);
460 glEnableVertexAttribArray(2);
461 glEnableVertexAttribArray(3);
462
463 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
464 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
465
466 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
467 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
468
469 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
470 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
471
472 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
473 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
474
475 float cam_speed = 1.0f;
476 float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
477 float cam_pitch_speed = 60.0f*ONE_DEG_IN_RAD;
478
479 // glm::lookAt can create the view matrix
480 // glm::perspective can create the projection matrix
481
482 cam_pos = vec3(0.0f, 0.0f, 2.0f);
483 float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
484 float cam_pitch = 0.0f * 2.0f * 3.14159f / 360.0f;
485
486 mat4 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
487 mat4 R = mat4();
488 view_mat = R*T;
489
490 float fov = 67.0f * ONE_DEG_IN_RAD;
491 float aspect = (float)width / (float)height;
492
493 float range = tan(fov * 0.5f) * NEAR_CLIP;
494 float Sx = NEAR_CLIP / (range * aspect);
495 float Sy = NEAR_CLIP / range;
496 float Sz = -(FAR_CLIP + NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
497 float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
498
499 float proj_arr[] = {
500 Sx, 0.0f, 0.0f, 0.0f,
501 0.0f, Sy, 0.0f, 0.0f,
502 0.0f, 0.0f, Sz, -1.0f,
503 0.0f, 0.0f, Pz, 0.0f,
504 };
505 proj_mat = make_mat4(proj_arr);
506
507 GLuint ub_binding_point = 0;
508
509 GLuint view_test_loc = glGetUniformLocation(color_sp, "view");
510 GLuint proj_test_loc = glGetUniformLocation(color_sp, "proj");
511 GLuint color_sp_ub_index = glGetUniformBlockIndex(color_sp, "models");
512
513 GLuint view_mat_loc = glGetUniformLocation(texture_sp, "view");
514 GLuint proj_mat_loc = glGetUniformLocation(texture_sp, "proj");
515 GLuint texture_sp_ub_index = glGetUniformBlockIndex(texture_sp, "models");
516
517 glUseProgram(color_sp);
518 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
519 glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
520
521 glUniformBlockBinding(color_sp, color_sp_ub_index, ub_binding_point);
522 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
523
524 glUseProgram(texture_sp);
525 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
526 glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
527
528 glUniformBlockBinding(texture_sp, texture_sp_ub_index, ub_binding_point);
529 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
530
531 bool cam_moved = false;
532
533 int frame_count = 0;
534 double elapsed_seconds_fps = 0.0f;
535 double previous_seconds = glfwGetTime();
536
537 // This draws wireframes. Useful for seeing separate faces and occluded objects.
538 //glPolygonMode(GL_FRONT, GL_LINE);
539
540 if (DISABLE_VSYNC && SHOW_FPS) {
541 glfwSwapInterval(0);
542 }
543
544 State curState = STATE_MAIN_MENU;
545
546 while (!glfwWindowShouldClose(window) && isRunning) {
547 double current_seconds = glfwGetTime();
548 double elapsed_seconds = current_seconds - previous_seconds;
549 previous_seconds = current_seconds;
550
551 if (SHOW_FPS) {
552 elapsed_seconds_fps += elapsed_seconds;
553 if (elapsed_seconds_fps > 0.25f) {
554 fps = (double)frame_count / elapsed_seconds_fps;
555 cout << "FPS: " << fps << endl;
556
557 frame_count = 0;
558 elapsed_seconds_fps = 0.0f;
559 }
560
561 frame_count++;
562 }
563
564 // Handle events
565
566 clickedObject = NULL;
567
568 // reset the all key states to KEY_STATE_UNCHANGED (something the GLFW key callback can never return)
569 // so that GLFW_PRESS and GLFW_RELEASE are only detected once
570 // TODO: Change this if we ever need to act on GLFW_REPEAT (which is when a key is held down continuously)
571 fill(key_state, key_state + NUM_KEYS, KEY_STATE_UNCHANGED);
572
573 glfwPollEvents();
574
575 while (!events.empty()) {
576 switch (events.front()) {
577 case EVENT_GO_TO_MAIN_MENU:
578 curState = STATE_MAIN_MENU;
579 break;
580 case EVENT_GO_TO_GAME:
581 curState = STATE_GAME;
582 break;
583 case EVENT_QUIT:
584 isRunning = false;
585 break;
586 }
587 events.pop();
588 }
589
590 if (curState == STATE_GAME) {
591 if (clickedObject == &objects[0]) {
592 selectedObject = &objects[0];
593 }
594 if (clickedObject == &objects[1]) {
595 selectedObject = &objects[1];
596 }
597
598 /*
599 if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
600 transformObject(objects[1], translate(mat4(), vec3(0.3f, 0.0f, 0.0f)), ubo);
601 }
602 if (key_pressed[GLFW_KEY_RIGHT]) {
603 transformObject(objects[2], translate(mat4(), vec3(0.01f, 0.0f, 0.0f)), ubo);
604 }
605 if (key_pressed[GLFW_KEY_LEFT]) {
606 transformObject(objects[2], translate(mat4(), vec3(-0.01f, 0.0f, 0.0f)), ubo);
607 }
608 */
609 }
610
611 // Render scene
612
613 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
614
615 switch (curState) {
616 case STATE_MAIN_MENU:
617 renderMainMenu();
618 renderMainMenuGui();
619 break;
620 case STATE_GAME:
621 renderScene(objects,
622 color_sp, texture_sp,
623 vao, vao2,
624 points_vbo, normals_vbo,
625 colors_vbo, texcoords_vbo, selected_colors_vbo,
626 selectedObject,
627 shaderCounts, curShaderBase);
628 renderSceneGui();
629 break;
630 }
631
632 glfwSwapBuffers(window);
633
634 if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
635 glfwSetWindowShouldClose(window, 1);
636 }
637
638 float dist = cam_speed * elapsed_seconds;
639 if (glfwGetKey(window, GLFW_KEY_A)) {
640 vec3 dir = (inverse(R) * vec4(-1.0f, 0.0f, 0.0f, 1.0f)).xyz();
641 cam_pos += dir * dist;
642
643 cam_moved = true;
644 }
645 if (glfwGetKey(window, GLFW_KEY_D)) {
646 vec3 dir = (inverse(R) * vec4(1.0f, 0.0f, 0.0f, 1.0f)).xyz();
647 cam_pos += dir * dist;
648
649 cam_moved = true;
650 }
651 if (glfwGetKey(window, GLFW_KEY_W)) {
652 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, -1.0f, 1.0f)).xyz();
653 cam_pos += dir * dist;
654
655 cam_moved = true;
656 }
657 if (glfwGetKey(window, GLFW_KEY_S)) {
658 vec3 dir = (inverse(R) * vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
659 cam_pos += dir * dist;
660
661 cam_moved = true;
662 }
663 if (glfwGetKey(window, GLFW_KEY_LEFT)) {
664 cam_yaw += cam_yaw_speed * elapsed_seconds;
665 cam_moved = true;
666 }
667 if (glfwGetKey(window, GLFW_KEY_RIGHT)) {
668 cam_yaw -= cam_yaw_speed * elapsed_seconds;
669 cam_moved = true;
670 }
671 if (glfwGetKey(window, GLFW_KEY_UP)) {
672 cam_pitch += cam_pitch_speed * elapsed_seconds;
673 cam_moved = true;
674 }
675 if (glfwGetKey(window, GLFW_KEY_DOWN)) {
676 cam_pitch -= cam_pitch_speed * elapsed_seconds;
677 cam_moved = true;
678 }
679 if (cam_moved) {
680 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
681
682 mat4 yaw_mat = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
683 mat4 pitch_mat = rotate(mat4(), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
684 R = pitch_mat * yaw_mat;
685
686 view_mat = R*T;
687
688 printVector("cam pos", cam_pos);
689
690 glUseProgram(color_sp);
691 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
692
693 glUseProgram(texture_sp);
694 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
695
696 cam_moved = false;
697 }
698 }
699
700 ImGui_ImplGlfwGL3_Shutdown();
701 ImGui::DestroyContext();
702
703 glfwDestroyWindow(window);
704 glfwTerminate();
705
706 return 0;
707}
708
709void glfw_error_callback(int error, const char* description) {
710 gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
711}
712
713void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
714 double mouse_x, mouse_y;
715 glfwGetCursorPos(window, &mouse_x, &mouse_y);
716
717 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
718 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
719 selectedObject = NULL;
720
721 float x = (2.0f*mouse_x) / width - 1.0f;
722 float y = 1.0f - (2.0f*mouse_y) / height;
723
724 cout << "x: " << x << ", y: " << y << endl;
725
726 vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
727 vec4 ray_eye = inverse(proj_mat) * ray_clip;
728 ray_eye = vec4(ray_eye.xy(), -1.0f, 1.0f);
729 vec4 ray_world = inverse(view_mat) * ray_eye;
730
731 vec4 cam_pos_temp = vec4(cam_pos, 1.0f);
732
733 vec4 click_point;
734 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
735 SceneObject* closest_object = NULL;
736
737 for (vector<SceneObject>::iterator it = objects.begin(); it != objects.end(); it++) {
738 for (unsigned int p_idx = 0; p_idx < it->points.size(); p_idx += 9) {
739 if (faceClicked(
740 {
741 vec3(it->points[p_idx], it->points[p_idx + 1], it->points[p_idx + 2]),
742 vec3(it->points[p_idx + 3], it->points[p_idx + 4], it->points[p_idx + 5]),
743 vec3(it->points[p_idx + 6], it->points[p_idx + 7], it->points[p_idx + 8]),
744 },
745 &*it, ray_world, cam_pos_temp, click_point
746 )) {
747 click_point = view_mat * click_point;
748
749 if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
750 closest_point = click_point.xyz();
751 closest_object = &*it;
752 }
753 }
754 }
755 }
756
757 if (closest_object == NULL) {
758 cout << "No object was clicked" << endl;
759 } else {
760 clickedObject = closest_object;
761 cout << "Clicked object: " << clickedObject->id << endl;
762 }
763 }
764}
765
766void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
767 key_state[key] = action;
768
769 // should be true for GLFW_PRESS and GLFW_REPEAT
770 key_pressed[key] = (action != GLFW_RELEASE);
771}
772
773
774GLuint loadShader(GLenum type, string file) {
775 cout << "Loading shader from file " << file << endl;
776
777 ifstream shaderFile(file);
778 GLuint shaderId = 0;
779
780 if (shaderFile.is_open()) {
781 string line, shaderString;
782
783 while(getline(shaderFile, line)) {
784 shaderString += line + "\n";
785 }
786 shaderFile.close();
787 const char* shaderCString = shaderString.c_str();
788
789 shaderId = glCreateShader(type);
790 glShaderSource(shaderId, 1, &shaderCString, NULL);
791 glCompileShader(shaderId);
792
793 cout << "Loaded successfully" << endl;
794 } else {
795 cout << "Failed to load the file" << endl;
796 }
797
798 return shaderId;
799}
800
801GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
802 GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
803 GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
804
805 GLuint shader_program = glCreateProgram();
806 glAttachShader(shader_program, vs);
807 glAttachShader(shader_program, fs);
808
809 glLinkProgram(shader_program);
810
811 return shader_program;
812}
813
814unsigned char* loadImage(string file_name, int* x, int* y) {
815 int n;
816 int force_channels = 4; // This forces RGBA (4 bytes per pixel)
817 unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
818
819 int width_in_bytes = *x * 4;
820 unsigned char *top = NULL;
821 unsigned char *bottom = NULL;
822 unsigned char temp = 0;
823 int half_height = *y / 2;
824
825 // flip image upside-down to account for OpenGL treating lower-left as (0, 0)
826 for (int row = 0; row < half_height; row++) {
827 top = image_data + row * width_in_bytes;
828 bottom = image_data + (*y - row - 1) * width_in_bytes;
829 for (int col = 0; col < width_in_bytes; col++) {
830 temp = *top;
831 *top = *bottom;
832 *bottom = temp;
833 top++;
834 bottom++;
835 }
836 }
837
838 if (!image_data) {
839 fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
840 }
841
842 // Not Power-of-2 check
843 if ((*x & (*x - 1)) != 0 || (*y & (*y - 1)) != 0) {
844 fprintf(stderr, "WARNING: texture %s is not power-of-2 dimensions\n", file_name.c_str());
845 }
846
847 return image_data;
848}
849
850bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point) {
851 // LINE EQUATION: P = O + Dt
852 // O = cam
853 // D = ray_world
854
855 // PLANE EQUATION: P dot n + d = 0
856 // n is the normal vector
857 // d is the offset from the origin
858
859 // Take the cross-product of two vectors on the plane to get the normal
860 vec3 v1 = points[1] - points[0];
861 vec3 v2 = points[2] - points[0];
862
863 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);
864
865 vec3 local_ray = (inverse(obj->model_mat) * world_ray).xyz();
866 vec3 local_cam = (inverse(obj->model_mat) * cam).xyz();
867
868 local_ray = local_ray - local_cam;
869
870 float d = -glm::dot(points[0], normal);
871 float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
872
873 vec3 intersection = local_cam + t*local_ray;
874
875 if (insideTriangle(intersection, points)) {
876 click_point = obj->model_mat * vec4(intersection, 1.0f);
877 return true;
878 } else {
879 return false;
880 }
881}
882
883bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
884 vec3 v21 = triangle_points[1] - triangle_points[0];
885 vec3 v31 = triangle_points[2] - triangle_points[0];
886 vec3 pv1 = p - triangle_points[0];
887
888 float y = (pv1.y*v21.x - pv1.x*v21.y) / (v31.y*v21.x - v31.x*v21.y);
889 float x = (pv1.x-y*v31.x) / v21.x;
890
891 return x > 0.0f && y > 0.0f && x+y < 1.0f;
892}
893
894void printVector(string label, vec3 v) {
895 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
896}
897
898void print4DVector(string label, vec4 v) {
899 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
900}
901
902void addObjectToScene(SceneObject& obj) {
903 obj.id = objects.size(); // currently unused
904 obj.num_points = obj.points.size() / 3;
905 obj.model_transform = mat4();
906
907 obj.normals.reserve(obj.points.size());
908 for (int i = 0; i < obj.points.size(); i += 9) {
909 vec3 point1 = vec3(obj.points[i], obj.points[i + 1], obj.points[i + 2]);
910 vec3 point2 = vec3(obj.points[i + 3], obj.points[i + 4], obj.points[i + 5]);
911 vec3 point3 = vec3(obj.points[i + 6], obj.points[i + 7], obj.points[i + 8]);
912
913 vec3 normal = normalize(cross(point2 - point1, point3 - point1));
914
915 // Add the same normal for all 3 points
916 for (int j = 0; j < 3; j++) {
917 obj.normals.push_back(normal.x);
918 obj.normals.push_back(normal.y);
919 obj.normals.push_back(normal.z);
920 }
921 }
922
923 objects.push_back(obj);
924}
925
926void populateBuffers(vector<SceneObject>& objects,
927 GLuint* points_vbo,
928 GLuint* colors_vbo,
929 GLuint* selected_colors_vbo,
930 GLuint* texcoords_vbo,
931 GLuint* normals_vbo,
932 GLuint* ubo,
933 GLuint* model_mat_idx_vbo,
934 map<GLuint, unsigned int>& shaderCounts,
935 map<GLuint, unsigned int>& curShaderBase) {
936 GLsizeiptr points_buffer_size = 0;
937 GLsizeiptr textures_buffer_size = 0;
938 GLsizeiptr ubo_buffer_size = 0;
939 GLsizeiptr model_mat_idx_buffer_size = 0;
940
941 map<GLuint, unsigned int> curShaderOffset;
942
943 map<GLuint, unsigned int> shaderUboCounts;
944 map<GLuint, unsigned int> curShaderUboBase;
945 map<GLuint, unsigned int> curShaderUboOffset;
946
947 vector<SceneObject>::iterator it;
948
949 /* Find all shaders that need to be used and the number of objects and
950 * number of points for each shader. Construct a map from shader id to count
951 * of points being drawn using that shader (for thw model matrix ubo, we
952 * need object counts instead). These will be used to get offsets into the
953 * vertex buffer for each shader.
954 */
955 for (it = objects.begin(); it != objects.end(); it++) {
956 points_buffer_size += it->points.size() * sizeof(GLfloat);
957 textures_buffer_size += it->texcoords.size() * sizeof(GLfloat);
958 ubo_buffer_size += 16 * sizeof(GLfloat);
959 model_mat_idx_buffer_size += it->num_points * sizeof(GLuint);
960
961 if (shaderCounts.count(it->shader_program) == 0) {
962 shaderCounts[it->shader_program] = it->num_points;
963 shaderUboCounts[it->shader_program] = 1;
964 } else {
965 shaderCounts[it->shader_program] += it->num_points;
966 shaderUboCounts[it->shader_program]++;
967 }
968 }
969
970 map<GLuint, unsigned int>::iterator shaderIt;
971 unsigned int lastShaderCount = 0;
972 unsigned int lastShaderUboCount = 0;
973
974 /*
975 * The counts calculated above can be used to get the starting offset of
976 * each shader in the vertex buffer. Create a map of base offsets to mark
977 * where the data for the first object using a given shader begins. Also,
978 * create a map of current offsets to mark where to copy data for the next
979 * object being added.
980 */
981 cout << "Shader counts:" << endl;
982 for (shaderIt = shaderCounts.begin(); shaderIt != shaderCounts.end(); shaderIt++) {
983 curShaderOffset[shaderIt->first] = 0;
984 curShaderUboOffset[shaderIt->first] = 0;
985
986 curShaderBase[shaderIt->first] = lastShaderCount;
987 lastShaderCount += shaderCounts[shaderIt->first];
988
989 curShaderUboBase[shaderIt->first] = lastShaderUboCount;
990 lastShaderUboCount += shaderUboCounts[shaderIt->first];
991 }
992
993 // Initialize all the buffers using the counts calculated above
994
995 *points_vbo = 0;
996 glGenBuffers(1, points_vbo);
997 glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
998 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
999
1000 *colors_vbo = 0;
1001 glGenBuffers(1, colors_vbo);
1002 glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
1003 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1004
1005 *selected_colors_vbo = 0;
1006 glGenBuffers(1, selected_colors_vbo);
1007 glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
1008 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1009
1010 *texcoords_vbo = 0;
1011 glGenBuffers(1, texcoords_vbo);
1012 glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
1013 glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
1014
1015 *normals_vbo = 0;
1016 glGenBuffers(1, normals_vbo);
1017 glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
1018 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1019
1020 *ubo = 0;
1021 glGenBuffers(1, ubo);
1022 glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
1023 glBufferData(GL_UNIFORM_BUFFER, ubo_buffer_size, NULL, GL_DYNAMIC_DRAW);
1024
1025 *model_mat_idx_vbo = 0;
1026 glGenBuffers(1, model_mat_idx_vbo);
1027 glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
1028 glBufferData(GL_ARRAY_BUFFER, model_mat_idx_buffer_size, NULL, GL_DYNAMIC_DRAW);
1029
1030 for (it = objects.begin(); it != objects.end(); it++) {
1031 it->vertex_vbo_offset = curShaderBase[it->shader_program] + curShaderOffset[it->shader_program];
1032 it->ubo_offset = curShaderUboBase[it->shader_program] + curShaderUboOffset[it->shader_program];
1033
1034 glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
1035 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->points.size() * sizeof(GLfloat), &it->points[0]);
1036
1037 glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
1038 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->colors.size() * sizeof(GLfloat), &it->colors[0]);
1039
1040 glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
1041 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->selected_colors.size() * sizeof(GLfloat), &it->selected_colors[0]);
1042
1043 glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
1044 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 2, it->texcoords.size() * sizeof(GLfloat), &it->texcoords[0]);
1045
1046 glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
1047 glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->normals.size() * sizeof(GLfloat), &it->normals[0]);
1048
1049 glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
1050 for (int i = 0; i < it->num_points; i++) {
1051 glBufferSubData(GL_ARRAY_BUFFER, (it->vertex_vbo_offset + i) * sizeof(GLuint), sizeof(GLuint), &it->ubo_offset);
1052 }
1053
1054 curShaderOffset[it->shader_program] += it->num_points;
1055
1056 it->model_mat = it->model_base * it->model_transform;
1057 glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
1058 glBufferSubData(GL_UNIFORM_BUFFER, it->ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(it->model_mat));
1059
1060 curShaderUboOffset[it->shader_program]++;
1061 }
1062}
1063
1064void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo) {
1065 obj.model_transform = obj.model_transform * transform;
1066 obj.model_mat = obj.model_transform * obj.model_base;
1067
1068 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1069 glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
1070}
1071
1072void renderScene(vector<SceneObject>& objects,
1073 GLuint color_sp, GLuint texture_sp,
1074 GLuint vao1, GLuint vao2,
1075 GLuint points_vbo, GLuint normals_vbo,
1076 GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
1077 SceneObject* selectedObject,
1078 map<GLuint, unsigned int>& shaderCounts,
1079 map<GLuint, unsigned int>& curShaderBase) {
1080
1081 glUseProgram(color_sp);
1082 glBindVertexArray(vao1);
1083
1084 if (selectedObject != NULL) {
1085 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1086 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1087
1088 glDrawArrays(GL_TRIANGLES, selectedObject->vertex_vbo_offset, selectedObject->num_points);
1089 }
1090
1091 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
1092 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
1093
1094 glDrawArrays(GL_TRIANGLES, curShaderBase[color_sp], shaderCounts[color_sp]);
1095
1096 glUseProgram(texture_sp);
1097 glBindVertexArray(vao2);
1098
1099 glDrawArrays(GL_TRIANGLES, curShaderBase[texture_sp], shaderCounts[texture_sp]);
1100}
1101
1102void renderSceneGui() {
1103 ImGui_ImplGlfwGL3_NewFrame();
1104
1105 // 1. Show a simple window.
1106 // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
1107 /*
1108 {
1109 static float f = 0.0f;
1110 static int counter = 0;
1111 ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
1112 ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
1113 ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
1114
1115 ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
1116 ImGui::Checkbox("Another Window", &show_another_window);
1117
1118 if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
1119 counter++;
1120 ImGui::SameLine();
1121 ImGui::Text("counter = %d", counter);
1122
1123 ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
1124 }
1125 */
1126
1127 {
1128 ImGui::SetNextWindowSize(ImVec2(85, 22), ImGuiCond_Once);
1129 ImGui::SetNextWindowPos(ImVec2(10, 50), ImGuiCond_Once);
1130 ImGui::Begin("WndStats", NULL,
1131 ImGuiWindowFlags_NoTitleBar |
1132 ImGuiWindowFlags_NoResize |
1133 ImGuiWindowFlags_NoMove);
1134 ImGui::Text("Score: ???");
1135 ImGui::End();
1136 }
1137
1138 {
1139 ImGui::SetNextWindowPos(ImVec2(380, 10), ImGuiCond_Once);
1140 ImGui::SetNextWindowSize(ImVec2(250, 35), ImGuiCond_Once);
1141 ImGui::Begin("WndMenubar", NULL,
1142 ImGuiWindowFlags_NoTitleBar |
1143 ImGuiWindowFlags_NoResize |
1144 ImGuiWindowFlags_NoMove);
1145 ImGui::InvisibleButton("", ImVec2(155, 18));
1146 ImGui::SameLine();
1147 if (ImGui::Button("Main Menu")) {
1148 events.push(EVENT_GO_TO_MAIN_MENU);
1149 }
1150 ImGui::End();
1151 }
1152
1153 ImGui::Render();
1154 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1155}
1156
1157void renderMainMenu() {
1158}
1159
1160void renderMainMenuGui() {
1161 ImGui_ImplGlfwGL3_NewFrame();
1162
1163 {
1164 int padding = 4;
1165 ImGui::SetNextWindowPos(ImVec2(-padding, -padding), ImGuiCond_Once);
1166 ImGui::SetNextWindowSize(ImVec2(width + 2 * padding, height + 2 * padding), ImGuiCond_Once);
1167 ImGui::Begin("WndMain", NULL,
1168 ImGuiWindowFlags_NoTitleBar |
1169 ImGuiWindowFlags_NoResize |
1170 ImGuiWindowFlags_NoMove);
1171
1172 ImGui::InvisibleButton("", ImVec2(10, 80));
1173 ImGui::InvisibleButton("", ImVec2(285, 18));
1174 ImGui::SameLine();
1175 if (ImGui::Button("New Game")) {
1176 events.push(EVENT_GO_TO_GAME);
1177 }
1178
1179 ImGui::InvisibleButton("", ImVec2(10, 15));
1180 ImGui::InvisibleButton("", ImVec2(300, 18));
1181 ImGui::SameLine();
1182 if (ImGui::Button("Quit")) {
1183 events.push(EVENT_QUIT);
1184 }
1185
1186 ImGui::End();
1187 }
1188
1189 ImGui::Render();
1190 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1191}
Note: See TracBrowser for help on using the repository browser.