SuperimposeMesh
All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
SICAD.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-2019 Istituto Italiano di Tecnologia (IIT)
3  *
4  * This software may be modified and distributed under the terms of the
5  * BSD 3-Clause license. See the accompanying LICENSE file for details.
6  */
7 
9 
10 #include <iostream>
11 #include <exception>
12 #include <string>
13 
14 #include <assimp/Importer.hpp>
15 #include <assimp/scene.h>
16 #include <assimp/postprocess.h>
17 
18 #include <glm/gtc/matrix_transform.hpp>
19 #include <glm/gtc/type_ptr.hpp>
20 
21 #include <opencv2/imgproc/imgproc.hpp>
22 
23 
24 int SICAD::class_counter_ = 0;
25 GLsizei SICAD::renderbuffer_size_ = 0;
26 
27 
29 (
30  const ModelPathContainer& objfile_map,
31  const GLsizei cam_width,
32  const GLsizei cam_height,
33  const GLfloat cam_fx,
34  const GLfloat cam_fy,
35  const GLfloat cam_cx,
36  const GLfloat cam_cy
37 ) :
38  SICAD(objfile_map, cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy, 1, "__prc/shader", { 1.0f, 0.0f, 0.0f, 0.0f })
39 { }
40 
41 
43 (
44  const ModelPathContainer& objfile_map,
45  const GLsizei cam_width,
46  const GLsizei cam_height,
47  const GLfloat cam_fx,
48  const GLfloat cam_fy,
49  const GLfloat cam_cx,
50  const GLfloat cam_cy,
51  const GLint num_images
52 ) :
53  SICAD(objfile_map, cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy, num_images, "__prc/shader", { 1.0f, 0.0f, 0.0f, 0.0f })
54 { }
55 
56 
58 (
59  const ModelPathContainer& objfile_map,
60  const GLsizei cam_width,
61  const GLsizei cam_height,
62  const GLfloat cam_fx,
63  const GLfloat cam_fy,
64  const GLfloat cam_cx,
65  const GLfloat cam_cy,
66  const GLint num_images,
67  const std::string& shader_folder
68 ) :
69  SICAD(objfile_map, cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy, num_images, shader_folder, { 1.0f, 0.0f, 0.0f, 0.0f })
70 { }
71 
72 
74 (
75  const ModelPathContainer& objfile_map,
76  const GLsizei cam_width,
77  const GLsizei cam_height,
78  const GLfloat cam_fx,
79  const GLfloat cam_fy,
80  const GLfloat cam_cx,
81  const GLfloat cam_cy,
82  const GLint num_images,
83  const std::string& shader_folder,
84  const std::vector<float>& ogl_to_cam
85 )
86 {
87  if (ogl_to_cam.size() != 4)
88  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tWrong size provided for ogl_to_cam.\n\tShould be 4, was given " + std::to_string(ogl_to_cam.size()) + ".");
89 
90 
91  std::cout << log_ID_ << "Start setting up OpenGL rendering facilities." << std::endl;
92 
93 
94  /* Initialize GLFW. */
95  if (glfwInit() == GL_FALSE)
96  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tFailed to initialize GLFW.");
97 
98 
99  /* Set context properties by "hinting" specific (property, value) pairs. */
100  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
101  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
102  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
103  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
104  glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
105  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
106  glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR, GLFW_RELEASE_BEHAVIOR_NONE);
107 #ifdef GLFW_MAC
108  glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GL_FALSE);
109 #endif
110 
111 
112  /* Create window to create context and enquire OpenGL for the maximum size of the renderbuffer */
113  window_ = glfwCreateWindow(1, 1, "OpenGL window", nullptr, nullptr);
114  if (window_ == nullptr)
115  {
116  glfwTerminate();
117  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tFailed to create GLFW window.");
118  }
119 
120  /* Make the OpenGL context of window the current one handled by this thread. */
121  glfwMakeContextCurrent(window_);
122 
123 
124  /* Enquire GPU for maximum renderbuffer size (both width and height) of the default framebuffer */
125  glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &renderbuffer_size_);
126  std::cout << log_ID_ << "Max renderbuffer size is " + std::to_string(renderbuffer_size_) + "x" + std::to_string(renderbuffer_size_) + " size." << std::endl;
127 
128 
129  /* Given image size */
130  image_width_ = cam_width;
131  image_height_ = cam_height;
132  std::cout << log_ID_ << "Given image size " + std::to_string(image_width_) + "x" + std::to_string(image_height_) + "." << std::endl;
133 
134 
135  /* Compute the maximum number of images that can be rendered conditioned on the maximum renderbuffer size */
136  factorize_int(num_images, std::floor(renderbuffer_size_ / image_width_), std::floor(renderbuffer_size_ / image_height_), tiles_cols_, tiles_rows_);
137  tiles_num_ = tiles_rows_ * tiles_cols_;
138  std::cout << log_ID_ << "Required to render " + std::to_string(num_images) + " image(s)." << std::endl;
139  std::cout << log_ID_ << "Allowed number or rendered images is " + std::to_string(tiles_num_) + " (" + std::to_string(tiles_rows_) + "x" + std::to_string(tiles_cols_) + " grid)." << std::endl;
140 
141  /* Set framebuffer size. */
142  framebuffer_width_ = image_width_ * tiles_cols_;
143  framebuffer_height_ = image_height_ * tiles_rows_;
144 
145  /* Set rendered image size. May vary in HDPI monitors. */
146  tile_img_width_ = framebuffer_width_ / tiles_cols_;
147  tile_img_height_ = framebuffer_height_ / tiles_rows_;
148  std::cout << log_ID_ << "The rendered image size is " + std::to_string(tile_img_width_) + "x" + std::to_string(tile_img_height_) + "." << std::endl;
149 
150 
151  /* Initialize GLEW to use the OpenGL implementation provided by the videocard manufacturer. */
152  glewExperimental = GL_TRUE;
153  if (glewInit() != GLEW_OK)
154  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tFailed to initialize GLEW.");
155 
156 
157  /* Set GL property. */
158  glfwPollEvents();
159  main_thread_id_ = std::this_thread::get_id();
160 
161 
162  std::cout << log_ID_ << "Succesfully set up OpenGL facilities!" << std::endl;
163 
164 
165  std::cout << log_ID_ << "Setting up OpenGL shaders, buffers and textures." << std::endl;
166 
167 
168  /* Rotation from real camera to OpenGL frame */
169  ogl_to_cam_ = glm::mat3(glm::rotate(glm::mat4(1.0f), ogl_to_cam[3], glm::make_vec3(ogl_to_cam.data())));
170 
171 
172  /* Create a framebuffer color texture. */
173  glGenFramebuffers(1, &fbo_);
174  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
175 
176  glGenTextures(1, &texture_color_buffer_);
177  glBindTexture(GL_TEXTURE_2D, texture_color_buffer_);
178  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, framebuffer_width_, framebuffer_height_, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
179  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
180  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
181  glBindTexture(GL_TEXTURE_2D, 0);
182 
183  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_color_buffer_, 0);
184 
185  /* Create a framebuffer depth texture. */
186  glGenTextures(1, &texture_depth_buffer_);
187  glBindTexture(GL_TEXTURE_2D, texture_depth_buffer_);
188  glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, framebuffer_width_, framebuffer_height_, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
189  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
190  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
191  glBindTexture(GL_TEXTURE_2D, 0);
192 
193  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture_depth_buffer_, 0);
194 
195  /* Check whether the framebuffer has been completely created or not. */
196  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
197  throw std::runtime_error("ERROR::SICAD::CTOR::\nERROR:\n\tCustom framebuffer could not be created.");
198 
199 
200  /* Enable depth and scissor test. */
201  glEnable(GL_DEPTH_TEST);
202  glEnable(GL_SCISSOR_TEST);
203 
204 
205  /* Unbind framebuffer. */
206  glBindFramebuffer(GL_FRAMEBUFFER, 0);
207 
208 
209  /* Crate the vertices for 3D reference frame. */
210  glGenVertexArrays(1, &vao_frame_);
211  glBindVertexArray(vao_frame_);
212 
213  glGenBuffers(1, &vbo_frame_);
214  glBindBuffer(GL_ARRAY_BUFFER, vbo_frame_);
215 
216  GLfloat vert_frame[] = {// Positions // Colors
217  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Origin X
218  0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // End X
219  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, // Origin Y
220  0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, // End Y
221  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, // Origin Z
222  0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f }; // End Z
223 
224  glBufferData(GL_ARRAY_BUFFER, sizeof(vert_frame), vert_frame, GL_STATIC_DRAW);
225 
226  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(0));
227  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
228 
229  glEnableVertexAttribArray(0);
230  glEnableVertexAttribArray(1);
231 
232  glBindVertexArray(0);
233 
234 
235  /* Create a background texture. */
236  glGenTextures(1, &texture_background_);
237 
238  /* Crate the squared support for the backround texture. */
239  glGenVertexArrays(1, &vao_background_);
240  glBindVertexArray(vao_background_);
241 
242  glGenBuffers(1, &vbo_background_);
243  glBindBuffer(GL_ARRAY_BUFFER, vbo_background_);
244 
245  GLfloat vert_background[] = {// Positions // Colors // Texture Coords
246  1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top Right
247  1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
248  -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Left
249  -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }; // Top Left
250 
251  glBufferData(GL_ARRAY_BUFFER, sizeof(vert_background), vert_background, GL_STATIC_DRAW);
252 
253  glGenBuffers(1, &ebo_background_);
254  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_background_);
255 
256  GLuint indices[] = { 0, 1, 3, // First Triangle
257  1, 2, 3 }; // Second Triangle
258 
259  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
260 
261  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (GLvoid*)(0));
262  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
263  glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (GLvoid*)(5 * sizeof(GLfloat)));
264 
265  glEnableVertexAttribArray(0);
266  glEnableVertexAttribArray(1);
267  glEnableVertexAttribArray(2);
268 
269  glBindVertexArray(0);
270 
271 
272  /* Crate the Pixel Buffer Objects for reading rendered images and manipulate data directly on GPU. */
273  glGenBuffers(2, pbo_);
274  unsigned int number_of_channel = 3;
275 
276  glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_[0]);
277  glBufferData(GL_PIXEL_PACK_BUFFER, framebuffer_width_ * framebuffer_height_ * number_of_channel, 0, GL_STREAM_READ);
278 
279  glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_[1]);
280  glBufferData(GL_PIXEL_PACK_BUFFER, framebuffer_width_ * framebuffer_height_ * number_of_channel, 0, GL_STREAM_READ);
281 
282  glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
283 
284  /* FIXME
285  * Delete std::nothrow and change try-catch logic.
286  */
287  /* FIXME
288  * Add std::make_unique in an utility header.
289  */
290  /* Crate background shader program. */
291  std::cout << log_ID_ << "Setting up background shader." << std::endl;
292 
293  try
294  {
295  shader_background_ = new (std::nothrow) Shader((shader_folder + "/shader_background.vert").c_str(), (shader_folder + "/shader_background.frag").c_str());
296  }
297  catch (const std::runtime_error& e)
298  {
299  throw std::runtime_error(e.what());
300  }
301  if (shader_background_ == nullptr)
302  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tBackground shader source file not found!");
303 
304  std::cout << log_ID_ << "Background shader succesfully set up!" << std::endl;
305 
306 
307  /* Crate shader program for mesh model. */
308  std::cout << log_ID_ << "Setting up shader for mesh models." << std::endl;
309 
310  try
311  {
312  shader_cad_ = new (std::nothrow) Shader((shader_folder + "/shader_model.vert").c_str(), (shader_folder + "/shader_model.frag").c_str());
313  }
314  catch (const std::runtime_error& e)
315  {
316  throw std::runtime_error(e.what());
317  }
318  if (shader_cad_ == nullptr)
319  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\t3D model shader source file not found!");
320 
321  std::cout << log_ID_ << "Shader for mesh models succesfully set up!" << std::endl;
322 
323 
324  /* Crate shader program for textured model. */
325  std::cout << log_ID_ << "Setting up shader for textured mesh model." << std::endl;
326 
327  try
328  {
329  shader_mesh_texture_ = std::unique_ptr<Shader>(new Shader((shader_folder + "/shader_model.vert").c_str(), (shader_folder + "/shader_model_texture.frag").c_str()));
330  }
331  catch (const std::runtime_error& e)
332  {
333  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tFailed to create shader program for textured meshes.\n" + std::string(e.what()));
334  }
335 
336  std::cout << log_ID_ << "Shader for textured mesh models succesfully set up!" << std::endl;
337 
338 
339  /* Crate axis frame shader program. */
340  std::cout << log_ID_ << "Setting up maxis frame shader." << std::endl;
341 
342  try
343  {
344  shader_frame_ = new (std::nothrow) Shader((shader_folder + "/shader_frame.vert").c_str(), (shader_folder + "/shader_frame.frag").c_str());
345  }
346  catch (const std::runtime_error& e)
347  {
348  throw std::runtime_error(e.what());
349  }
350  if (shader_frame_ == nullptr)
351  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tAxis frame shader source file not found!");
352 
353  std::cout << log_ID_ << "Axis frame shader succesfully set up!" << std::endl;
354 
355 
356  /* Load models. */
357  for (const ModelPathElement& pair : objfile_map)
358  {
359  auto search = model_obj_.find(pair.first);
360  if(search == model_obj_.end())
361  {
362  std::cout << log_ID_ << "Loading " + pair.first + " model for OpenGL rendering from " << pair.second << "." << std::endl;
363 
364  model_obj_[pair.first] = new (std::nothrow) Model(pair.second.c_str());
365 
366  if (model_obj_[pair.first] == nullptr)
367  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\t" + pair.first + " model file from " + pair.second + " not found!");
368  }
369  else
370  {
371  std::cout << log_ID_ << "Skipping " + pair.first + " model for OpenGL rendering. Object name already exists." << std::endl;
372  std::cout << log_ID_ << "If you want to update " + pair.first + " model for OpenGL rendering, use the updateModel function." << std::endl;
373  }
374  }
375 
376  back_proj_ = glm::ortho(-1.001f, 1.001f, -1.001f, 1.001f, 0.0f, far_*100.f);
377 
378  glfwMakeContextCurrent(nullptr);
379 
380 
381  std::cout << log_ID_ << "Succesfully set up OpenGL shaders, buffers and textures." << std::endl;
382 
383 
384  /* Set projection matrix */
385  std::cout << log_ID_ << "Setting up projection matrix." << std::endl;
386 
387  if (!setProjectionMatrix(cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy))
388  throw std::runtime_error("ERROR::SICAD::CTOR\nERROR:\n\tFailed to set projection matrix.");
389 
390 
391  /* Increase static class counter. */
392  ++class_counter_;
393 
394 
395  std::cout << log_ID_ << "Initialization completed!" << std::endl;
396 }
397 
398 
400 {
401  std::cout << log_ID_ << "Deallocating OpenGL resources..." << std::endl;
402 
403 
404  glfwMakeContextCurrent(window_);
405 
406 
407  for (const ModelElement& pair : model_obj_)
408  {
409  std::cout << log_ID_ << "Deleting OpenGL "+ pair.first+" model." << std::endl;
410  delete pair.second;
411  }
412 
413 
414  glDeleteTextures(1, &texture_color_buffer_);
415  glDeleteTextures(1, &texture_depth_buffer_);
416  glDeleteFramebuffers(1, &fbo_);
417  glDeleteVertexArrays(1, &vao_background_);
418  glDeleteBuffers(1, &ebo_background_);
419  glDeleteBuffers(1, &vbo_background_);
420  glDeleteVertexArrays(1, &vao_frame_);
421  glDeleteBuffers(1, &vbo_frame_);
422  glDeleteTextures(1, &texture_background_);
423  glDeleteBuffers(2, pbo_);
424 
425 
426  std::cout << log_ID_ << "Deleting OpenGL shaders." << std::endl;
427  delete shader_background_;
428  delete shader_cad_;
429  delete shader_frame_;
430 
431 
432  std::cout << log_ID_ << "Closing OpenGL window/context." << std::endl;
433  glfwSetWindowShouldClose(window_, GL_TRUE);
434  glfwMakeContextCurrent(nullptr);
435 
436 
437  class_counter_--;
438  if (class_counter_ == 0)
439  {
440  std::cout << log_ID_ << "Terminating GLFW." << std::endl;
441  glfwTerminate();
442  }
443 
444 
445  std::cout << log_ID_ << "OpenGL resource deallocation completed!" << std::endl;
446 }
447 
448 
450 {
451  return (glfwWindowShouldClose(window_) == GL_TRUE ? true : false);
452 }
453 
454 
455 void SICAD::setOglWindowShouldClose(bool should_close)
456 {
457  glfwSetWindowShouldClose(window_, GL_TRUE);
458 
459  pollOrPostEvent();
460 }
461 
462 
464 (
465  const ModelPoseContainer& objpos_map,
466  const double* cam_x,
467  const double* cam_o,
468  cv::Mat& img
469 )
470 {
471  glfwMakeContextCurrent(window_);
472 
473  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
474 
475  /* Render in the upper-left-most tile of the render grid */
476  glViewport(0, framebuffer_height_ - tile_img_height_,
477  tile_img_width_, tile_img_height_ );
478  glScissor (0, framebuffer_height_ - tile_img_height_,
479  tile_img_width_, tile_img_height_ );
480 
481  /* Clear the colorbuffer. */
482  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
483  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
484 
485  /* Draw the background picture. */
486  if (getBackgroundOpt())
487  renderBackground(img);
488 
489  /* View mesh filled or as wireframe. */
490  setWireframe(getWireframeOpt());
491 
492  /* View transformation matrix. */
493  glm::mat4 view = getViewTransformationMatrix(cam_x, cam_o);
494 
495  /* Install/Use the program specified by the shader. */
496  shader_cad_->install();
497  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
498  shader_cad_->uninstall();
499 
500  shader_mesh_texture_->install();
501  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
502  shader_mesh_texture_->uninstall();
503 
504  shader_frame_->install();
505  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
506  shader_frame_->uninstall();
507 
508  /* Model transformation matrix. */
509  for (const ModelPoseContainerElement& pair : objpos_map)
510  {
511  const double* pose = pair.second.data();
512 
513  glm::mat4 model = glm::rotate(glm::mat4(1.0f), static_cast<float>(pose[6]), glm::vec3(static_cast<float>(pose[3]), static_cast<float>(pose[4]), static_cast<float>(pose[5])));
514  model[3][0] = pose[0];
515  model[3][1] = pose[1];
516  model[3][2] = pose[2];
517 
518  auto iter_model = model_obj_.find(pair.first);
519  if (iter_model != model_obj_.end())
520  {
521  if ((iter_model->second)->has_texture())
522  {
523  shader_mesh_texture_->install();
524  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
525 
526  (iter_model->second)->Draw(*shader_mesh_texture_);
527 
528  shader_mesh_texture_->uninstall();
529  }
530  else
531  {
532  shader_cad_->install();
533  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
534 
535  (iter_model->second)->Draw(*shader_cad_);
536 
537  shader_cad_->uninstall();
538  }
539  }
540  else if (pair.first == "frame")
541  {
542  shader_frame_->install();
543  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
544  glBindVertexArray(vao_frame_);
545  glDrawArrays(GL_LINES, 0, 6);
546  glBindVertexArray(0);
547  shader_frame_->uninstall();
548  }
549  }
550 
551  /* Read before swap. glReadPixels read the current framebuffer, i.e. the back one. */
552  /* See: http://stackoverflow.com/questions/16809833/opencv-image-loading-for-opengl-texture#16812529
553  and http://stackoverflow.com/questions/9097756/converting-data-from-glreadpixels-to-opencvmat#9098883 */
554  cv::Mat ogl_pixel(framebuffer_height_ / tiles_rows_, framebuffer_width_ / tiles_cols_, CV_8UC3);
555  glReadBuffer(GL_COLOR_ATTACHMENT0);
556  glPixelStorei(GL_PACK_ALIGNMENT, (ogl_pixel.step & 3) ? 1 : 4);
557  glPixelStorei(GL_PACK_ROW_LENGTH, ogl_pixel.step/ogl_pixel.elemSize());
558  glReadPixels(0, framebuffer_height_ - tile_img_height_, tile_img_width_, tile_img_height_, GL_BGR, GL_UNSIGNED_BYTE, ogl_pixel.data);
559 
560  cv::flip(ogl_pixel, img, 0);
561 
562  /* Swap the buffers. */
563  glfwSwapBuffers(window_);
564 
565  pollOrPostEvent();
566 
567  glBindFramebuffer(GL_FRAMEBUFFER, 0);
568 
569  glfwMakeContextCurrent(nullptr);
570 
571  return true;
572 }
573 
574 
576 (
577  const std::vector<ModelPoseContainer>& objpos_multimap,
578  const double* cam_x,
579  const double* cam_o,
580  cv::Mat& img
581 )
582 {
583  /* Model transformation matrix. */
584  const int objpos_num = objpos_multimap.size();
585  if (objpos_num != tiles_num_) return false;
586 
587  glfwMakeContextCurrent(window_);
588 
589  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
590 
591  /* View transformation matrix. */
592  glm::mat4 view = getViewTransformationMatrix(cam_x, cam_o);
593 
594  /* Install/Use the program specified by the shader. */
595  shader_cad_->install();
596  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
597  shader_cad_->uninstall();
598 
599  shader_mesh_texture_->install();
600  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
601  shader_mesh_texture_->uninstall();
602 
603  shader_frame_->install();
604  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
605  shader_frame_->uninstall();
606 
607  for (unsigned int i = 0; i < tiles_rows_; ++i)
608  {
609  for (unsigned int j = 0; j < tiles_cols_; ++j)
610  {
611  /* Multimap index */
612  int idx = i * tiles_cols_ + j;
613 
614  /* Render starting by the upper-left-most tile of the render grid, proceding by columns and rows. */
615  glViewport(tile_img_width_ * j, framebuffer_height_ - (tile_img_height_ * (i + 1)),
616  tile_img_width_ , tile_img_height_ );
617  glScissor (tile_img_width_ * j, framebuffer_height_ - (tile_img_height_ * (i + 1)),
618  tile_img_width_ , tile_img_height_ );
619 
620  /* Clear the colorbuffer. */
621  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
622  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
623 
624  /* Draw the background picture. */
625  if (getBackgroundOpt())
626  renderBackground(img);
627 
628  /* View mesh filled or as wireframe. */
629  setWireframe(getWireframeOpt());
630 
631  /* Install/Use the program specified by the shader. */
632  for (const ModelPoseContainerElement& pair : objpos_multimap[idx])
633  {
634  const double* pose = pair.second.data();
635 
636  glm::mat4 model = glm::rotate(glm::mat4(1.0f), static_cast<float>(pose[6]), glm::vec3(static_cast<float>(pose[3]), static_cast<float>(pose[4]), static_cast<float>(pose[5])));
637  model[3][0] = static_cast<float>(pose[0]);
638  model[3][1] = static_cast<float>(pose[1]);
639  model[3][2] = static_cast<float>(pose[2]);
640 
641  auto iter_model = model_obj_.find(pair.first);
642  if (iter_model != model_obj_.end())
643  {
644  if ((iter_model->second)->has_texture())
645  {
646  shader_mesh_texture_->install();
647  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
648 
649  (iter_model->second)->Draw(*shader_mesh_texture_);
650 
651  shader_mesh_texture_->uninstall();
652  }
653  else
654  {
655  shader_cad_->install();
656  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
657 
658  (iter_model->second)->Draw(*shader_cad_);
659 
660  shader_cad_->uninstall();
661  }
662  }
663  else if (pair.first == "frame")
664  {
665  shader_frame_->install();
666  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
667  glBindVertexArray(vao_frame_);
668  glDrawArrays(GL_LINES, 0, 6);
669  glBindVertexArray(0);
670  shader_frame_->uninstall();
671  }
672  }
673  }
674  }
675 
676  /* Read before swap. glReadPixels read the current framebuffer, i.e. the back one. */
677  /* See: http://stackoverflow.com/questions/16809833/opencv-image-loading-for-opengl-texture#16812529
678  and http://stackoverflow.com/questions/9097756/converting-data-from-glreadpixels-to-opencvmat#9098883 */
679  cv::Mat ogl_pixel(framebuffer_height_, framebuffer_width_, CV_8UC3);
680  glReadBuffer(GL_COLOR_ATTACHMENT0);
681  glPixelStorei(GL_PACK_ALIGNMENT, (ogl_pixel.step & 3) ? 1 : 4);
682  glPixelStorei(GL_PACK_ROW_LENGTH, ogl_pixel.step/ogl_pixel.elemSize());
683  glReadPixels(0, 0, framebuffer_width_, framebuffer_height_, GL_BGR, GL_UNSIGNED_BYTE, ogl_pixel.data);
684 
685  cv::flip(ogl_pixel, img, 0);
686 
687  /* Swap the buffers. */
688  glfwSwapBuffers(window_);
689 
690  pollOrPostEvent();
691 
692  glBindFramebuffer(GL_FRAMEBUFFER, 0);
693 
694  glfwMakeContextCurrent(nullptr);
695 
696  return true;
697 }
698 
699 
701 (
702  const ModelPoseContainer& objpos_map,
703  const double* cam_x,
704  const double* cam_o,
705  cv::Mat& img,
706  const GLsizei cam_width,
707  const GLsizei cam_height,
708  const GLfloat cam_fx,
709  const GLfloat cam_fy,
710  const GLfloat cam_cx,
711  const GLfloat cam_cy
712 )
713 {
714  if (!setProjectionMatrix(cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy))
715  return false;
716 
717  return superimpose(objpos_map, cam_x, cam_o, img);
718 }
719 
720 
722 (
723  const std::vector<ModelPoseContainer>& objpos_multimap,
724  const double* cam_x,
725  const double* cam_o,
726  cv::Mat& img,
727  const GLsizei cam_width,
728  const GLsizei cam_height,
729  const GLfloat cam_fx,
730  const GLfloat cam_fy,
731  const GLfloat cam_cx,
732  const GLfloat cam_cy
733 )
734 {
735  if (!setProjectionMatrix(cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy))
736  return false;
737 
738  return superimpose(objpos_multimap, cam_x, cam_o, img);
739 }
740 
741 
743 (
744  const ModelPoseContainer& objpos_map,
745  const double* cam_x,
746  const double* cam_o,
747  const size_t pbo_index
748 )
749 {
750  if (!(pbo_index < pbo_number_))
751  {
752  std::cerr << "ERROR::SICAD::SUPERIMPOSE\nERROR:\n\tSICAD PBO index out of bound." << std::endl;
753  return false;
754  }
755 
756 
757  glfwMakeContextCurrent(window_);
758 
759  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
760 
761  /* Render in the upper-left-most tile of the render grid */
762  glViewport(0, framebuffer_height_ - tile_img_height_,
763  tile_img_width_, tile_img_height_ );
764  glScissor (0, framebuffer_height_ - tile_img_height_,
765  tile_img_width_, tile_img_height_ );
766 
767  /* Clear the colorbuffer. */
768  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
769  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
770 
771  /* View mesh filled or as wireframe. */
772  setWireframe(getWireframeOpt());
773 
774  /* View transformation matrix. */
775  glm::mat4 view = getViewTransformationMatrix(cam_x, cam_o);
776 
777  /* Install/Use the program specified by the shader. */
778  shader_cad_->install();
779  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
780  shader_cad_->uninstall();
781 
782  shader_mesh_texture_->install();
783  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
784  shader_mesh_texture_->uninstall();
785 
786  shader_frame_->install();
787  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
788  shader_frame_->uninstall();
789 
790  /* Model transformation matrix. */
791  for (const ModelPoseContainerElement& pair : objpos_map)
792  {
793  const double* pose = pair.second.data();
794 
795  glm::mat4 model = glm::rotate(glm::mat4(1.0f), static_cast<float>(pose[6]), glm::vec3(static_cast<float>(pose[3]), static_cast<float>(pose[4]), static_cast<float>(pose[5])));
796  model[3][0] = pose[0];
797  model[3][1] = pose[1];
798  model[3][2] = pose[2];
799 
800  auto iter_model = model_obj_.find(pair.first);
801  if (iter_model != model_obj_.end())
802  {
803  if ((iter_model->second)->has_texture())
804  {
805  shader_mesh_texture_->install();
806  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
807 
808  (iter_model->second)->Draw(*shader_mesh_texture_);
809 
810  shader_mesh_texture_->uninstall();
811  }
812  else
813  {
814  shader_cad_->install();
815  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
816 
817  (iter_model->second)->Draw(*shader_cad_);
818 
819  shader_cad_->uninstall();
820  }
821  }
822  else if (pair.first == "frame")
823  {
824  shader_frame_->install();
825  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
826  glBindVertexArray(vao_frame_);
827  glDrawArrays(GL_LINES, 0, 6);
828  glBindVertexArray(0);
829  shader_frame_->uninstall();
830  }
831  }
832 
833  glReadBuffer(GL_COLOR_ATTACHMENT0);
834  glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_[pbo_index]);
835  glReadPixels(0, framebuffer_height_ - tile_img_height_, tile_img_width_, tile_img_height_, GL_BGR, GL_UNSIGNED_BYTE, 0);
836 
837  /* Swap the buffers. */
838  glfwSwapBuffers(window_);
839 
840  pollOrPostEvent();
841 
842  glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
843  glBindFramebuffer(GL_FRAMEBUFFER, 0);
844 
845  return true;
846 }
847 
848 
850 (
851  const ModelPoseContainer& objpos_map,
852  const double* cam_x,
853  const double* cam_o,
854  const size_t pbo_index,
855  const cv::Mat& img
856 )
857 {
858  if (!(pbo_index < pbo_number_))
859  {
860  std::cerr << "ERROR::SICAD::SUPERIMPOSE\nERROR:\n\tSICAD PBO index out of bound." << std::endl;
861  return false;
862  }
863 
864 
865  glfwMakeContextCurrent(window_);
866 
867  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
868 
869  /* Render in the upper-left-most tile of the render grid */
870  glViewport(0, framebuffer_height_ - tile_img_height_,
871  tile_img_width_, tile_img_height_ );
872  glScissor (0, framebuffer_height_ - tile_img_height_,
873  tile_img_width_, tile_img_height_ );
874 
875  /* Clear the colorbuffer. */
876  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
877  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
878 
879  /* Draw the background picture. */
880  if (getBackgroundOpt())
881  renderBackground(img);
882 
883  /* View mesh filled or as wireframe. */
884  setWireframe(getWireframeOpt());
885 
886  /* View transformation matrix. */
887  glm::mat4 view = getViewTransformationMatrix(cam_x, cam_o);
888 
889  /* Install/Use the program specified by the shader. */
890  shader_cad_->install();
891  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
892  shader_cad_->uninstall();
893 
894  shader_mesh_texture_->install();
895  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
896  shader_mesh_texture_->uninstall();
897 
898  shader_frame_->install();
899  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
900  shader_frame_->uninstall();
901 
902  /* Model transformation matrix. */
903  for (const ModelPoseContainerElement& pair : objpos_map)
904  {
905  const double* pose = pair.second.data();
906 
907  glm::mat4 model = glm::rotate(glm::mat4(1.0f), static_cast<float>(pose[6]), glm::vec3(static_cast<float>(pose[3]), static_cast<float>(pose[4]), static_cast<float>(pose[5])));
908  model[3][0] = pose[0];
909  model[3][1] = pose[1];
910  model[3][2] = pose[2];
911 
912  auto iter_model = model_obj_.find(pair.first);
913  if (iter_model != model_obj_.end())
914  {
915  if ((iter_model->second)->has_texture())
916  {
917  shader_mesh_texture_->install();
918  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
919 
920  (iter_model->second)->Draw(*shader_mesh_texture_);
921 
922  shader_mesh_texture_->uninstall();
923  }
924  else
925  {
926  shader_cad_->install();
927  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
928 
929  (iter_model->second)->Draw(*shader_cad_);
930 
931  shader_cad_->uninstall();
932  }
933  }
934  else if (pair.first == "frame")
935  {
936  shader_frame_->install();
937  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
938  glBindVertexArray(vao_frame_);
939  glDrawArrays(GL_LINES, 0, 6);
940  glBindVertexArray(0);
941  shader_frame_->uninstall();
942  }
943  }
944 
945  glReadBuffer(GL_COLOR_ATTACHMENT0);
946  glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_[pbo_index]);
947  glReadPixels(0, framebuffer_height_ - tile_img_height_, tile_img_width_, tile_img_height_, GL_BGR, GL_UNSIGNED_BYTE, 0);
948 
949  /* Swap the buffers. */
950  glfwSwapBuffers(window_);
951 
952  pollOrPostEvent();
953 
954  glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
955  glBindFramebuffer(GL_FRAMEBUFFER, 0);
956 
957  return true;
958 }
959 
960 
962 (
963  const std::vector<ModelPoseContainer>& objpos_multimap,
964  const double* cam_x,
965  const double* cam_o,
966  const size_t pbo_index
967 )
968 {
969  if (!(pbo_index < pbo_number_))
970  {
971  std::cerr << "ERROR::SICAD::SUPERIMPOSE\nERROR:\n\tSICAD PBO index out of bound." << std::endl;
972  return false;
973  }
974 
975 
976  /* Model transformation matrix. */
977  const int objpos_num = objpos_multimap.size();
978  if (objpos_num != tiles_num_) return false;
979 
980  glfwMakeContextCurrent(window_);
981 
982  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
983 
984  /* View transformation matrix. */
985  glm::mat4 view = getViewTransformationMatrix(cam_x, cam_o);
986 
987  /* Install/Use the program specified by the shader. */
988  shader_cad_->install();
989  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
990  shader_cad_->uninstall();
991 
992  shader_mesh_texture_->install();
993  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
994  shader_mesh_texture_->uninstall();
995 
996  shader_frame_->install();
997  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
998  shader_frame_->uninstall();
999 
1000  for (unsigned int i = 0; i < tiles_rows_; ++i)
1001  {
1002  for (unsigned int j = 0; j < tiles_cols_; ++j)
1003  {
1004  /* Multimap index */
1005  int idx = i * tiles_cols_ + j;
1006 
1007  /* Render starting by the upper-left-most tile of the render grid, proceding by columns and rows. */
1008  glViewport(tile_img_width_ * j, framebuffer_height_ - (tile_img_height_ * (i + 1)),
1009  tile_img_width_, tile_img_height_ );
1010  glScissor (tile_img_width_ * j, framebuffer_height_ - (tile_img_height_ * (i + 1)),
1011  tile_img_width_, tile_img_height_ );
1012 
1013  /* Clear the colorbuffer. */
1014  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1015  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1016 
1017  /* View mesh filled or as wireframe. */
1018  setWireframe(getWireframeOpt());
1019 
1020  /* Install/Use the program specified by the shader. */
1021  for (const ModelPoseContainerElement& pair : objpos_multimap[idx])
1022  {
1023  const double* pose = pair.second.data();
1024 
1025  glm::mat4 model = glm::rotate(glm::mat4(1.0f), static_cast<float>(pose[6]), glm::vec3(static_cast<float>(pose[3]), static_cast<float>(pose[4]), static_cast<float>(pose[5])));
1026  model[3][0] = static_cast<float>(pose[0]);
1027  model[3][1] = static_cast<float>(pose[1]);
1028  model[3][2] = static_cast<float>(pose[2]);
1029 
1030  auto iter_model = model_obj_.find(pair.first);
1031  if (iter_model != model_obj_.end())
1032  {
1033  if ((iter_model->second)->has_texture())
1034  {
1035  shader_mesh_texture_->install();
1036  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
1037 
1038  (iter_model->second)->Draw(*shader_mesh_texture_);
1039 
1040  shader_mesh_texture_->uninstall();
1041  }
1042  else
1043  {
1044  shader_cad_->install();
1045  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
1046 
1047  (iter_model->second)->Draw(*shader_cad_);
1048 
1049  shader_cad_->uninstall();
1050  }
1051  }
1052  else if (pair.first == "frame")
1053  {
1054  shader_frame_->install();
1055  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
1056  glBindVertexArray(vao_frame_);
1057  glDrawArrays(GL_LINES, 0, 6);
1058  glBindVertexArray(0);
1059  shader_frame_->uninstall();
1060  }
1061  }
1062  }
1063  }
1064 
1065  glReadBuffer(GL_COLOR_ATTACHMENT0);
1066  glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_[pbo_index]);
1067  glReadPixels(0, 0, framebuffer_width_, framebuffer_height_, GL_BGR, GL_UNSIGNED_BYTE, 0);
1068 
1069  /* Swap the buffers. */
1070  glfwSwapBuffers(window_);
1071 
1072  pollOrPostEvent();
1073 
1074  glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
1075  glBindFramebuffer(GL_FRAMEBUFFER, 0);
1076 
1077  return true;
1078 }
1079 
1080 
1081 bool SICAD::superimpose
1083  const std::vector<ModelPoseContainer>& objpos_multimap,
1084  const double* cam_x,
1085  const double* cam_o,
1086  const size_t pbo_index,
1087  const cv::Mat& img
1088 )
1089 {
1090  if (!(pbo_index < pbo_number_))
1091  {
1092  std::cerr << "ERROR::SICAD::SUPERIMPOSE\nERROR:\n\tSICAD PBO index out of bound." << std::endl;
1093  return false;
1094  }
1095 
1096 
1097  /* Model transformation matrix. */
1098  const int objpos_num = objpos_multimap.size();
1099  if (objpos_num != tiles_num_) return false;
1100 
1101  glfwMakeContextCurrent(window_);
1102 
1103  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
1104 
1105  /* View transformation matrix. */
1106  glm::mat4 view = getViewTransformationMatrix(cam_x, cam_o);
1107 
1108  /* Install/Use the program specified by the shader. */
1109  shader_cad_->install();
1110  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
1111  shader_cad_->uninstall();
1112 
1113  shader_mesh_texture_->install();
1114  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
1115  shader_mesh_texture_->uninstall();
1116 
1117  shader_frame_->install();
1118  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "view"), 1, GL_FALSE, glm::value_ptr(view));
1119  shader_frame_->uninstall();
1120 
1121  for (unsigned int i = 0; i < tiles_rows_; ++i)
1122  {
1123  for (unsigned int j = 0; j < tiles_cols_; ++j)
1124  {
1125  /* Multimap index */
1126  int idx = i * tiles_cols_ + j;
1127 
1128  /* Render starting by the upper-left-most tile of the render grid, proceding by columns and rows. */
1129  glViewport(tile_img_width_ * j, framebuffer_height_ - (tile_img_height_ * (i + 1)),
1130  tile_img_width_, tile_img_height_ );
1131  glScissor (tile_img_width_ * j, framebuffer_height_ - (tile_img_height_ * (i + 1)),
1132  tile_img_width_, tile_img_height_ );
1133 
1134  /* Clear the colorbuffer. */
1135  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1136  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1137 
1138  /* Draw the background picture. */
1139  if (getBackgroundOpt())
1140  renderBackground(img);
1141 
1142  /* View mesh filled or as wireframe. */
1143  setWireframe(getWireframeOpt());
1144 
1145  /* Install/Use the program specified by the shader. */
1146  for (const ModelPoseContainerElement& pair : objpos_multimap[idx])
1147  {
1148  const double* pose = pair.second.data();
1149 
1150  glm::mat4 model = glm::rotate(glm::mat4(1.0f), static_cast<float>(pose[6]), glm::vec3(static_cast<float>(pose[3]), static_cast<float>(pose[4]), static_cast<float>(pose[5])));
1151  model[3][0] = static_cast<float>(pose[0]);
1152  model[3][1] = static_cast<float>(pose[1]);
1153  model[3][2] = static_cast<float>(pose[2]);
1154 
1155  auto iter_model = model_obj_.find(pair.first);
1156  if (iter_model != model_obj_.end())
1157  {
1158  if ((iter_model->second)->has_texture())
1159  {
1160  shader_mesh_texture_->install();
1161  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
1162 
1163  (iter_model->second)->Draw(*shader_mesh_texture_);
1164 
1165  shader_mesh_texture_->uninstall();
1166  }
1167  else
1168  {
1169  shader_cad_->install();
1170  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
1171 
1172  (iter_model->second)->Draw(*shader_cad_);
1173 
1174  shader_cad_->uninstall();
1175  }
1176  }
1177  else if (pair.first == "frame")
1178  {
1179  shader_frame_->install();
1180  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "model"), 1, GL_FALSE, glm::value_ptr(model));
1181  glBindVertexArray(vao_frame_);
1182  glDrawArrays(GL_LINES, 0, 6);
1183  glBindVertexArray(0);
1184  shader_frame_->uninstall();
1185  }
1186  }
1187  }
1188  }
1189 
1190  glReadBuffer(GL_COLOR_ATTACHMENT0);
1191  glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_[pbo_index]);
1192  glReadPixels(0, 0, framebuffer_width_, framebuffer_height_, GL_BGR, GL_UNSIGNED_BYTE, 0);
1193 
1194  /* Swap the buffers. */
1195  glfwSwapBuffers(window_);
1196 
1197  pollOrPostEvent();
1198 
1199  glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
1200  glBindFramebuffer(GL_FRAMEBUFFER, 0);
1201 
1202  return true;
1203 }
1204 
1205 
1207 {
1208  glfwMakeContextCurrent(nullptr);
1209 }
1210 
1211 
1212 std::pair<const GLuint*, size_t> SICAD::getPBOs() const
1213 {
1214  glfwMakeContextCurrent(window_);
1215 
1216  return std::make_pair(pbo_, pbo_number_);
1217 }
1218 
1219 
1220 std::pair<bool, GLuint> SICAD::getPBO(const size_t pbo_index) const
1221 {
1222  if (pbo_index < pbo_number_)
1223  {
1224  glfwMakeContextCurrent(window_);
1225 
1226  return std::make_pair(true, pbo_[pbo_index]);
1227  }
1228 
1229  return std::make_pair(false, 0);
1230 }
1231 
1232 
1235  const GLsizei cam_width,
1236  const GLsizei cam_height,
1237  const GLfloat cam_fx,
1238  const GLfloat cam_fy,
1239  const GLfloat cam_cx,
1240  const GLfloat cam_cy
1241 )
1242 {
1243  glfwMakeContextCurrent(window_);
1244 
1245  /* Projection matrix. */
1246  /* In both OpenGL window coordinates and Hartley-Zisserman (HZ) image coordinate systems, (0,0) is the lower left corner with X and Y increasing right and up, respectively. In a normal image file, the (0,0) pixel is in the upper left corner.
1247  There are two possibilities to convert this coordinate system into the image file system coordinate (also used by OpenCV).
1248  1. We can render/draw our images upside down, so that we have already a correspondence between OpenGL and image coordinate systems.
1249  The projection matrix is the following:
1250  [2*K00/width, -2*K01/width, (width - 2*K02 + 2*x0)/width, 0]
1251  [ 0, -2*K11/height, (height - 2*K12 + 2*y0)/height, 0]
1252  [ 0, 0, (-zfar - znear)/(zfar - znear), -2*zfar*znear/(zfar - znear)]
1253  [ 0, 0, -1, 0]
1254  2. We can render/draw our image normally and compensate the the flipped image externally (e.g. with OpenCV flip()).
1255  The projection matrix is the following:
1256  [2*K00/width, -2*K01/width, (width - 2*K02 + 2*x0)/width, 0]
1257  [ 0, 2*K11/height, (-height + 2*K12 + 2*y0)/height, 0]
1258  [ 0, 0, (-zfar - znear)/(zfar - znear), -2*zfar*znear/(zfar - znear)]
1259  [ 0, 0, -1, 0]
1260  Where "Knm" is the (n,m) entry of the 3x3 HZ instrinsic camera calibration matrix K. K is upper triangular and scaled such that the lower-right entry is one. "width" and "height" are the size of the camera image, in pixels, and "x0" and "y0" are the camera image origin, which are normally zero. "znear" and "zfar" are the standard OpenGL near and far clipping planes, respectively. */
1261  // projection_ = glm::mat4(2.0f*(cam_fx/cam_width), 0, 0, 0,
1262  // 0, -2.0f*(cam_fy/cam_height), 0, 0,
1263  // 1-2.0f*(cam_cx/cam_width), 1-2.0f*(cam_cy/cam_height), -(far_+near_)/(far_-near_), -1,
1264  // 0, 0, -2.0f*(far_*near_)/(far_-near_), 0);
1265 
1266  projection_ = glm::mat4(2.0f*(cam_fx/cam_width), 0, 0, 0,
1267  0, 2.0f*(cam_fy/cam_height), 0, 0,
1268  1-2.0f*(cam_cx/cam_width), 2.0f*(cam_cy/cam_height)-1, -(far_+near_)/(far_-near_), -1,
1269  0, 0, -2.0f*(far_*near_)/(far_-near_), 0 );
1270 
1271  /* Install/Use the program specified by the shader. */
1272  shader_cad_->install();
1273  glUniformMatrix4fv(glGetUniformLocation(shader_cad_->get_program(), "projection"), 1, GL_FALSE, glm::value_ptr(projection_));
1274  shader_cad_->uninstall();
1275 
1276  shader_mesh_texture_->install();
1277  glUniformMatrix4fv(glGetUniformLocation(shader_mesh_texture_->get_program(), "projection"), 1, GL_FALSE, glm::value_ptr(projection_));
1278  shader_mesh_texture_->uninstall();
1279 
1280  shader_frame_->install();
1281  glUniformMatrix4fv(glGetUniformLocation(shader_frame_->get_program(), "projection"), 1, GL_FALSE, glm::value_ptr(projection_));
1282  shader_frame_->uninstall();
1283 
1284  glfwSwapBuffers(window_);
1285  glfwMakeContextCurrent(nullptr);
1286 
1287  return true;
1288 }
1289 
1290 
1291 void SICAD::setBackgroundOpt(bool show_background)
1292 {
1293  show_background_ = show_background;
1294 }
1295 
1296 
1298 {
1299  return show_background_;
1300 }
1301 
1302 
1303 void SICAD::setWireframeOpt(bool show_mesh_wires)
1304 {
1305  if (show_mesh_wires) show_mesh_mode_ = GL_LINE;
1306  else show_mesh_mode_ = GL_FILL;
1307 }
1308 
1309 
1310 void SICAD::setMipmapsOpt(const MIPMaps& mipmaps)
1311 {
1312  mesh_mmaps_ = mipmaps;
1313 }
1314 
1315 
1317 {
1318  return show_mesh_mode_;
1319 }
1320 
1321 
1323 {
1324  return mesh_mmaps_;
1325 }
1326 
1327 
1329 {
1330  return tiles_rows_ * tiles_cols_;
1331 }
1332 
1333 
1335 {
1336  return tiles_rows_;
1337 }
1338 
1339 
1341 {
1342  return tiles_cols_;
1343 }
1344 
1345 
1346 glm::mat4 SICAD::getViewTransformationMatrix(const double* cam_x, const double* cam_o)
1347 {
1348  glm::mat4 root_cam_t = glm::translate(glm::mat4(1.0f),
1349  glm::vec3(static_cast<float>(cam_x[0]), static_cast<float>(cam_x[1]), static_cast<float>(cam_x[2])));
1350  glm::mat4 cam_to_root = glm::rotate(glm::mat4(1.0f),
1351  static_cast<float>(cam_o[3]), glm::vec3(static_cast<float>(cam_o[0]), static_cast<float>(cam_o[1]), static_cast<float>(cam_o[2])));
1352 
1353  glm::mat4 view = glm::lookAt(glm::vec3(root_cam_t[3].x, root_cam_t[3].y, root_cam_t[3].z),
1354  glm::vec3(root_cam_t[3].x, root_cam_t[3].y, root_cam_t[3].z) + glm::mat3(cam_to_root) * ogl_to_cam_ * glm::vec3(0.0f, 0.0f, -1.0f),
1355  glm::mat3(cam_to_root) * ogl_to_cam_ * glm::vec3(0.0f, 1.0f, 0.0f));
1356 
1357  return view;
1358 }
1359 
1360 
1362 {
1363  if(main_thread_id_ == std::this_thread::get_id())
1364  glfwPollEvents();
1365  else
1366  glfwPostEmptyEvent();
1367 }
1368 
1369 
1370 void SICAD::renderBackground(const cv::Mat& img) const
1371 {
1372  /* Load and generate the texture. */
1373  glBindTexture(GL_TEXTURE_2D, texture_background_);
1374 
1375  /* Set the texture wrapping/filtering options (on the currently bound texture object). */
1377  {
1378  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1379  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1380  }
1381  else if (getMipmapsOpt() == MIPMaps::linear)
1382  {
1383  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1384  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1385  }
1386 
1387  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.cols, img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, img.data);
1388  glGenerateMipmap(GL_TEXTURE_2D);
1389 
1390  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1391 
1392  /* Install/Use the program specified by the shader. */
1394  glUniformMatrix4fv(glGetUniformLocation(shader_background_->get_program(), "projection"), 1, GL_FALSE, glm::value_ptr(back_proj_));
1395 
1396  glBindVertexArray(vao_background_);
1397  glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1398  glBindVertexArray(0);
1399 
1400  glBindTexture(GL_TEXTURE_2D, 0);
1402 }
1403 
1404 
1405 void SICAD::setWireframe(GLenum mode)
1406 {
1407  glPolygonMode(GL_FRONT_AND_BACK, mode);
1408 }
1409 
1410 
1413  const GLsizei area,
1414  const GLsizei width_limit,
1415  const GLsizei height_limit,
1416  GLsizei& width,
1417  GLsizei& height
1418 )
1419 {
1420  double sqrt_area = std::floor(std::sqrt(static_cast<double>(area)));
1421  height = std::min(static_cast<int>(sqrt_area), height_limit);
1422  width = std::min(area / height, width_limit);
1423 }
std::unordered_map< std::string, std::string > ModelPathContainer
Definition: SICAD.h:33
GLuint texture_background_
Definition: SICAD.h:388
void install()
Activate the shader program.
Definition: Shader.cpp:129
ModelContainer model_obj_
Definition: SICAD.h:380
void renderBackground(const cv::Mat &img) const
Definition: SICAD.cpp:1370
std::pair< std::string, std::string > ModelPathElement
Definition: SICAD.h:35
Shader * shader_background_
Definition: SICAD.h:372
static int class_counter_
Definition: SICAD.h:332
bool show_background_
Definition: SICAD.h:366
void setBackgroundOpt(bool show_background)
Definition: SICAD.cpp:1291
int getTilesCols() const
Definition: SICAD.cpp:1340
std::thread::id main_thread_id_
Definition: SICAD.h:364
int getTilesNumber() const
Definition: SICAD.cpp:1328
MIPMaps mesh_mmaps_
Definition: SICAD.h:370
bool getBackgroundOpt() const
Definition: SICAD.cpp:1297
Definition: Shader.h:17
std::pair< bool, GLuint > getPBO(const size_t pbo_index) const
Returns pbo_index-th Pixel Buffer Object (PBO) value.
Definition: SICAD.cpp:1220
virtual ~SICAD()
Definition: SICAD.cpp:399
static GLsizei renderbuffer_size_
Definition: SICAD.h:334
GLuint fbo_
Definition: SICAD.h:382
MIPMaps
Definition: SICAD.h:41
std::pair< std::string, Model * > ModelElement
Definition: SICAD.h:39
SICAD(const ModelPathContainer &objfile_map, const GLsizei cam_width, const GLsizei cam_height, const GLfloat cam_fx, const GLfloat cam_fy, const GLfloat cam_cx, const GLfloat cam_cy)
Create a SICAD object with a dedicated OpenGL context and default shaders.
Definition: SICAD.cpp:29
bool setProjectionMatrix(const GLsizei cam_width, const GLsizei cam_height, const GLfloat cam_fx, const GLfloat cam_fy, const GLfloat cam_cx, const GLfloat cam_cy)
Definition: SICAD.cpp:1234
GLuint ebo_background_
Definition: SICAD.h:392
Shader * shader_frame_
Definition: SICAD.h:378
void setWireframeOpt(bool show_mesh_wires)
Definition: SICAD.cpp:1303
bool superimpose(const ModelPoseContainer &objpos_map, const double *cam_x, const double *cam_o, cv::Mat &img) override
Render the mesh models in the pose specified in objpos_map and move the virtual camera in cam_x posit...
Definition: SICAD.cpp:464
GLFWwindow * window_
Definition: SICAD.h:338
void pollOrPostEvent()
Definition: SICAD.cpp:1361
void setOglWindowShouldClose(bool should_close)
Definition: SICAD.cpp:455
glm::mat4 back_proj_
Definition: SICAD.h:404
std::pair< std::string, ModelPose > ModelPoseContainerElement
Definition: Superimpose.h:27
GLenum getWireframeOpt() const
Definition: SICAD.cpp:1316
size_t pbo_number_
Definition: SICAD.h:400
A Superimpose derived class to superimpose mesh models on images.
Definition: SICAD.h:30
bool getOglWindowShouldClose()
Definition: SICAD.cpp:449
int getTilesRows() const
Definition: SICAD.cpp:1334
std::multimap< std::string, ModelPose > ModelPoseContainer
Definition: Superimpose.h:25
GLenum show_mesh_mode_
Definition: SICAD.h:368
GLuint texture_depth_buffer_
Definition: SICAD.h:386
Shader * shader_cad_
Definition: SICAD.h:374
void setWireframe(GLenum mode)
Definition: SICAD.cpp:1405
GLuint pbo_[2]
Definition: SICAD.h:402
Definition: Model.h:22
glm::mat4 getViewTransformationMatrix(const double *cam_x, const double *cam_o)
Definition: SICAD.cpp:1346
GLuint vbo_background_
Definition: SICAD.h:394
virtual void releaseContext() const
Make the current thread OpenGL context not current.
Definition: SICAD.cpp:1206
GLuint vao_background_
Definition: SICAD.h:390
std::pair< const GLuint *, size_t > getPBOs() const
Returns the Pixel Buffer Object (PBO) vector and its size.
Definition: SICAD.cpp:1212
glm::mat3 ogl_to_cam_
Definition: SICAD.h:350
const GLuint get_program()
Definition: Shader.h:36
GLsizei tiles_cols_
Definition: SICAD.h:342
void setMipmapsOpt(const MIPMaps &mipmaps)
Definition: SICAD.cpp:1310
void factorize_int(const GLsizei area, const GLsizei width_limit, const GLsizei height_limit, GLsizei &width, GLsizei &height)
Definition: SICAD.cpp:1412
GLuint vao_frame_
Definition: SICAD.h:396
GLsizei tiles_rows_
Definition: SICAD.h:344
GLuint texture_color_buffer_
Definition: SICAD.h:384
MIPMaps getMipmapsOpt() const
Definition: SICAD.cpp:1322
const std::string log_ID_
Definition: SICAD.h:336
void uninstall()
Deactivate the shader program.
Definition: Shader.cpp:135
GLuint vbo_frame_
Definition: SICAD.h:398