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

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

Use glm mat types instead of arrays and mat swizzle operators (e.g. pos.x) instead of array indices more often, add a mouse click event handler, and start writing code to detect which 3d object the user clicked on.

  • Property mode set to 100644
File size: 14.2 KB
RevLine 
[22b2c37]1#include "logger.h"
[5272b6b]2
[485424b]3#include "stb_image.h"
4
[c62eee6]5#define GLM_SWIZZLE
6#include <glm/mat4x4.hpp>
[7ee66ea]7#include <glm/gtc/matrix_transform.hpp>
8#include <glm/gtc/type_ptr.hpp>
9
[5272b6b]10#include <GL/glew.h>
11#include <GLFW/glfw3.h>
12
[22b2c37]13#include <cstdio>
14#include <iostream>
[ec4456b]15#include <fstream>
[7ee66ea]16
17#define _USE_MATH_DEFINES
[93baa0e]18#include <cmath>
[22b2c37]19
[5272b6b]20using namespace std;
[7ee66ea]21using namespace glm;
22
23#define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444
[c62eee6]24
[485424b]25const bool FULLSCREEN = false;
[c62eee6]26int width = 640;
27int height = 480;
28
29vec3 cam_pos;
30
31vec3 face_point1, face_point2, face_point3;
32
33mat4 view_mat;
34mat4 proj_mat;
[5272b6b]35
[ec4456b]36GLuint loadShader(GLenum type, string file);
[485424b]37GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath);
38unsigned char* loadImage(string file_name, int* x, int* y);
[ec4456b]39
40void glfw_error_callback(int error, const char* description) {
41 gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
42}
43
[c62eee6]44void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
45 double mouse_x, mouse_y;
46 glfwGetCursorPos(window, &mouse_x, &mouse_y);
47
48 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
49 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
50
51 float x = (2.0f*mouse_x) / width - 1.0f;
52 float y = 1.0f - (2.0f*mouse_y) / height;
53
54 vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
55 vec4 ray_eye = inverse(proj_mat) * ray_clip;
56 ray_eye = vec4(ray_eye.xy(), -1.0f, 0.0f);
57 vec3 ray_world = normalize((inverse(view_mat) * ray_eye).xyz());
58
59 vec3 click_point = cam_pos + ray_world;
60
61 /* Now, we need to generate the constants for the equations describing
62 * a 3D line:
63 * (x - x0) / a = (y - y0) / b = (z - z0) / c
64 *
65 * The line goes through the camera position, so
66 * cam_pos = <x0, y0, z0>
67 */
68
69 cout << "Converted -> (" << ray_world.x << "," << ray_world.y << "," << ray_world.z << ")" << endl << endl;;
70 cout << "Camera -> (" << cam_pos.x << "," << cam_pos.y << "," << cam_pos.z << ")" << endl;
71 cout << "Click point -> (" << click_point.x << "," << click_point.y << "," << click_point.z << ")" << endl;
72
73 float a = 1.0f;
74 float b = a * (click_point.y - cam_pos.y) / (click_point.x - cam_pos.x);
75 float c = a * (click_point.z - cam_pos.z) / (click_point.x - cam_pos.x);
76
77 cout << "(x - " << cam_pos.x << ") / " << a << " = ";
78 cout << "(y - " << cam_pos.y << ") / " << b << " = ";
79 cout << "(z - " << cam_pos.z << ") / " << c << endl;;
80
81 /* Now, we need to generate the constants for the equations describing
82 * a 3D plane:
83 * dx + ey +fz +g = 0
84 */
85
86 cout << "Points on the plane" << endl;
87 cout << "(" << face_point1.x << "," << face_point1.y << "," << face_point1.z << ")" << endl;
88 cout << "(" << face_point2.x << "," << face_point2.y << "," << face_point2.z << ")" << endl;
89 cout << "(" << face_point3.x << "," << face_point3.y << "," << face_point3.z << ")" << endl;
90
91 // get intersection
92 }
93}
94
[5272b6b]95int main(int argc, char* argv[]) {
96 cout << "New OpenGL Game" << endl;
97
[ec4456b]98 if (!restart_gl_log()) {}
99 gl_log("starting GLFW\n%s\n", glfwGetVersionString());
[22b2c37]100
[ec4456b]101 glfwSetErrorCallback(glfw_error_callback);
[5272b6b]102 if (!glfwInit()) {
103 fprintf(stderr, "ERROR: could not start GLFW3\n");
104 return 1;
[be246ad]105 }
106
107#ifdef __APPLE__
108 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
109 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
110 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
111 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
112#endif
[5272b6b]113
[ec4456b]114 glfwWindowHint(GLFW_SAMPLES, 4);
115
116 GLFWwindow* window = NULL;
117
118 if (FULLSCREEN) {
119 GLFWmonitor* mon = glfwGetPrimaryMonitor();
120 const GLFWvidmode* vmode = glfwGetVideoMode(mon);
121
122 cout << "Fullscreen resolution " << vmode->width << "x" << vmode->height << endl;
123 window = glfwCreateWindow(vmode->width, vmode->height, "Extended GL Init", mon, NULL);
124
125 width = vmode->width;
126 height = vmode->height;
127 } else {
128 window = glfwCreateWindow(width, height, "Hello Triangle", NULL, NULL);
129 }
130
[5272b6b]131 if (!window) {
132 fprintf(stderr, "ERROR: could not open window with GLFW3\n");
133 glfwTerminate();
134 return 1;
135 }
[c62eee6]136
137 glfwSetMouseButtonCallback(window, mouse_button_callback);
138
[644a2e4]139 glfwMakeContextCurrent(window);
[5272b6b]140 glewExperimental = GL_TRUE;
141 glewInit();
142
[ec4456b]143 // glViewport(0, 0, width*2, height*2);
144
[5272b6b]145 const GLubyte* renderer = glGetString(GL_RENDERER);
146 const GLubyte* version = glGetString(GL_VERSION);
147 printf("Renderer: %s\n", renderer);
148 printf("OpenGL version supported %s\n", version);
[93baa0e]149
[5272b6b]150 glEnable(GL_DEPTH_TEST);
151 glDepthFunc(GL_LESS);
[516668e]152
[93baa0e]153 glEnable(GL_CULL_FACE);
154 // glCullFace(GL_BACK);
155 // glFrontFace(GL_CW);
156
[485424b]157 int x, y;
158 unsigned char* texImage = loadImage("test.png", &x, &y);
159 if (texImage) {
160 cout << "Yay, I loaded an image!" << endl;
161 cout << x << endl;
162 cout << y << endl;
163 printf ("first 4 bytes are: %i %i %i %i\n", texImage[0], texImage[1], texImage[2], texImage[3]);
164 }
165
166 GLuint tex = 0;
167 glGenTextures(1, &tex);
168 glActiveTexture(GL_TEXTURE0);
169 glBindTexture(GL_TEXTURE_2D, tex);
170 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage);
171
172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
174 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
175 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
176
[516668e]177 GLfloat points[] = {
178 0.0f, 0.5f, 0.0f,
179 -0.5f, -0.5f, 0.0f,
[93baa0e]180 0.5f, -0.5f, 0.0f,
[7ee66ea]181 0.5f, -0.5f, 0.0f,
182 -0.5f, -0.5f, 0.0f,
183 0.0f, 0.5f, 0.0f,
[516668e]184 };
185
[c62eee6]186 // initialize global variables for click intersection test
187 face_point1 = vec3(points[0], points[1], points[2]);
188 face_point2 = vec3(points[3], points[4], points[5]);
189 face_point3 = vec3(points[6], points[7], points[8]);
190
[8b7cfcf]191 GLfloat colors[] = {
192 1.0, 0.0, 0.0,
193 0.0, 0.0, 1.0,
[93baa0e]194 0.0, 1.0, 0.0,
[7ee66ea]195 0.0, 1.0, 0.0,
196 0.0, 0.0, 1.0,
197 1.0, 0.0, 0.0,
[93baa0e]198 };
199
[485424b]200 // Each point is made of 3 floats
201 int numPoints = (sizeof(points) / sizeof(float)) / 3;
202
203 GLfloat points2[] = {
204 0.5f, 0.5f, 0.0f,
205 -0.5f, 0.5f, 0.0f,
206 -0.5f, -0.5f, 0.0f,
207 0.5f, 0.5f, 0.0f,
208 -0.5f, -0.5f, 0.0f,
209 0.5f, -0.5f, 0.0f,
210 };
211
212 /*
213 GLfloat colors2[] = {
214 0.0, 0.9, 0.9,
215 0.0, 0.9, 0.9,
216 0.0, 0.9, 0.9,
217 0.0, 0.9, 0.9,
218 0.0, 0.9, 0.9,
219 0.0, 0.9, 0.9,
220 };
221 */
222
223 GLfloat texcoords[] = {
224 1.0f, 1.0f,
225 0.0f, 1.0f,
226 0.0, 0.0,
227 1.0, 1.0,
228 0.0, 0.0,
229 1.0, 0.0
230 };
231
232 // Each point is made of 3 floats
233 int numPoints2 = (sizeof(points2) / sizeof(float)) / 3;
234
[c62eee6]235 /*
[201e2f8]236 mat4 T_model = translate(mat4(), vec3(0.5f, 0.0f, 0.0f));
237 mat4 R_model = rotate(mat4(), 4.0f, vec3(0.0f, 1.0f, 0.0f));
[c62eee6]238 */
239 mat4 T_model = translate(mat4(), vec3(0.0f, 0.0f, 0.0f));
240 mat4 R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
[201e2f8]241 mat4 model_mat = T_model*R_model;
[8b7cfcf]242
[485424b]243 mat4 T_model2 = translate(mat4(), vec3(-1.0f, 0.0f, 0.0f));
244 mat4 R_model2 = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
245 mat4 model_mat2 = T_model2*R_model2;
246
[8b7cfcf]247 GLuint points_vbo = 0;
248 glGenBuffers(1, &points_vbo);
249 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
[516668e]250 glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
251
[8b7cfcf]252 GLuint colors_vbo = 0;
253 glGenBuffers(1, &colors_vbo);
254 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
255 glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
256
[644a2e4]257 GLuint vao = 0;
[516668e]258 glGenVertexArrays(1, &vao);
259 glBindVertexArray(vao);
[8b7cfcf]260 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
[516668e]261 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
[8b7cfcf]262 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
263 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
[516668e]264
[8b7cfcf]265 glEnableVertexAttribArray(0);
266 glEnableVertexAttribArray(1);
[644a2e4]267
[485424b]268 GLuint points2_vbo = 0;
269 glGenBuffers(1, &points2_vbo);
270 glBindBuffer(GL_ARRAY_BUFFER, points2_vbo);
271 glBufferData(GL_ARRAY_BUFFER, sizeof(points2), points2, GL_STATIC_DRAW);
272
273 /*
274 GLuint colors2_vbo = 0;
275 glGenBuffers(1, &colors2_vbo);
276 glBindBuffer(GL_ARRAY_BUFFER, colors2_vbo);
277 glBufferData(GL_ARRAY_BUFFER, sizeof(colors2), colors2, GL_STATIC_DRAW);
278 */
279
280 GLuint vt_vbo;
281 glGenBuffers(1, &vt_vbo);
282 glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
283 glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW);
284
285 GLuint vao2 = 0;
286 glGenVertexArrays(1, &vao2);
287 glBindVertexArray(vao2);
288 glBindBuffer(GL_ARRAY_BUFFER, points2_vbo);
289 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
290 // glBindBuffer(GL_ARRAY_BUFFER, colors2_vbo);
291 // glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
292 glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
293 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
[644a2e4]294
[485424b]295 glEnableVertexAttribArray(0);
296 glEnableVertexAttribArray(1);
[8b7cfcf]297
[485424b]298 GLuint shader_program = loadShaderProgram("./color.vert", "./color.frag");
299 GLuint shader_program2 = loadShaderProgram("./texture.vert", "./texture.frag");
[644a2e4]300
[93baa0e]301 float speed = 1.0f;
302 float last_position = 0.0f;
303
[7ee66ea]304 float cam_speed = 1.0f;
[201e2f8]305 float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
[7ee66ea]306
[c62eee6]307 cam_pos = vec3(0.0f, 0.0f, 2.0f);
[7ee66ea]308 float cam_yaw = 0.0f;
309
[c62eee6]310 mat4 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
[7ee66ea]311 mat4 R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
[c62eee6]312 view_mat = R*T;
[7ee66ea]313
314 float near = 0.1f;
315 float far = 100.0f;
316 float fov = 67.0f * ONE_DEG_IN_RAD;
317 float aspect = (float)width / (float)height;
318
319 float range = tan(fov * 0.5f) * near;
320 float Sx = near / (range * aspect);
321 float Sy = near / range;
322 float Sz = -(far + near) / (far - near);
323 float Pz = -(2.0f * far * near) / (far - near);
324
[c62eee6]325 float proj_arr[] = {
[7ee66ea]326 Sx, 0.0f, 0.0f, 0.0f,
327 0.0f, Sy, 0.0f, 0.0f,
328 0.0f, 0.0f, Sz, -1.0f,
329 0.0f, 0.0f, Pz, 0.0f,
330 };
[c62eee6]331 proj_mat = make_mat4(proj_arr);
[7ee66ea]332
[485424b]333 GLint model_mat_loc = glGetUniformLocation(shader_program2, "model");
334 GLint view_mat_loc = glGetUniformLocation(shader_program2, "view");
335 GLint proj_mat_loc = glGetUniformLocation(shader_program2, "proj");
336
337 GLint model_test_loc = glGetUniformLocation(shader_program, "model");
338 GLint view_test_loc = glGetUniformLocation(shader_program, "view");
339 GLint proj_test_loc = glGetUniformLocation(shader_program, "proj");
[7ee66ea]340
341 glUseProgram(shader_program);
[485424b]342 glUniformMatrix4fv(model_test_loc, 1, GL_FALSE, value_ptr(model_mat));
[c62eee6]343 glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
[485424b]344
345 glUseProgram(shader_program2);
346 glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, value_ptr(model_mat2));
[c62eee6]347 glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
[7ee66ea]348
[485424b]349 // glUniform1i(tex_loc, 0);
350
[7ee66ea]351 bool cam_moved = false;
352
[93baa0e]353 double previous_seconds = glfwGetTime();
[644a2e4]354 while (!glfwWindowShouldClose(window)) {
[93baa0e]355 double current_seconds = glfwGetTime();
356 double elapsed_seconds = current_seconds - previous_seconds;
357 previous_seconds = current_seconds;
358
359 if (fabs(last_position) > 1.0f) {
360 speed = -speed;
361 }
362
[7ee66ea]363 /*
[93baa0e]364 model[12] = last_position + speed*elapsed_seconds;
365 last_position = model[12];
[7ee66ea]366 */
[93baa0e]367
368 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[485424b]369
370 glUseProgram(shader_program);
371 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
372
[644a2e4]373 glBindVertexArray(vao);
[93baa0e]374
[7ee66ea]375 glDrawArrays(GL_TRIANGLES, 0, numPoints);
[ec4456b]376
[485424b]377 glUseProgram(shader_program2);
378 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
379
380 glBindVertexArray(vao2);
381
382 glDrawArrays(GL_TRIANGLES, 0, numPoints2);
383
[644a2e4]384 glfwPollEvents();
385 glfwSwapBuffers(window);
[ec4456b]386
387 if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
388 glfwSetWindowShouldClose(window, 1);
389 }
[7ee66ea]390
391 float dist = cam_speed * elapsed_seconds;
392 if (glfwGetKey(window, GLFW_KEY_A)) {
[c62eee6]393 cam_pos.x -= cos(cam_yaw)*dist;
394 cam_pos.z += sin(cam_yaw)*dist;
[7ee66ea]395 cam_moved = true;
396 }
397 if (glfwGetKey(window, GLFW_KEY_D)) {
[c62eee6]398 cam_pos.x += cos(cam_yaw)*dist;
399 cam_pos.z -= sin(cam_yaw)*dist;
[7ee66ea]400 cam_moved = true;
401 }
402 if (glfwGetKey(window, GLFW_KEY_W)) {
[c62eee6]403 cam_pos.x -= sin(cam_yaw)*dist;
404 cam_pos.z -= cos(cam_yaw)*dist;
[7ee66ea]405 cam_moved = true;
406 }
407 if (glfwGetKey(window, GLFW_KEY_S)) {
[c62eee6]408 cam_pos.x += sin(cam_yaw)*dist;
409 cam_pos.z += cos(cam_yaw)*dist;
[7ee66ea]410 cam_moved = true;
411 }
412 if (glfwGetKey(window, GLFW_KEY_LEFT)) {
413 cam_yaw += cam_yaw_speed * elapsed_seconds;
414 cam_moved = true;
415 }
416 if (glfwGetKey(window, GLFW_KEY_RIGHT)) {
417 cam_yaw -= cam_yaw_speed * elapsed_seconds;
418 cam_moved = true;
419 }
420 if (cam_moved) {
[c62eee6]421 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
[7ee66ea]422 R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
423 view_mat = R*T;
424
425 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
426 cam_moved = false;
427 }
[644a2e4]428 }
429
[5272b6b]430 glfwTerminate();
431 return 0;
432}
[ec4456b]433
434GLuint loadShader(GLenum type, string file) {
435 cout << "Loading shader from file " << file << endl;
436
437 ifstream shaderFile(file);
438 GLuint shaderId = 0;
439
440 if (shaderFile.is_open()) {
441 string line, shaderString;
442
443 while(getline(shaderFile, line)) {
444 shaderString += line + "\n";
445 }
446 shaderFile.close();
447 const char* shaderCString = shaderString.c_str();
448
449 shaderId = glCreateShader(type);
450 glShaderSource(shaderId, 1, &shaderCString, NULL);
451 glCompileShader(shaderId);
452
453 cout << "Loaded successfully" << endl;
454 } else {
455 cout << "Failed to loade the file" << endl;
456 }
457
458 return shaderId;
459}
[485424b]460
461GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
462 GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
463 GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
464
465 GLuint shader_program = glCreateProgram();
466 glAttachShader(shader_program, vs);
467 glAttachShader(shader_program, fs);
468
469 glLinkProgram(shader_program);
470
471 return shader_program;
472}
473
474unsigned char* loadImage(string file_name, int* x, int* y) {
475 int n;
476 int force_channels = 4;
477 unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
478 if (!image_data) {
479 fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
480 }
481 return image_data;
482}
Note: See TracBrowser for help on using the repository browser.