Advertisement
JoelSjogren

Untitled

Mar 18th, 2021
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.09 KB | None | 0 0
  1. /**
  2. * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/OpenGL_Programming
  3. * This file is in the public domain.
  4. * Contributors: Sylvain Beucler
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <math.h>
  9. #include <iostream>
  10. #include <fstream>
  11. #include <sstream>
  12. #include <vector>
  13. /* Use glew.h instead of gl.h to get all the GL prototypes declared */
  14. #include <GL/glew.h>
  15. /* Using the GLUT library for the base windowing setup */
  16. #include <GL/glut.h>
  17. /* GLM */
  18. // #define GLM_MESSAGES
  19. #define GLM_FORCE_RADIANS
  20. #include <glm/glm.hpp>
  21. #include <glm/gtc/matrix_transform.hpp>
  22. #include <glm/gtc/type_ptr.hpp>
  23. #include "../common/shader_utils.h"
  24.  
  25. #define GROUND_SIZE 20
  26.  
  27. int screen_width=800, screen_height=600;
  28. GLuint program;
  29. GLint attribute_v_coord = -1;
  30. GLint attribute_v_normal = -1;
  31. GLint uniform_m = -1, uniform_v = -1, uniform_p = -1;
  32. GLint uniform_m_3x3_inv_transp = -1, uniform_v_inv = -1;
  33. bool compute_arcball;
  34. int last_mx = 0, last_my = 0, cur_mx = 0, cur_my = 0;
  35. int arcball_on = false;
  36.  
  37. using namespace std;
  38.  
  39. enum MODES { MODE_OBJECT, MODE_CAMERA, MODE_LIGHT, MODE_LAST } view_mode;
  40. int rotY_direction = 0, rotX_direction = 0, transZ_direction = 0, strife = 0;
  41. float speed_factor = 1;
  42. glm::mat4 transforms[MODE_LAST];
  43. int last_ticks = 0;
  44.  
  45. static unsigned int fps_start = glutGet(GLUT_ELAPSED_TIME);
  46. static unsigned int fps_frames = 0;
  47.  
  48. class Mesh {
  49. private:
  50. GLuint vbo_vertices, vbo_normals, ibo_elements;
  51. public:
  52. vector<glm::vec4> vertices;
  53. vector<glm::vec3> normals;
  54. vector<GLushort> elements;
  55. glm::mat4 object2world;
  56.  
  57. Mesh() : vbo_vertices(0), vbo_normals(0), ibo_elements(0), object2world(glm::mat4(1)) {}
  58. ~Mesh() {
  59. if (vbo_vertices != 0)
  60. glDeleteBuffers(1, &vbo_vertices);
  61. if (vbo_normals != 0)
  62. glDeleteBuffers(1, &vbo_normals);
  63. if (ibo_elements != 0)
  64. glDeleteBuffers(1, &ibo_elements);
  65. }
  66.  
  67. /**
  68. * Store object vertices, normals and/or elements in graphic card
  69. * buffers
  70. */
  71. void upload() {
  72. if (this->vertices.size() > 0) {
  73. glGenBuffers(1, &this->vbo_vertices);
  74. glBindBuffer(GL_ARRAY_BUFFER, this->vbo_vertices);
  75. glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(this->vertices[0]),
  76. this->vertices.data(), GL_STATIC_DRAW);
  77. }
  78.  
  79. if (this->normals.size() > 0) {
  80. glGenBuffers(1, &this->vbo_normals);
  81. glBindBuffer(GL_ARRAY_BUFFER, this->vbo_normals);
  82. glBufferData(GL_ARRAY_BUFFER, this->normals.size() * sizeof(this->normals[0]),
  83. this->normals.data(), GL_STATIC_DRAW);
  84. }
  85.  
  86. if (this->elements.size() > 0) {
  87. glGenBuffers(1, &this->ibo_elements);
  88. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ibo_elements);
  89. glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->elements.size() * sizeof(this->elements[0]),
  90. this->elements.data(), GL_STATIC_DRAW);
  91. }
  92. }
  93.  
  94. /**
  95. * Draw the object
  96. */
  97. void draw() {
  98. if (this->vbo_vertices != 0) {
  99. glEnableVertexAttribArray(attribute_v_coord);
  100. glBindBuffer(GL_ARRAY_BUFFER, this->vbo_vertices);
  101. glVertexAttribPointer(
  102. attribute_v_coord, // attribute
  103. 4, // number of elements per vertex, here (x,y,z,w)
  104. GL_FLOAT, // the type of each element
  105. GL_FALSE, // take our values as-is
  106. 0, // no extra data between each position
  107. 0 // offset of first element
  108. );
  109. }
  110.  
  111. if (this->vbo_normals != 0) {
  112. glEnableVertexAttribArray(attribute_v_normal);
  113. glBindBuffer(GL_ARRAY_BUFFER, this->vbo_normals);
  114. glVertexAttribPointer(
  115. attribute_v_normal, // attribute
  116. 3, // number of elements per vertex, here (x,y,z)
  117. GL_FLOAT, // the type of each element
  118. GL_FALSE, // take our values as-is
  119. 0, // no extra data between each position
  120. 0 // offset of first element
  121. );
  122. }
  123.  
  124. /* Apply object's transformation matrix */
  125. glUniformMatrix4fv(uniform_m, 1, GL_FALSE, glm::value_ptr(this->object2world));
  126. /* Transform normal vectors with transpose of inverse of upper left
  127. 3x3 model matrix (ex-gl_NormalMatrix): */
  128. glm::mat3 m_3x3_inv_transp = glm::transpose(glm::inverse(glm::mat3(this->object2world)));
  129. glUniformMatrix3fv(uniform_m_3x3_inv_transp, 1, GL_FALSE, glm::value_ptr(m_3x3_inv_transp));
  130.  
  131. /* Push each element in buffer_vertices to the vertex shader */
  132. if (this->ibo_elements != 0) {
  133. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ibo_elements);
  134. int size; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
  135. glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
  136. } else {
  137. glDrawArrays(GL_TRIANGLES, 0, this->vertices.size());
  138. }
  139.  
  140. if (this->vbo_normals != 0)
  141. glDisableVertexAttribArray(attribute_v_normal);
  142. if (this->vbo_vertices != 0)
  143. glDisableVertexAttribArray(attribute_v_coord);
  144. }
  145.  
  146. /**
  147. * Draw object bounding box
  148. */
  149. void draw_bbox() {
  150. if (this->vertices.size() == 0)
  151. return;
  152.  
  153. // Cube 1x1x1, centered on origin
  154. GLfloat vertices[] = {
  155. -0.5, -0.5, -0.5, 1.0,
  156. 0.5, -0.5, -0.5, 1.0,
  157. 0.5, 0.5, -0.5, 1.0,
  158. -0.5, 0.5, -0.5, 1.0,
  159. -0.5, -0.5, 0.5, 1.0,
  160. 0.5, -0.5, 0.5, 1.0,
  161. 0.5, 0.5, 0.5, 1.0,
  162. -0.5, 0.5, 0.5, 1.0,
  163. };
  164. GLuint vbo_vertices;
  165. glGenBuffers(1, &vbo_vertices);
  166. glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
  167. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  168. glBindBuffer(GL_ARRAY_BUFFER, 0);
  169.  
  170. GLushort elements[] = {
  171. 0, 1, 2, 3,
  172. 4, 5, 6, 7,
  173. 0, 4, 1, 5, 2, 6, 3, 7
  174. };
  175. GLuint ibo_elements;
  176. glGenBuffers(1, &ibo_elements);
  177. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_elements);
  178. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
  179. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  180.  
  181. GLfloat
  182. min_x, max_x,
  183. min_y, max_y,
  184. min_z, max_z;
  185. min_x = max_x = this->vertices[0].x;
  186. min_y = max_y = this->vertices[0].y;
  187. min_z = max_z = this->vertices[0].z;
  188. for (unsigned int i = 0; i < this->vertices.size(); i++) {
  189. if (this->vertices[i].x < min_x) min_x = this->vertices[i].x;
  190. if (this->vertices[i].x > max_x) max_x = this->vertices[i].x;
  191. if (this->vertices[i].y < min_y) min_y = this->vertices[i].y;
  192. if (this->vertices[i].y > max_y) max_y = this->vertices[i].y;
  193. if (this->vertices[i].z < min_z) min_z = this->vertices[i].z;
  194. if (this->vertices[i].z > max_z) max_z = this->vertices[i].z;
  195. }
  196. glm::vec3 size = glm::vec3(max_x-min_x, max_y-min_y, max_z-min_z);
  197. glm::vec3 center = glm::vec3((min_x+max_x)/2, (min_y+max_y)/2, (min_z+max_z)/2);
  198. glm::mat4 transform = glm::scale(glm::mat4(1), size) * glm::translate(glm::mat4(1), center);
  199.  
  200. /* Apply object's transformation matrix */
  201. glm::mat4 m = this->object2world * transform;
  202. glUniformMatrix4fv(uniform_m, 1, GL_FALSE, glm::value_ptr(m));
  203.  
  204. glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
  205. glEnableVertexAttribArray(attribute_v_coord);
  206. glVertexAttribPointer(
  207. attribute_v_coord, // attribute
  208. 4, // number of elements per vertex, here (x,y,z,w)
  209. GL_FLOAT, // the type of each element
  210. GL_FALSE, // take our values as-is
  211. 0, // no extra data between each position
  212. 0 // offset of first element
  213. );
  214.  
  215. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_elements);
  216. glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0);
  217. glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (GLvoid*)(4*sizeof(GLushort)));
  218. glDrawElements(GL_LINES, 8, GL_UNSIGNED_SHORT, (GLvoid*)(8*sizeof(GLushort)));
  219. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  220.  
  221. glDisableVertexAttribArray(attribute_v_coord);
  222. glBindBuffer(GL_ARRAY_BUFFER, 0);
  223.  
  224. glDeleteBuffers(1, &vbo_vertices);
  225. glDeleteBuffers(1, &ibo_elements);
  226. }
  227. };
  228. Mesh ground, main_object, light_bbox;
  229.  
  230.  
  231. const vector<const char*> pieces_filenames {"10in.tom.shell_Cylinder.004.piece", "12in.tom.shell._Cylinder.003.piece", "14in.shell_Cylinder.005.piece", "badge.001_Circle.009.piece", "badge.002_Circle.014.piece", "badge.003_Circle.026.piece", "badge.004_Circle.035.piece", "badge_Circle.005.piece", "Ball.001_Sphere.002.piece", "ball.mount.001_Cube.007.piece", "ball.mount_Cube.piece", "ball.mount.hardware.000_Cylinder.010.piece", "ball.mount.hardware.001_Cylinder.006.piece", "Ball_Sphere.piece", "Cube_Cube.005.piece", "cymbal.crash_Circle.038.piece", "cymbal.hi-hat_Circle.036.piece", "cymbal.ride_Circle.039.piece", "head.bottom.001_Circle.002.piece", "head.bottom.002_Circle.003.piece", "head.bottom.003_Circle.015.piece", "head.bottom.004_Circle.016.piece", "head.bottom.005_Circle.022.piece", "head.bottom.006_Circle.023.piece", "head.bottom.007_Circle.027.piece", "head.bottom.008_Circle.029.piece", "head.bottom_Circle.008.piece", "head.top_Circle.007.piece", "hoop.10in._Circle.001.piece", "hoop.12in._Circle.013.piece", "hoop.bottom_Circle.011.piece", "hoop.top.001_Circle.019.piece", "hoop.top_Circle.010.piece", "KDtom.mount_Cylinder.013.piece", "kick.hoops_Cylinder.009.piece", "kick.leg_Cylinder.011.piece", "kick_pedal_Plane.007.piece", "kick.shell_Cylinder.008.piece", "lick.lugs_Circle.030.piece", "lug.002_Cube.001.piece", "lug.003_Cube.003.piece", "lug.004_Cube.004.piece", "lug_Cube.002.piece", "middle_lugs.001_Circle.000.piece", "middle_lugs.002_Circle.012.piece", "middle_lugs.003_Circle.021.piece", "middle_lugs_Circle.004.piece", "Plane.001_Plane.006.piece", "Plane.002_Plane.005.piece", "Plane.004_Plane.009.piece", "Plane.005_Plane.010.piece", "Plane.piece", "port.001_Circle.028.piece", "port.002_Circle.032.piece", "port.003_Circle.033.piece", "port.004_Circle.034.piece", "port_Circle.006.piece", "snare.shell_Cylinder.piece", "snare_wire.001_Plane.001.piece", "stand.clamp.001_Cube.008.piece", "stand.clamp_Cube.006.piece", "stand.cymbal.001_Cylinder.017.piece", "stand.cymbal_Cylinder.016.piece", "stand.hi-hat_Cylinder.014.piece", "stand.middle_Cylinder.002.piece", "strainer_Cylinder.001.piece", "throne_Cylinder.007.piece", "tom_mount.001_Circle.020.piece", "tom_mount.002_Circle.024.piece", "tom_mount_Circle.piece", "tom.mount.clamp.001_Circle.018.piece", "tom.mount.clamp.002_Circle.025.piece", "tom.mount.clamp_Circle.017.piece", "tom.mount.main_Circle.031.piece", "wireholder.001_Plane.003.piece", "wireholder_Plane.004.piece"};
  232.  
  233. vector<Mesh> kit_objects(pieces_filenames.size());
  234.  
  235.  
  236. void load_obj(const char* filename, Mesh* mesh) {
  237. ifstream in(filename, ios::in);
  238. if (!in) { cerr << "Cannot open " << filename << endl; exit(1); }
  239. vector<int> nb_seen;
  240.  
  241. string line;
  242.  
  243. long vertex_count = 0;
  244. long face_count = 0;
  245.  
  246. while (getline(in, line)) {
  247. if (line.substr(0,2) == "v ") {
  248. istringstream s(line.substr(2));
  249. glm::vec4 v; s >> v.x; s >> v.y; s >> v.z; v.w = 1.0;
  250. mesh->vertices.push_back(v);
  251. vertex_count++;
  252. } else if (line.substr(0,2) == "f ") {
  253. istringstream s(line.substr(2));
  254. GLushort a,b,c;
  255. s >> a; s >> b; s >> c;
  256. a--; b--; c--;
  257. mesh->elements.push_back(a); mesh->elements.push_back(b); mesh->elements.push_back(c);
  258. face_count++;
  259. }
  260. else if (line[0] == '#') { /* ignoring this line */ }
  261. else { /* ignoring this line */ }
  262. }
  263.  
  264. mesh->normals.resize(mesh->vertices.size(), glm::vec3(0.0, 0.0, 0.0));
  265. nb_seen.resize(mesh->vertices.size(), 0);
  266. for (unsigned int i = 0; i < mesh->elements.size(); i+=3) {
  267. GLushort ia = mesh->elements[i];
  268. GLushort ib = mesh->elements[i+1];
  269. GLushort ic = mesh->elements[i+2];
  270. glm::vec3 normal = glm::normalize(glm::cross(
  271. glm::vec3(mesh->vertices[ib]) - glm::vec3(mesh->vertices[ia]),
  272. glm::vec3(mesh->vertices[ic]) - glm::vec3(mesh->vertices[ia])));
  273.  
  274. int v[3]; v[0] = ia; v[1] = ib; v[2] = ic;
  275. for (int j = 0; j < 3; j++) {
  276. GLushort cur_v = v[j];
  277. nb_seen[cur_v]++;
  278. if (nb_seen[cur_v] == 1) {
  279. mesh->normals[cur_v] = normal;
  280. } else {
  281. // average
  282. mesh->normals[cur_v].x = mesh->normals[cur_v].x * (1.0 - 1.0/nb_seen[cur_v]) + normal.x * 1.0/nb_seen[cur_v];
  283. mesh->normals[cur_v].y = mesh->normals[cur_v].y * (1.0 - 1.0/nb_seen[cur_v]) + normal.y * 1.0/nb_seen[cur_v];
  284. mesh->normals[cur_v].z = mesh->normals[cur_v].z * (1.0 - 1.0/nb_seen[cur_v]) + normal.z * 1.0/nb_seen[cur_v];
  285. mesh->normals[cur_v] = glm::normalize(mesh->normals[cur_v]);
  286. }
  287. }
  288. }
  289.  
  290. //printf("vertex_count: %ld, face_count: %ld\n", vertex_count, face_count);
  291. }
  292.  
  293. void load_drum_kit() {
  294. // pieces_filenames kit_objects
  295.  
  296. for (int i = 0; i < pieces_filenames.size(); i++) {
  297. char buffer[1024]; strcpy(buffer, "../../split/"); strcat(buffer, pieces_filenames[i]);
  298. load_obj(buffer, &kit_objects[i]);
  299. }
  300.  
  301. printf("OK\n");
  302.  
  303. }
  304.  
  305.  
  306. int init_resources(char* model_filename, char* vshader_filename, char* fshader_filename)
  307. {
  308. load_obj(model_filename, &main_object);
  309. // mesh position initialized in init_view()
  310. load_drum_kit();
  311.  
  312.  
  313. for (int i = -GROUND_SIZE/2; i < GROUND_SIZE/2; i++) {
  314. for (int j = -GROUND_SIZE/2; j < GROUND_SIZE/2; j++) {
  315. ground.vertices.push_back(glm::vec4(i, 0.0, j+1, 1.0));
  316. ground.vertices.push_back(glm::vec4(i+1, 0.0, j+1, 1.0));
  317. ground.vertices.push_back(glm::vec4(i, 0.0, j, 1.0));
  318. ground.vertices.push_back(glm::vec4(i, 0.0, j, 1.0));
  319. ground.vertices.push_back(glm::vec4(i+1, 0.0, j+1, 1.0));
  320. ground.vertices.push_back(glm::vec4(i+1, 0.0, j, 1.0));
  321. for (unsigned int k = 0; k < 6; k++)
  322. ground.normals.push_back(glm::vec3(0.0, 1.0, 0.0));
  323. }
  324. }
  325.  
  326. glm::vec3 light_position = glm::vec3(0.0, 1.0, 2.0);
  327. light_bbox.vertices.push_back(glm::vec4(-0.1, -0.1, -0.1, 0.0));
  328. light_bbox.vertices.push_back(glm::vec4( 0.1, -0.1, -0.1, 0.0));
  329. light_bbox.vertices.push_back(glm::vec4( 0.1, 0.1, -0.1, 0.0));
  330. light_bbox.vertices.push_back(glm::vec4(-0.1, 0.1, -0.1, 0.0));
  331. light_bbox.vertices.push_back(glm::vec4(-0.1, -0.1, 0.1, 0.0));
  332. light_bbox.vertices.push_back(glm::vec4( 0.1, -0.1, 0.1, 0.0));
  333. light_bbox.vertices.push_back(glm::vec4( 0.1, 0.1, 0.1, 0.0));
  334. light_bbox.vertices.push_back(glm::vec4(-0.1, 0.1, 0.1, 0.0));
  335. light_bbox.object2world = glm::translate(glm::mat4(1), light_position);
  336.  
  337. main_object.upload();
  338. ground.upload();
  339. light_bbox.upload();
  340.  
  341. for (int i = 0; i < kit_objects.size(); i++) {
  342. kit_objects[i].upload();
  343. }
  344.  
  345.  
  346. /* Compile and link shaders */
  347. GLint link_ok = GL_FALSE;
  348. GLint validate_ok = GL_FALSE;
  349.  
  350. GLuint vs, fs;
  351. if ((vs = create_shader(vshader_filename, GL_VERTEX_SHADER)) == 0) return 0;
  352. if ((fs = create_shader(fshader_filename, GL_FRAGMENT_SHADER)) == 0) return 0;
  353.  
  354. program = glCreateProgram();
  355. glAttachShader(program, vs);
  356. glAttachShader(program, fs);
  357. glLinkProgram(program);
  358. glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
  359. if (!link_ok) {
  360. fprintf(stderr, "glLinkProgram:");
  361. print_log(program);
  362. return 0;
  363. }
  364. glValidateProgram(program);
  365. glGetProgramiv(program, GL_VALIDATE_STATUS, &validate_ok);
  366. if (!validate_ok) {
  367. fprintf(stderr, "glValidateProgram:");
  368. print_log(program);
  369. }
  370.  
  371. const char* attribute_name;
  372. attribute_name = "v_coord";
  373. attribute_v_coord = glGetAttribLocation(program, attribute_name);
  374. if (attribute_v_coord == -1) {
  375. fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
  376. return 0;
  377. }
  378. attribute_name = "v_normal";
  379. attribute_v_normal = glGetAttribLocation(program, attribute_name);
  380. if (attribute_v_normal == -1) {
  381. fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
  382. return 0;
  383. }
  384. const char* uniform_name;
  385. uniform_name = "m";
  386. uniform_m = glGetUniformLocation(program, uniform_name);
  387. if (uniform_m == -1) {
  388. fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
  389. return 0;
  390. }
  391. uniform_name = "v";
  392. uniform_v = glGetUniformLocation(program, uniform_name);
  393. if (uniform_v == -1) {
  394. fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
  395. return 0;
  396. }
  397. uniform_name = "p";
  398. uniform_p = glGetUniformLocation(program, uniform_name);
  399. if (uniform_p == -1) {
  400. fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
  401. return 0;
  402. }
  403. uniform_name = "m_3x3_inv_transp";
  404. uniform_m_3x3_inv_transp = glGetUniformLocation(program, uniform_name);
  405. if (uniform_m_3x3_inv_transp == -1) {
  406. fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
  407. return 0;
  408. }
  409. uniform_name = "v_inv";
  410. uniform_v_inv = glGetUniformLocation(program, uniform_name);
  411. if (uniform_v_inv == -1) {
  412. fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
  413. return 0;
  414. }
  415.  
  416. fps_start = glutGet(GLUT_ELAPSED_TIME);
  417.  
  418. return 1;
  419. }
  420.  
  421. void init_view() {
  422. main_object.object2world = glm::mat4(1);
  423. for (int i = 0; i < kit_objects.size(); i++) {
  424. kit_objects[i].object2world = glm::mat4(1);
  425. }
  426.  
  427. transforms[MODE_CAMERA] = glm::lookAt(
  428. glm::vec3(0.0, 0.0, 4.0), // eye
  429. glm::vec3(0.0, 0.0, 0.0), // direction
  430. glm::vec3(0.0, 1.0, 0.0)); // up
  431. }
  432.  
  433. void onSpecial(int key, int x, int y) {
  434. int modifiers = glutGetModifiers();
  435. if ((modifiers & GLUT_ACTIVE_ALT) == GLUT_ACTIVE_ALT)
  436. strife = 1;
  437. else
  438. strife = 0;
  439.  
  440. if ((modifiers & GLUT_ACTIVE_SHIFT) == GLUT_ACTIVE_SHIFT)
  441. speed_factor = 0.1;
  442. else
  443. speed_factor = 1;
  444.  
  445. switch (key) {
  446. case GLUT_KEY_F1:
  447. view_mode = MODE_OBJECT;
  448. break;
  449. case GLUT_KEY_F2:
  450. view_mode = MODE_CAMERA;
  451. break;
  452. case GLUT_KEY_F3:
  453. view_mode = MODE_LIGHT;
  454. break;
  455. case GLUT_KEY_LEFT:
  456. rotY_direction = 1;
  457. break;
  458. case GLUT_KEY_RIGHT:
  459. rotY_direction = -1;
  460. break;
  461. case GLUT_KEY_UP:
  462. transZ_direction = 1;
  463. break;
  464. case GLUT_KEY_DOWN:
  465. transZ_direction = -1;
  466. break;
  467. case GLUT_KEY_PAGE_UP:
  468. rotX_direction = -1;
  469. break;
  470. case GLUT_KEY_PAGE_DOWN:
  471. rotX_direction = 1;
  472. break;
  473. case GLUT_KEY_HOME:
  474. init_view();
  475. break;
  476. }
  477. }
  478.  
  479. void onSpecialUp(int key, int x, int y) {
  480. switch (key) {
  481. case GLUT_KEY_LEFT:
  482. case GLUT_KEY_RIGHT:
  483. rotY_direction = 0;
  484. break;
  485. case GLUT_KEY_UP:
  486. case GLUT_KEY_DOWN:
  487. transZ_direction = 0;
  488. break;
  489. case GLUT_KEY_PAGE_UP:
  490. case GLUT_KEY_PAGE_DOWN:
  491. rotX_direction = 0;
  492. break;
  493. }
  494. }
  495.  
  496. /**
  497. * Get a normalized vector from the center of the virtual ball O to a
  498. * point P on the virtual ball surface, such that P is aligned on
  499. * screen's (X,Y) coordinates. If (X,Y) is too far away from the
  500. * sphere, return the nearest point on the virtual ball surface.
  501. */
  502. glm::vec3 get_arcball_vector(int x, int y) {
  503. glm::vec3 P = glm::vec3(1.0*x/screen_width*2 - 1.0,
  504. 1.0*y/screen_height*2 - 1.0,
  505. 0);
  506. P.y = -P.y;
  507. float OP_squared = P.x * P.x + P.y * P.y;
  508. if (OP_squared <= 1*1)
  509. P.z = sqrt(1*1 - OP_squared); // Pythagore
  510. else
  511. P = glm::normalize(P); // nearest point
  512. return P;
  513. }
  514.  
  515. void logic() {
  516. /* FPS count */
  517. {
  518. fps_frames++;
  519. int delta_t = glutGet(GLUT_ELAPSED_TIME) - fps_start;
  520. if (delta_t > 1000) {
  521. cout << 1000.0 * fps_frames / delta_t << endl;
  522. fps_frames = 0;
  523. fps_start = glutGet(GLUT_ELAPSED_TIME);
  524. }
  525. }
  526.  
  527. /* Handle keyboard-based transformations */
  528. int delta_t = glutGet(GLUT_ELAPSED_TIME) - last_ticks;
  529. last_ticks = glutGet(GLUT_ELAPSED_TIME);
  530.  
  531. float delta_transZ = transZ_direction * delta_t / 1000.0 * 5 * speed_factor; // 5 units per second
  532. float delta_transX = 0, delta_transY = 0, delta_rotY = 0, delta_rotX = 0;
  533. if (strife) {
  534. delta_transX = rotY_direction * delta_t / 1000.0 * 3 * speed_factor; // 3 units per second
  535. delta_transY = rotX_direction * delta_t / 1000.0 * 3 * speed_factor; // 3 units per second
  536. } else {
  537. delta_rotY = rotY_direction * delta_t / 1000.0 * 120 * speed_factor; // 120° per second
  538. delta_rotX = -rotX_direction * delta_t / 1000.0 * 120 * speed_factor; // 120° per second
  539. }
  540.  
  541. if (view_mode == MODE_OBJECT) {
  542. main_object.object2world = glm::rotate(main_object.object2world, glm::radians(delta_rotY), glm::vec3(0.0, 1.0, 0.0));
  543. main_object.object2world = glm::rotate(main_object.object2world, glm::radians(delta_rotX), glm::vec3(1.0, 0.0, 0.0));
  544. main_object.object2world = glm::translate(main_object.object2world, glm::vec3(0.0, 0.0, delta_transZ));
  545. for (int i = 0; i < kit_objects.size(); i++) {
  546. kit_objects[i].object2world = glm::rotate(kit_objects[i].object2world, glm::radians(delta_rotY), glm::vec3(0.0, 1.0, 0.0));
  547. kit_objects[i].object2world = glm::rotate(kit_objects[i].object2world, glm::radians(delta_rotX), glm::vec3(1.0, 0.0, 0.0));
  548. kit_objects[i].object2world = glm::translate(kit_objects[i].object2world, glm::vec3(0.0, 0.0, delta_transZ));
  549. }
  550. } else if (view_mode == MODE_CAMERA) {
  551. // Camera is reverse-facing, so reverse Z translation and X rotation.
  552. // Plus, the View matrix is the inverse of the camera2world (it's
  553. // world->camera), so we'll reverse the transformations.
  554. // Alternatively, imagine that you transform the world, instead of positioning the camera.
  555. if (strife) {
  556. transforms[MODE_CAMERA] = glm::translate(glm::mat4(1.0), glm::vec3(delta_transX, 0.0, 0.0)) * transforms[MODE_CAMERA];
  557. } else {
  558. glm::vec3 y_axis_world = glm::mat3(transforms[MODE_CAMERA]) * glm::vec3(0.0, 1.0, 0.0);
  559. transforms[MODE_CAMERA] = glm::rotate(glm::mat4(1.0), glm::radians(-delta_rotY), y_axis_world) * transforms[MODE_CAMERA];
  560. }
  561.  
  562. if (strife)
  563. transforms[MODE_CAMERA] = glm::translate(glm::mat4(1.0), glm::vec3(0.0, delta_transY, 0.0)) * transforms[MODE_CAMERA];
  564. else
  565. transforms[MODE_CAMERA] = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, delta_transZ)) * transforms[MODE_CAMERA];
  566.  
  567. transforms[MODE_CAMERA] = glm::rotate(glm::mat4(1.0), glm::radians(delta_rotX), glm::vec3(1.0, 0.0, 0.0)) * transforms[MODE_CAMERA];
  568. }
  569.  
  570. /* Handle arcball */
  571. if (cur_mx != last_mx || cur_my != last_my) {
  572. glm::vec3 va = get_arcball_vector(last_mx, last_my);
  573. glm::vec3 vb = get_arcball_vector( cur_mx, cur_my);
  574. float angle = acos(min(1.0f, glm::dot(va, vb)));
  575. glm::vec3 axis_in_camera_coord = glm::cross(va, vb);
  576.  
  577. glm::mat3 camera2object = glm::inverse(glm::mat3(transforms[MODE_CAMERA]) * glm::mat3(main_object.object2world));
  578. glm::vec3 axis_in_object_coord = camera2object * axis_in_camera_coord;
  579. main_object.object2world = glm::rotate(main_object.object2world, angle, axis_in_object_coord);
  580.  
  581. for (int i = 0; i < kit_objects.size(); i++) {
  582. glm::mat3 camera2object = glm::inverse(glm::mat3(transforms[MODE_CAMERA]) * glm::mat3(kit_objects[i].object2world));
  583. glm::vec3 axis_in_object_coord = camera2object * axis_in_camera_coord;
  584. kit_objects[i].object2world = glm::rotate(kit_objects[i].object2world, angle, axis_in_object_coord);
  585. }
  586.  
  587. last_mx = cur_mx;
  588. last_my = cur_my;
  589. }
  590.  
  591. // Model
  592. // Set in onDisplay() - cf. main_object.object2world
  593.  
  594. // View
  595. glm::mat4 world2camera = transforms[MODE_CAMERA];
  596.  
  597. // Projection
  598. glm::mat4 camera2screen = glm::perspective(45.0f, 1.0f*screen_width/screen_height, 0.1f, 100.0f);
  599.  
  600. glUseProgram(program);
  601. glUniformMatrix4fv(uniform_v, 1, GL_FALSE, glm::value_ptr(world2camera));
  602. glUniformMatrix4fv(uniform_p, 1, GL_FALSE, glm::value_ptr(camera2screen));
  603.  
  604. glm::mat4 v_inv = glm::inverse(world2camera);
  605. glUniformMatrix4fv(uniform_v_inv, 1, GL_FALSE, glm::value_ptr(v_inv));
  606.  
  607. glutPostRedisplay();
  608. }
  609.  
  610. void draw() {
  611. glClearColor(0.45, 0.45, 0.45, 1.0);
  612. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  613.  
  614. glUseProgram(program);
  615.  
  616. //main_object.draw();
  617. for (int i = 0; i < kit_objects.size(); i++) {
  618. kit_objects[i].draw();
  619. }
  620. ground.draw();
  621. light_bbox.draw_bbox();
  622. }
  623.  
  624. void onDisplay()
  625. {
  626. logic();
  627. draw();
  628. glutSwapBuffers();
  629. }
  630.  
  631. void onMouse(int button, int state, int x, int y) {
  632. if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  633. arcball_on = true;
  634. last_mx = cur_mx = x;
  635. last_my = cur_my = y;
  636. } else {
  637. arcball_on = false;
  638. }
  639. }
  640.  
  641. void onMotion(int x, int y) {
  642. if (arcball_on) { // if left button is pressed
  643. cur_mx = x;
  644. cur_my = y;
  645. }
  646. }
  647.  
  648. void onReshape(int width, int height) {
  649. screen_width = width;
  650. screen_height = height;
  651. glViewport(0, 0, screen_width, screen_height);
  652. }
  653.  
  654. void free_resources()
  655. {
  656. glDeleteProgram(program);
  657. }
  658.  
  659.  
  660. int main(int argc, char* argv[]) {
  661. glutInit(&argc, argv);
  662. glutInitDisplayMode(GLUT_RGBA|GLUT_ALPHA|GLUT_DOUBLE|GLUT_DEPTH);
  663. glutInitWindowSize(screen_width, screen_height);
  664. glutCreateWindow("OBJ viewer");
  665.  
  666. GLenum glew_status = glewInit();
  667. if (glew_status != GLEW_OK) {
  668. fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
  669. return 1;
  670. }
  671.  
  672. if (!GLEW_VERSION_2_0) {
  673. fprintf(stderr, "Error: your graphic card does not support OpenGL 2.0\n");
  674. return 1;
  675. }
  676.  
  677. char* obj_filename = (char*) "blendswapdrums2-justthethrone-simplified.obj"; //"blendswapdrums2-simplified.obj"; //"monkey.obj"; //"suzanne.obj";
  678. char* v_shader_filename = (char*) "phong-shading.v.glsl";
  679. char* f_shader_filename = (char*) "phong-shading.f.glsl";
  680. if (argc != 4) {
  681. fprintf(stderr, "Usage: %s model.obj vertex_shader.v.glsl fragment_shader.f.glsl\n", argv[0]);
  682. } else {
  683. obj_filename = argv[1];
  684. v_shader_filename = argv[2];
  685. f_shader_filename = argv[3];
  686. }
  687.  
  688. if (init_resources(obj_filename, v_shader_filename, f_shader_filename)) {
  689. init_view();
  690. glutDisplayFunc(onDisplay);
  691. glutSpecialFunc(onSpecial);
  692. glutSpecialUpFunc(onSpecialUp);
  693. glutMouseFunc(onMouse);
  694. glutMotionFunc(onMotion);
  695. glutReshapeFunc(onReshape);
  696. glEnable(GL_BLEND);
  697. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  698. glEnable(GL_DEPTH_TEST);
  699. //glDepthFunc(GL_LEQUAL);
  700. //glDepthRange(1, 0);
  701. last_ticks = glutGet(GLUT_ELAPSED_TIME);
  702. glutMainLoop();
  703. }
  704.  
  705. free_resources();
  706. return 0;
  707. }
  708.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement