source: opengl-game/new-game.cpp@ 147ac6d

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

Remove the clicked field of the SceneObject and instead use a clickedObject variable to keep track of which object was just clicked.

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