source: opengl-game/new-game.cpp@ 5c9d193

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

Created a faceClicked method to encapsulate checking for the intersection of the world ray with a given face, and check all the faces in the scene when trying to determine which object was clicked.

  • Property mode set to 100644
File size: 24.8 KB
RevLine 
[22b2c37]1#include "logger.h"
[5272b6b]2
[485424b]3#include "stb_image.h"
4
[1099b95]5#define _USE_MATH_DEFINES
[c62eee6]6#define GLM_SWIZZLE
[1099b95]7
[5c9d193]8// This is to fix a non-alignment issue when passing vec4 params.
9// Check if it got fixed in a later version of GLM
10#define GLM_FORCE_PURE
11
[c62eee6]12#include <glm/mat4x4.hpp>
[7ee66ea]13#include <glm/gtc/matrix_transform.hpp>
14#include <glm/gtc/type_ptr.hpp>
15
[5272b6b]16#include <GL/glew.h>
17#include <GLFW/glfw3.h>
18
[22b2c37]19#include <cstdio>
20#include <iostream>
[ec4456b]21#include <fstream>
[93baa0e]22#include <cmath>
[1099b95]23#include <string>
[19c9338]24#include <array>
[df652d5]25#include <vector>
[22b2c37]26
[5272b6b]27using namespace std;
[7ee66ea]28using namespace glm;
29
30#define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444
[c62eee6]31
[df652d5]32struct SceneObject {
33 mat4 model_mat;
34};
35
36struct ObjectFace {
37 unsigned int objectId;
38 array<vec3, 3> points;
39};
40
[485424b]41const bool FULLSCREEN = false;
[c62eee6]42int width = 640;
43int height = 480;
44
45vec3 cam_pos;
46
47mat4 view_mat;
48mat4 proj_mat;
[5272b6b]49
[df652d5]50vector<SceneObject> objects;
51vector<ObjectFace> faces;
52
[147ac6d]53SceneObject* clickedObject = NULL;
54SceneObject* selectedObject = NULL;
55
[5c9d193]56bool faceClicked(ObjectFace* face, vec4 world_ray, vec4 cam);
57bool insideTriangle(vec3 p, array<vec3, 3> triangle_points);
[33a9664]58
[ec4456b]59GLuint loadShader(GLenum type, string file);
[485424b]60GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath);
61unsigned char* loadImage(string file_name, int* x, int* y);
[ec4456b]62
[d12d003]63void printVector(string label, vec3 v);
64
65float NEAR_CLIP = 0.1f;
66float FAR_CLIP = 100.0f;
67
[ec4456b]68void glfw_error_callback(int error, const char* description) {
69 gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
70}
71
[c62eee6]72void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
[df652d5]73 /*
[c62eee6]74 double mouse_x, mouse_y;
75 glfwGetCursorPos(window, &mouse_x, &mouse_y);
76
77 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
78 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
79
80 float x = (2.0f*mouse_x) / width - 1.0f;
81 float y = 1.0f - (2.0f*mouse_y) / height;
[33a9664]82 cout << "x: " << x << ", y: " << y << endl;
83
84 // Since the projection matrix gets applied before the view matrix,
85 // treat the initial camera position (aka origin of the ray) as (0, 0, 0)
86
87 // When getting the ray direction, you can use near and fov to get the
88 // coordinates
[c62eee6]89
[33a9664]90 vec4 ray_clip = vec4(x, y, -1.0f, 1.0f); // this should have a z equal to the near clipping plane
[c62eee6]91 vec4 ray_eye = inverse(proj_mat) * ray_clip;
92 ray_eye = vec4(ray_eye.xy(), -1.0f, 0.0f);
93 vec3 ray_world = normalize((inverse(view_mat) * ray_eye).xyz());
94
[df652d5]95 / * LATEST NOTES:
[33a9664]96 *
97 * Normalizing the world ray caused issues, although it should make sense with the projection
98 * matrix, since the z coordinate has meaning there.
99 *
100 * Now, I need to figure out the correct intersection test in 2D space
101 * Also, need to check that the global triangle points are correct
[df652d5]102 * /
[33a9664]103
104 // since ray_world is the end result we want anyway, we probably don't need to add cam_pos to
105 // it, only to subtract it later
106
[c62eee6]107 vec3 click_point = cam_pos + ray_world;
108
[df652d5]109 / * Now, we need to generate the constants for the equations describing
[c62eee6]110 * a 3D line:
111 * (x - x0) / a = (y - y0) / b = (z - z0) / c
112 *
113 * The line goes through the camera position, so
114 * cam_pos = <x0, y0, z0>
[df652d5]115 * /
[c62eee6]116
[33a9664]117 // upper right corner is 1, 1 in opengl
118
[c62eee6]119 cout << "Converted -> (" << ray_world.x << "," << ray_world.y << "," << ray_world.z << ")" << endl << endl;;
120 cout << "Camera -> (" << cam_pos.x << "," << cam_pos.y << "," << cam_pos.z << ")" << endl;
121 cout << "Click point -> (" << click_point.x << "," << click_point.y << "," << click_point.z << ")" << endl;
122
123 float a = 1.0f;
124 float b = a * (click_point.y - cam_pos.y) / (click_point.x - cam_pos.x);
125 float c = a * (click_point.z - cam_pos.z) / (click_point.x - cam_pos.x);
126
127 cout << "(x - " << cam_pos.x << ") / " << a << " = ";
128 cout << "(y - " << cam_pos.y << ") / " << b << " = ";
129 cout << "(z - " << cam_pos.z << ") / " << c << endl;;
130
[df652d5]131 / * Now, we need to generate the constants for the equations describing
[c62eee6]132 * a 3D plane:
133 * dx + ey +fz +g = 0
[df652d5]134 * /
[c62eee6]135
[19c9338]136 vec3 fp1 = triangle_face[0];
137 vec3 fp2 = triangle_face[1];
138 vec3 fp3 = triangle_face[2];
[33a9664]139
[c62eee6]140 cout << "Points on the plane" << endl;
[33a9664]141 cout << "(" << fp1.x << ", " << fp1.y << ", " << fp1.z << ")" << endl;
142 cout << "(" << fp2.x << ", " << fp2.y << ", " << fp2.z << ")" << endl;
143 cout << "(" << fp3.x << ", " << fp3.y << ", " << fp3.z << ")" << endl;
144
145 float pa = (fp2.y-fp1.y)*(fp3.z-fp1.z) - (fp3.y-fp1.y)*(fp2.z-fp1.z);
146 float pb = (fp2.z-fp1.z)*(fp3.x-fp1.x) - (fp3.z-fp1.z)*(fp2.x-fp1.x);
147 float pc = (fp2.x-fp1.x)*(fp3.y-fp1.y) - (fp3.x-fp1.x)*(fp2.y-fp1.y);
148 float pd = -(pa*fp1.x+pb*fp1.y+pc*fp1.z);
149
150 cout << pa << "x+" << pb << "y+" << pc << "z+" << pd << "=0" << endl;
[c62eee6]151
152 // get intersection
[33a9664]153
154 // the intersection this computes is incorrect
155 // it doesn't match the equation of the plane
156 vec3 i;
157 i.z = -cam_pos.z - pc*pd/(pa*a+pb*b);
158 i.x = cam_pos.x + a * (i.z-cam_pos.z) / c;
159 i.y = cam_pos.y + b * (i.z-cam_pos.z) / c;
160
161 cout << "The holy grail?" << endl;
162 cout << "(" << i.x << "," << i.y << "," << i.z << ")" << endl;
163
[19c9338]164 clicked = insideTriangle(i, triangle_face);
[d12d003]165 cout << (clicked ? "true" : "false") << endl;
[33a9664]166 }
[df652d5]167 */
[33a9664]168}
169
[19c9338]170/* REFACTORING PLAN:
171 *
172 * Have an array of object structs
173 * Each object struct has:
174 * -a model matrix
175 * -a selected boolean
176 * Eventually, maybe also want to store a reference to the correct shader
177 * or whatever other info I need to properly render it
178 *
179 * Have an array of face structs
180 * Each face struct has
181 * -an object index indicating which object it is a part of
182 * -an array of three points
183 *
184 * The mouse button callback will:
185 * -iterate through the faces array
186 * -For each face, it will call faceClicked() with the following params:
187 * -Probably a world ray created from the mouse click coordinates
188 * -An array of 3 points representing the face
189 * -The object struct represnting the object the face is a part of
[df652d5]190 *
191 * -Really, all I need to pass in are the world ray and an ObjectFace reference
192 * -The world ray will first need to be multiplied by the view and projection matrices before being passed in
[19c9338]193 */
194
[33a9664]195void mouse_button_callback_new(GLFWwindow* window, int button, int action, int mods) {
196 double mouse_x, mouse_y;
197 glfwGetCursorPos(window, &mouse_x, &mouse_y);
198
199 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
200 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
[147ac6d]201 selectedObject = NULL;
[33a9664]202
203 float x = (2.0f*mouse_x) / width - 1.0f;
204 float y = 1.0f - (2.0f*mouse_y) / height;
[d12d003]205
[33a9664]206 cout << "x: " << x << ", y: " << y << endl;
207
208 // Since the projection matrix gets applied before the view matrix,
209 // treat the initial camera position (aka origin of the ray) as (0, 0, 0)
210
211 // When getting the ray direction, you can use near and fov to get the
212 // coordinates
213
214 // vec4 ray_clip = vec4(x, y, -1.0f, 1.0f); // this should have a z equal to the near clipping plane
215 // vec4 ray_eye = inverse(proj_mat) * ray_clip;
216 // ray_eye = vec4(ray_eye.xy(), -1.0f, 0.0f);
217 // vec3 ray_world = normalize((inverse(view_mat) * ray_eye).xyz());
218
[a5b5e95]219 vec4 ray_clip = vec4(x, y, NEAR_CLIP, 1.0f); // this should have a z equal to the near clipping plane
[5c9d193]220 vec4 ray_eye = ray_clip; // Need to apply the projection matrix here
221 vec4 ray_world = inverse(view_mat) * ray_eye;
[33a9664]222
223 /* LATEST NOTES:
224 *
225 * Normalizing the world ray caused issues, although it should make sense with the projection
226 * matrix, since the z coordinate has meaning there.
[19c9338]227 * Plus, we really want to normalize it only once we recompute it below as the difference of two points,
228 * although doing so shouldn't effect the results. Check the book to see if there is a good reason for doing so.
[33a9664]229 */
230
[5c9d193]231 printVector("Initial world ray:", ray_world.xyz());
[33a9664]232
[a5b5e95]233 vec4 cam_pos_origin = vec4(x, y, 0.0f, 1.0f);
[5c9d193]234 vec4 cam_pos_temp = inverse(view_mat) * cam_pos_origin;
[33a9664]235
[d12d003]236 cout << "Ray clip -> (" << ray_clip.x << "," << ray_clip.y << "," << ray_clip.z << ")" << endl << endl;;
237 cout << "Ray world -> (" << ray_world.x << "," << ray_world.y << "," << ray_world.z << ")" << endl << endl;;
238 cout << "Camera -> (" << cam_pos_temp.x << "," << cam_pos_temp.y << "," << cam_pos_temp.z << ")" << endl;
[33a9664]239
[5c9d193]240 // Need to account for faces that are behind one another
241 // Using an iterator for the loop makes it difficult to get a reference to each face (for the faceClicked function)
242 for (int i = 0; i<faces.size(); i++) {
243 if (faceClicked(&faces[i], ray_world, cam_pos_temp)) {
244 clickedObject = &objects[faces[i].objectId];
245 cout << "Clicked object: " << faces[i].objectId << endl;
246 break;
247 }
248 }
[d12d003]249
[5c9d193]250 if (clickedObject == NULL) {
251 cout << "No object was clicked" << endl;
[147ac6d]252 }
[c62eee6]253 }
254}
255
[5272b6b]256int main(int argc, char* argv[]) {
257 cout << "New OpenGL Game" << endl;
258
[ec4456b]259 if (!restart_gl_log()) {}
260 gl_log("starting GLFW\n%s\n", glfwGetVersionString());
[22b2c37]261
[ec4456b]262 glfwSetErrorCallback(glfw_error_callback);
[5272b6b]263 if (!glfwInit()) {
264 fprintf(stderr, "ERROR: could not start GLFW3\n");
265 return 1;
[be246ad]266 }
267
268#ifdef __APPLE__
269 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
270 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
271 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
272 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
273#endif
[5272b6b]274
[ec4456b]275 glfwWindowHint(GLFW_SAMPLES, 4);
276
277 GLFWwindow* window = NULL;
278
279 if (FULLSCREEN) {
280 GLFWmonitor* mon = glfwGetPrimaryMonitor();
281 const GLFWvidmode* vmode = glfwGetVideoMode(mon);
282
283 cout << "Fullscreen resolution " << vmode->width << "x" << vmode->height << endl;
284 window = glfwCreateWindow(vmode->width, vmode->height, "Extended GL Init", mon, NULL);
285
286 width = vmode->width;
287 height = vmode->height;
288 } else {
289 window = glfwCreateWindow(width, height, "Hello Triangle", NULL, NULL);
290 }
291
[5272b6b]292 if (!window) {
293 fprintf(stderr, "ERROR: could not open window with GLFW3\n");
294 glfwTerminate();
295 return 1;
296 }
[c62eee6]297
[df652d5]298 bool squareSelected = false;
299
[d12d003]300 glfwSetMouseButtonCallback(window, mouse_button_callback_new);
[c62eee6]301
[644a2e4]302 glfwMakeContextCurrent(window);
[5272b6b]303 glewExperimental = GL_TRUE;
304 glewInit();
305
[df652d5]306 // Check if we might ever need this. If not, remove it.
[ec4456b]307 // glViewport(0, 0, width*2, height*2);
308
[5272b6b]309 const GLubyte* renderer = glGetString(GL_RENDERER);
310 const GLubyte* version = glGetString(GL_VERSION);
311 printf("Renderer: %s\n", renderer);
312 printf("OpenGL version supported %s\n", version);
[93baa0e]313
[5272b6b]314 glEnable(GL_DEPTH_TEST);
315 glDepthFunc(GL_LESS);
[516668e]316
[93baa0e]317 glEnable(GL_CULL_FACE);
318 // glCullFace(GL_BACK);
319 // glFrontFace(GL_CW);
320
[485424b]321 int x, y;
322 unsigned char* texImage = loadImage("test.png", &x, &y);
323 if (texImage) {
324 cout << "Yay, I loaded an image!" << endl;
325 cout << x << endl;
326 cout << y << endl;
327 printf ("first 4 bytes are: %i %i %i %i\n", texImage[0], texImage[1], texImage[2], texImage[3]);
328 }
329
330 GLuint tex = 0;
331 glGenTextures(1, &tex);
332 glActiveTexture(GL_TEXTURE0);
333 glBindTexture(GL_TEXTURE_2D, tex);
334 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage);
335
336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
338 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
339 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
340
[516668e]341 GLfloat points[] = {
[d12d003]342 0.0f, 0.5f, 0.0f,
343 -0.5f, -0.5f, 0.0f,
344 0.5f, -0.5f, 0.0f,
345 0.5f, -0.5f, 0.0f,
346 -0.5f, -0.5f, 0.0f,
347 0.0f, 0.5f, 0.0f,
[516668e]348 };
[c62eee6]349
[8b7cfcf]350 GLfloat colors[] = {
[64a70f4]351 1.0, 0.0, 0.0,
352 0.0, 0.0, 1.0,
353 0.0, 1.0, 0.0,
354 0.0, 1.0, 0.0,
355 0.0, 0.0, 1.0,
356 1.0, 0.0, 0.0,
[93baa0e]357 };
358
[33a9664]359 GLfloat colors_new[] = {
[64a70f4]360 0.0, 1.0, 0.0,
361 0.0, 1.0, 0.0,
362 0.0, 1.0, 0.0,
363 0.0, 1.0, 0.0,
364 0.0, 1.0, 0.0,
365 0.0, 1.0, 0.0,
[33a9664]366 };
367
[485424b]368 // Each point is made of 3 floats
369 int numPoints = (sizeof(points) / sizeof(float)) / 3;
370
371 GLfloat points2[] = {
[64a70f4]372 0.5f, 0.5f, 0.0f,
[d12d003]373 -0.5f, 0.5f, 0.0f,
374 -0.5f, -0.5f, 0.0f,
[64a70f4]375 0.5f, 0.5f, 0.0f,
[d12d003]376 -0.5f, -0.5f, 0.0f,
[64a70f4]377 0.5f, -0.5f, 0.0f,
378 };
[485424b]379
380 GLfloat colors2[] = {
[64a70f4]381 0.0, 0.9, 0.9,
382 0.0, 0.9, 0.9,
383 0.0, 0.9, 0.9,
384 0.0, 0.9, 0.9,
385 0.0, 0.9, 0.9,
386 0.0, 0.9, 0.9,
[485424b]387 };
388
389 GLfloat texcoords[] = {
[64a70f4]390 1.0f, 1.0f,
391 0.0f, 1.0f,
392 0.0, 0.0,
393 1.0, 1.0,
394 0.0, 0.0,
395 1.0, 0.0
[485424b]396 };
397
398 // Each point is made of 3 floats
399 int numPoints2 = (sizeof(points2) / sizeof(float)) / 3;
400
[19c9338]401 // initialize global variables for click intersection tests
402
[df652d5]403 mat4 T_model, R_model;
404
405 // triangle
406 objects.push_back(SceneObject());
407
408 /*
409 mat4 R_model = rotate(mat4(), 4.0f, vec3(0.0f, 1.0f, 0.0f));
410 */
411 T_model = translate(mat4(), vec3(0.5f, 0.0f, 0.0f));
412 R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
413 objects[0].model_mat = T_model*R_model;
414
415 faces.push_back(ObjectFace());
416 faces[0].objectId = 0;
417 faces[0].points = {
[19c9338]418 vec3(points[0], points[1], points[2]),
419 vec3(points[3], points[4], points[5]),
420 vec3(points[6], points[7], points[8]),
421 };
422
[df652d5]423 // square
424 objects.push_back(SceneObject());
425
426 // mat4 T_model2 = translate(mat4(), vec3(-1.0f, 0.0f, 0.0f));
427 T_model = translate(mat4(), vec3(-0.5f, 0.0f, 0.0f));
428 R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
429 objects[1].model_mat = T_model*R_model;
430
431 faces.push_back(ObjectFace());
432 faces[1].objectId = 1;
433 faces[1].points = {
[19c9338]434 vec3(points2[0], points2[1], points2[2]),
435 vec3(points2[3], points2[4], points2[5]),
436 vec3(points2[6], points2[7], points2[8]),
437 };
438
[df652d5]439 faces.push_back(ObjectFace());
440 faces[2].objectId = 1;
441 faces[2].points = {
[19c9338]442 vec3(points2[9], points2[10], points2[11]),
443 vec3(points2[12], points2[13], points2[14]),
444 vec3(points2[15], points2[16], points2[17]),
445 };
446
[8b7cfcf]447 GLuint points_vbo = 0;
448 glGenBuffers(1, &points_vbo);
449 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
[516668e]450 glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
451
[8b7cfcf]452 GLuint colors_vbo = 0;
453 glGenBuffers(1, &colors_vbo);
454 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
455 glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
456
[644a2e4]457 GLuint vao = 0;
[516668e]458 glGenVertexArrays(1, &vao);
459 glBindVertexArray(vao);
[8b7cfcf]460 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
[516668e]461 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
[8b7cfcf]462 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
463 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
[516668e]464
[8b7cfcf]465 glEnableVertexAttribArray(0);
466 glEnableVertexAttribArray(1);
[644a2e4]467
[485424b]468 GLuint points2_vbo = 0;
469 glGenBuffers(1, &points2_vbo);
470 glBindBuffer(GL_ARRAY_BUFFER, points2_vbo);
471 glBufferData(GL_ARRAY_BUFFER, sizeof(points2), points2, GL_STATIC_DRAW);
472
473 GLuint colors2_vbo = 0;
474 glGenBuffers(1, &colors2_vbo);
475 glBindBuffer(GL_ARRAY_BUFFER, colors2_vbo);
476 glBufferData(GL_ARRAY_BUFFER, sizeof(colors2), colors2, GL_STATIC_DRAW);
477
478 GLuint vt_vbo;
479 glGenBuffers(1, &vt_vbo);
480 glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
481 glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW);
482
483 GLuint vao2 = 0;
484 glGenVertexArrays(1, &vao2);
485 glBindVertexArray(vao2);
486 glBindBuffer(GL_ARRAY_BUFFER, points2_vbo);
487 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
488 // glBindBuffer(GL_ARRAY_BUFFER, colors2_vbo);
489 // glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
490 glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
491 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
[644a2e4]492
[485424b]493 glEnableVertexAttribArray(0);
494 glEnableVertexAttribArray(1);
[8b7cfcf]495
[485424b]496 GLuint shader_program = loadShaderProgram("./color.vert", "./color.frag");
497 GLuint shader_program2 = loadShaderProgram("./texture.vert", "./texture.frag");
[644a2e4]498
[93baa0e]499 float speed = 1.0f;
500 float last_position = 0.0f;
501
[7ee66ea]502 float cam_speed = 1.0f;
[201e2f8]503 float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
[7ee66ea]504
[d12d003]505 //cam_pos = vec3(0.0f, 0.0f, 2.0f);
[64a70f4]506 cam_pos = vec3(0.0f, 0.0f, 0.3f);
507 float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
[7ee66ea]508
[c62eee6]509 mat4 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
[7ee66ea]510 mat4 R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
[33a9664]511 /*
512 mat4 T = translate(mat4(), vec3(0.0f, 0.0f, 0.0f));
513 mat4 R = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
514 */
[c62eee6]515 view_mat = R*T;
[7ee66ea]516
517 float fov = 67.0f * ONE_DEG_IN_RAD;
518 float aspect = (float)width / (float)height;
519
[d12d003]520 float range = tan(fov * 0.5f) * NEAR_CLIP;
521 float Sx = NEAR_CLIP / (range * aspect);
522 float Sy = NEAR_CLIP / range;
523 float Sz = -(FAR_CLIP + NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
524 float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
[7ee66ea]525
[d12d003]526 /*
[c62eee6]527 float proj_arr[] = {
[7ee66ea]528 Sx, 0.0f, 0.0f, 0.0f,
529 0.0f, Sy, 0.0f, 0.0f,
530 0.0f, 0.0f, Sz, -1.0f,
531 0.0f, 0.0f, Pz, 0.0f,
532 };
[d12d003]533 */
[33a9664]534 float proj_arr[] = {
535 1.0f, 0.0f, 0.0f, 0.0f,
536 0.0f, 1.0f, 0.0f, 0.0f,
537 0.0f, 0.0f, 1.0f, 0.0f,
538 0.0f, 0.0f, 0.0f, 1.0f,
539 };
[c62eee6]540 proj_mat = make_mat4(proj_arr);
[7ee66ea]541
[485424b]542 GLint model_test_loc = glGetUniformLocation(shader_program, "model");
543 GLint view_test_loc = glGetUniformLocation(shader_program, "view");
544 GLint proj_test_loc = glGetUniformLocation(shader_program, "proj");
[7ee66ea]545
[19c9338]546 GLint model_mat_loc = glGetUniformLocation(shader_program2, "model");
547 GLint view_mat_loc = glGetUniformLocation(shader_program2, "view");
548 GLint proj_mat_loc = glGetUniformLocation(shader_program2, "proj");
549
[7ee66ea]550 glUseProgram(shader_program);
[df652d5]551 glUniformMatrix4fv(model_test_loc, 1, GL_FALSE, value_ptr(objects[0].model_mat));
[19c9338]552 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
[c62eee6]553 glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
[485424b]554
555 glUseProgram(shader_program2);
[df652d5]556 glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, value_ptr(objects[1].model_mat));
[19c9338]557 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
[c62eee6]558 glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
[7ee66ea]559
560 bool cam_moved = false;
561
[93baa0e]562 double previous_seconds = glfwGetTime();
[644a2e4]563 while (!glfwWindowShouldClose(window)) {
[93baa0e]564 double current_seconds = glfwGetTime();
565 double elapsed_seconds = current_seconds - previous_seconds;
566 previous_seconds = current_seconds;
567
568 if (fabs(last_position) > 1.0f) {
569 speed = -speed;
570 }
571
[147ac6d]572 if (clickedObject == &objects[0]) {
573 selectedObject = &objects[0];
574 }
[33a9664]575
[147ac6d]576 // At some point, I should change this to only rebind the buffer once per click, not once per frame
577 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
578 if (selectedObject == &objects[0]) {
579 glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors_new, GL_STATIC_DRAW);
580 }
581 else {
582 glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
[64a70f4]583 }
[33a9664]584
[7ee66ea]585 /*
[93baa0e]586 model[12] = last_position + speed*elapsed_seconds;
587 last_position = model[12];
[7ee66ea]588 */
[93baa0e]589
590 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[485424b]591
592 glUseProgram(shader_program);
[19c9338]593
594 // this is temporary.
595 // It's needed to offset the code for the recoloring of the square working during click detection
[df652d5]596 glUniformMatrix4fv(model_test_loc, 1, GL_FALSE, value_ptr(objects[0].model_mat));
[485424b]597
[644a2e4]598 glBindVertexArray(vao);
[93baa0e]599
[7ee66ea]600 glDrawArrays(GL_TRIANGLES, 0, numPoints);
[ec4456b]601
[147ac6d]602 if (clickedObject == &objects[1]) {
[df652d5]603 squareSelected = !squareSelected;
[147ac6d]604 selectedObject = &objects[1];
[df652d5]605 }
606
[147ac6d]607 if (selectedObject == &objects[1]) {
[64a70f4]608 glUseProgram(shader_program);
[19c9338]609
610 // this is temporary.
611 // It's needed to get the recoloring of the square working during click detection
[df652d5]612 glUniformMatrix4fv(model_test_loc, 1, GL_FALSE, value_ptr(objects[1].model_mat));
[64a70f4]613
614 glBindVertexArray(vao2);
[485424b]615
[64a70f4]616 glBindBuffer(GL_ARRAY_BUFFER, colors2_vbo);
617 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
618 } else {
619 glUseProgram(shader_program2);
620
621 glBindVertexArray(vao2);
622
623 glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
624 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
625 }
[485424b]626
[64a70f4]627 glDrawArrays(GL_TRIANGLES, 0, numPoints2);
[485424b]628
[147ac6d]629 clickedObject = NULL;
[df652d5]630
[644a2e4]631 glfwPollEvents();
632 glfwSwapBuffers(window);
[ec4456b]633
634 if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
635 glfwSetWindowShouldClose(window, 1);
636 }
[7ee66ea]637
638 float dist = cam_speed * elapsed_seconds;
639 if (glfwGetKey(window, GLFW_KEY_A)) {
[c62eee6]640 cam_pos.x -= cos(cam_yaw)*dist;
641 cam_pos.z += sin(cam_yaw)*dist;
[7ee66ea]642 cam_moved = true;
643 }
644 if (glfwGetKey(window, GLFW_KEY_D)) {
[c62eee6]645 cam_pos.x += cos(cam_yaw)*dist;
646 cam_pos.z -= sin(cam_yaw)*dist;
[7ee66ea]647 cam_moved = true;
648 }
649 if (glfwGetKey(window, GLFW_KEY_W)) {
[c62eee6]650 cam_pos.x -= sin(cam_yaw)*dist;
651 cam_pos.z -= cos(cam_yaw)*dist;
[7ee66ea]652 cam_moved = true;
653 }
654 if (glfwGetKey(window, GLFW_KEY_S)) {
[c62eee6]655 cam_pos.x += sin(cam_yaw)*dist;
656 cam_pos.z += cos(cam_yaw)*dist;
[7ee66ea]657 cam_moved = true;
658 }
659 if (glfwGetKey(window, GLFW_KEY_LEFT)) {
660 cam_yaw += cam_yaw_speed * elapsed_seconds;
661 cam_moved = true;
662 }
663 if (glfwGetKey(window, GLFW_KEY_RIGHT)) {
664 cam_yaw -= cam_yaw_speed * elapsed_seconds;
665 cam_moved = true;
666 }
667 if (cam_moved) {
[c62eee6]668 T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
[7ee66ea]669 R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
[33a9664]670 // view_mat = R*T;
[7ee66ea]671
672 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
673 cam_moved = false;
674 }
[644a2e4]675 }
676
[5272b6b]677 glfwTerminate();
678 return 0;
679}
[ec4456b]680
681GLuint loadShader(GLenum type, string file) {
682 cout << "Loading shader from file " << file << endl;
683
684 ifstream shaderFile(file);
685 GLuint shaderId = 0;
686
687 if (shaderFile.is_open()) {
688 string line, shaderString;
689
690 while(getline(shaderFile, line)) {
691 shaderString += line + "\n";
692 }
693 shaderFile.close();
694 const char* shaderCString = shaderString.c_str();
695
696 shaderId = glCreateShader(type);
697 glShaderSource(shaderId, 1, &shaderCString, NULL);
698 glCompileShader(shaderId);
699
700 cout << "Loaded successfully" << endl;
701 } else {
702 cout << "Failed to loade the file" << endl;
703 }
704
705 return shaderId;
706}
[485424b]707
708GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
709 GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
710 GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
711
712 GLuint shader_program = glCreateProgram();
713 glAttachShader(shader_program, vs);
714 glAttachShader(shader_program, fs);
715
716 glLinkProgram(shader_program);
717
718 return shader_program;
719}
720
721unsigned char* loadImage(string file_name, int* x, int* y) {
722 int n;
723 int force_channels = 4;
724 unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
725 if (!image_data) {
726 fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
727 }
728 return image_data;
729}
[33a9664]730
[5c9d193]731bool faceClicked(ObjectFace* face, vec4 world_ray, vec4 cam) {
732 cout << "Points on the plane" << endl;
733 printVector("fp1", face->points[0]);
734 printVector("fp2", face->points[1]);
735 printVector("fp3", face->points[2]);
736
737 // LINE EQUATION: P = O + Dt
738 // O = cam_pos
739 // D = ray_world
740
741 // PLANE EQUATION: P dot n + d = 0 (n is the normal vector and d is the offset from the origin)
742
743 // Take the cross-product of two vectors on the plane to get the normal
744 vec3 v1 = face->points[1] - face->points[0];
745 vec3 v2 = face->points[2] - face->points[0];
746
747 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);
748 printVector("v1", v1);
749 printVector("v2", v2);
750 printVector("Cross", normal);
751
752 SceneObject* obj = &objects[face->objectId];
753 vec3 local_ray = (inverse(obj->model_mat) * world_ray).xyz();
754 vec3 local_cam = (inverse(obj->model_mat) * cam).xyz();
755 local_ray = local_ray - local_cam;
756
757 cout << "Test theory: " << glm::dot(local_cam, normal) << endl;
758 cout << "Test 2: " << glm::dot(local_ray, normal) << endl;
759
760 float d = -glm::dot(face->points[0], normal);
761 cout << "d: " << d << endl;
762
763 float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
764 cout << "t: " << t << endl;
765
766 vec3 intersection = local_cam + t*local_ray;
767 printVector("Intersection", intersection);
768
769 return insideTriangle(intersection, face->points);
770}
771
772bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
773 vec3 v21 = triangle_points[1]- triangle_points[0];
774 vec3 v31 = triangle_points[2]- triangle_points[0];
775 vec3 pv1 = p- triangle_points[0];
[33a9664]776
777 float y = (pv1.y*v21.x - pv1.x*v21.y) / (v31.y*v21.x - v31.x*v21.y);
778 float x = (pv1.x-y*v31.x) / v21.x;
779
780 cout << "(" << x << ", " << y << ")" << endl;
781
782 return x > 0.0f && y > 0.0f && x+y < 1.0f;
783}
[d12d003]784
785void printVector(string label, vec3 v) {
786 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
787}
Note: See TracBrowser for help on using the repository browser.