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

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

Create SceneObject and ObjectFace structs, a list of objects, and a list of faces, and start using them in the rendering and click detection code to better encapsulate objects in the scene.

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